Merge branch 'master' into tv-mode

Conflicts:
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java
This commit is contained in:
Lennart Hensler
2012-03-12 10:22:47 +01:00
26 changed files with 617 additions and 246 deletions
@@ -79,7 +79,9 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
}
public DBCollection getWindTrackCollection() {
return database.getCollection(CollectionNames.WIND_TRACKS.name());
DBCollection result = database.getCollection(CollectionNames.WIND_TRACKS.name());
result.ensureIndex(new BasicDBObject(FieldNames.EVENT_NAME.name(), null));
return result;
}
public DBObject storeWindTrackEntry(Event event, RaceDefinition race, WindSource windSource, Wind wind) {
@@ -109,7 +109,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
}
}
for (Receiver receiver : receivers) {
receiver.stopAfterNotReceivingEventsForSomeTime(/* timeoutInMilliseconds */ 5000l);
receiver.stopAfterNotReceivingEventsForSomeTime(/* timeoutInMilliseconds */ 60000l);
}
for (Receiver receiver : receivers) {
receiver.join();
@@ -2,11 +2,13 @@ package com.sap.sailing.domain.tracking.impl;
import java.util.NavigableSet;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.WindTrackImpl.DummyWind;
/**
* Delivers what {@link TrackedRace#getWind(Position, TimePoint)} delivers, as a navigable set.
@@ -35,4 +37,16 @@ public class CombinedWindAsNavigableSet extends VirtualWindFixesAsNavigableSet {
return new CombinedWindAsNavigableSet(track, trackedRace, from, to, getResolutionInMilliseconds());
}
/**
* 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#getAssumedEnd() 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.
*/
protected TimePoint getTo() {
return getToInternal() == null ? getTrackedRace().getAssumedEnd() == null ? new MillisecondsTimePoint(1)
: ceilingToResolution(new DummyWind(getTrackedRace().getAssumedEnd())) : getToInternal();
}
}
@@ -853,52 +853,52 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
LegType legType;
try {
legType = trackedLeg.getLegType(timePoint);
if (legType != LegType.REACHING) {
GPSFixTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
if (!track.hasDirectionChange(timePoint, getManeuverDegreeAngleThreshold())) {
SpeedWithBearingWithConfidence<TimePoint> estimatedSpeedWithConfidence = track
.getEstimatedSpeed(timePoint, weigher);
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
isNavigatingForward(estimatedSpeedWithConfidence.getObject().getBearing(), trackedLeg,
timePoint)) {
// additionally to generally excluding maneuvers, reduce confidence around mark passings:
NavigableSet<MarkPassing> markPassings = getMarkPassings(competitor);
double markPassingProximityConfidenceReduction = 1.0;
synchronized (markPassings) {
NavigableSet<MarkPassing> prevMarkPassing = markPassings.headSet(
dummyMarkPassingForNow, /* inclusive */true);
NavigableSet<MarkPassing> nextMarkPassing = markPassings.tailSet(
dummyMarkPassingForNow, /* inclusive */true);
if (prevMarkPassing != null && !prevMarkPassing.isEmpty()) {
markPassingProximityConfidenceReduction *= Math.max(0.0,
1.0 - weigherForMarkPassingProximity.getConfidence(prevMarkPassing.last()
.getTimePoint(), timePoint));
}
if (nextMarkPassing != null && !nextMarkPassing.isEmpty()) {
markPassingProximityConfidenceReduction *= Math.max(0.0,
1.0 - weigherForMarkPassingProximity.getConfidence(nextMarkPassing.first()
.getTimePoint(), timePoint));
}
}
BearingWithConfidence<TimePoint> bearing = new BearingWithConfidenceImpl<TimePoint>(
estimatedSpeedWithConfidence.getObject() == null ? null
: estimatedSpeedWithConfidence.getObject().getBearing(),
markPassingProximityConfidenceReduction
* estimatedSpeedWithConfidence.getConfidence(),
estimatedSpeedWithConfidence.getRelativeTo());
BearingWithConfidenceCluster<TimePoint> bearingClusterForLegType = bearings.get(legType);
bearingClusterForLegType.add(bearing);
}
}
}
} catch (NoWindException e) {
logger.warning("Unable to determine leg type for race " + getRace().getName()
+ " while trying to estimate wind");
return null;
}
if (legType != LegType.REACHING) {
GPSFixTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
if (!track.hasDirectionChange(timePoint, getManeuverDegreeAngleThreshold())) {
SpeedWithBearingWithConfidence<TimePoint> estimatedSpeedWithConfidence = track
.getEstimatedSpeed(timePoint, weigher);
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
isNavigatingForward(estimatedSpeedWithConfidence.getObject().getBearing(), trackedLeg,
timePoint)) {
// additionally to generally excluding maneuvers, reduce confidence around mark passings:
NavigableSet<MarkPassing> markPassings = getMarkPassings(competitor);
double markPassingProximityConfidenceReduction = 1.0;
synchronized (markPassings) {
NavigableSet<MarkPassing> prevMarkPassing = markPassings.headSet(
dummyMarkPassingForNow, /* inclusive */true);
NavigableSet<MarkPassing> nextMarkPassing = markPassings.tailSet(
dummyMarkPassingForNow, /* inclusive */true);
if (prevMarkPassing != null && !prevMarkPassing.isEmpty()) {
markPassingProximityConfidenceReduction *= Math.max(0.0,
1.0 - weigherForMarkPassingProximity.getConfidence(prevMarkPassing.last()
.getTimePoint(), timePoint));
}
if (nextMarkPassing != null && !nextMarkPassing.isEmpty()) {
markPassingProximityConfidenceReduction *= Math.max(0.0,
1.0 - weigherForMarkPassingProximity.getConfidence(nextMarkPassing.first()
.getTimePoint(), timePoint));
}
}
BearingWithConfidence<TimePoint> bearing = new BearingWithConfidenceImpl<TimePoint>(
estimatedSpeedWithConfidence.getObject() == null ? null
: estimatedSpeedWithConfidence.getObject().getBearing(),
markPassingProximityConfidenceReduction
* estimatedSpeedWithConfidence.getConfidence(),
estimatedSpeedWithConfidence.getRelativeTo());
BearingWithConfidenceCluster<TimePoint> bearingClusterForLegType = bearings.get(legType);
bearingClusterForLegType.add(bearing);
}
}
bearings = null;
}
}
}
@@ -74,7 +74,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
protected TimePoint lowerToResolution(Wind w) {
TimePoint result;
final TimePoint timePointOfLastEvent = trackedRace.getTimePointOfLastEvent();
final TimePoint timePointOfLastEvent = getTrackedRace().getTimePointOfLastEvent();
if (timePointOfLastEvent == null) {
// nothing received yet; "lowering" to end of time
result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / getResolutionInMilliseconds()
@@ -90,7 +90,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
protected TimePoint floorToResolution(Wind w) {
TimePoint result;
final TimePoint timePointOfLastEvent = trackedRace.getTimePointOfLastEvent();
final TimePoint timePointOfLastEvent = getTrackedRace().getTimePointOfLastEvent();
if (timePointOfLastEvent == null) {
// nothing received yet; "lowering" to end of time
result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / getResolutionInMilliseconds()
@@ -106,7 +106,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
protected TimePoint ceilingToResolution(Wind w) {
TimePoint result;
final TimePoint startOfTracking = trackedRace.getStartOfTracking();
final TimePoint startOfTracking = getTrackedRace().getStartOfTracking();
if (startOfTracking == null) {
// no start of tracking yet; "ceiling" to beginning of time
result = new MillisecondsTimePoint(0);
@@ -121,7 +121,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
protected TimePoint higherToResolution(Wind w) {
TimePoint result;
final TimePoint startOfTracking = trackedRace.getStartOfTracking();
final TimePoint startOfTracking = getTrackedRace().getStartOfTracking();
if (startOfTracking == null) {
// no start of tracking yet; "ceiling" to beginning of time
result = new MillisecondsTimePoint(0);
@@ -141,9 +141,9 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
* will be returned instead. If no valid start time can be obtained from the race, <code>Long.MAX_VALUE</code> is
* returned instead.
*/
private TimePoint getFrom() {
return from == null ? trackedRace.getStart() == null ? new MillisecondsTimePoint(Long.MAX_VALUE)
: floorToResolution(new DummyWind(trackedRace.getStart())) : from;
protected TimePoint getFrom() {
return from == null ? getTrackedRace().getStart() == null ? new MillisecondsTimePoint(Long.MAX_VALUE)
: floorToResolution(new DummyWind(getTrackedRace().getStart())) : from;
}
/**
@@ -153,9 +153,9 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
* {@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.
*/
private TimePoint getTo() {
return to == null ? trackedRace.getTimePointOfNewestEvent() == null ? new MillisecondsTimePoint(1)
: ceilingToResolution(new DummyWind(trackedRace.getTimePointOfNewestEvent())) : to;
protected TimePoint getTo() {
return getToInternal() == null ? getTrackedRace().getTimePointOfNewestEvent() == null ? new MillisecondsTimePoint(1)
: ceilingToResolution(new DummyWind(getTrackedRace().getTimePointOfNewestEvent())) : getToInternal();
}
@Override
@@ -242,7 +242,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
@Override
public NavigableSet<Wind> subSet(Wind fromElement, boolean fromInclusive, Wind toElement, boolean toInclusive) {
return createSubset(track, trackedRace, fromInclusive ? ceilingToResolution(fromElement)
return createSubset(track, getTrackedRace(), fromInclusive ? ceilingToResolution(fromElement)
: higherToResolution(fromElement), toInclusive ? floorToResolution(toElement)
: lowerToResolution(toElement));
}
@@ -254,13 +254,13 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
@Override
public NavigableSet<Wind> headSet(Wind toElement, boolean inclusive) {
return createSubset(track, trackedRace, /* from */ null,
return createSubset(track, getTrackedRace(), /* from */ null,
inclusive ? ceilingToResolution(toElement) : lowerToResolution(toElement));
}
@Override
public NavigableSet<Wind> tailSet(Wind fromElement, boolean inclusive) {
return createSubset(track, trackedRace, inclusive ? floorToResolution(fromElement)
return createSubset(track, getTrackedRace(), inclusive ? floorToResolution(fromElement)
: higherToResolution(fromElement),
/* to */ null);
}
@@ -335,5 +335,9 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl
T[] tResult = (T[]) result;
return tResult;
}
protected TimePoint getToInternal() {
return to;
}
}
@@ -17,11 +17,9 @@ public class LeaderboardPanelMock extends LeaderboardPanel {
public LeaderboardPanelMock(SailingServiceAsync sailingService,
String leaderboardName, ErrorReporter errorReporter,
StringMessages stringConstants) {
super(sailingService, LeaderboardSettingsFactory.getInstance()
.createNewDefaultSettings(
/* autoExpandFirstRace */false), new CompetitorSelectionModel(/* hasMultiSelection */true),
leaderboardName, null, errorReporter, stringConstants, null);
// TODO Auto-generated constructor stub
super(sailingService, LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(
/* racesToShow */null, /* namesOfRacesToShow */ null, /* autoExpandFirstRace */false), new CompetitorSelectionModel(
/* hasMultiSelection */true), leaderboardName, null, errorReporter, stringConstants, null);
}
@Override
@@ -57,7 +57,7 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements EventR
raceMapPanel.setSize("90%", "90%");
tabPanel.add(raceMapPanel, stringMessages.map(), /* asHTML */ false);
LeaderboardSettings defaultLeaderboardSettings = LeaderboardSettingsFactory.getInstance()
.createNewDefaultSettings(/* autoExpandFirstRace */false);
.createNewDefaultSettings(/* racesToShow */ null, /* namesOfRacesToShow */ null, /* autoExpandFirstRace */false);
final LeaderboardPanel defaultLeaderboardPanel = new LeaderboardPanel(sailingService,
defaultLeaderboardSettings,
/* preSelectedRace */null, new CompetitorSelectionModel(/* hasMultiSelection */true),
@@ -41,12 +41,15 @@ import com.google.gwt.maps.client.overlay.Polyline;
import com.google.gwt.maps.client.overlay.PolylineOptions;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.gwt.ui.adminconsole.RaceMapZoomSettings.ZoomTypes;
@@ -69,12 +72,14 @@ import com.sap.sailing.gwt.ui.shared.MarkDTO;
import com.sap.sailing.gwt.ui.shared.PositionDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
public class RaceMap extends SimplePanel implements TimeListener, CompetitorSelectionChangeListener, RaceSelectionChangeListener,
Component<RaceMapSettings>, RequiresDataInitialization {
Component<RaceMapSettings>, RequiresDataInitialization, RequiresResize {
protected MapWidget map;
private final SailingServiceAsync sailingService;
@@ -111,6 +116,10 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
private final Map<MarkDTO, Marker> buoyMarkers;
private Marker combinedWindMarker;
private int combinedWindMarkerPosX;
private int combinedWindMarkerPosY;
/**
* markers displayed in response to
* {@link SailingServiceAsync#getDouglasPoints(String, String, Map, Map, double, AsyncCallback)}
@@ -197,6 +206,8 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
fixes = new HashMap<CompetitorDTO, List<GPSFixDTO>>();
this.competitorSelection = competitorSelection;
competitorSelection.addCompetitorSelectionChangeListener(this);
combinedWindMarkerPosX = 30;
combinedWindMarkerPosY = 30;
settings = new RaceMapSettings();
lastTimeChangeBeforeInitialization = null;
dataInitialized = false;
@@ -296,8 +307,6 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
final ParallelExecutionCallback<Map<CompetitorDTO, List<GPSFixDTO>>> getBoatsCallback = new ParallelExecutionCallback<Map<CompetitorDTO, List<GPSFixDTO>>>();
final ParallelExecutionCallback<List<MarkDTO>> getMarksCallback = new ParallelExecutionCallback<List<MarkDTO>>();
final ParallelExecutionCallback<List<QuickRankDTO>> getQuickRanksCallback = new ParallelExecutionCallback<List<QuickRankDTO>>();
// final ParallelExecutionCallback<WindInfoForRaceDTO> getWindCallback = new ParallelExecutionCallback<WindInfoForRaceDTO>();
// new ParallelExecutionHolder(getBoatsCallback, getMarksCallback, getQuickRanksCallback, getWindCallback) {
new ParallelExecutionHolder(getBoatsCallback, getMarksCallback, getQuickRanksCallback) {
@Override
protected void handleSuccess() {
@@ -339,7 +348,6 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
mapZoomedOrPannedSinceLastRaceSelectionChange = false;
}
}
// showWindOnMap(getWindCallback.getData());
} else {
lastTimeChangeBeforeInitialization = date;
}
@@ -353,7 +361,23 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
sailingService.getBoatPositions(race, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), true, getBoatsCallback);
sailingService.getMarkPositions(race, date, getMarksCallback);
sailingService.getQuickRanks(race, date, getQuickRanksCallback);
// sailingService.getWindInfo(race, date, 0, 0, 0, null, getWindCallback);
// draw the wind into the map, get the combined wind
List<String> windSourceTypeNames = new ArrayList<String>();
windSourceTypeNames.add(WindSourceType.COMBINED.name());
windSourceTypeNames.add(WindSourceType.EXPEDITION.name());
sailingService.getWindInfo(race, date, 1000L, 1, 0.0, 0.0, null,
new AsyncCallback<WindInfoForRaceDTO>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error obtaining wind: " + caught.getMessage());
}
@Override
public void onSuccess(WindInfoForRaceDTO windInfoForRaceDTO) {
showWindOnMap(windInfoForRaceDTO);
}
});
}
}
}
@@ -450,22 +474,57 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
}
protected void showWindOnMap(WindInfoForRaceDTO windInfo) {
// DON'T DELETE... THIS WILL BE IMPLEMENTED SOON
// System.out.println("Windsources: " + windInfo.windTrackInfoByWindSource.size());
// for(WindSource windSource: windInfo.windTrackInfoByWindSource.keySet()) {
// switch (windSource) {
// case COURSE_BASED:
// case EXPEDITION:
// case TRACK_BASED_ESTIMATION:
// case WEB:
// WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource);
// for(WindDTO windDTO: windTrackInfoDTO.windFixes) {
// Long timepoint = windDTO.timepoint;
// }
// }
// }
for(WindSource windSource: windInfo.windTrackInfoByWindSource.keySet()) {
WindTrackInfoDTO windTrackInfoDTO = windInfo.windTrackInfoByWindSource.get(windSource);
switch (windSource.getType()) {
case COMBINED:
{
if(windTrackInfoDTO.windFixes.size() > 0) {
WindDTO windDTO = windTrackInfoDTO.windFixes.get(0);
// double speedInKnots = windDTO.dampenedTrueWindSpeedInKnots;
double windFromDeg = windDTO.dampenedTrueWindFromDeg;
if(combinedWindMarker == null)
createCombinedWindMarker();
if(map != null && combinedWindMarker != null) {
LatLng windMarkerPositionLatLng = map.convertDivPixelToLatLng(Point.newInstance(combinedWindMarkerPosX, combinedWindMarkerPosY));
combinedWindMarker.setLatLng(windMarkerPositionLatLng);
ImageTransformer transformer = imageResources.getCombinedWindIconTransformer();
String transformedImageURL = transformer.getTransformedImageURL(windFromDeg, 1.0);
combinedWindMarker.setImage(transformedImageURL);
}
}
}
break;
case EXPEDITION:
{
}
break;
}
}
}
protected Marker createCombinedWindMarker() {
if(map != null && combinedWindMarker == null) {
LatLng windMarkerPositionLatLng = map.convertDivPixelToLatLng(Point.newInstance(combinedWindMarkerPosX, combinedWindMarkerPosY));
Icon icon = Icon.newInstance();
icon.setImageURL(null);
icon.setShadowURL(null);
MarkerOptions options = MarkerOptions.newInstance(icon);
combinedWindMarker = new Marker(windMarkerPositionLatLng, options);
combinedWindMarker.addMarkerClickHandler(new MarkerClickHandler() {
@Override
public void onClick(MarkerClickEvent event) {
}
});
map.addOverlay(combinedWindMarker);
}
return combinedWindMarker;
}
protected void showMarksOnMap(List<MarkDTO> result) {
if (map != null) {
Set<MarkDTO> toRemove = new HashSet<MarkDTO>(buoyMarkers.keySet());
@@ -925,6 +984,9 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
}
}
/**
* @return The last shown GPS fix for the given competitor
*/
protected GPSFixDTO getBoatFix(CompetitorDTO competitorDTO) {
return fixes.get(competitorDTO).get(lastShownFix.get(competitorDTO));
}
@@ -1138,21 +1200,23 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
competitors = isZoomOnlyToSelectedCompetitors() ? selectedCompetitors : forMap.getCompetitorsToShow();
}
for (CompetitorDTO competitor : competitors) {
List<GPSFixDTO> competitorFixes = forMap.fixes.get(competitor);
Integer lastShownFixForCompetitor = forMap.lastShownFix.get(competitor);
GPSFixDTO competitorFix = competitorFixes != null && lastShownFixForCompetitor != null ? competitorFixes.get(lastShownFixForCompetitor) : null;
PositionDTO competitorPosition = competitorFix != null ? competitorFix.position : null;
LatLng competitorLatLng = competitorPosition != null ? LatLng.newInstance(competitorPosition.latDeg,
competitorPosition.lngDeg) : null;
LatLngBounds bounds = competitorLatLng != null ? LatLngBounds.newInstance(competitorLatLng,
competitorLatLng) : null;
if (bounds != null) {
if (newBounds == null) {
newBounds = bounds;
} else {
newBounds.extend(bounds.getNorthEast());
newBounds.extend(bounds.getSouthWest());
try {
GPSFixDTO competitorFix = forMap.getBoatFix(competitor);
PositionDTO competitorPosition = competitorFix != null ? competitorFix.position : null;
LatLng competitorLatLng = competitorPosition != null ? LatLng.newInstance(competitorPosition.latDeg,
competitorPosition.lngDeg) : null;
LatLngBounds bounds = competitorLatLng != null ? LatLngBounds.newInstance(competitorLatLng,
competitorLatLng) : null;
if (bounds != null) {
if (newBounds == null) {
newBounds = bounds;
} else {
newBounds.extend(bounds.getNorthEast());
newBounds.extend(bounds.getSouthWest());
}
}
} catch (IndexOutOfBoundsException e) {
//Catch this in case the competitor has no GPS fixes at the current time (e.g. in race 'Finale 2' of STG)
}
}
return newBounds;
@@ -1214,4 +1278,10 @@ public class RaceMap extends SimplePanel implements TimeListener, CompetitorSele
public boolean isDataInitialized() {
return dataInitialized;
}
@Override
public void onResize() {
map.checkResize();
zoomMapToNewBounds(getSettings().getZoomSettings().getNewBounds(RaceMap.this));
}
}
@@ -57,6 +57,11 @@ public class RaceMapResources {
*/
protected ImageTransformer boatIconHighlightedStarboardTransformer;
/**
* An arrow showing the combined wind depending on the wind direction
*/
protected ImageTransformer combinedWindIconTransformer;
protected Icon buoyIcon;
protected Map<Pair<ManeuverType, Tack>, Icon> maneuverIconsForTypeAndTargetTack;
@@ -76,6 +81,7 @@ public class RaceMapResources {
boatIconHighlightedPortTransformer = new ImageTransformer(resources.highlightedBoatIcon_Port());
boatIconStarboardTransformer = new ImageTransformer(resources.lowlightedBoatIcon_Starboard());
boatIconHighlightedStarboardTransformer = new ImageTransformer(resources.highlightedBoatIcon_Starboard());
combinedWindIconTransformer = new ImageTransformer(resources.windDirectionIcon());
}
/**
@@ -174,6 +180,10 @@ public class RaceMapResources {
}
}
public ImageTransformer getCombinedWindIconTransformer() {
return combinedWindIconTransformer;
}
public String getBoatImageURL(GPSFixDTO boatFix, boolean highlighted) {
return getBoatImageURL(getBoatImageTransformer(boatFix, highlighted), boatFix);
}
@@ -20,6 +20,8 @@ import org.moxieapps.gwt.highcharts.client.ToolTipData;
import org.moxieapps.gwt.highcharts.client.ToolTipFormatter;
import org.moxieapps.gwt.highcharts.client.events.ChartClickEvent;
import org.moxieapps.gwt.highcharts.client.events.ChartClickEventHandler;
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEvent;
import org.moxieapps.gwt.highcharts.client.events.ChartSelectionEventHandler;
import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions;
import org.moxieapps.gwt.highcharts.client.plotOptions.Marker;
@@ -61,6 +63,7 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
private final ErrorReporter errorReporter;
private final SailingServiceAsync sailingService;
private final Chart chart;
private boolean ignoreClickOnce;
private final Timer timer;
private final DateTimeFormat dateFormat = DateTimeFormat.getFormat("HH:mm:ss");
@@ -114,10 +117,28 @@ public class WindChart extends SimplePanel implements Component<WindChartSetting
chart.setClickEventHandler(new ChartClickEventHandler() {
@Override
public boolean onClick(ChartClickEvent chartClickEvent) {
WindChart.this.timer.setTime(chartClickEvent.getXAxisValueAsLong());
if (ignoreClickOnce) {
ignoreClickOnce = false;
} else {
WindChart.this.timer.setTime(chartClickEvent.getXAxisValueAsLong());
}
return true;
}
});
chart.setSelectionEventHandler(new ChartSelectionEventHandler() {
@Override
public boolean onSelection(ChartSelectionEvent chartSelectionEvent) {
try {
chartSelectionEvent.getXAxisMaxAsLong();
chartSelectionEvent.getXAxisMinAsLong();
ignoreClickOnce = true;
return true;
} catch (Throwable t) {
chart.redraw();
return true;
}
}
});
chart.getXAxis().setType(Axis.Type.DATE_TIME).setMaxZoom(10000) // ten seconds
.setAxisTitleText(stringMessages.time());
chart.getYAxis(0).setAxisTitleText(stringMessages.fromDeg()).setStartOnTick(false).setShowFirstLabel(false);
@@ -59,7 +59,7 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint {
mainPanel.add(tvViewPanel);
} else {
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService,
LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(/* autoExpandFirstRace */ false),
LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, /* autoExpandFirstRace */ false),
/* preSelectedRace */ null, new CompetitorSelectionModel(/* hasMultiSelection */ true),
new Timer(PlayModes.Replay, /* delayBetweenAutoAdvancesInMilliseconds */3000l),
leaderboardName, leaderboardGroupName,
@@ -147,11 +147,6 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private final Timer timer;
/**
* The delay with which the timer shall work. Before the timer is resumed, the delay is set to this value.
*/
private long delayInMilliseconds;
private boolean autoExpandFirstRace;
/**
@@ -184,6 +179,22 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private final BusyIndicator busyIndicator;
/**
* Tells whether the leaderboard settings were explicitly changed by an external call to
* {@link #updateSettings(LeaderboardSettings)}. If so, a {@link #playStateChanged(PlayStates, PlayModes) play state
* change} will not automatically lead to a settings change.
*/
private boolean settingsUpdatedExplicitly = false;
/**
* Tells if the leaderboard is currently handling a {@link #playStateChanged(PlayStates, PlayModes) play state change}.
* If this is the case, a call to {@link #updateSettings(LeaderboardSettings)} won't set the
* {@link #settingsUpdatedExplicitly} flag.
*/
private boolean currentlyHandlingPlayStateChange;
private PlayModes oldPlayMode;
private class SettingsClickHandler implements ClickHandler {
private final StringMessages stringMessages;
@@ -223,6 +234,9 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
public void updateSettings(LeaderboardSettings newSettings) {
if (!currentlyHandlingPlayStateChange) {
settingsUpdatedExplicitly = true;
}
List<ExpandableSortableColumn<?>> columnsToExpandAgain = new ArrayList<ExpandableSortableColumn<?>>();
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(i);
@@ -237,24 +251,52 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
}
}
selectedManeuverDetails.clear();
selectedManeuverDetails.addAll(newSettings.getManeuverDetailsToShow());
selectedLegDetails.clear();
selectedLegDetails.addAll(newSettings.getLegDetailsToShow());
selectedRaceDetails.clear();
selectedRaceDetails.addAll(newSettings.getRaceDetailsToShow());
selectedRaceColumns.clear();
selectedRaceColumns.addAll(newSettings.getRaceColumnsToShow());
if (newSettings.getManeuverDetailsToShow() != null) {
selectedManeuverDetails.clear();
selectedManeuverDetails.addAll(newSettings.getManeuverDetailsToShow());
}
if (newSettings.getLegDetailsToShow() != null) {
selectedLegDetails.clear();
selectedLegDetails.addAll(newSettings.getLegDetailsToShow());
}
if (newSettings.getRaceDetailsToShow() != null) {
selectedRaceDetails.clear();
selectedRaceDetails.addAll(newSettings.getRaceDetailsToShow());
}
if (newSettings.getNamesOfRaceColumnsToShow() != null) {
selectedRaceColumns.clear();
for (String nameOfRaceColumnToShow : newSettings.getNamesOfRaceColumnsToShow()) {
RaceInLeaderboardDTO raceColumnToShow = getRaceByColumnName(nameOfRaceColumnToShow);
if (raceColumnToShow != null) {
selectedRaceColumns.add(raceColumnToShow);
}
}
} else if (newSettings.getNamesOfRacesToShow() != null) {
selectedRaceColumns.clear();
for (String nameOfRaceToShow : newSettings.getNamesOfRacesToShow()) {
RaceInLeaderboardDTO raceColumnToShow = getRaceByName(nameOfRaceToShow);
if (raceColumnToShow != null) {
selectedRaceColumns.add(raceColumnToShow);
}
}
}
setAutoExpandFirstRace(false); // avoid expansion during updateLeaderboard(...); will expand later if it was expanded before
// update leaderboard after settings panel column selection change
updateLeaderboard(leaderboard);
setAutoExpandFirstRace(newSettings.isAutoExpandFirstRace());
timer.setRefreshInterval(newSettings.getDelayBetweenAutoAdvancesInMilliseconds());
setDelayInMilliseconds(newSettings.getDelayInMilliseconds());
if (newSettings.getDelayBetweenAutoAdvancesInMilliseconds() != null) {
timer.setRefreshInterval(newSettings.getDelayBetweenAutoAdvancesInMilliseconds());
}
if (newSettings.getDelayInMilliseconds() != null) {
setDelayInMilliseconds(newSettings.getDelayInMilliseconds());
}
for (ExpandableSortableColumn<?> expandableSortableColumn : columnsToExpandAgain) {
expandableSortableColumn.toggleExpansion();
}
if (newSettings.getNameOfRaceToSort() != null) {
sort(getRaceColumnByRaceName(newSettings.getNameOfRaceToSort()), /* ascending */ true);
}
}
protected class CompetitorColumn extends SortableColumn<LeaderboardRowDTO, String> {
@@ -362,7 +404,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
return race;
}
public String getRaceName() {
public String getRaceColumnName() {
return race.getRaceColumnName();
}
@@ -390,7 +432,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
*/
@Override
public void render(Context context, LeaderboardRowDTO object, SafeHtmlBuilder html) {
LeaderboardEntryDTO entry = object.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO entry = object.fieldsByRaceName.get(getRaceColumnName());
if (entry != null) {
// don't show points if max points / penalty
if (entry.reasonForMaxPoints.equals("NONE")) {
@@ -422,18 +464,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
if (race.isMedalRace()) {
return getLeaderboard().getMedalRaceComparator(race.getRaceColumnName());
} else {
return new Comparator<LeaderboardRowDTO>() {
@Override
public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) {
boolean ascending = isSortedAscendingForThisColumn(getLeaderboardPanel().getLeaderboardTable());
LeaderboardEntryDTO o1Entry = o1.fieldsByRaceName.get(race.getRaceColumnName());
LeaderboardEntryDTO o2Entry = o2.fieldsByRaceName.get(race.getRaceColumnName());
return (o1Entry == null || o1Entry.netPoints == 0) ? (o2Entry == null || o2Entry.netPoints == 0) ? 0
: ascending ? 1 : -1
: (o2Entry == null || o2Entry.netPoints == 0) ? ascending ? -1 : 1 : o1Entry.netPoints
- o2Entry.netPoints;
}
};
return new NetPointsComparator(isSortedAscendingForThisColumn(getLeaderboardPanel().getLeaderboardTable()),
race.getRaceColumnName());
}
}
@@ -473,12 +505,12 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public String getValue(LeaderboardRowDTO object) {
return "" + object.fieldsByRaceName.get(getRaceName()).totalPoints;
return "" + object.fieldsByRaceName.get(getRaceColumnName()).totalPoints;
}
@Override
protected void ensureExpansionDataIsLoaded(final Runnable callWhenExpansionDataIsLoaded) {
if (getLeaderboard().getLegCount(getRaceName()) != -1) {
if (getLeaderboard().getLegCount(getRaceColumnName()) != -1) {
callWhenExpansionDataIsLoaded.run();
} else {
getSailingService().getLeaderboardByName(getLeaderboardName(), getLeaderboardDisplayDate(),
@@ -546,7 +578,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
// it is important to re-use existing LegColumn objects because
// removing the columns from the table
// is based on column identity
int legCount = getLeaderboard().getLegCount(getRaceName());
int legCount = getLeaderboard().getLegCount(getRaceColumnName());
if (legCount != -1) {
for (int i = 0; i < legCount; i++) {
LegColumn legColumn = getLegColumn(i);
@@ -569,7 +601,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
if (legColumns.size() > legNumber && legColumns.get(legNumber) != null) {
result = legColumns.get(legNumber);
} else {
result = new LegColumn(LeaderboardPanel.this, getRaceName(), legNumber, stringMessages,
result = new LegColumn(LeaderboardPanel.this, getRaceColumnName(), legNumber, stringMessages,
Collections.unmodifiableList(selectedLegDetails), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE,
LEG_DETAIL_COLUMN_HEADER_STYLE, LEG_DETAIL_COLUMN_STYLE);
while (legColumns.size() <= legNumber) {
@@ -589,7 +621,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public Double get(LeaderboardRowDTO row) {
Double result = null;
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceColumnName());
if (fieldsForRace != null && fieldsForRace.legDetails != null) {
double distanceTraveledInMeters = 0;
long timeInMilliseconds = 0;
@@ -616,7 +648,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public Double get(LeaderboardRowDTO row) {
Double result = null;
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceColumnName());
if (fieldsForRace != null && fieldsForRace.legDetails != null) {
for (LegEntryDTO legDetail : fieldsForRace.legDetails) {
if (legDetail != null) {
@@ -637,7 +669,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public Double get(LeaderboardRowDTO row) {
Double result = null;
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceColumnName());
if (fieldsForRace != null && fieldsForRace.legDetails != null && !fieldsForRace.legDetails.isEmpty()) {
for (LegEntryDTO legDetail : fieldsForRace.legDetails) {
if (legDetail != null) {
@@ -668,7 +700,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public Double get(LeaderboardRowDTO row) {
Double result = null;
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceColumnName());
if (fieldsForRace != null && fieldsForRace.legDetails != null) {
int lastLegIndex = fieldsForRace.legDetails.size() - 1;
LegEntryDTO lastLegDetail = fieldsForRace.legDetails.get(lastLegIndex);
@@ -693,7 +725,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public Double get(LeaderboardRowDTO row) {
Double result = null;
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceName());
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceName.get(getRaceColumnName());
if (fieldsForRace != null && fieldsForRace.windwardDistanceToOverallLeaderInMeters != null) {
result = fieldsForRace.windwardDistanceToOverallLeaderInMeters;
}
@@ -820,7 +852,6 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
ErrorReporter errorReporter, final StringMessages stringMessages, final UserAgentTypes userAgentType) {
this(sailingService, settings, preSelectedRace, competitorSelectionProvider, new Timer(PlayModes.Replay, /* delayBetweenAutoAdvancesInMilliseconds */3000l),
leaderboardName, leaderboardGroupName, errorReporter, stringMessages, userAgentType);
timer.setDelay(getDelayInMilliseconds()); // set time/delay before adding as listener
}
public LeaderboardPanel(SailingServiceAsync sailingService, LeaderboardSettings settings, RaceIdentifier preSelectedRace,
@@ -841,7 +872,6 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
selectedLegDetails.addAll(settings.getLegDetailsToShow());
selectedManeuverDetails.addAll(settings.getManeuverDetailsToShow());
selectedRaceDetails.addAll(settings.getRaceDetailsToShow());
delayInMilliseconds = settings.getDelayInMilliseconds();
setAutoExpandFirstRace(settings.isAutoExpandFirstRace());
this.timer = timer;
@@ -906,7 +936,6 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
if (LeaderboardPanel.this.timer.getPlayState() == PlayStates.Playing) {
LeaderboardPanel.this.timer.pause();
} else {
LeaderboardPanel.this.timer.setDelay(getDelayInMilliseconds());
LeaderboardPanel.this.timer.play();
}
}
@@ -949,6 +978,43 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
contentPanel.add(getLeaderboardTable());
setWidget(contentPanel);
if (settings.getNameOfRaceToSort() != null) {
RaceColumn<?> column = getRaceColumnByRaceName(settings.getNameOfRaceToSort());
sort(column, settings.isSortAscending());
}
}
private RaceInLeaderboardDTO getRaceByName(String raceName) {
if (getLeaderboard() != null) {
for (RaceInLeaderboardDTO race : getLeaderboard().getRaceList()) {
if (race.getRaceIdentifier() != null && raceName.equals(race.getRaceIdentifier().getRaceName())) {
return race;
}
}
}
return null;
}
private RaceInLeaderboardDTO getRaceByColumnName(String columnName) {
if (getLeaderboard() != null) {
for (RaceInLeaderboardDTO race : getLeaderboard().getRaceList()) {
if (columnName.equals(race.getRaceColumnName())) {
return race;
}
}
}
return null;
}
private RaceColumn<?> getRaceColumnByRaceName(String raceName) {
for (int i=0; i<getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDTO, ?> column = getLeaderboardTable().getColumn(i);
if (column instanceof RaceColumn<?>
&& ((RaceColumn<?>) column).getRace().getRaceIdentifier().getRaceName().equals(raceName)) {
return (RaceColumn<?>) column;
}
}
return null;
}
private SafeHtml getPlayPauseImgHtml(PlayStates playState) {
@@ -958,16 +1024,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
return AbstractImagePrototype.create(playIcon).getSafeHtml();
}
private long getDelayInMilliseconds() {
return delayInMilliseconds;
}
private void setDelayInMilliseconds(long delayInMilliseconds) {
this.delayInMilliseconds = delayInMilliseconds;
timer.setDelay(delayInMilliseconds);
if (timer.getPlayMode() == PlayModes.Live) {
}
}
public boolean isAutoExpandFirstRace() {
@@ -1081,7 +1139,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
if (column instanceof RaceColumn<?>) {
RaceColumn<?> raceColumn = (RaceColumn<?>) column;
if (raceColumn.isExpanded()) {
namesOfExpandedRaces.add(raceColumn.getRaceName());
namesOfExpandedRaces.add(raceColumn.getRaceColumnName());
}
}
}
@@ -1092,45 +1150,60 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* Also updates the min/max values on the columns
*/
protected void updateLeaderboard(LeaderboardDTO leaderboard) {
competitorSelectionProvider.setCompetitors(leaderboard.competitors);
selectedRaceColumns.addAll(getRaceColumnsToAddImplicitly(leaderboard));
setLeaderboard(leaderboard);
adjustColumnLayout(leaderboard);
getData().getList().clear();
if (leaderboard != null) {
boolean firstRace = true;
getData().getList().addAll(leaderboard.rows.values());
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
SortableColumn<?, ?> c = (SortableColumn<?, ?>) getLeaderboardTable().getColumn(i);
c.updateMinMax(leaderboard);
//Toggle the first race, if the setting is set and it isn't open yet
if (firstRace && isAutoExpandFirstRace() && c instanceof ExpandableSortableColumn<?>) {
ExpandableSortableColumn<?> expandableSortableColumn = (ExpandableSortableColumn<?>) c;
if (!expandableSortableColumn.isExpanded()) {
expandableSortableColumn.toggleExpansion();
competitorSelectionProvider.setCompetitors(leaderboard.competitors);
selectedRaceColumns.addAll(getRaceColumnsToAddImplicitly(leaderboard));
setLeaderboard(leaderboard);
adjustColumnLayout(leaderboard);
getData().getList().clear();
if (leaderboard != null) {
boolean firstRace = true;
getData().getList().addAll(leaderboard.rows.values());
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
SortableColumn<?, ?> c = (SortableColumn<?, ?>) getLeaderboardTable().getColumn(i);
c.updateMinMax(leaderboard);
// Toggle the first race, if the setting is set and it isn't open yet
if (firstRace && isAutoExpandFirstRace() && c instanceof ExpandableSortableColumn<?>) {
ExpandableSortableColumn<?> expandableSortableColumn = (ExpandableSortableColumn<?>) c;
if (!expandableSortableColumn.isExpanded()) {
expandableSortableColumn.toggleExpansion();
}
firstRace = false;
}
firstRace = false;
}
}
Comparator<LeaderboardRowDTO> comparator = getComparatorForSelectedSorting();
if (comparator != null) {
Collections.sort(getData().getList(), comparator);
} else {
// if no sorting was selected, sort by ascending rank and mark
// table header so
Collections.sort(getData().getList(), getRankColumn().getComparator());
getLeaderboardTable().getColumnSortList().push(getRankColumn());
}
//Reselect the selected rows
clearSelection();
for (LeaderboardRowDTO row : data.getList()) {
if (competitorSelectionProvider.isSelected(row.competitor)) {
leaderboardSelectionModel.setSelected(row, true);
Comparator<LeaderboardRowDTO> comparator = getComparatorForSelectedSorting();
if (comparator != null) {
Collections.sort(getData().getList(), comparator);
} else {
RankColumn columnToSortFor = getRankColumn();
// if no sorting was selected, sort by ascending rank and mark
// table header so
sort(columnToSortFor, true);
}
// Reselect the selected rows
clearSelection();
for (LeaderboardRowDTO row : data.getList()) {
if (competitorSelectionProvider.isSelected(row.competitor)) {
leaderboardSelectionModel.setSelected(row, true);
}
}
}
}
}
/**
* Sorts the leaderboard contents in ascending order according to <code>columnToSortFor</code>'s comparator and
* marks the table's column sort list so.
*/
private void sort(SortableColumn<LeaderboardRowDTO, ?> columnToSortFor, boolean ascending) {
Collections.sort(getData().getList(), getComparator(columnToSortFor, ascending));
ColumnSortInfo columnSortInfo = getLeaderboardTable().getColumnSortList().push(columnToSortFor);
if (ascending != columnSortInfo.isAscending()) {
// flip ascending bit by repeating the push:
getLeaderboardTable().getColumnSortList().push(columnToSortFor);
}
}
private void clearSelection() {
for (LeaderboardRowDTO row : getData().getList()) {
leaderboardSelectionModel.setSelected(row, false);
@@ -1162,11 +1235,19 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@SuppressWarnings("unchecked")
SortableColumn<LeaderboardRowDTO, ?> castResult = (SortableColumn<LeaderboardRowDTO, ?>) columnSortInfo
.getColumn();
if (columnSortInfo.isAscending()) {
result = castResult.getComparator();
} else {
result = Collections.reverseOrder(castResult.getComparator());
}
final boolean ascending = columnSortInfo.isAscending();
result = getComparator(castResult, ascending);
}
return result;
}
private Comparator<LeaderboardRowDTO> getComparator(SortableColumn<LeaderboardRowDTO, ?> column,
final boolean ascending) {
Comparator<LeaderboardRowDTO> result;
if (ascending) {
result = column.getComparator();
} else {
result = Collections.reverseOrder(column.getComparator());
}
return result;
}
@@ -1219,7 +1300,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (raceColumn.getRaceName().equals(race.getRaceColumnName())) {
if (raceColumn.getRaceColumnName().equals(race.getRaceColumnName())) {
correctColumnData(raceColumn);
return true;
}
@@ -1261,7 +1342,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
RaceColumn<?> raceColumn = (RaceColumn<?>) c;
if (!raceColumn.getRaceName().equals(race.getRaceColumnName()) && raceColumnStartIndex == counter) {
if (!raceColumn.getRaceColumnName().equals(race.getRaceColumnName()) && raceColumnStartIndex == counter) {
removeColumn(raceColumn);
} else {
return;
@@ -1339,7 +1420,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(i);
if (c instanceof RaceColumn
&& (leaderboard == null || !selectedRaceColumnNames.contains(((RaceColumn<?>) c).getRaceName()))) {
&& (leaderboard == null || !selectedRaceColumnNames.contains(((RaceColumn<?>) c).getRaceColumnName()))) {
columnsToRemove.add(c);
}
}
@@ -1392,7 +1473,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
for (int i = 0; i < getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(i);
if (c instanceof RaceColumn
&& (leaderboard == null || !leaderboard.raceListContains(((RaceColumn<?>) c).getRaceName()))) {
&& (leaderboard == null || !leaderboard.raceListContains(((RaceColumn<?>) c).getRaceColumnName()))) {
columnsToRemove.add(c);
}
}
@@ -1519,10 +1600,22 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
@Override
public void playStateChanged(PlayStates playState, PlayModes playMode) {
currentlyHandlingPlayStateChange = true;
playPause.setHTML(getPlayPauseImgHtml(playState));
playPause.setTitle(playState == PlayStates.Playing ? stringMessages.pauseAutomaticRefresh() : stringMessages.autoRefresh());
if (!settingsUpdatedExplicitly && playMode != oldPlayMode) {
// if settings weren't explicitly modified, auto-switch to live mode settings and sort for
// any pre-selected race
updateSettings(LeaderboardSettingsFactory.getInstance().createNewSettingsForPlayMode(
playMode,
/* don't touch columnToSort if no race was pre-selected */ preSelectedRace == null ? null : preSelectedRace.getRaceName(),
/* don't change nameOfRaceColumnToShow */ null,
/* set nameOfRaceToShow if race was pre-selected */ preSelectedRace == null ? null : preSelectedRace.getRaceName()));
}
currentlyHandlingPlayStateChange = false;
oldPlayMode = playMode;
}
private void compareCompetitors() {
List<RaceIdentifier> races = getTrackedRacesIdentifiers();
CompareCompetitorsChartDialog chartDialog = new CompareCompetitorsChartDialog(sailingService, races,
@@ -1556,7 +1649,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
Collections.unmodifiableList(selectedLegDetails),
Collections.unmodifiableList(selectedRaceDetails), /* All races to select */
leaderboard.getRaceList(), selectedRaceColumns,
autoExpandFirstRace, timer.getRefreshInterval(), delayInMilliseconds, stringMessages);
autoExpandFirstRace, timer.getRefreshInterval(), timer.getLivePlayDelayInMillis(), stringMessages);
}
@Override
@@ -2,28 +2,61 @@ package com.sap.sailing.gwt.ui.leaderboard;
import java.util.List;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.domain.common.DetailType;
public class LeaderboardSettings {
private final List<RaceInLeaderboardDTO> raceColumnsToShow;
/**
* Only one of {@link #namesOfRaceColumnsToShow} and {@link #namesOfRacesToShow} must be non-<code>null</code>.
*/
private final List<String> namesOfRaceColumnsToShow;
/**
* Only one of {@link #namesOfRaceColumnsToShow} and {@link #namesOfRacesToShow} must be non-<code>null</code>.
*/
private final List<String> namesOfRacesToShow;
private final List<DetailType> maneuverDetailsToShow;
private final List<DetailType> legDetailsToShow;
private final List<DetailType> raceDetailsToShow;
private final boolean autoExpandFirstRace;
private final long delayBetweenAutoAdvancesInMilliseconds;
private final long delayInMilliseconds;
private final Long delayBetweenAutoAdvancesInMilliseconds;
private final Long delayInMilliseconds;
/**
* An optional sort column; if <code>null</code>, the leaderboard sorting won't be touched when updating the settings.
* Otherwise, the leaderboard will be sorted by the race column (ascending if {@link #sortAscending}, descending otherwise.
*/
private final String nameOfRaceToSort;
private final boolean sortAscending;
/**
* @param meneuverDetailsToShow
* @param legDetailsToShow
* @param raceDetailsToShow
* @param namesOfRacesToShow
* @param autoExpandFirstRace
* @param delayBetweenAutoAdvancesInMilliseconds
* @param delayInMilliseconds
* @param nameOfRaceToSort
* @param sortAscending
* @param raceColumnsToShow <code>null</code> means don't modify the list of races shown
*/
public LeaderboardSettings(List<DetailType> meneuverDetailsToShow, List<DetailType> legDetailsToShow,
List<DetailType> raceDetailsToShow, List<RaceInLeaderboardDTO> raceColumnsToShow, boolean autoExpandFirstRace,
long delayBetweenAutoAdvancesInMilliseconds, long delayInMilliseconds) {
List<DetailType> raceDetailsToShow, List<String> namesOfRaceColumnsToShow,
List<String> namesOfRacesToShow, boolean autoExpandFirstRace, Long delayBetweenAutoAdvancesInMilliseconds,
Long delayInMilliseconds, String nameOfRaceToSort, boolean sortAscending) {
if (namesOfRacesToShow != null && namesOfRaceColumnsToShow != null) {
throw new IllegalArgumentException("You can identify races either only by their race or by their column names, not both");
}
this.legDetailsToShow = legDetailsToShow;
this.raceDetailsToShow = raceDetailsToShow;
this.raceColumnsToShow = raceColumnsToShow;
this.namesOfRacesToShow = namesOfRacesToShow;
this.namesOfRaceColumnsToShow = namesOfRaceColumnsToShow;
this.autoExpandFirstRace = autoExpandFirstRace;
this.delayBetweenAutoAdvancesInMilliseconds = delayBetweenAutoAdvancesInMilliseconds;
this.delayInMilliseconds = delayInMilliseconds;
this.maneuverDetailsToShow = meneuverDetailsToShow;
this.nameOfRaceToSort = nameOfRaceToSort;
this.sortAscending = sortAscending;
}
public List<DetailType> getManeuverDetailsToShow() {
@@ -38,19 +71,47 @@ public class LeaderboardSettings {
return raceDetailsToShow;
}
public List<RaceInLeaderboardDTO> getRaceColumnsToShow(){
return raceColumnsToShow;
/**
* If <code>null</code>, this is to mean that the race columns should not be modified by
* {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}.
*/
public List<String> getNamesOfRaceColumnsToShow() {
return namesOfRaceColumnsToShow;
}
/**
* If <code>null</code>, this is to mean that the race columns should not be modified by
* {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}.
*/
public List<String> getNamesOfRacesToShow() {
return namesOfRacesToShow;
}
public boolean isAutoExpandFirstRace() {
return autoExpandFirstRace;
}
public long getDelayBetweenAutoAdvancesInMilliseconds() {
/**
* @return if <code>null</code>, leave refresh interval alone (don't change in
* {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}
*/
public Long getDelayBetweenAutoAdvancesInMilliseconds() {
return delayBetweenAutoAdvancesInMilliseconds;
}
public long getDelayInMilliseconds() {
/**
* @return if <code>null</code>, leave delay alone (don't change in {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}
*/
public Long getDelayInMilliseconds() {
return delayInMilliseconds;
}
public String getNameOfRaceToSort() {
return nameOfRaceToSort;
}
public boolean isSortAscending() {
return sortAscending;
}
}
@@ -133,17 +133,18 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
legDetailsToShow.add(entry.getKey());
}
}
List<RaceInLeaderboardDTO> raceColumnsToShow = new ArrayList<RaceInLeaderboardDTO>();
List<String> namesOfRaceColumnsToShow = new ArrayList<String>();
for (Map.Entry<RaceInLeaderboardDTO, CheckBox> entry : raceColumnCheckboxes.entrySet()) {
if(entry.getValue().getValue()){
raceColumnsToShow.add(entry.getKey());
namesOfRaceColumnsToShow.add(entry.getKey().getRaceColumnName());
}
}
Long delayBetweenAutoAdvancesValue = delayBetweenAutoAdvancesInSecondsBox.getValue();
Long delayInSecondsValue = delayInSecondsBox.getValue();
return new LeaderboardSettings(maneuverDetailsToShow, legDetailsToShow, raceDetailsToShow, raceColumnsToShow, autoExpandFirstRace,
return new LeaderboardSettings(maneuverDetailsToShow, legDetailsToShow, raceDetailsToShow,
namesOfRaceColumnsToShow, /* nameOfRacesToShow */null, autoExpandFirstRace,
1000l * (delayBetweenAutoAdvancesValue == null ? 0l : delayBetweenAutoAdvancesValue.longValue()),
1000 * (delayInSecondsValue==null?0:delayInSecondsValue.longValue()));
1000 * (delayInSecondsValue == null ? 0 : delayInSecondsValue.longValue()), null, true);
}
@Override
@@ -1,10 +1,11 @@
package com.sap.sailing.gwt.ui.leaderboard;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
/*
* A factory class creating leaderboard settings for different contexts (user role, live or replay mode, etc.
@@ -19,8 +20,28 @@ public class LeaderboardSettingsFactory {
return instance;
}
public LeaderboardSettings createNewSettingsForPlayMode(PlayModes playMode) {
/**
* @param nameOfRaceToSort
* if <code>null</code>, don't sort any race column
* @param nameOfRaceColumnToShow
* if <code>null</code>, the settings returned will cause the list of race columns shown to remain
* unchanged during {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}; otherwise, the settings
* will show the single race column identified by this argument
* @param nameOfRaceToShow
* alternatively to <code>nameOfRaceColumnToShow</code>, this argument may be used in case the race name is known,
* but its column name is not. If <code>null</code>, and <code>nameOfRaceColumnToShow</code> is also <code>null</code>,
* no change to the selected race columns will happen while updating the leaderboard settings. It is an error
* to pass non-<code>null</code> values for both, <code>nameOfRaceColumnToShow</code> <em>and</em>
* <code>nameOfRaceToShow</code>, and an {@link IllegalArgumentException} will be thrown in this case.
*/
public LeaderboardSettings createNewSettingsForPlayMode(PlayModes playMode, String nameOfRaceToSort, String nameOfRaceColumnToShow,
String nameOfRaceToShow) {
if (nameOfRaceColumnToShow != null && nameOfRaceToShow != null) {
throw new IllegalArgumentException("Can identify only one race to show, either by race name or by its column name, but not both");
}
LeaderboardSettings settings = null;
List<String> namesOfRaceColumnsToShow = nameOfRaceColumnToShow == null ? null : Collections.singletonList(nameOfRaceColumnToShow);
List<String> namesOfRacesToShow = nameOfRaceToShow == null ? null : Collections.singletonList(nameOfRaceToShow);
switch (playMode) {
case Live:
ArrayList<DetailType> maneuverDetails = new ArrayList<DetailType>();
@@ -32,17 +53,35 @@ public class LeaderboardSettingsFactory {
legDetails.add(DetailType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
legDetails.add(DetailType.RANK_GAIN);
ArrayList<DetailType> raceDetails = new ArrayList<DetailType>();
ArrayList<RaceInLeaderboardDTO> raceColumns = new ArrayList<RaceInLeaderboardDTO>();
settings = new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, raceColumns, true, 0l, 0l);
raceDetails.add(DetailType.RACE_DISTANCE_TO_LEADER_IN_METERS);
raceDetails.add(DetailType.NUMBER_OF_MANEUVERS);
settings = new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, namesOfRaceColumnsToShow,
namesOfRacesToShow,
/* set autoExpandFirstRace to true if we look at a single race */ nameOfRaceColumnToShow != null || nameOfRaceToShow != null, /* refresh interval */ null,
/* delay to live */ null, /* name of race to sort */ nameOfRaceToSort, /* ascending */ true);
break;
case Replay:
settings = createNewDefaultSettings(true);
settings = createNewDefaultSettings(namesOfRaceColumnsToShow, namesOfRacesToShow, /* autoExpandFirstRace */ nameOfRaceColumnToShow != null);
break;
}
return settings;
}
public LeaderboardSettings createNewDefaultSettings(boolean autoExpandFirstRace) {
/**
* @param namesOfRaceColumnsToShow
* if <code>null</code>, create settings which leave the list of races to show unchanged when applied
* using {@link LeaderboardPanel#updateSettings(LeaderboardSettings)}; otherwise, the list of names of
* the race columns (not their races!) that will be shown, so that, e.g., an empty list causes no race
* columns to be shown
* @param namesOfRacesToShow
* alternatively, races to show can also be specified by their race names; if not <code>null</code>,
* <code>namesOfRaceColumnsToShow</code> must be <code>null
*/
public LeaderboardSettings createNewDefaultSettings(List<String> namesOfRaceColumnsToShow,
List<String> namesOfRacesToShow, boolean autoExpandFirstRace) {
if (namesOfRaceColumnsToShow != null && namesOfRacesToShow != null) {
throw new IllegalArgumentException("Can specify race columns either by column or by race name, not both");
}
ArrayList<DetailType> maneuverDetails = new ArrayList<DetailType>();
maneuverDetails.add(DetailType.TACK);
maneuverDetails.add(DetailType.JIBE);
@@ -53,7 +92,9 @@ public class LeaderboardSettingsFactory {
legDetails.add(DetailType.RANK_GAIN);
ArrayList<DetailType> raceDetails = new ArrayList<DetailType>();
raceDetails.add(DetailType.DISPLAY_LEGS);
ArrayList<RaceInLeaderboardDTO> raceColumns = new ArrayList<RaceInLeaderboardDTO>();
return new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, raceColumns, autoExpandFirstRace, 0l, 0l);
return new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, namesOfRaceColumnsToShow,
namesOfRacesToShow,
autoExpandFirstRace, /* refresh interval */ null,
/* delay to live */ null, /* sort by column */ null, /* ascending */ true);
}
}
@@ -170,7 +170,7 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
}
private String getRaceName() {
return raceNameProvider.getRaceName();
return raceNameProvider.getRaceColumnName();
}
@Override
@@ -0,0 +1,26 @@
package com.sap.sailing.gwt.ui.leaderboard;
import java.util.Comparator;
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
public class NetPointsComparator implements Comparator<LeaderboardRowDTO> {
private final boolean ascending;
private final String raceName;
public NetPointsComparator(boolean ascending, String raceName) {
super();
this.ascending = ascending;
this.raceName = raceName;
}
@Override
public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) {
LeaderboardEntryDTO o1Entry = o1.fieldsByRaceName.get(raceName);
LeaderboardEntryDTO o2Entry = o2.fieldsByRaceName.get(raceName);
return (o1Entry == null || o1Entry.netPoints == 0) ? (o2Entry == null || o2Entry.netPoints == 0) ? 0
: ascending ? 1 : -1 : (o2Entry == null || o2Entry.netPoints == 0) ? ascending ? -1 : 1
: o1Entry.netPoints - o2Entry.netPoints;
}
}
@@ -14,5 +14,5 @@ package com.sap.sailing.gwt.ui.leaderboard;
*
*/
public interface RaceNameProvider {
String getRaceName();
String getRaceColumnName();
}
@@ -57,7 +57,7 @@ public class TVViewPanel extends SimplePanel implements RaceTimesInfoProviderLis
}
private LeaderboardPanel createLeaderboardPanel(String leaderboardName) {
LeaderboardSettings settings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(/* autoExpandFirstRace */ false);
LeaderboardSettings settings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, /* autoExpandFirstRace */ false);
CompetitorSelectionModel selectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true);
Timer timer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */3000l);
timer.play();
@@ -253,7 +253,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
public EditableLeaderboardPanel(SailingServiceAsync sailingService, String leaderboardName, String leaderboardGroupName,
ErrorReporter errorReporter, StringMessages stringConstants, UserAgentTypes userAgentType) {
super(sailingService, LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(
/* autoExpandFirstRace */false), new CompetitorSelectionModel(/* hasMultiSelection */true),
/* racesToShow */ null, /* namesOfRacesToShow */ null, /* autoExpandFirstRace */false),
new CompetitorSelectionModel(/* hasMultiSelection */true),
leaderboardName, leaderboardGroupName, errorReporter, stringConstants, userAgentType);
}
@@ -131,8 +131,11 @@ public class RaceBoardPanel extends FormPanel implements EventDisplayer, RaceSel
componentsNavigationPanel.addStyleName("raceBoardNavigation");
// create the default leaderboard and select the right race
LeaderboardSettings leaderBoardSettings = LeaderboardSettingsFactory.getInstance().createNewSettingsForPlayMode(timer.getPlayMode());
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, leaderBoardSettings, selectedRaceIdentifier, competitorSelectionModel,
LeaderboardSettings leaderBoardSettings = LeaderboardSettingsFactory.getInstance()
.createNewSettingsForPlayMode(timer.getPlayMode(), /* nameOfRaceToSort */ selectedRaceIdentifier.getRaceName(),
/* nameOfRaceColumnToShow */ null, /* nameOfRaceToShow */ selectedRaceIdentifier.getRaceName());
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, leaderBoardSettings,
selectedRaceIdentifier, competitorSelectionModel,
timer, leaderboardName, leaderboardGroupName, errorReporter, stringMessages, userAgentType);
RaceMap raceMap = new RaceMap(sailingService, errorReporter, timer, competitorSelectionModel, stringMessages);
raceMap.onRaceSelectionChange(Collections.singletonList(selectedRaceIdentifier));
@@ -202,10 +205,12 @@ public class RaceBoardPanel extends FormPanel implements EventDisplayer, RaceSel
boolean showCompetitorCharts = true;
// create the default leaderboard and select the right race
if(showLeaderboard) {
LeaderboardSettings leaderBoardSettings = LeaderboardSettingsFactory.getInstance().createNewSettingsForPlayMode(timer.getPlayMode());
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, leaderBoardSettings, selectedRaceIdentifier, competitorSelectionModel,
timer, leaderboardName, leaderboardGroupName, errorReporter, stringMessages, userAgentType);
LeaderboardSettings leaderBoardSettings = LeaderboardSettingsFactory.getInstance()
.createNewSettingsForPlayMode(timer.getPlayMode(), /* nameOfRaceToSort */ selectedRaceIdentifier.getRaceName(),
/* nameOfRaceColumnToShow */ null, /* nameOfRaceToShow */ selectedRaceIdentifier.getRaceName());
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, leaderBoardSettings,
selectedRaceIdentifier, competitorSelectionModel, timer, leaderboardName, leaderboardGroupName,
errorReporter, stringMessages, userAgentType);
CollapsableComponentViewer<LeaderboardSettings> leaderboardViewer = new CollapsableComponentViewer<LeaderboardSettings>(
leaderboardPanel, "100%", "100%", stringMessages, ViewerPanelTypes.SCROLL_PANEL);
componentViewers.add(leaderboardViewer);
@@ -34,9 +34,7 @@ public class SideBySideComponentViewer implements ComponentViewer {
mainPanel = new LayoutPanel();
mainPanel.setSize("100%", "100%");
splitLayoutPanel = new SplitLayoutPanel();
mainPanel.add(splitLayoutPanel);
// splitLayoutPanel.setSize(defaultWidth, defaultHeight);
for(Component<?> component: components) {
if(component.isVisible())
@@ -254,6 +254,29 @@ public class LeaderboardDTO implements IsSerializable {
}
return competitors.indexOf(competitor) + 1;
};
/**
* Determines the competitor's rank in the race with name <code>raceName</code>. If a race with that name does not exist or the
* competitor has no score for that race, <code>null</code> is returned; the 1-based rank otherwise.
*/
public Integer getRank(CompetitorDTO competitor, String raceName) {
Integer result = null;
if (rows.get(competitor) != null) {
LeaderboardEntryDTO fields = rows.get(competitor).fieldsByRaceName.get(raceName);
if (fields != null) {
List<CompetitorDTO> competitorsOrderedByNetPoints = new ArrayList<CompetitorDTO>(competitors);
Collections.sort(competitorsOrderedByNetPoints, new Comparator<CompetitorDTO>() {
@Override
public int compare(CompetitorDTO o1, CompetitorDTO o2) {
return getTotalRankingComparator().compare(rows.get(o1), rows.get(o2));
}
});
competitorsOrderedAccordingToTotalRank = true;
result = competitorsOrderedByNetPoints.indexOf(competitor) + 1;
}
}
return result;
}
public boolean raceIsTracked(String raceColumnName) {
for (RaceInLeaderboardDTO race : races) {
@@ -303,15 +326,6 @@ public class LeaderboardDTO implements IsSerializable {
}
return null;
}
/*
public List<String> getRaceColumnNameList() {
List<String> raceColumnNames = new ArrayList<String>();
for (RaceInLeaderboardDTO raceInLeaderboardDTO : races) {
raceColumnNames.add(raceInLeaderboardDTO.getRaceColumnName());
}
return raceColumnNames;
}
*/
public List<RaceInLeaderboardDTO> getRaceList() {
return races;
@@ -55,17 +55,19 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
private ErrorReporter errorReporter;
private LeaderboardGroupDTO group;
private String root;
private String viewMode;
private FlowPanel mainPanel;
private Widget welcomeWidget = null;
public LeaderboardGroupPanel(SailingServiceAsync sailingService, StringMessages stringConstants,
ErrorReporter errorReporter, final String groupName, String root) {
ErrorReporter errorReporter, final String groupName, String root, String viewMode) {
super();
this.sailingService = sailingService;
this.stringConstants = stringConstants;
this.errorReporter = errorReporter;
this.root = root;
this.viewMode = viewMode;
if (this.root == null || this.root.length() == 0) {
this.root = "leaderboardGroupPanel";
}
@@ -187,15 +189,21 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
String displayName = race.getRaceColumnName();
if (race.getRaceColumnName().equals(stringConstants.overview())) {
String link = URLFactory.INSTANCE.encode("/gwt/Leaderboard.html?name=" + leaderboard.name
+ "&leaderboardGroupName=" + group.name + "&root=" + root
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
+ "&leaderboardGroupName=" + group.name + "&root=" + root);
if(debugParam != null && !debugParam.isEmpty())
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, displayName, STYLE_NAME_PREFIX + "ActiveLeaderboard"));
} else {
if (race.getRaceIdentifier() != null) {
EventNameAndRaceName raceId = (EventNameAndRaceName) race.getRaceIdentifier();
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name + "&raceName=" + raceId.getRaceName()
+ "&eventName=" + raceId.getEventName() + "&leaderboardGroupName=" + group.name + "&root=" + root
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
+ "&eventName=" + raceId.getEventName() + "&leaderboardGroupName=" + group.name + "&root=" + root);
if(debugParam != null && !debugParam.isEmpty())
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, displayName, STYLE_NAME_PREFIX + "ActiveRace"));
} else {
b.append(TEXTTEMPLATE.textWithClass(race.getRaceColumnName(), STYLE_NAME_PREFIX + "InactiveRace"));
@@ -213,8 +221,11 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
EventNameAndRaceName raceId = (EventNameAndRaceName) race.getRaceIdentifier();
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name
+ "&raceName=" + raceId.getRaceName() + "&root=" + root + raceId.getRaceName() + "&eventName="
+ raceId.getEventName() + "&leaderboardGroupName=" + group.name
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
+ raceId.getEventName() + "&leaderboardGroupName=" + group.name);
if(debugParam != null && !debugParam.isEmpty())
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, race.getRaceColumnName(), STYLE_NAME_PREFIX + "ActiveRace"));
} else {
if (!first) {
@@ -21,6 +21,7 @@ public class SpectatorEntryPoint extends AbstractEntryPoint implements EventRefr
public void onModuleLoad() {
super.onModuleLoad();
String groupParamValue = Window.Location.getParameter("leaderboardGroupName");
String viewModeParamValue = Window.Location.getParameter("viewMode");
final String groupName;
if (groupParamValue == null || groupParamValue.isEmpty()) {
groupName = null;
@@ -52,7 +53,7 @@ public class SpectatorEntryPoint extends AbstractEntryPoint implements EventRefr
// panelToDisplay = new LeaderboardGroupOverviewPanel(sailingService, this, stringMessages);
Window.alert("No leaderboard group name was given.");
} else {
panelToDisplay = new LeaderboardGroupPanel(sailingService, stringMessages, this, groupName, root);
panelToDisplay = new LeaderboardGroupPanel(sailingService, stringMessages, this, groupName, root, viewModeParamValue);
LeaderboardGroupPanel groupPanel = (LeaderboardGroupPanel) panelToDisplay;
groupPanel.setWelcomeWidget(new SimpleWelcomeWidget( stringMessages.welcomeToSailingAnalytics(),
"Understanding what happens out on the race course isn't always easy. To help solve this challenge and" +
+2 -2
View File
@@ -10,12 +10,12 @@
<body>
<h2>SAP Sailing Analytics Suite</h2>
<b>Übersicht über die SAP Sailing Analytics Suite</b>
<b>Overview SAP Sailing Analytics Suite</b>
<div style="height:1em;"></div>
<a href="/gwt/AdminConsole.html"><b>Administrator Console</b></a><br/>
<a href="/gwt/Leaderboard.html"><b>Leaderboard</b></a><br/>
<a href="/gwt/RaceBoard.html"><b>Race board</b></a><br/>
<a href="/gwt/RaceBoard.html"><b>Race Board</b></a><br/>
<a href="/gwt/Spectator.html"><b>Spectators</b></a><br/>
</body>
</html>