Merge remote-tracking branch 'external/master' into jens--media-synch

umn from SettableScoreCorrection to ScoreCorrection
This commit is contained in:
Jens Rommel committed 2013-04-10 10:08:08 +02:00
commit 6eea85c5a3
360 files changed
+39846 -3757

No files matched your search

@@ -131,3 +131,7 @@ body, table td, select, button {
.gwt-DialogBox {
z-index: 20;
}
.bold {
font-family: "OpenSansCondensedBold", sans-serif;
}
+1 -2
View File
@@ -176,8 +176,7 @@ input.magnifier {
margin: 0 0 25px 0;
}
.leaderboardGroupPanel-LeaderboardsTableLabel {
margin: 0 0 10px;
.leaderboardGroupPanel-LeaderboardsLabel {
font-size: 17px;
font-weight: 500;
}
@@ -1,39 +0,0 @@
package com.sap.sailing.gwt.ui.actions;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
public class GetBoatPositionsAction extends DefaultAsyncAction<Map<CompetitorDTO, List<GPSFixDTO>>> {
private final SailingServiceAsync sailingService;
private final RegattaAndRaceIdentifier raceIdentifier;
private final Map<CompetitorDTO, Date> from;
private final Map<CompetitorDTO, Date> to;
private final boolean extrapolate;
public GetBoatPositionsAction(SailingServiceAsync sailingService, RegattaAndRaceIdentifier raceIdentifier,
Map<CompetitorDTO, Date> from, Map<CompetitorDTO, Date> to, boolean extrapolate,
AsyncCallback<Map<CompetitorDTO, List<GPSFixDTO>>> callback) {
super(callback);
this.sailingService = sailingService;
this.raceIdentifier = raceIdentifier;
this.from = from;
this.to = to;
this.extrapolate = extrapolate;
}
@Override
public void execute(AsyncActionsExecutor asyncActionsExecutor) {
sailingService.getBoatPositions(raceIdentifier, from, to, extrapolate,
(AsyncCallback<Map<CompetitorDTO, List<GPSFixDTO>>>) getWrapperCallback(asyncActionsExecutor));
}
}
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Date;
import com.google.gwt.user.client.ui.DoubleBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
@@ -13,7 +15,7 @@ import com.sap.sailing.gwt.ui.shared.PositionDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
public class WindSettingDialog extends DataEntryDialog<WindDTO> {
public class AddWindFixDialog extends DataEntryDialog<WindDTO> {
private final StringMessages stringMessages;
private final DoubleBox speedInKnotsBox;
@@ -23,7 +25,7 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
private final DateBox timeBox;
protected static class WindDataValidator implements Validator<WindDTO> {
protected final StringMessages stringMessages;
private final StringMessages stringMessages;
public WindDataValidator(StringMessages stringMessages){
super();
@@ -42,24 +44,26 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
errorMessage = stringMessages.pleaseEnterAValue();
} else if(windDTO.trueWindFromDeg != null && (windDTO.trueWindFromDeg < 0.0 || windDTO.trueWindFromDeg > 360.0)){
errorMessage = stringMessages.valueMustBeBetweenMinMax(stringMessages.fromDeg(), "0", "360");
} else if(windDTO.measureTimepoint == null) {
errorMessage = stringMessages.pleaseEnterAValue();
} else if(windDTO.position != null) {
if(windDTO.position.latDeg < -90.0 || windDTO.position.latDeg > 90.0){
errorMessage = stringMessages.valueMustBeBetweenMinMax(stringMessages.latitude(), "-90", "90");
} else if(windDTO.position.lngDeg < -180.0 || windDTO.position.lngDeg > 180.0){
errorMessage = stringMessages.valueMustBeBetweenMinMax(stringMessages.longitude(), "-180", "180");
}
}
}
return errorMessage;
}
}
public WindSettingDialog(RaceDTO race, CoursePositionsDTO courseDTO, StringMessages stringMessages, DialogCallback<WindDTO> callback) {
public AddWindFixDialog(RaceDTO race, CoursePositionsDTO courseDTO, StringMessages stringMessages, DialogCallback<WindDTO> callback) {
super(stringMessages.actionAddWindData(), null, stringMessages.ok(), stringMessages.cancel(), new WindDataValidator(stringMessages), callback);
this.stringMessages = stringMessages;
speedInKnotsBox = createDoubleBox(5);
fromInDegBox = createDoubleBox(5);
if(courseDTO != null && courseDTO.waypointPositions.get(0) != null) {
if(courseDTO != null && courseDTO.waypointPositions != null && courseDTO.waypointPositions.get(0) != null) {
PositionDTO positionDTO = courseDTO.waypointPositions.get(0);
latDegBox = createDoubleBox(positionDTO.latDeg, 10);
lngDegBox = createDoubleBox(positionDTO.lngDeg, 10);
@@ -67,10 +71,11 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
latDegBox = createDoubleBox(10);
lngDegBox = createDoubleBox(10);
}
if(race.startOfRace != null) {
timeBox = createDateBox(race.startOfRace.getTime(), 20);
if(race.trackedRace != null && race.trackedRace.startOfTracking != null) {
timeBox = createDateBox(race.trackedRace.startOfTracking.getTime(), 20);
} else {
timeBox = createDateBox(20);
Date now = new Date();
timeBox = createDateBox(now.getTime(), 20);
}
}
@@ -84,12 +89,12 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
grid.setWidget(0, 1, speedInKnotsBox);
grid.setWidget(1, 0, new Label(stringMessages.fromDeg() + ":"));
grid.setWidget(1, 1, fromInDegBox);
grid.setWidget(2, 0, new Label(stringMessages.latitude() + " (" + stringMessages.optional() + "):"));
grid.setWidget(2, 1, latDegBox);
grid.setWidget(3, 0, new Label(stringMessages.longitude() + " (" + stringMessages.optional() + "):"));
grid.setWidget(3, 1, lngDegBox);
grid.setWidget(4, 0, new Label(stringMessages.time() + " (" + stringMessages.optional() + "):"));
grid.setWidget(4, 1, timeBox);
grid.setWidget(2, 0, new Label(stringMessages.time() + ":"));
grid.setWidget(2, 1, timeBox);
grid.setWidget(3, 0, new Label(stringMessages.latitude() + " (" + stringMessages.optional() + "):"));
grid.setWidget(3, 1, latDegBox);
grid.setWidget(4, 0, new Label(stringMessages.longitude() + " (" + stringMessages.optional() + "):"));
grid.setWidget(4, 1, lngDegBox);
return mainPanel;
}
@@ -100,7 +105,7 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
result.trueWindSpeedInKnots = speedInKnotsBox.getValue();
result.trueWindFromDeg = fromInDegBox.getValue();
result.measureTimepoint = timeBox.getValue() != null ? timeBox.getValue().getTime() : System.currentTimeMillis();
result.measureTimepoint = timeBox.getValue() != null ? timeBox.getValue().getTime() : null;
if (latDegBox.getValue() != null && lngDegBox.getValue() != null) {
result.position = new PositionDTO(latDegBox.getValue(), lngDegBox.getValue());
}
@@ -63,7 +63,7 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
tabPanel.add(swisstimingEventManagementPanel, stringMessages.swissTimingEvents(), false);
regattaDisplayers.add(swisstimingEventManagementPanel);
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService,this,stringMessages);
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService, this, stringMessages);
//createSwissTimingRacePanel.ensureDebugId("CreateSwissTimingRace");
createSwissTimingRacePanel.setSize("90%", "90%");
tabPanel.add(createSwissTimingRacePanel,"Create SwissTiming race",false);
@@ -96,7 +96,7 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
final LeaderboardConfigPanel leaderboardConfigPanel = new LeaderboardConfigPanel(sailingService, this, this, stringMessages,
/* showRaceDetails */ true);
//leaderboardConfigPanel.ensureDebugId("LeaderboardConfiguration");
leaderboardConfigPanel.ensureDebugId("LeaderboardConfiguration");
leaderboardConfigPanel.setSize("90%", "90%");
tabPanel.add(leaderboardConfigPanel, stringMessages.leaderboardConfiguration(), /* asHTML */ false);
regattaDisplayers.add(leaderboardConfigPanel);
@@ -1,24 +1,25 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Collection;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog {
public FlexibleLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, StringMessages stringMessages,
Collection<EventDTO> existingEvents, ErrorReporter errorReporter, DialogCallback<LeaderboardDescriptor> callback) {
super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback);
nameTextBox = createTextBox(null);
displayNameTextBox = createTextBox(null);
nameTextBox.setVisibleLength(50);
displayNameTextBox.setVisibleLength(50);
scoringSchemeListBox = createScoringSchemeListBox(this, stringMessages);
sailingEventsListBox = createSailingEventListBox();
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
}
}
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Collection;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog {
public FlexibleLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, StringMessages stringMessages,
Collection<EventDTO> existingEvents, ErrorReporter errorReporter, DialogCallback<LeaderboardDescriptor> callback) {
super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback);
nameTextBox = createTextBox(null);
nameTextBox.ensureDebugId("LeaderboardNameField");
displayNameTextBox = createTextBox(null);
nameTextBox.setVisibleLength(50);
displayNameTextBox.setVisibleLength(50);
scoringSchemeListBox = createScoringSchemeListBox(this, stringMessages);
sailingEventsListBox = createSailingEventListBox();
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
}
}
@@ -138,7 +138,7 @@ public class RaceColumnInLeaderboardDialog extends DataEntryDialog<RaceColumnInL
super.show();
if (isRegattaLeaderboard) {
explicitFactorBox.setFocus(true);
explicitFactorBox.setSelectionRange(0, explicitFactorBox.getText().length());
explicitFactorBox.selectAll();
} else {
raceNameBox.setFocus(true);
}
@@ -34,11 +34,14 @@ import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
@@ -138,14 +141,31 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
}
});
TextColumn<SwissTimingRaceRecordDTO> raceNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.ID;
}
};
TextColumn<SwissTimingRaceRecordDTO> raceDescriptionColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
return object.description;
}
};
TextColumn<SwissTimingRaceRecordDTO> boatClassColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
String result = object.boatClass != null ? object.boatClass : "";
if(object.discipline != null) {
result += " (" + object.discipline + ")";
}
return result;
}
};
TextColumn<SwissTimingRaceRecordDTO> raceStartTrackingColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
@Override
public String getValue(SwissTimingRaceRecordDTO object) {
@@ -153,7 +173,6 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
}
};
HorizontalPanel racesSplitPanel = new HorizontalPanel();
mainPanel.add(racesSplitPanel);
@@ -179,6 +198,15 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
filterPanel.setSpacing(5);
racesPanel.add(filterPanel);
// Regatta
HorizontalPanel regattaPanel = new HorizontalPanel();
regattaPanel.setSpacing(5);
Label regattaForTrackingLabel = new Label(stringMessages.regattaUsedForTheTrackedRace());
regattaForTrackingLabel.setWordWrap(false);
regattaPanel.add(regattaForTrackingLabel);
regattaPanel.add(getAvailableRegattasListBox());
racesPanel.add(regattaPanel);
Label lblFilterEvents = new Label(stringConstants.filterRacesByName() + ":");
filterPanel.add(lblFilterEvents);
filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE);
@@ -205,6 +233,8 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
raceTable = new CellTable<SwissTimingRaceRecordDTO>(/* pageSize */ 10000, tableRes);
raceTable.addColumn(raceNameColumn, stringConstants.name());
raceTable.addColumn(raceDescriptionColumn, stringConstants.description());
raceTable.addColumn(boatClassColumn, stringConstants.boatClass());
raceTable.addColumn(raceStartTrackingColumn, stringConstants.raceStartTimeColumn());
raceTable.setWidth("300px");
raceTable.setSelectionModel(new MultiSelectionModel<SwissTimingRaceRecordDTO>() {});
@@ -345,8 +375,13 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
selectedRaces.add(race);
}
}
RegattaDTO selectedRegatta = getSelectedRegatta();
RegattaIdentifier regattaIdentifier = null;
if (selectedRegatta != null) {
regattaIdentifier = new RegattaName(selectedRegatta.name);
}
sailingService.trackWithSwissTiming(
/* regattaToAddTo */null, // TODO allow user to select a pre-defined regatta
/* regattaToAddTo */ regattaIdentifier,
selectedRaces, hostname, port, /* canSendRequests */false, trackWind, correctWindByDeclination,
new AsyncCallback<Void>() {
@Override
@@ -186,9 +186,8 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
layoutTable.setWidget(2, 0, hostnameLabel);
layoutTable.setWidget(2, 1, this.hostnameTextBox);
// Regatta name
// Event name
Label eventNameLabel = new Label(this.stringMessages.eventName() + ":");
this.eventNameTextBox = new TextBox();
this.eventNameTextBox.ensureDebugId("RegattaName");
this.eventNameTextBox.setText("event_2011...");
@@ -198,7 +197,6 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
synchURIs();
}
});
layoutTable.setWidget(3, 0, eventNameLabel);
layoutTable.setWidget(3, 1, this.eventNameTextBox);
@@ -338,9 +336,8 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
//columnFormatter.setWidth(1, "80%");
// Regatta
Label regattaForTrackingLabel = new Label("Regatta used for the tracked race:");
Label regattaForTrackingLabel = new Label(stringMessages.regattaUsedForTheTrackedRace());
regattaForTrackingLabel.setWordWrap(false);
layoutTable.setWidget(0, 0, regattaForTrackingLabel);
layoutTable.setWidget(0, 1, getAvailableRegattasListBox());
@@ -619,11 +616,9 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
String storedURI = this.storedURITextBox.getValue();
RegattaDTO selectedRegatta = getSelectedRegatta();
RegattaIdentifier regattaIdentifier = null;
if (selectedRegatta != null) {
regattaIdentifier = new RegattaName(selectedRegatta.name);
}
// Check if the assigned regatta makes sense
List<TracTracRaceRecordDTO> allRaces = this.raceList.getList();
List<TracTracRaceRecordDTO> racesWithNotMatchingBoatClasses = new ArrayList<TracTracRaceRecordDTO>();
@@ -631,33 +626,27 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
for (TracTracRaceRecordDTO race : allRaces) {
if (selectionModel.isSelected(race)) {
if(!checkBoatClassMatch(race, selectedRegatta))
if (!checkBoatClassMatch(race, selectedRegatta))
racesWithNotMatchingBoatClasses.add(race);
}
}
if(racesWithNotMatchingBoatClasses.size() > 0) {
if (racesWithNotMatchingBoatClasses.size() > 0) {
StringBuilder builder = new StringBuilder(100 + racesWithNotMatchingBoatClasses.size() * 30);
builder.append("WARNING\n");
if(selectedRegatta != null) {
if (selectedRegatta != null) {
builder.append(this.stringMessages.boatClassDoesNotMatchSelectedRegatta(selectedRegatta.boatClass.name,
selectedRegatta.name));
} else {
builder.append(this.stringMessages.regattaExistForSelectedBoatClass());
}
builder.append("\n\n");
builder.append(this.stringMessages.races());
builder.append("\n");
for(TracTracRaceRecordDTO record: racesWithNotMatchingBoatClasses) {
for (TracTracRaceRecordDTO record: racesWithNotMatchingBoatClasses) {
builder.append(record.name);
builder.append("\n");
}
if(!Window.confirm(builder.toString())) {
if (!Window.confirm(builder.toString())) {
return;
}
}
@@ -109,7 +109,7 @@ public class WindPanel extends FormPanel implements RegattaDisplayer, WindShower
RegattaAndRaceIdentifier selectedRace = getSelectedRace();
if(selectedRace != null) {
final RaceDTO race = trackedRacesListComposite.getRaceByIdentifier(selectedRace);
sailingService.getCoursePositions(selectedRace, race.startOfRace, new AsyncCallback<CoursePositionsDTO>() {
sailingService.getCoursePositions(selectedRace, race.trackedRace.startOfTracking, new AsyncCallback<CoursePositionsDTO>() {
@Override
public void onFailure(Throwable caught) {
showWindSettingDialog(race, null);
@@ -215,7 +215,7 @@ public class WindPanel extends FormPanel implements RegattaDisplayer, WindShower
}
private void showWindSettingDialog(RaceDTO race, CoursePositionsDTO course) {
WindSettingDialog windSettingDialog = new WindSettingDialog(race, course, stringMessages,
AddWindFixDialog windSettingDialog = new AddWindFixDialog(race, course, stringMessages,
new DialogCallback<WindDTO>() {
@Override
public void cancel() {
@@ -88,9 +88,11 @@ public abstract class DataEntryDialog<T> {
this.validator = validator;
okButton = new Button(okButtonName);
okButton.getElement().getStyle().setMargin(3, Unit.PX);
okButton.ensureDebugId("OkButton");
FlowPanel dialogFPanel = new FlowPanel();
dialogFPanel.setWidth("100%");
statusLabel = new Label();
statusLabel.ensureDebugId("StatusLabel");
dialogFPanel.add(statusLabel);
if (message != null) {
Label messageLabel = new Label(message);
@@ -107,6 +109,7 @@ public abstract class DataEntryDialog<T> {
buttonPanel.add(okButton);
cancelButton = new Button(cancelButtonName);
cancelButton.getElement().getStyle().setMargin(3, Unit.PX);
cancelButton.ensureDebugId("CancelButton");
buttonPanel.add(cancelButton);
cancelButton.addClickHandler(new ClickHandler() {
@Override
@@ -238,19 +241,20 @@ public abstract class DataEntryDialog<T> {
}
private DateBox createDateBoxInternal(Date initialDate, int visibleLength) {
DateBox textBox = new DateBox();
textBox.getTextBox().setVisibleLength(visibleLength);
textBox.setValue(initialDate);
AbstractEntryPoint.addFocusUponKeyUpToggler(textBox.getTextBox());
textBox.getTextBox().addChangeHandler(new ChangeHandler() {
DateBox dateBox = new DateBox();
dateBox.getTextBox().setVisibleLength(visibleLength);
dateBox.setFireNullValues(true);
dateBox.setValue(initialDate);
AbstractEntryPoint.addFocusUponKeyUpToggler(dateBox.getTextBox());
dateBox.addValueChangeHandler(new ValueChangeHandler<Date>() {
@Override
public void onChange(ChangeEvent event) {
public void onValueChange(ValueChangeEvent<Date> event) {
validate();
}
});
AbstractEntryPoint.linkEnterToButton(getOkButton(), textBox.getTextBox());
AbstractEntryPoint.linkEscapeToButton(getCancelButton(), textBox.getTextBox());
return textBox;
AbstractEntryPoint.linkEnterToButton(getOkButton(), dateBox.getTextBox());
AbstractEntryPoint.linkEscapeToButton(getCancelButton(), dateBox.getTextBox());
return dateBox;
}
/**
@@ -405,4 +409,7 @@ public abstract class DataEntryDialog<T> {
dateEntryDialog.center();
}
public void ensureDebugId(String debugId) {
dateEntryDialog.ensureDebugId(debugId);
}
}
@@ -50,11 +50,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
// in case the race is not tracked anymore we reset the time slider
resetTimeSlider();
} else {
// check if the live delay is already been set
if (!isUserExplicitlyChangedLivePlayDelay() && timer.getLivePlayDelayInMillis() != raceTimesInfo.delayToLiveInMs) {
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
}
// timer will only accept this update if the delay hasn't been updated explicitly
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) &&
(raceTimesInfo.newestTrackingEvent != null || raceTimesInfo.endOfRace != null)) {
// we set here the min and max of the time slider, the start and end of the race as well as the known
@@ -108,14 +105,15 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
@Override
protected boolean isLiveModeToBeMadePossible() {
long livePlayDelayInMillis = timer.getLivePlayDelayInMillis();
long eventTimeoutTolerance = 60 * 1000; // 60s
long eventTimeoutTolerance = 60 * 1000; // 60s
long timeBeforeRaceStartTolerance = 3 * 60 * 1000; // 3min
long liveTimePointInMillis = System.currentTimeMillis() - livePlayDelayInMillis;
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
return lastRaceTimesInfo != null &&
lastRaceTimesInfo.newestTrackingEvent != null &&
liveTimePointInMillis < lastRaceTimesInfo.newestTrackingEvent.getTime() + eventTimeoutTolerance &&
lastRaceTimesInfo.startOfTracking != null &&
liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime();
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime())||
(lastRaceTimesInfo.startOfRace != null && liveTimePointInMillis > lastRaceTimesInfo.startOfRace.getTime() - timeBeforeRaceStartTolerance));
}
@Override
@@ -367,6 +367,7 @@ public interface StringMessages extends Messages {
String insertWaypointAfterSelected();
String scoringSchemeLowPointSystem();
String scoringSchemeHighPointSystem();
String scoringSchemeLowPointWinnerGetsZero();
String scoringSystem();
String createFlexibleLeaderboard();
String createRegattaLeaderboard();
@@ -520,4 +521,7 @@ public interface StringMessages extends Messages {
String correctScoreFor(String competitorName, String raceColumnName);
String penaltyOrRedress();
String netScore();
String timePointMustBeAfterStartOfTracking();
String timePointMustBeBeforeEndOfTracking();
String regattaUsedForTheTrackedRace();
}
@@ -395,6 +395,7 @@ scoringSchemeLowPointSystem=Low Point System
scoringSchemeHighPointSystem=High Point System
scoringSchemeHighPointEssOverall=High Point System ESS Overall
scoringSchemeHighPointLastBreaksTie=High Point System, Last Race Breaks Tie
scoringSchemeLowPointWinnerGetsZero=Low Point System, Winner Gets Zero
scoringSystem=Scoring system
createFlexibleLeaderboard=Create flexible leaderboard
createRegattaLeaderboard=Create regatta leaderboard
@@ -521,4 +522,7 @@ cannotAddRacesToRegattaLeaderboardButOnlyToRegatta=This is a regatta leaderboard
correctScore=Correct Score
correctScoreFor=Correct score for competitor {0} in race {1}
penaltyOrRedress=Penalty/Redress
netScore=Net points
netScore=Net points
timePointMustBeAfterStartOfTracking=Time point must be after start of tracking.
timePointMustBeBeforeEndOfTracking=Time point must be before end of tracking.
regattaUsedForTheTrackedRace=Regatta used for the tracked race
@@ -396,6 +396,7 @@ scoringSchemeLowPointSystem=Low Point System
scoringSchemeHighPointSystem=High Point System
scoringSchemeHighPointEssOverall=High Point System ESS Gesamtwertung
scoringSchemeHighPointLastBreaksTie=High Point System, letztes Rennen entscheidet bei Gleichstand
scoringSchemeLowPointWinnerGetsZero=Low Point System, Gewinner erhält 0 Punkte
scoringSystem=Bepunktungssystem
createFlexibleLeaderboard=Flexible Rangliste anlegen
createRegattaLeaderboard=Rangliste für Regatta anlegen
@@ -521,4 +522,7 @@ cannotAddRacesToRegattaLeaderboardButOnlyToRegatta=Dies ist eine Regatta-Ergebni
correctScore=Ergebnis bearbeiten
correctScoreFor=Ergebnis für Teilnehmer {0} in Rennen {1} bearbeiten
penaltyOrRedress=Strafe/Gutschrift
netScore=Nettoergebnis
netScore=Nettoergebnis
timePointMustBeAfterStartOfTracking=Der Zeitpunkt muß nach dem Trackingbeginn sein.
timePointMustBeBeforeEndOfTracking=Der Zeitpunkt muß vor dem Trackingende sein.
regattaUsedForTheTrackedRace=Regatta, zu der das Rennen rehört
@@ -55,13 +55,6 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
private final Button slowDownButton;
private final Button speedUpButton;
/**
* The live delay may be adjusted automatically if the server decides so. However, if the user explicitly sets a live delay,
* server-side updates to the delay should be suppressed. This flag records whether the user has performed a manual delay
* override.
*/
private boolean userExplicitlyChangedLivePlayDelay;
/**
* the minimum time the slider extends it's time when the end of the slider is reached
*/
@@ -89,7 +82,6 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
timer.addTimeListener(this);
timer.addPlayStateListener(this);
timeRangeProvider.addTimeRangeChangeListener(this);
userExplicitlyChangedLivePlayDelay = false;
FlowPanel timePanelInnerWrapper = new FlowPanel();
timePanelInnerWrapper.setStyleName("timePanelInnerWrapper");
timePanelInnerWrapper.setSize("100%", "100%");
@@ -460,16 +452,12 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
return new TimePanelSettingsDialogComponent<T>(getSettings(), stringMessages);
}
protected boolean isUserExplicitlyChangedLivePlayDelay() {
return userExplicitlyChangedLivePlayDelay;
}
@Override
public void updateSettings(T newSettings) {
boolean delayChanged = newSettings.getDelayToLivePlayInSeconds() != getSettings().getDelayToLivePlayInSeconds();
if (delayChanged) {
userExplicitlyChangedLivePlayDelay = true;
timer.setLivePlayDelayInMillis(1000l * newSettings.getDelayToLivePlayInSeconds());
// explicit change always goes through and disables further automatic delay updates in timer
timer.setLivePlayDelayInMillisExplicitly(1000l * newSettings.getDelayToLivePlayInSeconds());
if (timer.getPlayMode() == PlayModes.Live) {
timeDelayLabel.setText(String.valueOf(newSettings.getDelayToLivePlayInSeconds()) + " s");
}
@@ -78,6 +78,13 @@ public class Timer {
* Set to <code>true</code> to enable the timer to advance the max time automatically if the current time gets greater than the max time
*/
private boolean autoAdvance;
/**
* If {@link #setLivePlayDelayInMillisExplicitly(long)} was called, this flag is set to <code>true</code> which will
* cause calls to {@link #setLivePlayDelayInMillis(long)} to be ignored. Then, the only way to update the live delay is
* to call {@link #setLivePlayDelayInMillisExplicitly(long)}.
*/
private boolean delaySetExplicity;
/**
* The timer can run in two different modes: Live and Replay
@@ -261,6 +268,21 @@ public class Timer {
}
public void setLivePlayDelayInMillis(long delayInMilliseconds) {
if (!delaySetExplicity) {
basicSetLivePlayDelayInMillis(delayInMilliseconds);
}
}
/**
* Always updates the delay if it is different from the current delay setting. The fact that an explicit delay update was
* performed is recorded which will block further automatic delay updates from this point onwards.
*/
public void setLivePlayDelayInMillisExplicitly(long delayInMilliseconds) {
basicSetLivePlayDelayInMillis(delayInMilliseconds);
delaySetExplicity = true;
}
private void basicSetLivePlayDelayInMillis(long delayInMilliseconds) {
if (this.livePlayDelayInMillis != delayInMilliseconds) {
this.livePlayDelayInMillis = delayInMilliseconds;
if (getPlayMode() == PlayModes.Live) {
@@ -24,10 +24,13 @@ public abstract class AbstractRaceColumnSelection implements RaceColumnSelection
@Override
public Iterable<RaceColumnDTO> getSelectedRaceColumnsOrderedAsInLeaderboard(LeaderboardDTO leaderboard) {
Iterable<RaceColumnDTO> selectedColumns = getSelectedRaceColumns();
List<String> namesOfSelectedRaceColumns = new ArrayList<String>();
for (RaceColumnDTO selectedColumn : getSelectedRaceColumns()) {
namesOfSelectedRaceColumns.add(selectedColumn.name);
}
List<RaceColumnDTO> result = new ArrayList<RaceColumnDTO>();
for (RaceColumnDTO column : leaderboard.getRaceList()) {
if (Util.contains(selectedColumns, column)) {
if (Util.contains(namesOfSelectedRaceColumns, column.name)) {
result.add(column);
}
}
@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -15,18 +14,22 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.FleetDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
/**
* Doesn't respect requests to explicitly turn on or off certain columns. Instead, up to the last <code>n</code> (with
* <code>n</code> being an integer number to configure through the constructor) race columns will be selected. "Last" is
* decided based on the race start times which are obtained through a {@link RaceTimesInfoProvider}.
* decided based on the column ordering in the leaderboard, considering races with a valid start time which are obtained
* through a {@link RaceTimesInfoProvider} or a score correction.
*
* @author Axel Uhl (D043530)
*
*
*/
public class LastNRacesColumnSelection extends AbstractRaceColumnSelection implements RaceTimesInfoProviderListener {
private final int numberOfLastRacesToShow;
@@ -87,33 +90,35 @@ public class LastNRacesColumnSelection extends AbstractRaceColumnSelection imple
this.raceTimesInfo = raceTimesInfo;
}
private Iterable<RaceColumnDTO> getRaceColumnsFromNewestToOldest(LeaderboardDTO leaderboard,
private Iterable<RaceColumnDTO> getRaceColumnsFromNewestToOldest(final LeaderboardDTO leaderboard,
Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo) {
final Map<RaceColumnDTO, Date> latestStarts = new HashMap<RaceColumnDTO, Date>();
List<RaceColumnDTO> columns = new ArrayList<RaceColumnDTO>(leaderboard.getRaceList());
for (Iterator<RaceColumnDTO> i=columns.iterator(); i.hasNext(); ) {
RaceColumnDTO column = i.next();
Date latestStart = getLatestStart(column);
if (latestStart == null) {
if (getLatestStart(column) == null && !hasScoreCorrections(leaderboard, column)) {
i.remove();
} else {
latestStarts.put(column, latestStart);
}
}
Comparator<RaceColumnDTO> comparator = new Comparator<RaceColumnDTO>() {
@Override
public int compare(RaceColumnDTO o1, RaceColumnDTO o2) {
int result;
Date latestStartO1 = latestStarts.get(o1);
Date latestStartO2 = latestStarts.get(o2);
result = latestStartO2.compareTo(latestStartO1);
return result;
return leaderboard.getRaceList().indexOf(o2) - leaderboard.getRaceList().indexOf(o1);
}
};
Collections.sort(columns, comparator);
return columns;
}
private boolean hasScoreCorrections(LeaderboardDTO leaderboard, RaceColumnDTO column) {
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : leaderboard.rows.entrySet()) {
LeaderboardEntryDTO entry = e.getValue().fieldsByRaceColumnName.get(column.name);
if (entry != null && entry.hasScoreCorrection()) {
return true;
}
}
return false;
}
private Date getLatestStart(RaceColumnDTO column) {
Date latestStart = null;
for (FleetDTO fleet : column.getFleets()) {
@@ -47,6 +47,14 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint {
private static final String PARAM_REFRESH_INTERVAL_MILLIS = "refreshIntervalMillis";
private static final String PARAM_SHOW_OVERALL_LEADERBOARDS_ON_SAME_PAGE = "showOverallLeaderboardsOnSamePage";
private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis";
/**
* Parameter to support scaling the complete page by a given factor. This works by either using the
* CSS3 zoom property or by applying scale operation to the body element. This comes in handy
* when having to deal with screens that have high resolutions and that can't be controlled manually.
* It is also a very simple method of adapting the viewport to a tv resolution. This parameter works
* with value from 0.0 to 10.0 where 1.0 denotes the unchanged level (100%).
*/
private static final String PARAM_ZOOM_TO = "zoomTo";
/**
@@ -80,7 +88,7 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint {
final String zoomTo = Window.Location.getParameter(PARAM_ZOOM_TO);
if (zoomTo != null) {
RootPanel.getBodyElement().setAttribute("style", "zoom:"+zoomTo);
RootPanel.getBodyElement().setAttribute("style", "zoom: "+zoomTo+";-moz-transform: scale("+zoomTo+");-moz-transform-origin: 0 0;-o-transform: scale("+zoomTo+");-o-transform-origin: 0 0;-webkit-transform: scale("+zoomTo+");-webkit-transform-origin: 0 0;");
}
}
@@ -242,7 +242,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private final Label liveRaceLabel;
private final DateTimeFormat dateFormatter = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_LONG);
private final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm:ss");
private final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm:ss zzz");
private boolean isEmbedded = false;
@@ -430,7 +430,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
timer.setRefreshInterval(newSettings.getDelayBetweenAutoAdvancesInMilliseconds());
}
if (newSettings.getDelayInMilliseconds() != null) {
setDelayInMilliseconds(newSettings.getDelayInMilliseconds());
timer.setLivePlayDelayInMillisExplicitly(newSettings.getDelayInMilliseconds());
}
for (ExpandableSortableColumn<?> expandableSortableColumn : columnsToExpandAgain) {
expandableSortableColumn.toggleExpansion();
@@ -1840,11 +1840,11 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
/**
* Based on the {@link LeaderboardDTO#getDelayToLiveInMillisForLatestRace()} for the race that has the latest
* {@link RaceColumnDTO#getStartDate(FleetDTO) start time}, if no {@link #settingsUpdatedExplicitly explicit setting
* changes} were performed, automatically adjusts the delay accordingly.
* {@link RaceColumnDTO#getStartDate(FleetDTO) start time}, automatically adjusts the delay accordingly unless it
* was manually explicitly updated.
*/
private void adjustDelayToLive() {
if (!settingsUpdatedExplicitly && leaderboard.getDelayToLiveInMillisForLatestRace() != null) {
if (leaderboard.getDelayToLiveInMillisForLatestRace() != null) {
setDelayInMilliseconds(leaderboard.getDelayToLiveInMillisForLatestRace());
}
}
@@ -4,18 +4,20 @@ import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.gwt.ui.client.StringMessages;
public class ScoringSchemeTypeFormatter {
public static String format(ScoringSchemeType scoringSchemeType, StringMessages stringConstants) {
public static String format(ScoringSchemeType scoringSchemeType, StringMessages stringMessages) {
switch (scoringSchemeType) {
case LOW_POINT:
return stringConstants.scoringSchemeLowPointSystem();
return stringMessages.scoringSchemeLowPointSystem();
case HIGH_POINT:
return stringConstants.scoringSchemeHighPointSystem();
return stringMessages.scoringSchemeHighPointSystem();
case HIGH_POINT_ESS_OVERALL:
return stringConstants.scoringSchemeHighPointEssOverall();
return stringMessages.scoringSchemeHighPointEssOverall();
case HIGH_POINT_LAST_BREAKS_TIE:
return stringConstants.scoringSchemeHighPointLastBreaksTie();
return stringMessages.scoringSchemeHighPointLastBreaksTie();
case HIGH_POINT_FIRST_GETS_TEN:
return stringConstants.scoringSchemeHighPointFirstGetsTen();
return stringMessages.scoringSchemeHighPointFirstGetsTen();
case LOW_POINT_WINNER_GETS_ZERO:
return stringMessages.scoringSchemeLowPointWinnerGetsZero();
}
return null;
}
@@ -60,4 +60,11 @@ public class EditScoreDialog extends DataEntryDialog<Pair<MaxPointsReason, Doubl
grid.setWidget(1, 1, netPointsBox);
return grid;
}
@Override
public void show() {
super.show();
netPointsBox.setFocus(true);
netPointsBox.selectAll();
}
}
@@ -390,7 +390,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
String prefix;
String suffix;
if (netPointsCorrected) {
prefix = "<b>";
prefix = "<b class='bold'>";
suffix = "</b>";
} else {
prefix = "";
@@ -251,12 +251,16 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
if (officialSailID != null && raceNameOrNumber != null) {
ScoreCorrectionEntryDTO officialCorrectionEntry = regattaScoreCorrection
.getScoreCorrectionsByRaceNameOrNumber().get(raceNameOrNumber).get(officialSailID);
result.addMaxPointsReasonUpdate(competitor, raceColumn,
officialCorrectionEntry.getMaxPointsReason());
if (officialCorrectionEntry.getScore() != null) {
double officialTotalPoints = officialCorrectionEntry.getScore().doubleValue();
double officialNetPoints = officialTotalPoints / raceColumn.getEffectiveFactor();
result.addScoreUpdate(competitor, raceColumn, officialNetPoints);
// the competitor may not have an official result for this race, for example, if in case of split fleets
// the competitor raced in a different fleet
if (officialCorrectionEntry != null) {
result.addMaxPointsReasonUpdate(competitor, raceColumn,
officialCorrectionEntry.getMaxPointsReason());
if (officialCorrectionEntry.getScore() != null) {
double officialTotalPoints = officialCorrectionEntry.getScore().doubleValue();
double officialNetPoints = officialTotalPoints / raceColumn.getEffectiveFactor();
result.addScoreUpdate(competitor, raceColumn, officialNetPoints);
}
}
}
}
@@ -308,36 +312,42 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
ScoreCorrectionEntryDTO officialCorrectionEntry =
regattaScoreCorrection.getScoreCorrectionsByRaceNameOrNumber()
.get(raceNameOrNumber).get(officialSailID);
final Double officialTotalPoints = officialCorrectionEntry.isDiscarded() ? new Double(0) : officialCorrectionEntry.getScore();
final Double officialNetPoints = officialCorrectionEntry.getScore() == null ? null :
final Double officialTotalPoints = officialCorrectionEntry == null ? null :
officialCorrectionEntry.isDiscarded() ? new Double(0) : officialCorrectionEntry.getScore();
final Double officialNetPoints = officialCorrectionEntry == null ? null :
officialCorrectionEntry.getScore() == null ? null :
officialCorrectionEntry.getScore() / raceColumn.getEffectiveFactor();
final MaxPointsReason officialMaxPointsReason = officialCorrectionEntry == null ? null :
officialCorrectionEntry.getMaxPointsReason();
SafeHtmlBuilder sb = new SafeHtmlBuilder();
boolean entriesDiffer =
((officialNetPoints == null && entry.netPoints != null) || (officialNetPoints != null && entry.netPoints != null && !new Double(entry.netPoints).equals(officialNetPoints))) ||
((officialTotalPoints == null && entry.totalPoints != null) || (officialTotalPoints != null && entry.totalPoints != null && !new Double(entry.totalPoints).equals(officialTotalPoints))) ||
((officialCorrectionEntry.getMaxPointsReason() == null && entry.reasonForMaxPoints != MaxPointsReason.NONE) ||
officialCorrectionEntry.getMaxPointsReason() != null && officialCorrectionEntry.getMaxPointsReason() != entry.reasonForMaxPoints);
// entries not considered "different' in case we haven't got an entry for the competitor/race at all;
// those non-existing "entries" will be ignored by getResults anyhow
boolean entriesDiffer = officialCorrectionEntry != null &&
(((officialNetPoints == null && entry.netPoints != null) || (officialNetPoints != null && (entry.netPoints == null || !new Double(entry.netPoints).equals(officialNetPoints)))) ||
((officialTotalPoints == null && entry.totalPoints != null) || (officialTotalPoints != null && (entry.totalPoints == null || !new Double(entry.totalPoints).equals(officialTotalPoints)))) ||
((officialMaxPointsReason == null && entry.reasonForMaxPoints != MaxPointsReason.NONE) ||
officialMaxPointsReason != null && officialMaxPointsReason != entry.reasonForMaxPoints));
if (entriesDiffer) {
sb.appendHtmlConstant("<span style=\"color: #0000FF;\"><b>");
}
if (officialNetPoints == null) {
sb.append(0);
sb.appendEscaped("null");
} else {
sb.append(officialNetPoints);
}
sb.appendEscaped("/");
if (officialTotalPoints == null) {
sb.append(0);
sb.appendEscaped("null");
} else {
sb.append(officialTotalPoints);
}
sb.appendEscaped("/");
if (officialCorrectionEntry.getMaxPointsReason() != null) {
sb.appendEscaped(officialCorrectionEntry.getMaxPointsReason().name());
if (officialMaxPointsReason != null) {
sb.appendEscaped(officialMaxPointsReason.name());
} else {
sb.appendEscaped(MaxPointsReason.NONE.name());
}
if (officialCorrectionEntry.isDiscarded()) {
if (officialCorrectionEntry != null && officialCorrectionEntry.isDiscarded()) {
sb.appendEscaped("/discarded");
}
if (entriesDiffer) {
@@ -88,11 +88,11 @@ public class MediaSelector implements /*RaceTimesInfoProviderListener,*/ PlaySta
Collection<MediaTrack> reachableVideoTracks = new ArrayList<MediaTrack>();
Collection<MediaTrack> reachableAudioTracks = new ArrayList<MediaTrack>();
for (MediaTrack mediaTrack : mediaTracks) {
if (MediaTrack.Status.REACHABLE.equals(mediaTrack.status)) {
if (isPotentiallyPlayable(mediaTrack)) {
switch (mediaTrack.mimeType.mediaType) {
case video:
reachableVideoTracks.add(mediaTrack);
case audio: //intentionall fall through
case audio: //intentional fall through
reachableAudioTracks.add(mediaTrack);
}
}
@@ -129,20 +129,19 @@ public class MediaSelector implements /*RaceTimesInfoProviderListener,*/ PlaySta
}
private boolean isPotentiallyPlayable(MediaTrack mediaTrack) {
return MediaTrack.Status.REACHABLE.equals(mediaTrack.status) || MediaTrack.Status.UNDEFINED.equals(mediaTrack.status);
}
private void setStatus(final MediaTrack mediaTrack) {
if (!mediaTrack.isYoutube()) {
Audio audio = Audio.createIfSupported();
if (audio != null) {
AudioElement mediaReachableTester = audio.getAudioElement();
String canPlay = mediaReachableTester.canPlayType(mediaTrack.typeToString());
if (MediaElement.CAN_PLAY_PROBABLY.equals(canPlay) || MediaElement.CAN_PLAY_MAYBE.equals(canPlay)) {
addLoadMetadataHandler(mediaReachableTester, mediaTrack);
mediaReachableTester.setPreload(MediaElement.PRELOAD_METADATA);
mediaReachableTester.setSrc(mediaTrack.url);
mediaReachableTester.load();
} else {
mediaTrack.status = Status.CANNOT_PLAY;
}
addLoadMetadataHandler(mediaReachableTester, mediaTrack);
mediaReachableTester.setPreload(MediaElement.PRELOAD_METADATA);
mediaReachableTester.setSrc(mediaTrack.url);
mediaReachableTester.load();
} else {
mediaTrack.status = Status.CANNOT_PLAY;
}
@@ -156,11 +155,18 @@ public class MediaSelector implements /*RaceTimesInfoProviderListener,*/ PlaySta
mediaElement.addEventListener('loadedmetadata', function() {
that.@com.sap.sailing.gwt.ui.raceboard.MediaSelector::loadedmetadata(Lcom/sap/sailing/gwt/ui/shared/media/MediaTrack;)(mediaTrack);
});
mediaElement.addEventListener('error', function() {
that.@com.sap.sailing.gwt.ui.raceboard.MediaSelector::mediaError(Lcom/sap/sailing/gwt/ui/shared/media/MediaTrack;)(mediaTrack);
});
}-*/;
public void loadedmetadata(MediaTrack mediaTrack) {
mediaTrack.status = Status.REACHABLE;
}
public void mediaError(MediaTrack mediaTrack) {
mediaTrack.status = Status.NOT_REACHABLE;
}
private void playDefault() {
MediaTrack defaultVideo = getDefaultVideo();
@@ -176,7 +182,7 @@ public class MediaSelector implements /*RaceTimesInfoProviderListener,*/ PlaySta
private MediaTrack getDefaultAudio() {
//TODO: implement a better heuristic than just taking the first to come
for (MediaTrack mediaTrack : mediaTracks) {
if (MediaType.audio.equals(mediaTrack.mimeType.mediaType)) {
if (MediaType.audio.equals(mediaTrack.mimeType.mediaType) && isPotentiallyPlayable(mediaTrack)) {
return mediaTrack;
}
}
@@ -185,7 +191,7 @@ public class MediaSelector implements /*RaceTimesInfoProviderListener,*/ PlaySta
private MediaTrack getDefaultVideo() {
for (MediaTrack mediaTrack : mediaTracks) {
if (MediaType.video.equals(mediaTrack.mimeType.mediaType)) {
if (MediaType.video.equals(mediaTrack.mimeType.mediaType) && isPotentiallyPlayable(mediaTrack)) {
return mediaTrack;
}
}
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.util.impl.LockUtil;
/**
* Caches the expensive to compute {@link LeaderboardDTO} results of a
@@ -402,12 +403,21 @@ public class LeaderboardDTOCache {
future = map.get(key);
}
if (future == null) {
final Thread callerThread = Thread.currentThread();
future = new FutureTask<LeaderboardDTO>(new Callable<LeaderboardDTO>() {
@Override
public LeaderboardDTO call() throws Exception {
LeaderboardDTO result = sailingService.computeLeaderboardByName(leaderboard, adjustedTimePoint,
namesOfRaceColumnsForWhichToLoadLegDetails, waitForLatestAnalyses);
return result;
// The outer getLeaderboardByName(...) method will always wait for this future's completion.
// Therefore, it's safe to propagate the calling thread's locks to this one:
LockUtil.propagateLockSetFrom(callerThread);
try {
LeaderboardDTO result = sailingService.computeLeaderboardByName(leaderboard,
adjustedTimePoint, namesOfRaceColumnsForWhichToLoadLegDetails,
waitForLatestAnalyses);
return result;
} finally {
LockUtil.unpropagateLockSetFrom(callerThread);
}
}
});
computeLeadearboardByNameExecutor.execute(future);
@@ -72,6 +72,7 @@ import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.CountryCode;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.MaxPointsReason;
@@ -347,7 +348,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
/* workQueue */ new LinkedBlockingQueue<Runnable>());
raceDetailsExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
leaderboardByNameLiveUpdaters = new HashMap<String, LiveLeaderboardUpdater>();
leaderboardDTOCacheWaitingForLatestAnalysis = new LeaderboardDTOCache(this, /* waitForLatestAnalyses */ true);
// The leaderboard cache is invalidated upon all competitor and mark position changes; some analyses
// are pretty expensive, such as the maneuver re-calculation. Waiting for the latest analysis after only a
// single fix was updated is too expensive if users use the replay feature while a race is still running.
// Therefore, using waitForLatestAnalyses==false seems appropriate here.
leaderboardDTOCacheWaitingForLatestAnalysis = new LeaderboardDTOCache(this, /* waitForLatestAnalyses */ false);
}
private void writeObject(ObjectOutputStream oos) throws IOException {
@@ -509,7 +514,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
RegattaAndRaceIdentifier raceIdentifier = null;
RaceDTO race = null;
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
final FleetDTO fleetDTO = convertToFleetDTO(fleet);
final FleetDTO fleetDTO = convertToFleetDTO(raceColumn, fleet);
if (trackedRace != null) {
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta()
.getName(), trackedRace.getRace().getName());
@@ -577,7 +583,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public LeaderboardEntryDTO call() {
try {
Entry entry = leaderboard.getEntry(competitor, raceColumn, timePoint);
return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(competitor), competitor, timePoint,
return getLeaderboardEntryDTO(entry, raceColumn, competitor, timePoint,
namesOfRaceColumnsForWhichToLoadLegDetails != null
&& namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName()),
waitForLatestAnalyses, legRanksCache);
@@ -608,7 +614,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
}
}
logger.fine("computeLeaderboardByName("+leaderboard.getName()+", "+timePoint+", "+namesOfRaceColumnsForWhichToLoadLegDetails+") took "+
logger.info("computeLeaderboardByName("+leaderboard.getName()+", "+timePoint+", "+namesOfRaceColumnsForWhichToLoadLegDetails+") took "+
(System.currentTimeMillis()-startOfRequestHandling)+"ms");
return result;
}
@@ -646,10 +652,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
* may not reflect all data already received; otherwise, the method will always block for the latest
* cache updates to have happened before returning.
*/
private LeaderboardEntryDTO getLeaderboardEntryDTO(Entry entry, TrackedRace trackedRace, Competitor competitor,
private LeaderboardEntryDTO getLeaderboardEntryDTO(Entry entry, RaceColumn raceColumn, Competitor competitor,
TimePoint timePoint, boolean addLegDetails, boolean waitForLatestAnalyses,
Map<Leg, LinkedHashMap<Competitor, Integer>> legRanksCache) throws NoWindException {
LeaderboardEntryDTO entryDTO = new LeaderboardEntryDTO();
TrackedRace trackedRace = raceColumn.getTrackedRace(competitor);
entryDTO.race = trackedRace == null ? null : trackedRace.getRaceIdentifier();
entryDTO.netPoints = entry.getNetPoints();
entryDTO.netPointsCorrected = entry.isNetPointsCorrected();
@@ -671,7 +678,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
}
final Fleet fleet = entry.getFleet();
entryDTO.fleet = fleet == null ? null : convertToFleetDTO(fleet);
entryDTO.fleet = fleet == null ? null : convertToFleetDTO(raceColumn, fleet);
return entryDTO;
}
@@ -1068,7 +1075,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
private SeriesDTO convertToSeriesDTO(Series series) {
List<FleetDTO> fleets = new ArrayList<FleetDTO>();
for (Fleet fleet : series.getFleets()) {
fleets.add(convertToFleetDTO(fleet));
fleets.add(convertToFleetDTO(series, fleet));
}
List<RaceColumnDTO> raceColumns = new ArrayList<RaceColumnDTO>();
for (RaceColumnInSeries raceColumn : series.getRaceColumns()) {
@@ -1082,8 +1089,16 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return result;
}
private FleetDTO convertToFleetDTO(Fleet fleet) {
return new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor());
private FleetDTO convertToFleetDTO(Series series, Fleet fleet) {
return new FleetDTO(fleet.getName(), series.getName(), fleet.getOrdering(), fleet.getColor());
}
private FleetDTO convertToFleetDTO(RaceColumn raceColumn, Fleet fleet) {
String seriesNameOfFleet = null;
if (raceColumn instanceof RaceColumnInSeries) {
seriesNameOfFleet = ((RaceColumnInSeries) raceColumn).getSeries().getName();
}
return new FleetDTO(fleet.getName(), seriesNameOfFleet, fleet.getOrdering(), fleet.getColor());
}
private List<RaceWithCompetitorsDTO> convertToRaceDTOs(Regatta regatta) {
@@ -2132,7 +2147,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
latestTimePointAfterQueryTimePointWhenATrackedRaceWasLive = liveTimePointForTrackedRace;
}
}
final FleetDTO fleetDTO = convertToFleetDTO(fleet);
final FleetDTO fleetDTO = convertToFleetDTO(raceColumn, fleet);
RaceColumnDTO raceColumnDTO = leaderboardDTO.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), raceColumn.getFactor(),
fleetDTO, raceColumn.isMedalRace(), raceIdentifier, raceDTO);
if (latestTimePointAfterQueryTimePointWhenATrackedRaceWasLive != null) {
@@ -2407,7 +2422,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
throws UnknownHostException, IOException, InterruptedException, ParseException {
List<SwissTimingRaceRecordDTO> result = new ArrayList<SwissTimingRaceRecordDTO>();
for (com.sap.sailing.domain.swisstimingadapter.RaceRecord rr : getService().getSwissTimingRaceRecords(hostname, port, canSendRequests)) {
result.add(new SwissTimingRaceRecordDTO(rr.getRaceID(), rr.getDescription(), rr.getStartTime()));
SwissTimingRaceRecordDTO swissTimingRaceRecordDTO = new SwissTimingRaceRecordDTO(rr.getRaceID(), rr.getDescription(), rr.getStartTime());
BoatClass boatClass = com.sap.sailing.domain.swisstimingadapter.DomainFactory.INSTANCE.getOrCreateBoatClassFromRaceID(rr.getRaceID());
swissTimingRaceRecordDTO.boatClass = boatClass != null ? boatClass.getName() : null;
swissTimingRaceRecordDTO.discipline = rr.getRaceID().length() >= 3 ? rr.getRaceID().substring(2, 3) : null;
result.add(swissTimingRaceRecordDTO);
}
return result;
}
@@ -2421,7 +2440,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable<SwissTimingRaceRecordDTO> rrs, String hostname, int port,
boolean canSendRequests, boolean trackWind, final boolean correctWindByDeclination) throws Exception {
for (SwissTimingRaceRecordDTO rr : rrs) {
final RacesHandle raceHandle = getService().addSwissTimingRace(regattaToAddTo, rr.ID, hostname, port,
canSendRequests,
MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory),
@@ -2476,11 +2494,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
regatta = getService().createRegatta(
replayRaceDTO.rsc,
boatClass.trim(),
RegattaImpl.getFullName(replayRaceDTO.rsc, replayRaceDTO.boat_class),
RegattaImpl.getDefaultName(replayRaceDTO.rsc, replayRaceDTO.boat_class),
Collections.singletonList(new SeriesImpl(
"Default",
LeaderboardNameConstants.DEFAULT_SERIES_NAME,
/* isMedal */false,
Collections.singletonList(new FleetImpl("Default")),
Collections.singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)),
/* race column names */ new ArrayList<String>(), getService())),
false,
baseDomainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT), null);
@@ -7,10 +7,14 @@ public class FleetDTO extends NamedDTO implements IsSerializable {
private Color color;
private int orderNo;
/** the name of the series the fleet belongs to */
private String seriesName;
public FleetDTO() {}
public FleetDTO(String fleetName, int orderNo, Color color) {
public FleetDTO(String fleetName, String seriesName, int orderNo, Color color) {
super(fleetName);
this.seriesName = seriesName;
this.orderNo = orderNo;
this.color = color;
}
@@ -31,12 +35,17 @@ public class FleetDTO extends NamedDTO implements IsSerializable {
this.orderNo = orderNo;
}
public String getSeriesName() {
return seriesName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((color == null) ? 0 : color.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + orderNo;
result = prime * result + ((seriesName == null) ? 0 : seriesName.hashCode());
return result;
}
@@ -49,13 +58,19 @@ public class FleetDTO extends NamedDTO implements IsSerializable {
if (getClass() != obj.getClass())
return false;
FleetDTO other = (FleetDTO) obj;
if (color == null) {
if (other.color != null)
if (name == null) {
if (other.name != null)
return false;
} else if (!color.equals(other.color))
} else if (!name.equals(other.name))
return false;
if (orderNo != other.orderNo)
return false;
if (seriesName == null) {
if (other.seriesName != null)
return false;
} else if (!seriesName.equals(other.seriesName))
return false;
return true;
}
}
@@ -56,6 +56,10 @@ public class LeaderboardEntryDTO implements IsSerializable {
public FleetDTO fleet;
public LeaderboardEntryDTO() { }
public boolean hasScoreCorrection() {
return netPointsCorrected || (reasonForMaxPoints != null && reasonForMaxPoints != MaxPointsReason.NONE);
}
@Override
public int hashCode() {
@@ -11,10 +11,9 @@ import java.util.Set;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.TimingConstants;
public class RaceColumnDTO extends NamedDTO implements IsSerializable {
private static final long IS_LIVE_GRACE_PERIOD_IN_MILLIS = 3 * 60 * 1000; // three minutes
private boolean medalRace;
private List<FleetDTO> fleets;
private Map<FleetDTO, RegattaAndRaceIdentifier> trackedRaceIdentifiersPerFleet;
@@ -150,7 +149,7 @@ public class RaceColumnDTO extends NamedDTO implements IsSerializable {
boolean result = false;
final long now = System.currentTimeMillis();
Date whenLastTrackedRaceWasLive = getWhenLastTrackedRaceWasLive(fleet);
if (whenLastTrackedRaceWasLive != null && whenLastTrackedRaceWasLive.getTime() > now - IS_LIVE_GRACE_PERIOD_IN_MILLIS) {
if (whenLastTrackedRaceWasLive != null && whenLastTrackedRaceWasLive.getTime() > now - TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS) {
result = true;
}
return result;
@@ -8,6 +8,10 @@ public class SwissTimingRaceRecordDTO implements IsSerializable {
public String ID;
public String description;
public Date raceStartTime;
/** boatClass and discipline (men, woman, all) are derived data from the object ID */
public String boatClass;
public String discipline;
public SwissTimingRaceRecordDTO() {}
@@ -527,7 +527,7 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
if (timeOfEarliestRequestInMillis == null || date.getTime() < timeOfEarliestRequestInMillis) {
loadData(timeRangeWithZoomProvider.getFromTime(), date, /* append */ true);
} else if (date.getTime() > timeOfLatestRequestInMillis) {
loadData(new Date(timeOfLatestRequestInMillis), timeRangeWithZoomProvider.getToTime(), /* append */true);
loadData(new Date(timeOfLatestRequestInMillis), date, /* append */true);
}
}
break;
@@ -43,7 +43,17 @@ public class MediaTrack implements IsSerializable {
}
public enum Status {
UNDEFINED, CANNOT_PLAY, NOT_REACHABLE, REACHABLE;
UNDEFINED('?'), CANNOT_PLAY('-'), NOT_REACHABLE('#'), REACHABLE('+');
private final char symbol;
private Status(char symbol) {
this.symbol = symbol;
}
public String toString() {
return String.valueOf(this.symbol);
}
}
public class MediaSection implements IsSerializable {
@@ -76,7 +86,7 @@ public class MediaTrack implements IsSerializable {
}
public String toString() {
return title + " - " + url + " [" + typeToString() + ']' + startTime + " [" + durationInMillis + ']';
return title + " - " + url + " [" + typeToString() + ']' + startTime + " [" + durationInMillis + status + ']';
}
public String typeToString() {
@@ -1,286 +1,320 @@
package com.sap.sailing.gwt.ui.shared.racemap;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.resources.client.ImageResource;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.Tack;
/**
* Boat classes are displayed with different images (e.g. on a map) depending on the wind direction
* and the course (upwind, downwind). This class holds all required images for the different situations.
* @author C5163874
*
*/
public class BoatClassImageData {
private String mainBoatClassName;
private String[] aliasBoatClassNames;
private double boatClassLengthInMeter;
private int boatClassImageLengthInPx;
private int imageWidthInPx;
private int imageHeightInPx;
private ImageResource upWindPortIcon;
private ImageResource upWindPortIconSelected;
private ImageResource upWindStarboardIcon;
private ImageResource upWindStarboardIconSelected;
/**
* Boat image for wind from port and sails on starboard (downwind)
*/
private ImageResource downWindPortIcon;
private ImageResource downWindPortIconSelected;
/**
* Boat image with wind from starboard and sails on port (downwind)
*/
private ImageResource downWindStarboardIcon;
private ImageResource downWindStarboardIconSelected;
private final String mainBoatClassName;
private final List<String> compatibleBoatClassNames;
private final double boatClassLengthInMeter;
private final int boatClassImageLengthInPx;
private final int imageWidthInPx;
private final int imageHeightInPx;
private ImageResource reachingPortIcon;
private ImageResource reachingPortIconSelected;
private ImageResource reachingStarboardIcon;
private ImageResource reachingStarboardIconSelected;
private ImageResource upWindPortIcon;
private ImageResource upWindPortIconSelected;
private ImageResource upWindStarboardIcon;
private ImageResource upWindStarboardIconSelected;
private ImageTransformer upWindPortImageTransformer;
private ImageTransformer upWindPortImageTransformerSelected;
private ImageTransformer upWindStarboardImageTransformer;
private ImageTransformer upWindStarboardImageTransformerSelected;
private ImageTransformer downWindPortImageTransformer;
private ImageTransformer downWindPortImageTransformerSelected;
private ImageTransformer downWindStarboardImageTransformer;
private ImageTransformer downWindStarboardImageTransformerSelected;
/**
* Boat image for wind from port and sails on starboard (downwind)
*/
private ImageResource downWindPortIcon;
private ImageResource downWindPortIconSelected;
private ImageTransformer reachingPortImageTransformer;
private ImageTransformer reachingPortImageTransformerSelected;
private ImageTransformer reachingStarboardImageTransformer;
private ImageTransformer reachingStarboardImageTransformerSelected;
/**
* Boat image with wind from starboard and sails on port (downwind)
*/
private ImageResource downWindStarboardIcon;
private ImageResource downWindStarboardIconSelected;
public BoatClassImageData(String mainBoatClassName, double boatClassLengthInMeter, int boatClassImageLengthInPx, int imageWidthInPx, int imageHeightInPx) {
this.mainBoatClassName = mainBoatClassName;
this.boatClassLengthInMeter = boatClassLengthInMeter;
this.boatClassImageLengthInPx = boatClassImageLengthInPx;
this.imageWidthInPx = imageWidthInPx;
this.imageHeightInPx = imageHeightInPx;
}
private ImageResource reachingPortIcon;
private ImageResource reachingPortIconSelected;
private ImageResource reachingStarboardIcon;
private ImageResource reachingStarboardIconSelected;
public BoatClassImageData(String mainBoatClassName, double boatClassLengthInMeter, int boatClassImageLengthInPx, int imageWidthInPx, int imageHeightInPx, String... aliasBoatClassNames ) {
this(mainBoatClassName, boatClassLengthInMeter, boatClassImageLengthInPx, imageWidthInPx, imageHeightInPx);
this.aliasBoatClassNames = aliasBoatClassNames;
}
public ImageTransformer getBoatImageTransformerByLegTypeAndTack(LegType legType, Tack tack, boolean isSelected) {
ImageTransformer result = null;
switch(tack) {
case STARBOARD:
switch (legType) {
case DOWNWIND:
if(isSelected) {
result = downWindPortImageTransformerSelected;
} else {
result = downWindPortImageTransformer;
}
break;
case REACHING:
if(isSelected) {
result = reachingPortImageTransformerSelected;
} else {
result = reachingPortImageTransformer;
}
break;
case UPWIND:
if(isSelected) {
result = upWindPortImageTransformerSelected;
} else {
result = upWindPortImageTransformer;
}
break;
}
break;
case PORT:
switch (legType) {
case DOWNWIND:
if(isSelected) {
result = downWindStarboardImageTransformerSelected;
} else {
result = downWindStarboardImageTransformer;
}
break;
case REACHING:
if(isSelected) {
result = reachingStarboardImageTransformerSelected;
} else {
result = reachingStarboardImageTransformer;
}
break;
case UPWIND:
if(isSelected) {
result = upWindStarboardImageTransformerSelected;
} else {
result = upWindStarboardImageTransformer;
}
break;
}
break;
}
return result;
}
private ImageTransformer upWindPortImageTransformer;
private ImageTransformer upWindPortImageTransformerSelected;
private ImageTransformer upWindStarboardImageTransformer;
private ImageTransformer upWindStarboardImageTransformerSelected;
public ImageTransformer getBoatImageTransformerByTack(Tack tack, boolean isSelected) {
ImageTransformer result = null;
switch(tack) {
case STARBOARD:
if(isSelected) {
result = reachingPortImageTransformerSelected;
} else {
result = reachingPortImageTransformer;
}
break;
case PORT:
if(isSelected) {
result = reachingStarboardImageTransformerSelected;
} else {
result = reachingStarboardImageTransformer;
}
}
return result;
}
private ImageTransformer downWindPortImageTransformer;
private ImageTransformer downWindPortImageTransformerSelected;
private ImageTransformer downWindStarboardImageTransformer;
private ImageTransformer downWindStarboardImageTransformerSelected;
public void setUpWindPortIcons(ImageResource upWindPortIcon, ImageResource upWindPortIconSelected) {
this.upWindPortIcon = upWindPortIcon;
this.upWindPortIconSelected = upWindPortIconSelected;
private ImageTransformer reachingPortImageTransformer;
private ImageTransformer reachingPortImageTransformerSelected;
private ImageTransformer reachingStarboardImageTransformer;
private ImageTransformer reachingStarboardImageTransformerSelected;
if(upWindPortIcon != null) {
upWindPortImageTransformer = new ImageTransformer(upWindPortIcon);
}
if(upWindPortIconSelected != null) {
upWindPortImageTransformerSelected = new ImageTransformer(upWindPortIconSelected);
}
}
public BoatClassImageData(String mainBoatClassName, double boatClassLengthInMeter, int boatClassImageLengthInPx,
int imageWidthInPx, int imageHeightInPx) {
this.mainBoatClassName = mainBoatClassName;
this.boatClassLengthInMeter = boatClassLengthInMeter;
this.boatClassImageLengthInPx = boatClassImageLengthInPx;
this.imageWidthInPx = imageWidthInPx;
this.imageHeightInPx = imageHeightInPx;
this.compatibleBoatClassNames = new ArrayList<String>();
}
public void setUpWindStarboardIcons(ImageResource upWindStarboardIcon, ImageResource upWindStarboardIconSelected) {
this.upWindStarboardIcon = upWindStarboardIcon;
this.upWindStarboardIconSelected = upWindStarboardIconSelected;
public BoatClassImageData(String mainBoatClassName, double boatClassLengthInMeter, int boatClassImageLengthInPx,
int imageWidthInPx, int imageHeightInPx, String... compatibleBoatClasses) {
this(mainBoatClassName, boatClassLengthInMeter, boatClassImageLengthInPx, imageWidthInPx, imageHeightInPx);
for(String compatibleBoatClass: compatibleBoatClasses) {
this.compatibleBoatClassNames.add(compatibleBoatClass);
}
}
if(upWindStarboardIcon != null) {
upWindStarboardImageTransformer = new ImageTransformer(upWindStarboardIcon);
}
if(upWindStarboardIconSelected != null) {
upWindStarboardImageTransformerSelected = new ImageTransformer(upWindStarboardIconSelected);
}
}
public ImageTransformer getBoatImageTransformerByLegTypeAndTack(LegType legType, Tack tack, boolean isSelected) {
ImageTransformer result = null;
switch (tack) {
case STARBOARD:
switch (legType) {
case DOWNWIND:
if (isSelected) {
result = downWindPortImageTransformerSelected;
} else {
result = downWindPortImageTransformer;
}
break;
case REACHING:
if (isSelected) {
result = reachingPortImageTransformerSelected;
} else {
result = reachingPortImageTransformer;
}
break;
case UPWIND:
if (isSelected) {
result = upWindPortImageTransformerSelected;
} else {
result = upWindPortImageTransformer;
}
break;
}
break;
case PORT:
switch (legType) {
case DOWNWIND:
if (isSelected) {
result = downWindStarboardImageTransformerSelected;
} else {
result = downWindStarboardImageTransformer;
}
break;
case REACHING:
if (isSelected) {
result = reachingStarboardImageTransformerSelected;
} else {
result = reachingStarboardImageTransformer;
}
break;
case UPWIND:
if (isSelected) {
result = upWindStarboardImageTransformerSelected;
} else {
result = upWindStarboardImageTransformer;
}
break;
}
break;
}
return result;
}
public void setDownWindPortIcons(ImageResource downWindPortIcon, ImageResource downWindPortIconSelected) {
this.downWindPortIcon = downWindPortIcon;
this.downWindPortIconSelected = downWindPortIconSelected;
public ImageTransformer getBoatImageTransformerByTack(Tack tack, boolean isSelected) {
ImageTransformer result = null;
switch (tack) {
case STARBOARD:
if (isSelected) {
result = upWindPortImageTransformerSelected;
} else {
result = upWindPortImageTransformer;
}
break;
case PORT:
if (isSelected) {
result = upWindStarboardImageTransformerSelected;
} else {
result = upWindStarboardImageTransformer;
}
}
return result;
}
if(downWindPortIcon != null) {
downWindPortImageTransformer = new ImageTransformer(downWindPortIcon);
}
if(downWindPortIconSelected != null) {
downWindPortImageTransformerSelected = new ImageTransformer(downWindPortIconSelected);
}
}
public void setUpWindPortIcons(ImageResource upWindPortIcon, ImageResource upWindPortIconSelected) {
this.upWindPortIcon = upWindPortIcon;
this.upWindPortIconSelected = upWindPortIconSelected;
public void setDownWindStarboardIcons(ImageResource downWindStarboardIcon, ImageResource downWindStarboardIconSelected) {
this.downWindStarboardIcon = downWindStarboardIcon;
this.downWindStarboardIconSelected = downWindStarboardIconSelected;
if (upWindPortIcon != null) {
upWindPortImageTransformer = new ImageTransformer(upWindPortIcon);
}
if (upWindPortIconSelected != null) {
upWindPortImageTransformerSelected = new ImageTransformer(upWindPortIconSelected);
}
}
if(downWindStarboardIcon != null) {
downWindStarboardImageTransformer = new ImageTransformer(downWindStarboardIcon);
}
if(downWindStarboardIconSelected != null) {
downWindStarboardImageTransformerSelected = new ImageTransformer(downWindStarboardIconSelected);
}
}
public void setUpWindStarboardIcons(ImageResource upWindStarboardIcon, ImageResource upWindStarboardIconSelected) {
this.upWindStarboardIcon = upWindStarboardIcon;
this.upWindStarboardIconSelected = upWindStarboardIconSelected;
public void setReachingPortIcons(ImageResource reachingPortIcon, ImageResource reachingPortIconSelected) {
this.reachingPortIcon = reachingPortIcon;
this.reachingPortIconSelected = reachingPortIconSelected;
if (upWindStarboardIcon != null) {
upWindStarboardImageTransformer = new ImageTransformer(upWindStarboardIcon);
}
if (upWindStarboardIconSelected != null) {
upWindStarboardImageTransformerSelected = new ImageTransformer(upWindStarboardIconSelected);
}
}
if(reachingPortIcon != null) {
reachingPortImageTransformer = new ImageTransformer(reachingPortIcon);
}
if(reachingPortIconSelected != null) {
reachingPortImageTransformerSelected = new ImageTransformer(reachingPortIconSelected);
}
}
public void setDownWindPortIcons(ImageResource downWindPortIcon, ImageResource downWindPortIconSelected) {
this.downWindPortIcon = downWindPortIcon;
this.downWindPortIconSelected = downWindPortIconSelected;
public void setReachingStarboardIcons(ImageResource reachingStarboardIcon, ImageResource reachingStarboardIconSelected) {
this.reachingStarboardIcon = reachingStarboardIcon;
this.reachingStarboardIconSelected = reachingStarboardIconSelected;
if (downWindPortIcon != null) {
downWindPortImageTransformer = new ImageTransformer(downWindPortIcon);
}
if (downWindPortIconSelected != null) {
downWindPortImageTransformerSelected = new ImageTransformer(downWindPortIconSelected);
}
}
if(reachingStarboardIcon != null) {
reachingStarboardImageTransformer = new ImageTransformer(reachingStarboardIcon);
}
if(reachingStarboardIconSelected != null) {
reachingStarboardImageTransformerSelected = new ImageTransformer(reachingStarboardIconSelected);
}
}
public String getMainBoatClassName() {
return mainBoatClassName;
}
public void setDownWindStarboardIcons(ImageResource downWindStarboardIcon, ImageResource downWindStarboardIconSelected) {
this.downWindStarboardIcon = downWindStarboardIcon;
this.downWindStarboardIconSelected = downWindStarboardIconSelected;
public String[] getAliasBoatClassNames() {
return aliasBoatClassNames;
}
if (downWindStarboardIcon != null) {
downWindStarboardImageTransformer = new ImageTransformer(downWindStarboardIcon);
}
if (downWindStarboardIconSelected != null) {
downWindStarboardImageTransformerSelected = new ImageTransformer(downWindStarboardIconSelected);
}
}
public ImageResource getUpWindPortIcon() {
return upWindPortIcon;
}
public void setReachingPortIcons(ImageResource reachingPortIcon, ImageResource reachingPortIconSelected) {
this.reachingPortIcon = reachingPortIcon;
this.reachingPortIconSelected = reachingPortIconSelected;
public ImageResource getUpWindPortIconSelected() {
return upWindPortIconSelected;
}
if (reachingPortIcon != null) {
reachingPortImageTransformer = new ImageTransformer(reachingPortIcon);
}
if (reachingPortIconSelected != null) {
reachingPortImageTransformerSelected = new ImageTransformer(reachingPortIconSelected);
}
}
public ImageResource getUpWindStarboardIcon() {
return upWindStarboardIcon;
}
public void setReachingStarboardIcons(ImageResource reachingStarboardIcon,
ImageResource reachingStarboardIconSelected) {
this.reachingStarboardIcon = reachingStarboardIcon;
this.reachingStarboardIconSelected = reachingStarboardIconSelected;
public ImageResource getUpWindStarboardIconSelected() {
return upWindStarboardIconSelected;
}
if (reachingStarboardIcon != null) {
reachingStarboardImageTransformer = new ImageTransformer(reachingStarboardIcon);
}
if (reachingStarboardIconSelected != null) {
reachingStarboardImageTransformerSelected = new ImageTransformer(reachingStarboardIconSelected);
}
}
public ImageResource getDownWindPortIcon() {
return downWindPortIcon;
}
public boolean isBoatClassNameCompatible(String boatClass) {
boolean result = false;
// remove all white space characters
String boatClassToCheck = boatClass.replaceAll("\\s","");
// remove all '-' characters
boatClassToCheck = boatClass.replaceAll("-","");
if(mainBoatClassName.equalsIgnoreCase(boatClassToCheck)) {
result = true;
} else {
for(String compatibleName: compatibleBoatClassNames) {
if(compatibleName.equalsIgnoreCase(boatClassToCheck)) {
result = true;
break;
}
}
}
return result;
}
public String getMainBoatClassName() {
return mainBoatClassName;
}
public ImageResource getDownWindPortIconSelected() {
return downWindPortIconSelected;
}
public List<String> getCompatibleBoatClassNames() {
return compatibleBoatClassNames;
}
public ImageResource getDownWindStarboardIcon() {
return downWindStarboardIcon;
}
public ImageResource getUpWindPortIcon() {
return upWindPortIcon;
}
public ImageResource getDownWindStarboardIconSelected() {
return downWindStarboardIconSelected;
}
public ImageResource getUpWindPortIconSelected() {
return upWindPortIconSelected;
}
public double getBoatClassLengthInMeter() {
return boatClassLengthInMeter;
}
public ImageResource getUpWindStarboardIcon() {
return upWindStarboardIcon;
}
public int getBoatClassImageLengthInPx() {
return boatClassImageLengthInPx;
}
public ImageResource getUpWindStarboardIconSelected() {
return upWindStarboardIconSelected;
}
public int getImageWidthInPx() {
return imageWidthInPx;
}
public ImageResource getDownWindPortIcon() {
return downWindPortIcon;
}
public int getImageHeightInPx() {
return imageHeightInPx;
}
public ImageResource getDownWindPortIconSelected() {
return downWindPortIconSelected;
}
public ImageResource getReachingPortIcon() {
return reachingPortIcon;
}
public ImageResource getDownWindStarboardIcon() {
return downWindStarboardIcon;
}
public ImageResource getReachingPortIconSelected() {
return reachingPortIconSelected;
}
public ImageResource getDownWindStarboardIconSelected() {
return downWindStarboardIconSelected;
}
public ImageResource getReachingStarboardIcon() {
return reachingStarboardIcon;
}
public double getBoatClassLengthInMeter() {
return boatClassLengthInMeter;
}
public ImageResource getReachingStarboardIconSelected() {
return reachingStarboardIconSelected;
}
public int getBoatClassImageLengthInPx() {
return boatClassImageLengthInPx;
}
public int getImageWidthInPx() {
return imageWidthInPx;
}
public int getImageHeightInPx() {
return imageHeightInPx;
}
public ImageResource getReachingPortIcon() {
return reachingPortIcon;
}
public ImageResource getReachingPortIconSelected() {
return reachingPortIconSelected;
}
public ImageResource getReachingStarboardIcon() {
return reachingStarboardIcon;
}
public ImageResource getReachingStarboardIconSelected() {
return reachingStarboardIconSelected;
}
}
@@ -5,15 +5,21 @@ import java.util.Map;
import com.google.gwt.core.client.GWT;
/**
* A resolver utility for finding a boat image for a given boat class
* @author C5163874
*/
public class BoatClassImageDataResolver {
private static Map<String, BoatClassImageData> boatImagesMap;
private static BoatClassImageData defaultBoatImages;
private static Map<String, BoatClassImageData> boatImagesMap;
private static Map<String, BoatClassImageData> compatibleBoatImagesMap;
private static BoatClassImageData defaultBoatImages;
private static BoatImageResources boatImageResources = GWT.create(BoatImageResources.class);
static {
boatImagesMap = new HashMap<String, BoatClassImageData>();
compatibleBoatImagesMap = new HashMap<String, BoatClassImageData>();
BoatClassImageData _470er = new BoatClassImageData("470er", 4.70, 44, 72, 42, "470");
_470er.setDownWindPortIcons(boatImageResources.class470er_DownWindPortIcon(), boatImageResources.class470er_DownWindPortIconSelected());
_470er.setDownWindStarboardIcons(boatImageResources.class470er_DownWindStarboardIcon(), boatImageResources.class470er_DownWindStarboardIconSelected());
@@ -22,7 +28,7 @@ public class BoatClassImageDataResolver {
_470er.setReachingPortIcons(boatImageResources.class470er_ReachingPortIcon(), boatImageResources.class470er_ReachingPortIconSelected());
_470er.setReachingStarboardIcons(boatImageResources.class470er_ReachingStarboardIcon(), boatImageResources.class470er_ReachingStarboardIconSelected());
BoatClassImageData _49er = new BoatClassImageData("49er", 4.90, 42, 67, 31, "49");
BoatClassImageData _49er = new BoatClassImageData("49er", 4.90, 42, 67, 31, "49er FX");
_49er.setDownWindPortIcons(boatImageResources.class49er_DownWindPortIcon(), boatImageResources.class49er_DownWindPortIconSelected());
_49er.setDownWindStarboardIcons(boatImageResources.class49er_DownWindStarboardIcon(), boatImageResources.class49er_DownWindStarboardIconSelected());
_49er.setUpWindPortIcons(boatImageResources.class49er_UpWindPortIcon(), boatImageResources.class49er_UpWindPortIconSelected());
@@ -42,13 +48,24 @@ public class BoatClassImageDataResolver {
boatImagesMap.put(_470er.getMainBoatClassName(), _470er);
boatImagesMap.put(_49er.getMainBoatClassName(), _49er);
boatImagesMap.put(extreme40.getMainBoatClassName(), extreme40);
}
}
public static BoatClassImageData getBoatClassImages(String boatClassName) {
BoatClassImageData result = boatImagesMap.get(boatClassName);
if( result == null) {
result = defaultBoatImages;
}
return result;
}
public static BoatClassImageData resolveBoatClassImages(String boatClassName) {
BoatClassImageData result = defaultBoatImages;
if(boatImagesMap.containsKey(boatClassName)) {
result = boatImagesMap.get(boatClassName);
} else if (compatibleBoatImagesMap.containsKey(boatClassName)) {
result = compatibleBoatImagesMap.get(boatClassName);
} else {
// now try to find compatible boat class images
for(BoatClassImageData boatClassImageData: boatImagesMap.values()) {
if(boatClassImageData.isBoatClassNameCompatible(boatClassName)) {
result = boatClassImageData;
compatibleBoatImagesMap.put(boatClassName, boatClassImageData);
break;
}
}
}
return result;
}
}
@@ -41,7 +41,7 @@ public class BoatOverlay extends CanvasOverlay {
super();
this.competitorDTO = competitorDTO;
this.boatClass = competitorDTO.boatClass;
this.boatClassImageData = BoatClassImageDataResolver.getBoatClassImages(boatClass.name);
this.boatClassImageData = BoatClassImageDataResolver.resolveBoatClassImages(boatClass.name);
}
@Override
@@ -50,35 +50,38 @@ public class MarkImageDescriptor {
/**
* An utility method to check if the mark icon has compatible display properties.
* In case of null values at least one valid display property must exist and fit.
* In case of null values at least the mark type and the color must exist and fit.
*/
public boolean isCompatible(MarkType typeToCheck, String colorToCheck, String shapeToCheck, String patternToCheck) {
boolean result = false;
if((typeToCheck != null && type == null) || (typeToCheck == null && type != null)) {
result = false;
} else if(typeToCheck != null && type != null) {
result = type == typeToCheck;
}
public int getCompatibilityLevel(MarkType typeToCheck, String colorToCheck, String shapeToCheck, String patternToCheck) {
boolean isSameType = false;
boolean isSameColor = false;
boolean isSameShape = false;
boolean isSamePattern = false;
int result = -1;
if((colorToCheck != null && color == null) || (colorToCheck == null && color != null)) {
result = false;
} else if(colorToCheck != null && color != null) {
result = color.equalsIgnoreCase(colorToCheck) ? true : false;
if(typeToCheck != null && type != null) {
isSameType = type == typeToCheck;
}
if((shapeToCheck != null && shape == null) || (shapeToCheck == null && shape != null)) {
result = false;
} else if(shapeToCheck != null && shape != null) {
result = shape.equalsIgnoreCase(shapeToCheck) ? true : false;
if(colorToCheck != null && color != null) {
isSameColor = color.equalsIgnoreCase(colorToCheck) ? true : false;
}
if((patternToCheck != null && pattern == null) || (patternToCheck == null && pattern != null)) {
result = false;
} else if(patternToCheck != null && pattern != null) {
result = pattern.equalsIgnoreCase(patternToCheck) ? true : false;
if(shapeToCheck != null && shape != null) {
isSameShape = shape.equalsIgnoreCase(shapeToCheck) ? true : false;
}
if(patternToCheck != null && pattern != null) {
isSamePattern = pattern.equalsIgnoreCase(patternToCheck) ? true : false;
}
if(isSameType && isSameColor) {
result = 1;
if(isSameShape) {
result += 1;
}
if(isSamePattern) {
result += 1;
}
}
return result;
}
@@ -322,6 +322,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
}
//Data has been initialized
RaceMap.this.dataInitialized = true;
RaceMap.this.redraw();
}
});
}
@@ -49,11 +49,16 @@ public class RaceMapImageManager {
public MarkImageDescriptor resolveMarkImage(MarkType type, String color, String shape, String pattern) {
MarkImageDescriptor result = defaultCourseMarkDescriptor;
int highestCompatibilityLevel = -1;
for (MarkImageDescriptor imageDescriptor: markImageDescriptors) {
if(imageDescriptor.isCompatible(type, color, shape, pattern)) {
result = imageDescriptor;
break;
int compatibilityLevel = imageDescriptor.getCompatibilityLevel(type, color, shape, pattern);
if(compatibilityLevel > highestCompatibilityLevel) {
result = imageDescriptor;
highestCompatibilityLevel = compatibilityLevel;
if(highestCompatibilityLevel == 3) {
break;
}
}
}
@@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.spectator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -17,12 +16,12 @@ import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.NoSelectionModel;
@@ -45,7 +44,7 @@ import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.panels.WelcomeWidget;
public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget {
public class LeaderboardGroupPanel extends SimplePanel implements HasWelcomeWidget {
interface AnchorTemplates extends SafeHtmlTemplates {
@SafeHtmlTemplates.Template("<a class=\"{2}\" href=\"{0}\">{1}</a>")
@@ -110,8 +109,10 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
this.errorReporter = errorReporter;
this.root = (root == null || root.length() == 0) ? "leaderboardGroupPanel" : root;
this.viewMode = viewMode;
setWidth("95%");
regattasByName = new HashMap<String, RegattaDTO>();
mainPanel = new VerticalPanel();
mainPanel.setWidth("100%");
mainPanel.addStyleName("mainPanel");
add(mainPanel);
loadLeaderboardGroup(groupName);
@@ -163,34 +164,40 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
HTML leaderboardGroupDescriptionLabel = new HTML(new SafeHtmlBuilder().appendEscapedLines(leaderboardGroup.description).toSafeHtml());
leaderboardGroupDescriptionLabel.setStyleName(STYLE_NAME_PREFIX + "GroupDescription");
mainPanel.add(leaderboardGroupDescriptionLabel);
DockPanel labelAndLegendPanel = new DockPanel();
labelAndLegendPanel.setWidth("90%");
labelAndLegendPanel.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
Label leaderboardsTableLabel = new Label(stringMessages.leaderboards());
leaderboardsTableLabel.setStyleName(STYLE_NAME_PREFIX + "LeaderboardsTableLabel");
labelAndLegendPanel.add(leaderboardsTableLabel, DockPanel.WEST);
// legend
if (!isEmbedded) {
HorizontalPanel legendPanel = createLegendPanel();
labelAndLegendPanel.add(legendPanel, DockPanel.CENTER);
}
mainPanel.add(labelAndLegendPanel);
if (leaderboardGroup.hasOverallLeaderboard()) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLEncoder.encode("/gwt/Leaderboard.html?name=" + leaderboardGroup.name+" "+LeaderboardNameConstants.OVERALL
+ (showRaceDetails ? "&showRaceDetails=true" : "")
+ (isEmbedded ? "&embedded=true" : "")
+ "&displayName=" + stringMessages.overallStandings()
+ "&leaderboardGroupName=" + leaderboardGroup.name + "&root=" + root
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
Anchor overallStandingsLink = new Anchor(stringMessages.overallStandings(), true, link);
overallStandingsLink.setStyleName(STYLE_ACTIVE_LEADERBOARD);
overallStandingsLink.addStyleName("overallStandings");
mainPanel.add(overallStandingsLink);
}
}
FlexTable flexTable = new FlexTable();
Label leaderboardsLabel = new Label(stringMessages.leaderboards());
leaderboardsLabel.addStyleName(STYLE_NAME_PREFIX + "LeaderboardsLabel");
if(leaderboardGroup.hasOverallLeaderboard() && !isEmbedded) {
mainPanel.add(leaderboardsLabel);
} else {
flexTable.setWidget(0, 0, leaderboardsLabel);
}
mainPanel.add(flexTable);
flexTable.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
// legend
HorizontalPanel legendPanel = createLegendPanel();
flexTable.setWidget(0, 1, legendPanel);
if (leaderboardGroup.hasOverallLeaderboard()) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLEncoder.encode("/gwt/Leaderboard.html?name=" + leaderboardGroup.name+" "+LeaderboardNameConstants.OVERALL
+ (showRaceDetails ? "&showRaceDetails=true" : "")
+ (isEmbedded ? "&embedded=true" : "")
+ "&displayName=" + stringMessages.overallStandings()
+ "&leaderboardGroupName=" + leaderboardGroup.name + "&root=" + root
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
Anchor overallStandingsLink = new Anchor(stringMessages.overallStandings(), true, link);
overallStandingsLink.setStyleName(STYLE_ACTIVE_LEADERBOARD);
overallStandingsLink.addStyleName("overallStandings");
flexTable.setWidget(0, 0, overallStandingsLink);
}
SafeHtmlCell leaderboardNameCell = new SafeHtmlCell();
Column<StrippedLeaderboardDTO, SafeHtml> leaderboardNameColumn = new Column<StrippedLeaderboardDTO, SafeHtml>(
leaderboardNameCell) {
@@ -221,7 +228,6 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
LeaderboardGroupFullTableResources tableResources = GWT.create(LeaderboardGroupFullTableResources.class);
CellTable<StrippedLeaderboardDTO> leaderboardsTable = new CellTable<StrippedLeaderboardDTO>(10000, tableResources);
leaderboardsTable.setWidth("90%");
leaderboardsTable.setSelectionModel(new NoSelectionModel<StrippedLeaderboardDTO>());
leaderboardsTable.addColumn(leaderboardNameColumn, stringMessages.regatta());
leaderboardsTable.addColumn(overviewColumn, "");
@@ -236,12 +242,14 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
};
leaderboardsTable.addColumn(racesColumn, stringMessages.races());
}
if(leaderboardGroup.displayLeaderboardsInReverseOrder) {
leaderboardsTable.setRowData(leaderboardGroup.getLeaderboardsInReverseOrder());
} else {
leaderboardsTable.setRowData(leaderboardGroup.getLeaderboards());
}
mainPanel.add(leaderboardsTable);
flexTable.setWidget(1, 0,leaderboardsTable);
flexTable.getFlexCellFormatter().setColSpan(1, 0,2);
}
@@ -282,14 +290,13 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
}
} else {
List<RaceColumnDTO> raceColumns = leaderboard.getRaceList();
renderRacesToHTml(leaderboard.name, raceColumns, new FleetDTO("Default", 0, null), b);
renderRacesToHTml(leaderboard.name, raceColumns, new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, /* series name */ null, 0, null), b);
}
return b.toSafeHtml();
}
private void renderSeriesToHtml(StrippedLeaderboardDTO leaderboard, SeriesDTO series, boolean renderSeriesName, SafeHtmlBuilder b) {
boolean hasMultipleFleets = series.getFleets().size() > 1;
Map<String, List<RaceColumnDTO>> racesOrderedByFleets = getRacesOrderedByFleets(leaderboard);
b.appendHtmlConstant("<div style=\"float:left;\">");
if(renderSeriesName) {
b.append(TEXTTEMPLATE.textWithClass(series.name, 50, STYLE_TABLE_TEXT));
@@ -298,7 +305,6 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
b.appendHtmlConstant("<div style=\"float:left;\">");
for(FleetDTO fleet: series.getFleets()) {
Color color = fleet.getColor();
List<RaceColumnDTO> raceColumns = racesOrderedByFleets.get(fleet.name);
// show the "fleet" and the color only if there are more than one fleet in this fleet group and a color has been set
b.appendHtmlConstant("<div style=\"\">");
@@ -314,7 +320,8 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
}
}
renderRacesToHTml(leaderboard.name, raceColumns, fleet, b);
List<RaceColumnDTO> raceColumnsOfSeries = getRacesOfFleet(leaderboard, series, fleet);
renderRacesToHTml(leaderboard.name, raceColumnsOfSeries, fleet, b);
b.appendHtmlConstant("</div>");
}
@@ -329,6 +336,19 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
}
}
private List<RaceColumnDTO> getRacesOfFleet(StrippedLeaderboardDTO leaderboard, SeriesDTO series, FleetDTO fleet) {
List<RaceColumnDTO> racesColumnsOfFleet = new ArrayList<RaceColumnDTO>();
for (RaceColumnDTO raceColumn : leaderboard.getRaceList()) {
for (FleetDTO fleetOfRaceColumn : raceColumn.getFleets()) {
if(fleet.equals(fleetOfRaceColumn)) {
racesColumnsOfFleet.add(raceColumn);
}
}
}
return racesColumnsOfFleet;
}
private void renderRaceLink(String leaderboardName, RaceDTO race, boolean isLive, String raceColumnName, SafeHtmlBuilder b) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
if (race != null) {
@@ -355,24 +375,6 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
}
}
private Map<String, List<RaceColumnDTO>> getRacesOrderedByFleets(StrippedLeaderboardDTO leaderboard) {
Map<String, List<RaceColumnDTO>> racesOrderedByFleets = new LinkedHashMap<String, List<RaceColumnDTO>>();
for (RaceColumnDTO raceColumn : leaderboard.getRaceList()) {
for (FleetDTO fleet : raceColumn.getFleets()) {
List<RaceColumnDTO> raceList = racesOrderedByFleets.get(fleet.name);
if (raceList == null) {
raceList = new ArrayList<RaceColumnDTO>();
raceList.add(raceColumn);
racesOrderedByFleets.put(fleet.name, raceList);
} else {
raceList.add(raceColumn);
}
}
}
return racesOrderedByFleets;
}
private SafeHtml getAnchor(String link, String linkText, String style) {
if (isEmbedded) {
return ANCHORTEMPLATE.anchorWithTarget(link, linkText, style, "_blank");
@@ -1,6 +1,5 @@
package com.sap.sailing.gwt.ui.spectator;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Window;
@@ -78,7 +77,6 @@ public class SpectatorEntryPoint extends AbstractEntryPoint implements RegattaRe
} else {
LeaderboardGroupPanel groupPanel = new LeaderboardGroupPanel(sailingService, stringMessages, this,
groupName, root, viewModeParamValue, embedded, showRaceDetails);
groupPanel.getElement().getStyle().setFloat(Style.Float.LEFT);
groupAndFeedbackPanel.add(groupPanel);
if (!embedded) {
groupPanel.setWelcomeWidget(new SimpleWelcomeWidget(stringMessages.welcomeToSailingAnalytics(),