solved merge conlficts after ribdashboard merge

This commit is contained in:
Alexander Ries committed 2015-10-13 13:49:31 +02:00
commit 9d69655caf
826 files changed
+12737 -14630

No files matched your search

@@ -27,46 +27,6 @@
height: 100% !important;
}
.bottomnotification {
position: absolute !important;
opacity: 0.9;
background-color: #F0AB00;
height: 0pt;
line-height: 0pt;
width: 100%;
bottom: 0pt;
text-align: center;
font-size: 15pt;
line-height: 30pt;
color: black;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
z-index: 2;
}
.bottomnotificationshow {
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
/* custom */
height: 30pt;
line-height: 30pt;
}
.bottomnotificationhidden {
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
/* custom */
height: 0pt;
line-height: 0pt;
}
.eventLogo {
position: absolute;
right: 12.5px;
@@ -74,62 +34,3 @@
height: 22.5pt;
z-index: 1;
}
.wrongOrientationNotification {
position: absolute !important;
top: 50%;
right: 50%;
background-color: white;
z-index: 2;
}
.wrongOrientationNotification_shown {
width: 200px;
height: 200px;
margin-right: -100px;
margin-top: -100px;
border-radius: 100px;
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
opacity: 1.0;
}
.wrongOrientationNotification_hidden {
width: 0px;
height: 0px;
marin-right: 0px;
margin-top: 0px;
border-radius: 0px;
overflow: hidden;
-webkit-transition: all 300ms;
/* older webkit */
-webkit-transition: all 300ms;
-moz-transition: all 300ms;
-o-transition: all 300ms;
transition: all 300ms;
opacity: 0.0;
}
.wrongOrientationNotification_logo {
max-width: 40%;
max-height: 40%;
margin: 30%;
margin-top: 23%
}
.wrongOrientationNotification_text {
position: absolute;
width: 100%;
height: 14px;
top: 76%;
line-height: 10px;
text-align: center;
font-weight: bold;
font-size: 13px;
color: grey;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
}
@@ -43,5 +43,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -startupUrl /dashboards/RibDashboard.html -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9998 com.sap.sailing.dashboards.gwt.RibDashboard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m"/>
</launchConfiguration>
@@ -43,5 +43,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.dashboards.gwt}&quot; -startupUrl /dashboards/RibDashboard.html -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto com.sap.sailing.dashboards.gwt.RibDashboard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.dashboards.gwt"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m"/>
</launchConfiguration>
@@ -41,9 +41,8 @@ public class RibDashboardEntryPoint extends AbstractEntryPoint<StringMessages> {
applyMGWTSettings();
RibDashboardPanel ribDashboardPanel = new RibDashboardPanel(ribdashboardService, sailingService, dataRetriever);
RootLayoutPanel.get().add(ribDashboardPanel);
WindBotDataRetriever windBotDataRetriever = new WindBotDataRetriever(sailingService);
WindBotDataRetriever windBotDataRetriever = new WindBotDataRetriever(ribdashboardService, sailingService);
windBotDataRetriever.addNumberOfWindBotsChangeListeners(ribDashboardPanel);
dataRetriever.addRaceSelectionChangeListener(windBotDataRetriever);
Timer dashboardTimer = new Timer(PlayModes.Live);
dashboardTimer.setRefreshInterval(DASHBOARD_RERFRESH_INTERVAL);
dashboardTimer.addTimeListener(windBotDataRetriever);
@@ -2,8 +2,6 @@ package com.sap.sailing.dashboards.gwt.client;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
@@ -45,7 +43,6 @@ public class RibDashboardPanel extends Composite implements RibDashboardDataRetr
}
private static RootUiBinder uiBinder = GWT.create(RootUiBinder.class);
private static final Logger logger = Logger.getLogger(RibDashboardPanel.class.getName());
@UiField
RibDashboardPanelStyle style;
@@ -179,7 +176,6 @@ public class RibDashboardPanel extends Composite implements RibDashboardDataRetr
@Override
public void numberOfWindBotsChanged(List<String> windBotIDs,
WindBotDataRetrieverProvider windBotDataRetrieverProvider) {
logger.log(Level.INFO, "Number of Windbots changed");
initWindBotComponents(windBotIDs, windBotDataRetrieverProvider);
}
}
@@ -7,10 +7,13 @@ import com.sap.sailing.dashboards.gwt.shared.dto.RibDashboardRaceInfoDTO;
import com.sap.sailing.dashboards.gwt.shared.dto.StartlineAdvantagesWithMaxAndAverageDTO;
import com.sap.sailing.dashboards.gwt.shared.dto.startanalysis.StartAnalysisDTO;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
public interface RibDashboardService extends RemoteService {
RibDashboardRaceInfoDTO getLiveRaceInfo(String leaderboardName) throws NoWindException;
RibDashboardRaceInfoDTO getLiveRaceInfo(String leaderboardName) throws NoWindException;
RegattaAndRaceIdentifier getIDFromRaceThatTakesWindFixesNow(String leaderboardName);
List<StartAnalysisDTO> getStartAnalysisListForCompetitorIDAndLeaderboardName(String competitorIdAsString, String leaderboardName);
@@ -6,6 +6,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.dashboards.gwt.shared.dto.RibDashboardRaceInfoDTO;
import com.sap.sailing.dashboards.gwt.shared.dto.StartlineAdvantagesWithMaxAndAverageDTO;
import com.sap.sailing.dashboards.gwt.shared.dto.startanalysis.StartAnalysisDTO;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
public interface RibDashboardServiceAsync {
@@ -17,4 +18,7 @@ public interface RibDashboardServiceAsync {
void getCompetitorsInLeaderboard(String leaderboardName, AsyncCallback<List<CompetitorDTO>> callback);
void getAdvantagesOnStartline(String leaderboardName, AsyncCallback<StartlineAdvantagesWithMaxAndAverageDTO> callback);
void getIDFromRaceThatTakesWindFixesNow(String leaderboardName, AsyncCallback<RegattaAndRaceIdentifier> callback);
}
@@ -0,0 +1,26 @@
package com.sap.sailing.dashboards.gwt.client.actions;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.dashboards.gwt.client.RibDashboardServiceAsync;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sse.gwt.client.async.AsyncAction;
/**
* @author Alexander Ries (D062114)
*
*/
public class GetIDFromRaceThatTakesWindFixesNowAction implements AsyncAction<RegattaAndRaceIdentifier> {
private final RibDashboardServiceAsync ribDashboardService;
private final String leaderboardName;
public GetIDFromRaceThatTakesWindFixesNowAction(RibDashboardServiceAsync ribDashboardService, String leaderboardName) {
this.ribDashboardService = ribDashboardService;
this.leaderboardName = leaderboardName;
}
@Override
public void execute(AsyncCallback<RegattaAndRaceIdentifier> callback) {
ribDashboardService.getIDFromRaceThatTakesWindFixesNow(leaderboardName, callback);
}
}
@@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -37,6 +39,7 @@ public class RibDashboardDataRetriever implements TimeListener, RaceSelectionPro
private final Object MUTEX;
private static final String PARAM_LEADERBOARD_NAME = "leaderboardName";
private static final Logger logger = Logger.getLogger(RibDashboardDataRetriever.class.getName());
public RibDashboardDataRetriever(RibDashboardServiceAsync ribDashboardService) {
initNonFinalMemberVariablesWithNoArgumentConstructor();
@@ -74,6 +77,7 @@ public class RibDashboardDataRetriever implements TimeListener, RaceSelectionPro
@Override
public void onFailure(Throwable caught) {
logger.log(Level.INFO, caught.getMessage());
}
});
}
@@ -5,50 +5,60 @@ import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.dashboards.gwt.client.RibDashboardServiceAsync;
import com.sap.sailing.dashboards.gwt.client.actions.GetIDFromRaceThatTakesWindFixesNowAction;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.gwt.ui.actions.GetWindInfoAction;
import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.TimeListener;
public class WindBotDataRetriever implements TimeListener, RaceSelectionChangeListener, WindBotDataRetrieverProvider {
public class WindBotDataRetriever implements TimeListener, WindBotDataRetrieverProvider {
private AsyncActionsExecutor asyncActionsExecutor;
private final RibDashboardServiceAsync ribDashboardService;
private final SailingServiceAsync sailingService;
private RegattaAndRaceIdentifier currentLiveRace;
private List<NumberOfWindBotsChangeListener> numberOfWindBotsChangeListeners;
private List<WindBotDataRetrieverListener> windBotDataRetrieverListeners;
private List<String> windBotIDsInLiveRace;
private String leaderboardName;
private final Set<String> windSourceTypeNames;
private final int WIND_CHART_RESOLUTION_IN_MILLISECONDS = 5000;
private final int ONE_HOUR_IN_MILLISECONDS = 1000*60*60;
private final String LODA_WIND_CHART_DATA_CATEGORY = "loadWindChartData";
private static final String PARAM_LEADERBOARD_NAME = "leaderboardName";
private boolean didInitialLoading;
public WindBotDataRetriever(SailingServiceAsync sailingService) {
private static final Logger logger = Logger.getLogger(WindBotDataRetriever.class.getName());
public WindBotDataRetriever(RibDashboardServiceAsync ribDashboardService, SailingServiceAsync sailingService) {
this.ribDashboardService = ribDashboardService;
this.sailingService = sailingService;
currentLiveRace = null;
didInitialLoading = false;
asyncActionsExecutor = new AsyncActionsExecutor();
numberOfWindBotsChangeListeners = new ArrayList<NumberOfWindBotsChangeListener>();
windBotDataRetrieverListeners = new ArrayList<WindBotDataRetrieverListener>();
windBotIDsInLiveRace = new ArrayList<String>();
windSourceTypeNames = new HashSet<>();
this.leaderboardName = Window.Location.getParameter(PARAM_LEADERBOARD_NAME);
windSourceTypeNames.add(WindSourceType.EXPEDITION.name());
}
private void loadWindBotData(Date from, Date to, RegattaAndRaceIdentifier selectedRaceIdentifier) {
if(!didInitialLoading){
if (!didInitialLoading) {
didInitialLoading = true;
from = new Date(from.getTime()-ONE_HOUR_IN_MILLISECONDS);
}
logger.log(Level.INFO, "Executing WindInfoAction with from "+from+" and to "+to);
GetWindInfoAction getWindInfoAction = new GetWindInfoAction(sailingService, selectedRaceIdentifier, from, to,
WIND_CHART_RESOLUTION_IN_MILLISECONDS, windSourceTypeNames, /*
* onlyUpToNewestEvent==true because we don't want to
@@ -58,18 +68,22 @@ public class WindBotDataRetriever implements TimeListener, RaceSelectionChangeLi
new AsyncCallback<WindInfoForRaceDTO>() {
@Override
public void onSuccess(WindInfoForRaceDTO result) {
logger.log(Level.INFO, "Received Response from WindInfoAction");
if (result != null) {
if(windBotIDsInLiveRace.size() != getWindBotIdsFrom(result).size()){
windBotIDsInLiveRace = getWindBotIdsFrom(result);
notifyListenersAboutNumberOfWindBotChange(windBotIDsInLiveRace);
logger.log(Level.INFO, "Number of Windbots changed");
}
notifyWindBotDataRetrieverListeners(result);
} else {
logger.log(Level.INFO, "Response WindInfoForRaceDTO from WindInfoAction null");
}
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.INFO, caught.getMessage());
}
});
}
@@ -116,17 +130,20 @@ public class WindBotDataRetriever implements TimeListener, RaceSelectionChangeLi
@Override
public void timeChanged(Date newTime, Date oldTime) {
if (currentLiveRace != null) {
loadWindBotData(oldTime, newTime, currentLiveRace);
}
}
final Date finalNewTime = newTime;
final Date finaloldTime = oldTime;
GetIDFromRaceThatTakesWindFixesNowAction getIDFromRaceThatTakesWindFixesNowAction = new GetIDFromRaceThatTakesWindFixesNowAction(ribDashboardService, leaderboardName);
asyncActionsExecutor.execute(getIDFromRaceThatTakesWindFixesNowAction, new AsyncCallback<RegattaAndRaceIdentifier>() {
@Override
public void onSuccess(RegattaAndRaceIdentifier result) {
if(result != null)
loadWindBotData(finaloldTime, finalNewTime, result);
}
@Override
public void onRaceSelectionChange(List<RegattaAndRaceIdentifier> selectedRaces) {
if (selectedRaces == null) {
currentLiveRace = null;
} else if (selectedRaces.size() > 0) {
currentLiveRace = selectedRaces.get(0);
}
@Override
public void onFailure(Throwable caught) {
logger.log(Level.INFO, caught.getMessage());
}
});
}
}
@@ -3,6 +3,7 @@ package com.sap.sailing.dashboards.gwt.client.notifications;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
@@ -21,38 +22,38 @@ public class BottomNotification extends FocusPanel {
private Timer timer;
private List<BottomNotificationClickListener> bottomNotificationClickListeners;
private static NotificationsResources resources = GWT.create(NotificationsResources.class);
public BottomNotification() {
this.addStyleName("bottomnotification");
resources.notificationsStyle().ensureInjected();
this.addStyleName(resources.notificationsStyle().bottomnotification());
this.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (shown == true) {
shown = false;
BottomNotification.this.getElement().getStyle().setOpacity(1.0);
nofitifyBottomNotificationClickListenersAboutClick();
hide();
}
}
});
this.addStyleName("bottomnotification");
bottomNotificationClickListeners = new ArrayList<BottomNotificationClickListener>();
}
public void show(BottomNotificationType bottomNotificationType) {
shown = true;
this.removeStyleName("bottomnotificationhidden");
this.addStyleName("bottomnotificationshow");
this.getElement().setInnerHTML(bottomNotificationType.getMessage());
this.getElement().getStyle().setBackgroundColor(bottomNotificationType.getBackgroundColorAsHex());
this.getElement().getStyle().setColor(bottomNotificationType.getTextColorAsHex());
if (bottomNotificationType.isShouldDisappearAfter20Seconds()) {
if (shown == false) {
this.removeStyleName(resources.notificationsStyle().bottomnotification_hidden());
this.addStyleName(resources.notificationsStyle().bottomnotification_shown());
this.getElement().setInnerHTML(bottomNotificationType.getMessage());
this.getElement().getStyle().setBackgroundColor(bottomNotificationType.getBackgroundColorAsHex());
this.getElement().getStyle().setColor(bottomNotificationType.getTextColorAsHex());
Timer timer = new Timer() {
public void run() {
hide();
}
};
timer.schedule(20000);
timer.schedule(bottomNotificationType.timeToDisappearInMilliseconds());
shown = true;
}
}
@@ -60,10 +61,10 @@ public class BottomNotification extends FocusPanel {
if (timer != null) {
timer.cancel();
}
shown = false;
this.removeStyleName("bottomnotificationshow");
this.addStyleName("bottomnotificationhidden");
this.removeStyleName(resources.notificationsStyle().bottomnotification_shown());
this.addStyleName(resources.notificationsStyle().bottomnotification_hidden());
this.getElement().setInnerHTML("");
shown = false;
}
public void addBottomNotificationClickListener(BottomNotificationClickListener bottomNotificationClickListener) {
@@ -75,8 +76,8 @@ public class BottomNotification extends FocusPanel {
}
private void nofitifyBottomNotificationClickListenersAboutClick() {
for (BottomNotificationClickListener bncl : bottomNotificationClickListeners) {
bncl.bottomNotificationClicked();
for (BottomNotificationClickListener bottomNotificationClickListener : bottomNotificationClickListeners) {
bottomNotificationClickListener.bottomNotificationClicked();
}
}
}
@@ -4,18 +4,18 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
public enum BottomNotificationType {
NEW_STARTANALYSIS_AVAILABLE(StringMessages.INSTANCE.dashboardNewStartAnalysisAvailable(), "#F0AB00", "#000000", true);
NEW_STARTANALYSIS_AVAILABLE(StringMessages.INSTANCE.dashboardNewStartAnalysisAvailable(), "#F0AB00", "#000000", 20000);
private String message;
private String backgroundColorAsHex;
private String textColorAsHex;
private boolean shouldDisappearAfter20Seconds;
private int timeToDisappearInMilliseconds;
private BottomNotificationType(String message, String backgroundColorAsHex, String textColorAsHex, boolean shouldDisappearAfter20Seconds) {
private BottomNotificationType(String message, String backgroundColorAsHex, String textColorAsHex, int timeToDisappearInMilliseconds) {
this.message = message;
this.backgroundColorAsHex = backgroundColorAsHex;
this.textColorAsHex = textColorAsHex;
this.shouldDisappearAfter20Seconds = shouldDisappearAfter20Seconds;
this.timeToDisappearInMilliseconds = timeToDisappearInMilliseconds;
}
public String getMessage() {
@@ -30,7 +30,7 @@ public enum BottomNotificationType {
return textColorAsHex;
}
public boolean isShouldDisappearAfter20Seconds() {
return shouldDisappearAfter20Seconds;
public int timeToDisappearInMilliseconds() {
return timeToDisappearInMilliseconds;
}
}
@@ -0,0 +1,100 @@
@CHARSET "UTF-8";
.bottomnotification {
position: absolute !important;
opacity: 0.9;
background-color: #F0AB00;
height: 0pt;
line-height: 0pt;
width: 100%;
bottom: 0pt;
text-align: center;
font-size: 15pt;
line-height: 30pt;
color: black;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
z-index: 2;
}
.bottomnotification_shown {
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 2.650);
/* custom */
height: 30pt;
line-height: 30pt;
}
.bottomnotification_hidden {
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.650);
/* custom */
height: 0pt;
line-height: 0pt;
}
.wrongorientationnotification {
position: absolute !important;
top: 50%;
right: 50%;
background-color: white;
z-index: 2;
}
.wrongorientationnotification_shown {
width: 200px;
height: 200px;
margin-right: -100px;
margin-top: -100px;
border-radius: 100px;
-webkit-transition: all 700ms cubic-bezier(0.480, 0, 0.000, 1);
/* older webkit */
-webkit-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
-moz-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
-o-transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
transition: all 700ms cubic-bezier(0.480, -0.035, 0.000, 1.250);
opacity: 1.0;
}
.wrongorientationnotification_hidden {
width: 0px;
height: 0px;
marin-right: 0px;
margin-top: 0px;
border-radius: 0px;
overflow: hidden;
-webkit-transition: all 300ms;
/* older webkit */
-webkit-transition: all 300ms;
-moz-transition: all 300ms;
-o-transition: all 300ms;
transition: all 300ms;
opacity: 0.0;
}
.wrongorientationnotification_logo {
max-width: 40%;
max-height: 40%;
margin: 30%;
margin-top: 23%
}
.wrongorientationnotification_text {
position: absolute;
width: 100%;
height: 14px;
top: 76%;
line-height: 10px;
text-align: center;
font-weight: bold;
font-size: 13px;
color: grey;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
}
@@ -0,0 +1,25 @@
package com.sap.sailing.dashboards.gwt.client.notifications;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
/**
* @author Alexander Ries (D062114)
*
*/
public interface NotificationsResources extends ClientBundle {
@Source("Notifications.css")
NotificationsStyle notificationsStyle();
public interface NotificationsStyle extends CssResource {
public String bottomnotification();
public String bottomnotification_shown();
public String bottomnotification_hidden();
public String wrongorientationnotification();
public String wrongorientationnotification_shown();
public String wrongorientationnotification_hidden();
public String wrongorientationnotification_logo();
public String wrongorientationnotification_text();
}
}
@@ -1,5 +1,6 @@
package com.sap.sailing.dashboards.gwt.client.notifications;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
@@ -15,18 +16,21 @@ public class WrongDeviceOrientationNotification extends AbsolutePanel implements
private Label rotateDeviceLabel;
private static NotificationsResources resources = GWT.create(NotificationsResources.class);
public WrongDeviceOrientationNotification() {
super();
this.addStyleName("wrongOrientationNotification");
this.addStyleName("wrongOrientationNotification_hidden");
resources.notificationsStyle().ensureInjected();
this.addStyleName(resources.notificationsStyle().wrongorientationnotification());
this.addStyleName(resources.notificationsStyle().wrongorientationnotification_hidden());
Image rotateDeviceIcon = new Image();
rotateDeviceIcon.setResource(RibDashboardImageResources.INSTANCE.rotatedevice());
rotateDeviceIcon.getElement().addClassName("wrongOrientationNotification_logo");
rotateDeviceIcon.getElement().addClassName(resources.notificationsStyle().wrongorientationnotification_logo());
add(rotateDeviceIcon);
rotateDeviceLabel = new Label();
rotateDeviceLabel.getElement().addClassName("wrongOrientationNotification_text");
rotateDeviceLabel.getElement().addClassName(resources.notificationsStyle().wrongorientationnotification_text());
rotateDeviceLabel.setText("Rotate Device");
add(rotateDeviceLabel);
@@ -35,14 +39,14 @@ public class WrongDeviceOrientationNotification extends AbsolutePanel implements
}
public void show() {
this.removeStyleName("wrongOrientationNotification_hidden");
this.addStyleName("wrongOrientationNotification_shown");
this.removeStyleName(resources.notificationsStyle().wrongorientationnotification_hidden());
this.addStyleName(resources.notificationsStyle().wrongorientationnotification_shown());
BlurEffect.getInstance().addToView(RootLayoutPanel.get());
}
public void hide() {
this.removeStyleName("wrongOrientationNotification_shown");
this.addStyleName("wrongOrientationNotification_hidden");
this.removeStyleName(resources.notificationsStyle().wrongorientationnotification_shown());
this.addStyleName(resources.notificationsStyle().wrongorientationnotification_hidden());
BlurEffect.getInstance().removeFromView(RootLayoutPanel.get());
}
@@ -271,7 +271,7 @@ public class StartlineAnalysisComponent extends Composite implements HasWidgets
if (displaysCards == true) {
if (clickedLeft) {
if (page != 0) {
currentScrollPosition = currentScrollPosition + SCROLL_OFFSET_STARTANALYSIS_CARDS;
currentScrollPosition += SCROLL_OFFSET_STARTANALYSIS_CARDS;
page--;
startanalysis_card_container.getElement().getStyle().setLeft(currentScrollPosition, Unit.PCT);
notifyStartAnalysisPageChangeListener(page);
@@ -72,10 +72,12 @@ public class StartlineAdvantagesByWindComponent extends Composite implements Has
@Override
public void onSuccess(StartlineAdvantagesWithMaxAndAverageDTO result) {
startlineAdvantagesOnLineChart.setStartlineAdvantages(result.advantages);
advantageMaximumLiveAverage.setLiveValue(""+result.maximum);
advantageMaximumLiveAverage.setAverageValue(""+result.average);
}
if (result != null) {
startlineAdvantagesOnLineChart.setStartlineAdvantages(result.advantages);
advantageMaximumLiveAverage.setLiveValue("" + result.maximum);
advantageMaximumLiveAverage.setAverageValue("" + result.average);
}
}
});
}
@@ -2,8 +2,6 @@ package com.sap.sailing.dashboards.gwt.client.startlineadvantage;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.moxieapps.gwt.highcharts.client.Animation;
import org.moxieapps.gwt.highcharts.client.Animation.Easing;
@@ -67,7 +65,6 @@ public class StartlineAdvantagesOnLineChart extends Composite implements HasWidg
private Series series;
private static final int POINT_ADDING_ANIMATION_DURATION_IN_MILLIS = 2000;
private static final Logger logger = Logger.getLogger(StartlineAdvantagesOnLineChart.class.getName());
public StartlineAdvantagesOnLineChart() {
initWidget(uiBinder.createAndBindUi(this));
@@ -200,9 +197,6 @@ public class StartlineAdvantagesOnLineChart extends Composite implements HasWidg
}
public void setStartlineAdvantages(List<StartLineAdvantageDTO> startlineAdvantages) {
for(StartLineAdvantageDTO startLineAdvantageDTO : startlineAdvantages) {
logger.log(Level.INFO, startLineAdvantageDTO.distanceToRCBoatInMeters +" "+startLineAdvantageDTO.startLineAdvantage);
}
if (series.getPoints() != null && series.getPoints().length > 0) {
updateStartlineAdvantages(startlineAdvantages, series);
} else {
@@ -213,19 +207,8 @@ public class StartlineAdvantagesOnLineChart extends Composite implements HasWidg
}
private void updateStartlineAdvantages(List<StartLineAdvantageDTO> startlineAdvantages, Series series) {
// Series newSeries = createSeries(chart);
// addStartlineAdvantages(startlineAdvantages, newSeries);
removeAllSeriesPoints(chart.getSeries()[0]);
logger.log(Level.INFO, "SERIES: " + chart.getSeries().length);
addStartlineAdvantages(startlineAdvantages, series);
// int counter = 0;
// for (Point point : series.getPoints()) {
// if(startlineAdvantages.size() -1 > counter){
// StartLineAdvantageDTO currentNewStartlineAdvantage = startlineAdvantages.get(counter);
// series.addPoint(currentNewStartlineAdvantage.distanceToRCBoatInMeters, currentNewStartlineAdvantage.startLineAdvantage);
// counter++;
// }
// }
}
private void removeAllSeriesPoints(Series series) {
@@ -235,11 +218,10 @@ public class StartlineAdvantagesOnLineChart extends Composite implements HasWidg
}
private void addStartlineAdvantages(List<StartLineAdvantageDTO> startlineAdvantages, Series series){
//TODO Build this with forEach Consumer as soon as the bundle uses GWT 2.8 with Java 8 Support.
//TODO Build this with forEach consumer as soon as the bundle uses GWT 2.8 with Java 8 Support.
for (StartLineAdvantageDTO startlineAdvantage : startlineAdvantages) {
Point point = new Point(startlineAdvantage.distanceToRCBoatInMeters, startlineAdvantage.startLineAdvantage);
series.addPoint(point, false, false, false);
//new Animation().setDuration(POINT_ADDING_ANIMATION_DURATION_IN_MILLIS)
}
setConfidenceGradientColorToSeries(series, startlineAdvantages);
chart.redraw();
@@ -287,10 +269,7 @@ public class StartlineAdvantagesOnLineChart extends Composite implements HasWidg
lastConfidence = startlineAdvantageDTO.confidence;
double gradientPosition = getGradientStopPositionFromStartlineLenghtAndDistanceToRCBoat(lineLenght,
startlineAdvantageDTO.distanceToRCBoatInMeters);
logger.log(Level.INFO, "Confidence " + startlineAdvantageDTO.confidence + "gradientPosition"
+ gradientPosition);
color.addColorStop(gradientPosition,
getColorAsHexStringFromConfidence(startlineAdvantageDTO.confidence));
color.addColorStop(gradientPosition, getColorAsHexStringFromConfidence(startlineAdvantageDTO.confidence));
}
}
return color;
@@ -3,6 +3,8 @@ package com.sap.sailing.dashboards.gwt.client.windchart;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.moxieapps.gwt.highcharts.client.Axis.Type;
import org.moxieapps.gwt.highcharts.client.Chart;
@@ -71,6 +73,8 @@ public class VerticalWindChart extends Composite implements HasWidgets {
private static final int MAX_SERIES_POINTS = 100000000;
private static VerticalWindChartUiBinder uiBinder = GWT.create(VerticalWindChartUiBinder.class);
private static final Logger logger = Logger.getLogger(VerticalWindChart.class.getName());
interface VerticalWindChartUiBinder extends UiBinder<Widget, VerticalWindChart> {
}
@@ -194,9 +198,11 @@ public class VerticalWindChart extends Composite implements HasWidgets {
if (verticalWindChartSeries == null) {
initVerticalWindChartSeries();
verticalWindChartSeries.setPoints(points, true);
logger.log(Level.INFO, "Set Points");
} else {
for (Point point : points) {
verticalWindChartSeries.addPoint(point, true, false, false);
logger.log(Level.INFO, "Add Point");
}
}
verticalWindChartSeries.updateThreshold("" + average);
@@ -6,6 +6,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -31,6 +32,7 @@ import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -38,7 +40,6 @@ import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -89,7 +90,7 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib
}
protected RacingEventService getRacingEventService() {
return racingEventServiceTracker.getService(); // grab the service
return racingEventServiceTracker.getService();
}
private PolarDataService getPolarService() {
@@ -129,6 +130,22 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib
}
return lRInfo;
}
@Override
public RegattaAndRaceIdentifier getIDFromRaceThatTakesWindFixesNow(String leaderboardName) {
RegattaAndRaceIdentifier result = null;
if(leaderboardName != null) {
List<TrackedRace> trackedRaces = getTrackedRacesFromLeaderboard(leaderboardName);
List<TrackedRace> filteredTrackedRaces = trackedRaces.stream().filter(trackedRace -> trackedRace.takesWindFixWithTimePoint(MillisecondsTimePoint.now())).collect(Collectors.toList());
if(filteredTrackedRaces != null && filteredTrackedRaces.size() > 0) {
TrackedRace raceThatTakesWindNow = filteredTrackedRaces.get(0);
if(raceThatTakesWindNow != null) {
result = raceThatTakesWindNow.getRaceIdentifier();
}
}
}
return result;
}
private void fillLiveRaceInfoDTOWithRaceData(RibDashboardRaceInfoDTO lRInfo, TimePoint now) {
if (runningRace != null) {
@@ -164,16 +181,9 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib
for (RaceColumn column : lb.getRaceColumns()) {
for (Fleet fleet : column.getFleets()) {
TrackedRace race = column.getTrackedRace(fleet);
if (race != null) {
if (race != null && race.isLive(MillisecondsTimePoint.now())) {
result = race;
notifyLiveTrackedRaceListenerAboutLiveTrackedRaceChange(race);
TimePoint startOfRace = race.getStartOfRace();
// not relying on isLive() because the time window is too short
// to retrieve wind information we need to extend the time window
if (startOfRace != null && race.getEndOfRace() == null &&
MillisecondsTimePoint.now().after(startOfRace.minus(Duration.ONE_MINUTE.times(20)))) {
result = race;
// no break here as we want to have the last race that is deemed to be live
}
}
}
}
@@ -268,19 +278,23 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib
@Override
public List<StartAnalysisDTO> getStartAnalysisListForCompetitorIDAndLeaderboardName(String competitorIdAsString,
String leaderboardName) {
List<StartAnalysisDTO> startAnalysisDTOs = new ArrayList<StartAnalysisDTO>();
if (leaderboardName != null) {
Competitor competitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString);
List<TrackedRace> trackedRacesForLeaderBoardName = getTrackedRacesFromLeaderboard(leaderboardName);
for (TrackedRace trackedRace : trackedRacesForLeaderBoardName) {
StartAnalysisDTO startAnalysisDTO = startAnalysisCreationController
.checkStartAnalysisForCompetitorInTrackedRace(competitor, trackedRace);
if (startAnalysisDTO != null) {
startAnalysisDTOs.add(startAnalysisDTO);
List<StartAnalysisDTO> result = null;
if (competitorIdAsString != null && leaderboardName != null) {
result = new ArrayList<StartAnalysisDTO>();
try {
Competitor competitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString);
List<TrackedRace> trackedRacesForLeaderBoardName = getTrackedRacesFromLeaderboard(leaderboardName);
for (TrackedRace trackedRace : trackedRacesForLeaderBoardName) {
StartAnalysisDTO startAnalysisDTO = startAnalysisCreationController.checkStartAnalysisForCompetitorInTrackedRace(competitor, trackedRace);
if (startAnalysisDTO != null) {
result.add(startAnalysisDTO);
}
}
} catch (NullPointerException e) {
logger.log(Level.INFO, "", e);
}
}
return startAnalysisDTOs;
return result;
}
@Override
@@ -10,8 +10,8 @@ import com.sap.sse.common.TimePoint;
public abstract class AbstractStartAnalysisCreationValidator {
private static int MINIMUM_MARKPASSIINGS_AT_FIRST_MARK = 3;
private static long MINIMUM_RACE_PROGRESSION_IN_MILLISECONDS = 6*60*1000;
protected static int MINIMUM_MARKPASSIINGS_AT_FIRST_MARK = 3;
protected static long MINIMUM_RACE_PROGRESSION_IN_MILLISECONDS = 6*60*1000;
protected boolean threeCompetitorsPassedSecondWayPoint(TrackedRace trackedRace){
Waypoint secondWaypoint = trackedRace.getRace().getCourse().getFirstLeg().getTo();
@@ -45,7 +45,8 @@ public abstract class AbstractStartAnalysisCreationValidator {
}
protected boolean raceProgressedFarEnough(Competitor competitor, TrackedRace trackedRace){
if(trackedRace.isGateStart()){
final Boolean isGateStart = trackedRace.isGateStart();
if(isGateStart == Boolean.TRUE){
return gateStartGolfFlagIsDown(trackedRace);
}else{
return competitorPassedSecondWayPoint(competitor, trackedRace);
@@ -19,15 +19,16 @@ public class StartAnalysisCreationController extends AbstractStartAnalysisCreati
}
public StartAnalysisDTO checkStartAnalysisForCompetitorInTrackedRace(Competitor competitor, TrackedRace trackedRace) {
StartAnalysisDTO startAnalysisDTO;
StartAnalysisDTO result = null;
if (threeCompetitorsPassedSecondWayPoint(trackedRace) &&
raceProgressedFarEnough(competitor, trackedRace))
{
logger.log(Level.INFO, "Trigger StartAnalysisDTO creation");
startAnalysisDTO = startAnalysisDTOFactory.createStartAnalysisForCompetitorAndTrackedRace(competitor, trackedRace);
return startAnalysisDTO;
}else{
return null;
logger.log(Level.INFO, "Creating startanalysis for race "+trackedRace.getRace().getName()+" and competitor: " + competitor.getName());
result = startAnalysisDTOFactory.createStartAnalysisForCompetitorAndTrackedRace(competitor, trackedRace);
}else {
logger.log(Level.INFO, "Waiting to create startanalysis for race "+trackedRace.getRace().getName()+" and competitor: " + competitor.getName());
}
return result;
}
}
@@ -32,7 +32,6 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory;
private static int MINIMUM_NUMBER_COMPETITORS_FOR_STARTANALYSIS = 3;
private static int DEFAULT_GATE_START_INTERVALL_IN_MILLISECONDS = 5*60*1000;
private static int ONE_MINUTE_INTERVALL_IN_MILLISECONDS = 60*1000;
@@ -42,17 +41,14 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
baseDomainFactory = racingEventService.getBaseDomainFactory();
}
public StartAnalysisDTO createStartAnalysisForCompetitorAndTrackedRace(Competitor competitor,
TrackedRace trackedRace) {
public StartAnalysisDTO createStartAnalysisForCompetitorAndTrackedRace(Competitor competitor, TrackedRace trackedRace) {
StartAnalysisDTO startAnalysisDTO = new StartAnalysisDTO();
addStaticDataToStartAnalysisDTOFrom(startAnalysisDTO, trackedRace);
List<StartAnalysisCompetitorDTO> competitors = new ArrayList<StartAnalysisCompetitorDTO>();
Waypoint secondWaypoint = trackedRace.getRace().getCourse().getFirstLeg().getTo();
List<MarkPassing> markPassingsInOrder = convertMarkpPassingsIteratorToList(trackedRace.getMarkPassingsInOrder(
secondWaypoint).iterator());
List<MarkPassing> markPassingsInOrder = convertMarkpPassingsIteratorToList(trackedRace.getMarkPassingsInOrder(secondWaypoint).iterator());
boolean isCompetitorOneOfFirstThree = false;
for (int i = 0; i < MINIMUM_NUMBER_COMPETITORS_FOR_STARTANALYSIS; i++) {
for (int i = 0; i < MINIMUM_MARKPASSIINGS_AT_FIRST_MARK; i++) {
competitors.add(createStartAnalysisCompetitorDTO(trackedRace, i + 1, markPassingsInOrder.get(i).getCompetitor()));
if (markPassingsInOrder.get(i).getCompetitor().equals(competitor)) {
isCompetitorOneOfFirstThree = true;
@@ -60,17 +56,14 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
}
if (!isCompetitorOneOfFirstThree) {
int rankOfCompetitorWhilePassingSecondWaypoint = getRankOfCompetitorWhilePassingSecondWaypoint(competitor,
trackedRace);
competitors.add(createStartAnalysisCompetitorDTO(trackedRace, rankOfCompetitorWhilePassingSecondWaypoint,
competitor));
int rankOfCompetitorWhilePassingSecondWaypoint = getRankOfCompetitorWhilePassingSecondWaypoint(competitor, trackedRace);
competitors.add(createStartAnalysisCompetitorDTO(trackedRace, rankOfCompetitorWhilePassingSecondWaypoint, competitor));
}
startAnalysisDTO.competitor = baseDomainFactory.getCompetitorStore().convertToCompetitorDTO(competitor);
startAnalysisDTO.startAnalysisCompetitorDTOs = competitors;
if (trackedRace.isGateStart()) {
logger.log(Level.INFO, "IS GATESTART");
final Boolean isGateStart = trackedRace.isGateStart();
if(isGateStart == Boolean.TRUE){
logger.log(Level.INFO, "Creating startanalysis for gate start");
startAnalysisDTO.racingProcedureType = RacingProcedureType.GateStart;
long timePointOfGolfDownTime = trackedRace.getGateStartGolfDownTime();
startAnalysisDTO.timeOfStartInMilliSeconds = trackedRace.getStartOfRace().asMillis();
@@ -80,12 +73,13 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
startAnalysisDTO.tailLenghtInMilliseconds = timePointOfGolfDownTime-trackedRace.getStartOfRace().asMillis();
}
} else {
logger.log(Level.INFO, "Creating startanalysis for ess start");
startAnalysisDTO.racingProcedureType = RacingProcedureType.ESS;
startAnalysisDTO.timeOfStartInMilliSeconds = trackedRace.getStartOfRace().asMillis();
startAnalysisDTO.tailLenghtInMilliseconds = ONE_MINUTE_INTERVALL_IN_MILLISECONDS;
}
startAnalysisDTO.regattaAndRaceIdentifier = trackedRace.getRaceIdentifier();
logger.log(Level.INFO, "Created StartAnalysis For Competitor " + competitor.getName() + " and "+ trackedRace.getRace().getName());
logger.log(Level.INFO, "Created startanalysis for competitor " + competitor.getName() + " and "+ trackedRace.getRace().getName());
return startAnalysisDTO;
}
@@ -109,8 +103,7 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
return 0;
}
private StartAnalysisDTO addStaticDataToStartAnalysisDTOFrom(StartAnalysisDTO startAnalysisDTO,
TrackedRace trackedRace) {
private StartAnalysisDTO addStaticDataToStartAnalysisDTOFrom(StartAnalysisDTO startAnalysisDTO, TrackedRace trackedRace) {
startAnalysisDTO.raceName = trackedRace.getRace().getName();
startAnalysisDTO.startAnalysisWindLineInfoDTO = createStartAnalysisWindAndLineData(trackedRace);
return startAnalysisDTO;
@@ -129,7 +122,8 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
tableentry.rankAtFirstMark = rank;
tableentry.teamName = competitor.getName();
tableentry.speedAtStartTime = trackedRace.getSpeed(competitor, 1).getKnots();
if (trackedRace.isGateStart()) {
final Boolean isGateStart = trackedRace.isGateStart();
if(isGateStart == Boolean.TRUE){
tableentry.distanceToLineAtStartTime = trackedRace.getDistanceFromStarboardSideOfStartLineWhenPassingStart(
competitor).getMeters();
} else {
@@ -177,7 +171,7 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida
return StartlineAdvantageType.WIND;
}
} catch (NoWindException e) {
e.printStackTrace();
logger.log(Level.INFO, "", e);
return null;
}
}
@@ -51,42 +51,45 @@ public class StartlineAdvantagesCalculator extends AbstracPreCalculationDataRet
// Calculate duration from two new distances for normal upwind starts
// Put all durations in one set
// Get the smallest of the durations and subtract number from every other number
public StartlineAdvantagesWithMaxAndAverageDTO getStartLineAdvantagesAccrossLineAtTimePoint(TimePoint timepoint){
public StartlineAdvantagesWithMaxAndAverageDTO getStartLineAdvantagesAccrossLineAtTimePoint(TimePoint timepoint) {
StartlineAdvantagesWithMaxAndAverageDTO result = new StartlineAdvantagesWithMaxAndAverageDTO();
if (currentLiveTrackedRace != null) {
retrieveDataForCalculation(currentLiveTrackedRace);
if(isStartlineCompletelyUnderneathLaylines()) {
logger.log(Level.INFO, "Startline is completely underneath laylines");
Pair<Double, Double> advantagesRange = new Pair<Double, Double>(0.0, startlineLenghtInMeters);
result.advantages = calculateStartlineAdvantagesUnderneathLaylinesInRange(advantagesRange);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
} else if (isStartlineCompletelyAboveLaylines()) {
logger.log(Level.INFO, "Startline is completely above laylines");
Pair<Double, Double> advantagesRange = new Pair<Double, Double>(0.0, startlineLenghtInMeters);
result.advantages = calculatePolarBasedStartlineAdvantagesInRange(advantagesRange);
subtractMinimumOfAllStartlineAdvantages(result.advantages);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
subtractAgainstMaximumOfAllStartlineAdvantages(result.advantages, maximum);
} else {
logger.log(Level.INFO, "Layline(s) cross startline");
Position intersectionOfRightLaylineAndStartline = getIntersectionOfRightLaylineAndStartline();
Position intersectionOfleftLaylineAndStartline = getIntersectionOfLeftLaylineAndStartline();
Pair<Double, Double> polarBasedStartlineAdvatagesRange = getStartAndEndPointOfPolarBasedStartlineAdvatagesInDistancesToRCBoat(intersectionOfRightLaylineAndStartline, intersectionOfleftLaylineAndStartline);
Pair<Double, Double> pinEndStartlineAdvatagesRange = getPinEndStartlineAdvantagesRangeFromPolarAdvantagesRange(polarBasedStartlineAdvatagesRange);
result.advantages = calculatePolarBasedStartlineAdvantagesInRange(polarBasedStartlineAdvatagesRange);
subtractMinimumOfAllStartlineAdvantages(result.advantages);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
subtractAgainstMaximumOfAllStartlineAdvantages(result.advantages, maximum);
addClosingZeroPointToMixedAdvantages(result.advantages, pinEndStartlineAdvatagesRange);
if (wind != null) {
if (isStartlineCompletelyUnderneathLaylines()) {
logger.log(Level.INFO, "Startline is completely underneath laylines");
Pair<Double, Double> advantagesRange = new Pair<Double, Double>(0.0, startlineLenghtInMeters);
result.advantages = calculateStartlineAdvantagesUnderneathLaylinesInRange(advantagesRange);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
} else if (isStartlineCompletelyAboveLaylines()) {
logger.log(Level.INFO, "Startline is completely above laylines");
Pair<Double, Double> advantagesRange = new Pair<Double, Double>(0.0, startlineLenghtInMeters);
result.advantages = calculatePolarBasedStartlineAdvantagesInRange(advantagesRange);
subtractMinimumOfAllStartlineAdvantages(result.advantages);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
subtractAgainstMaximumOfAllStartlineAdvantages(result.advantages, maximum);
} else {
logger.log(Level.INFO, "Layline(s) cross startline");
Position intersectionOfRightLaylineAndStartline = getIntersectionOfRightLaylineAndStartline();
Position intersectionOfleftLaylineAndStartline = getIntersectionOfLeftLaylineAndStartline();
Pair<Double, Double> polarBasedStartlineAdvatagesRange = getStartAndEndPointOfPolarBasedStartlineAdvatagesInDistancesToRCBoat(
intersectionOfRightLaylineAndStartline, intersectionOfleftLaylineAndStartline);
Pair<Double, Double> pinEndStartlineAdvatagesRange = getPinEndStartlineAdvantagesRangeFromPolarAdvantagesRange(polarBasedStartlineAdvatagesRange);
result.advantages = calculatePolarBasedStartlineAdvantagesInRange(polarBasedStartlineAdvatagesRange);
subtractMinimumOfAllStartlineAdvantages(result.advantages);
double maximum = getMaximumAdvantageOfStartlineAdvantageDTOs(result.advantages);
result.maximum = maximum;
advantageMaximumAverage.add(maximum);
result.average = advantageMaximumAverage.getAverage();
subtractAgainstMaximumOfAllStartlineAdvantages(result.advantages, maximum);
addClosingZeroPointToMixedAdvantages(result.advantages, pinEndStartlineAdvatagesRange);
}
}
} else {
logger.log(Level.INFO, "No live race available for startlineadvantages calculation");
@@ -1,9 +1,5 @@
package com.sap.sailing.dashboards.gwt.server.startlineadvantages.precalculation;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.dashboards.gwt.server.startlineadvantages.StartlineAdvantagesCalculator;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.common.BoatClassMasterdata;
import com.sap.sailing.domain.common.ManeuverType;
@@ -24,26 +20,11 @@ public abstract class AbstracPreCalculationDataRetriever implements PreCalculati
public Wind wind;
public double meouvreAngle;
private static final Logger logger = Logger.getLogger(StartlineAdvantagesCalculator.class.getName());
protected void retrieveDataForCalculation(TrackedRace trackedRace) {
startlineAndFirstMarkPositions = retrieveMarkPositions(trackedRace);
startlineAdvantageAtPinEndInMeters = retrieveStartlineAdvantage(trackedRace);
startlineLenghtInMeters = retrieveStartlineLenght(trackedRace);
wind = retrieveWindAtPosition(startlineAndFirstMarkPositions.startBoatPosition, trackedRace);
meouvreAngle = retrieveManouvreAngleAtWindSpeedAndBoatClass(new BoatClassImpl("Extreme40", BoatClassMasterdata.EXTREME_40), ManeuverType.TACK, wind);
printData();
}
private void printData() {
logger.log(Level.INFO, "Retrieved pre calculation data for startline advantages calculation");
logger.log(Level.INFO, "startlineAndFirstMarkPositions.startBoatPosition "+startlineAndFirstMarkPositions.startBoatPosition);
logger.log(Level.INFO, "startlineAndFirstMarkPositions.pinEndPosition "+startlineAndFirstMarkPositions.pinEndPosition);
logger.log(Level.INFO, "startlineAndFirstMarkPositions.firstMarkPosition "+startlineAndFirstMarkPositions.firstMarkPosition);
logger.log(Level.INFO, "startlineAdvantageAtPinEndInMeters "+startlineAdvantageAtPinEndInMeters);
logger.log(Level.INFO, "startlineLenghtInMeters "+startlineLenghtInMeters);
logger.log(Level.INFO, "wind.getBeaufort() "+wind.getKnots());
logger.log(Level.INFO, "wind.getBearing().getDegrees() "+wind.getBearing().getDegrees());
logger.log(Level.INFO, "meouvreAngle.getDegrees() "+meouvreAngle);
}
}
@@ -14,14 +14,16 @@ import com.sap.sailing.domain.polars.PolarDataService;
*/
public interface PreCalculationPolarDataRetriever {
default double retrieveManouvreAngleAtWindSpeedAndBoatClass(BoatClass boatClass, ManeuverType maneuverType,
Speed windSpeed) {
default double retrieveManouvreAngleAtWindSpeedAndBoatClass(BoatClass boatClass, ManeuverType maneuverType, Speed windSpeed) {
double result = 0;
try {
BearingWithConfidence<Void> bearingWithConfidence = getPolarDataService().getManeuverAngle(boatClass, maneuverType, windSpeed);
result = bearingWithConfidence.getObject().getDegrees();
if (boatClass != null && maneuverType != null && windSpeed != null) {
BearingWithConfidence<Void> bearingWithConfidence = getPolarDataService().getManeuverAngle(boatClass, maneuverType, windSpeed);
result = bearingWithConfidence.getObject().getDegrees();
} else {
result = DefaultPolarValues.getManouvreAngle(ManeuverType.TACK);
}
} catch (NotEnoughDataHasBeenAddedException | NullPointerException e) {
result = DefaultPolarValues.getManouvreAngle(ManeuverType.TACK);
e.printStackTrace();
}
return result;
@@ -48,6 +48,7 @@
<set-property name="gwt.logging.enabled" value="TRUE" />
<set-property name="gwt.logging.logLevel" value="FINE" />
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="user.agent" value="safari" />
@@ -46,7 +46,7 @@ Bft12=Orkan
RelativeScoreInRace=Relative Wertung im Rennen (0 am besten; 1 am schlechtesten)
WindSpeedInBeaufort=Windgeschwindigkeit in Bft.
DistanceAtStart=Distanz zur Startlinie zum Startzeitpunkt
SpeedAtStart=Geschwindigkeit zum Startzeitpunkt
SpeedWhenStarting=Geschwindigkeit beim Überqueren der Startlinie
SpeedTenSecondsBeforeStart=Geschwindigkeit 10s vor dem Startzeitpunkt
RankAtFirstMark=Position beim ersten Wegpunkt
NumberOfTacks=Anzahl der Wenden
@@ -46,7 +46,7 @@ Bft12=Hurricane
RelativeScoreInRace=Relative score in race (0 best; 1 worst)
WindSpeedInBeaufort=Wind speed in Bft
DistanceAtStart=Distance to start at start
SpeedAtStart=Speed at start
SpeedWhenStarting=Speed when starting
SpeedTenSecondsBeforeStart=Speed 10s before start
RankAtFirstMark=Rank at First Mark
NumberOfTacks=Number of Tacks
@@ -20,8 +20,8 @@ public interface HasRaceOfCompetitorContext {
@Statistic(messageKey="DistanceToStarboardSideAtStart", resultDecimals=2, ordinal=1)
public Double getNormalizedDistanceToStarboardSideAtStart();
@Connector(messageKey="SpeedAtStart", ordinal=2)
public Speed getSpeedAtStart();
@Connector(messageKey="SpeedWhenStarting", ordinal=2)
public Speed getSpeedWhenStarting();
@Connector(messageKey="SpeedTenSecondsBeforeStart", ordinal=3)
public Speed getSpeedTenSecondsBeforeStart();
@@ -28,8 +28,8 @@ public class ParallelDistanceMaxAggregationProcessor extends
}
@Override
protected Distance compareValuesAndReturnNewValue(Distance previousValue, Distance newValue) {
return previousValue.getMeters() >= newValue.getMeters() ? previousValue : newValue;
protected Distance compareValuesAndReturnNewResult(Distance currentResult, Distance newValue) {
return currentResult.getMeters() >= newValue.getMeters() ? currentResult : newValue;
}
}
@@ -28,8 +28,8 @@ public class ParallelDistanceMinAggregationProcessor extends
}
@Override
protected Distance compareValuesAndReturnNewValue(Distance previousValue, Distance newValue) {
return previousValue.getMeters() <= newValue.getMeters() ? previousValue : newValue;
protected Distance compareValuesAndReturnNewResult(Distance currentResult, Distance newValue) {
return currentResult.getMeters() <= newValue.getMeters() ? currentResult : newValue;
}
}
@@ -45,8 +45,8 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
}
@Override
public Speed getSpeedAtStart() {
return getTrackedRace().getSpeed(getCompetitor(), 0);
public Speed getSpeedWhenStarting() {
return getTrackedRace().getSpeedWhenCrossingStartLine(getCompetitor());
}
@Override
@@ -13,7 +13,7 @@ import com.sap.sailing.domain.common.WindSourceType;
public class WindSourceWithAdditionalID extends WindSourceImpl {
private static final long serialVersionUID = -142955860536561690L;
private String id;
private final String id;
public WindSourceWithAdditionalID(WindSourceType type, String id) {
super(type);
@@ -79,20 +79,12 @@ public interface RaceLogTrackingAdapter {
* @see #pingMark(RaceLog, Mark, GPSFix, RacingEventService) using a random {@link PingDeviceIdentifier}
*/
void pingMark(RaceLog raceLogToAddTo, Mark mark, GPSFix gpsFix, RacingEventService service);
/**
* @see #pingMark(RaceLog, Mark, GPSFix, RacingEventService)
*/
void pingMark(RegattaLog regattaLogToAddTo, Mark mark, GPSFix gpsFix, RacingEventService service);
/**
* Duplicate the course and competitor registrations in the newest {@link RaceLogCourseDesignChangedEvent} in
* {@code from} race log to the {@code to} race logs. The {@link Mark}s and {@link ControlPoint}s are duplicated and
* not reused. This also inserts the necessary {@link RaceLogDefineMarkEvent}s into the {@code to} race logs.
*/
void copyCourseAndCompetitors(RaceLog from, Set<RaceLog> to, SharedDomainFactory baseDomainFactory,
RacingEventService service);
/**
* If not yet registered, register the competitors in {@code competitors}, and unregister all already registered
* competitors not in {@code competitors}.
@@ -107,15 +99,31 @@ public interface RaceLogTrackingAdapter {
/**
* Invite competitors for tracking via the Tracking App by sending out emails.
* @throws MailException
*
* @throws MailException
*/
void inviteCompetitorsForTrackingViaEmail(Event event, Leaderboard leaderboard,
String serverUrlWithoutTrailingSlash, Set<Competitor> competitors, Locale locale) throws MailException;
/**
* Invite buoy tenders for buoy pinging via the Buoy Tender App by sending out emails.
* @throws MailException
*
* @throws MailException
*/
void inviteBuoyTenderViaEmail(Event event, Leaderboard leaderboard, String serverUrlWithoutTrailingSlash,
String emails, Locale locale) throws MailException;
/**
* Duplicate the course in the newest {@link RaceLogCourseDesignChangedEvent} in {@code from} race log to the
* {@code to} race logs. The {@link Mark}s and {@link ControlPoint}s are duplicated and not reused. This also
* inserts the necessary {@link RaceLogDefineMarkEvent}s into the {@code to} race logs.
*/
void copyCourse(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs, SharedDomainFactory baseDomainFactory,
RacingEventService service);
/**
* Duplicate the competitor registrations from the {@code from} race log to the {@code to} race logs.
*/
void copyCompetitors(RaceLog from, Set<RaceLog> to,
RacingEventService service);
}
@@ -92,8 +92,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
}
@Override
public RaceHandle startTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet)
throws NotDenotedForRaceLogTrackingException, Exception {
public RaceHandle startTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn,
Fleet fleet) throws NotDenotedForRaceLogTrackingException, Exception {
RaceLog raceLog = raceColumn.getRaceLog(fleet);
RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze();
if (!raceLogTrackingState.isForTracking()) {
@@ -189,8 +189,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
}
private void revokeAlreadyDefinedMarks(RaceLog raceLog, AbstractLogEventAuthor author) {
List<RaceLogEvent> markEvents = new AllEventsOfTypeFinder<>(raceLog, /* only unrevoked */ true, RaceLogDefineMarkEvent.class)
.analyze();
List<RaceLogEvent> markEvents = new AllEventsOfTypeFinder<>(raceLog, /* only unrevoked */true,
RaceLogDefineMarkEvent.class).analyze();
for (RaceLogEvent event : markEvents) {
try {
raceLog.revokeEvent(author, event, "removing mark that was already defined");
@@ -201,36 +201,52 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
}
@Override
public void copyCourseAndCompetitors(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs,
SharedDomainFactory baseDomainFactory, RacingEventService service) {
public void copyCourse(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs, SharedDomainFactory baseDomainFactory,
RacingEventService service) {
CourseBase course = new LastPublishedCourseDesignFinder(fromRaceLog).analyze();
final Set<Mark> marks = new HashSet<>();
course.getWaypoints().forEach(wp->Util.addAll(wp.getMarks(), marks));
final Set<Competitor> competitors = new RegisteredCompetitorsAnalyzer<>(fromRaceLog).analyze();
final List<RaceLogEvent> raceLogDeviceMarkMappingEvents = new AllEventsOfTypeFinder<>(fromRaceLog, /* only unrevoked */ true, RaceLogDeviceMarkMappingEvent.class).analyze();
if (course != null) {
course.getWaypoints().forEach(wp -> Util.addAll(wp.getMarks(), marks));
}
final List<RaceLogEvent> raceLogDeviceMarkMappingEvents = new AllEventsOfTypeFinder<>(fromRaceLog, /*
* only
* unrevoked
*/true,
RaceLogDeviceMarkMappingEvent.class).analyze();
for (RaceLog toRaceLog : toRaceLogs) {
if (course == null || !new RaceLogTrackingStateAnalyzer(toRaceLog).analyze().isForTracking()) {
continue;
if (new RaceLogTrackingStateAnalyzer(toRaceLog).analyze().isForTracking()) {
if (course != null) {
CourseBase newCourse = new CourseDataImpl("Copy of \"" + course.getName() + "\"");
TimePoint now = MillisecondsTimePoint.now();
int i = 0;
revokeAlreadyDefinedMarks(toRaceLog, service.getServerAuthor());
for (Waypoint oldWaypoint : course.getWaypoints()) {
newCourse.addWaypoint(i++, oldWaypoint);
}
for (Mark mark : marks) {
RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDefineMarkEvent(now,
service.getServerAuthor(), toRaceLog.getCurrentPassId(), mark);
toRaceLog.add(event);
}
for (RaceLogEvent raceLogDeviceMarkMappingEvent : raceLogDeviceMarkMappingEvents) {
toRaceLog.add(raceLogDeviceMarkMappingEvent);
}
int passId = toRaceLog.getCurrentPassId();
RaceLogEvent newCourseEvent = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now,
service.getServerAuthor(), passId, newCourse);
toRaceLog.add(newCourseEvent);
}
}
CourseBase newCourse = new CourseDataImpl("Copy of \"" + course.getName() + "\"");
TimePoint now = MillisecondsTimePoint.now();
int i = 0;
revokeAlreadyDefinedMarks(toRaceLog, service.getServerAuthor());
for (Waypoint oldWaypoint : course.getWaypoints()) {
newCourse.addWaypoint(i++, oldWaypoint);
}
for (Mark mark : marks) {
RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDefineMarkEvent(now,
service.getServerAuthor(), toRaceLog.getCurrentPassId(), mark);
toRaceLog.add(event);
}
for (RaceLogEvent raceLogDeviceMarkMappingEvent : raceLogDeviceMarkMappingEvents) {
toRaceLog.add(raceLogDeviceMarkMappingEvent);
}
int passId = toRaceLog.getCurrentPassId();
RaceLogEvent newCourseEvent = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now,
service.getServerAuthor(), passId, newCourse);
toRaceLog.add(newCourseEvent);
}
}
@Override
public void copyCompetitors(RaceLog fromRaceLog, Set<RaceLog> toRaceLogs,
RacingEventService service) {
final Set<Competitor> competitors = new RegisteredCompetitorsAnalyzer<>(fromRaceLog).analyze();
for (RaceLog toRaceLog : toRaceLogs) {
registerCompetitors(service, toRaceLog, competitors);
}
}
@@ -263,13 +279,10 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
@Override
public void pingMark(RegattaLog regattaLog, Mark mark, GPSFix gpsFix, RacingEventService service) {
pingMark(
regattaLog,
mark,
gpsFix,
service,
(DeviceIdentifier dev, TimePoint timePoint) -> new RegattaLogDeviceMarkMappingEventImpl(timePoint, service
.getServerAuthor(), timePoint, UUID.randomUUID(), mark, dev, timePoint, timePoint), new PingDeviceIdentifierImpl());
pingMark(regattaLog, mark, gpsFix, service,
(DeviceIdentifier dev, TimePoint timePoint) -> new RegattaLogDeviceMarkMappingEventImpl(timePoint,
service.getServerAuthor(), timePoint, UUID.randomUUID(), mark, dev, timePoint, timePoint),
new PingDeviceIdentifierImpl());
}
@Override
@@ -415,9 +428,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
String[] emailArray = emails.split(",");
String leaderboardName = leaderboard.getName();
String eventId = event.getId().toString();
// http://<host>/buoy-tender/checkin?event_id=<event-id>&leaderboard_name=<leaderboard-name>
String url = DeviceMappingConstants.getBuoyTenderInvitationUrl(serverUrlWithoutTrailingSlash, leaderboardName,
eventId, NonGwtUrlHelper.INSTANCE);
@@ -123,8 +123,11 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
try {
checkIfSuccessfullyRevokes(revokeEvent);
lockForWrite();
revokedEventIds.add(revokeEvent.getRevokedEventId());
unlockAfterWrite();
try {
revokedEventIds.add(revokeEvent.getRevokedEventId());
} finally {
unlockAfterWrite();
}
} catch (NotRevokableException e) {
logger.log(Level.WARNING, e.getMessage());
}
@@ -133,9 +136,12 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
private void checkIfSuccessfullyRevokes(RevokeEvent<?> revokeEvent) throws NotRevokableException {
lockForRead();
EventT revokedEvent = getEventById(revokeEvent.getRevokedEventId());
unlockAfterRead();
EventT revokedEvent;
try {
revokedEvent = getEventById(revokeEvent.getRevokedEventId());
} finally {
unlockAfterRead();
}
if (revokedEvent == null) {
// it can happen that the event that has been revoked is not yet loaded - as we assume
// that race log events never get removed we can safely continue and assume that
@@ -5,7 +5,6 @@ import java.util.Collection;
import java.util.List;
import com.sap.sailing.domain.abstractlog.AbstractLog;
import com.sap.sailing.domain.abstractlog.LogAnalyzer;
import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
@@ -13,15 +12,15 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer;
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent;
import com.sap.sailing.domain.base.Mark;
public class DefinedMarkFinder extends RaceLogAnalyzer<Collection<Mark>> {
public DefinedMarkFinder(RaceLog raceLog) {
public class RaceLogDefinedMarkFinder extends RaceLogAnalyzer<Collection<Mark>> {
public RaceLogDefinedMarkFinder(RaceLog raceLog) {
super(raceLog);
}
public static class Factory implements AnalyzerFactory<Collection<Mark>> {
@Override
public LogAnalyzer<Collection<Mark>> createAnalyzer(AbstractLog<?, ?> log) {
return new DefinedMarkFinder((RaceLog) log);
public RaceLogAnalyzer<Collection<Mark>> createAnalyzer(AbstractLog<?, ?> log) {
return new RaceLogDefinedMarkFinder((RaceLog) log);
}
}
@@ -2,7 +2,7 @@ package com.sap.sailing.domain.abstractlog.shared.events;
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
import com.sap.sailing.domain.abstractlog.Revokable;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMarkFinder;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogDefinedMarkFinder;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
@@ -19,7 +19,7 @@ import com.sap.sse.common.WithID;
* If one end of the time range enclosed by {@link #getFrom()} and {@link #getTo()} is open, this can be closed
* by a {@link CloseOpenEndedDeviceMappingEvent}.
*
* @see DefinedMarkFinder for rules by which {@link DeviceMapping}s are derived from these events.
* @see RaceLogDefinedMarkFinder for rules by which {@link DeviceMapping}s are derived from these events.
* @author Fredrik Teschke
*/
public interface DeviceMappingEvent<VisitorT, ItemType extends WithID> extends AbstractLogEvent<VisitorT>, Revokable {
@@ -41,15 +41,15 @@ public class CompetitorWithID implements Competitor {
return id;
}
@Override
public String toString() {
return "CompetitorWithID [boatID=" + boatID + ", threeLetterIOCCode="
+ threeLetterIOCCode + ", name=" + name + ", id=" + id + "]";
}
@Override
public String toString() {
return "CompetitorWithID [boatID=" + boatID + ", threeLetterIOCCode=" + threeLetterIOCCode + ", name=" + name
+ ", id=" + id + "]";
}
@Override
public List<CrewMember> getCrew() {
return crew;
}
@Override
public List<CrewMember> getCrew() {
return crew;
}
}
@@ -249,12 +249,12 @@ public class DomainFactoryImpl implements DomainFactory {
private Iterable<Competitor> createCompetitorList(StartList startList, String raceId, BoatClass boatClass) {
List<Competitor> result = new ArrayList<Competitor>();
for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) {
Competitor domainCompetitor;
if(swissTimingCompetitor.getID() != null) {
Competitor domainCompetitor;
if (swissTimingCompetitor.getID() != null) {
domainCompetitor = createCompetitorWithID(swissTimingCompetitor, boatClass);
} else {
} else {
domainCompetitor = createCompetitorWithoutID(swissTimingCompetitor, raceId, boatClass);
}
}
result.add(domainCompetitor);
}
return result;
@@ -0,0 +1,348 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory;
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.common.BoatClassMasterdata;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* Tests the behavior of the class {@link CompetitorProviderFromRaceColumnsAndRegattaLike}, paying particular
* attention to its caching and cache invalidation logic. When competitors are added to regatta logs or race logs
* or when a tracked race is attached to a column or a column is added or removed, its caches need to be
* invalidated and re-calculated accordingly.
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboardTest {
private CompetitorProviderFromRaceColumnsAndRegattaLike competitorProviderFlexibleLeaderboard;
private CompetitorProviderFromRaceColumnsAndRegattaLike competitorProviderRegattaLeaderboard;
private FlexibleLeaderboardImpl flexibleLeaderboard;
private RegattaLeaderboardImpl regattaLeaderboard;
private RegattaImpl regatta;
final int NUMBER_OF_COMP_LISTS = 4;
@SuppressWarnings("unchecked")
private List<Competitor>[] compLists = (List<Competitor>[]) new List<?>[NUMBER_OF_COMP_LISTS];
@Before
public void setUp() {
final CourseAreaImpl courseArea = new CourseAreaImpl(
"Test Course Area", UUID.randomUUID());
flexibleLeaderboard = new FlexibleLeaderboardImpl("Test Flexible Leaderboard",
new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), courseArea);
competitorProviderFlexibleLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(flexibleLeaderboard);
regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE,
EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl("49er", BoatClassMasterdata._49ER), /* startDate */
null, /* endDate */null, /* trackedRegattaRegistry */null, new LowPoint(), UUID.randomUUID(),
courseArea);
regattaLeaderboard = new RegattaLeaderboardImpl(regatta, new ThresholdBasedResultDiscardingRuleImpl(new int[0]));
regatta.addSeries(new SeriesImpl("Test Series", /* isMedal */false, Arrays.asList(new FleetImpl("Yellow"),
new FleetImpl("Blue")), Arrays.asList("R1", "R2", "R3"), /* trackedRegattaRegistry */null));
for (int l = 0; l < NUMBER_OF_COMP_LISTS; l++) {
compLists[l] = new ArrayList<Competitor>();
for (int i = 0; i < 10; i++) {
compLists[l].add(createCompetitor("" + l + "/" + i));
}
}
competitorProviderRegattaLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard);
}
@Test
public void testSimpleCompetitorListOnOneRaceInFlexibleLeaderboard() {
TrackedRace trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[0]);
flexibleLeaderboard.addRace(trackedRace, "R1", /* medalRace */ false);
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRace = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
assertEquals(expected, actualForRace);
}
@Test
public void testSimpleCompetitorListOnOneRaceLogInFlexibleLeaderboard() {
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME);
final int passId = 1;
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
final Map<Competitor, RaceLogRegisterCompetitorEvent> competitorOnRaceLogRegistrationEvents = new HashMap<>();
for (Competitor c : compLists[0]) {
final RaceLogRegisterCompetitorEvent registerCompetitorEvent = RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), author, passId, c);
raceLog.add(registerCompetitorEvent);
competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent);
}
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRace = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
assertEquals(expected, actualForRace);
// we're now revoking a competitor registration on the race log and assert
// that the competitor is gone from the list:
final Competitor competitorToRevokeFromRaceLog = compLists[0].get(2);
raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking"));
actualForRace = new HashSet<>(); // try another time; cache should of course yield an equal result (although
// we're not asserting here that the result actually comes from the cache)
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
expected.remove(competitorToRevokeFromRaceLog);
assertEquals(expected.size(), actualForRace.size());
assertEquals(expected, actualForRace);
flexibleLeaderboard.removeRaceColumn("R1"); // test that changes to the race columns invalidate the cache
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
actualForRace = new HashSet<>(); // try another time; cache should of course yield an equal result (although
// we're not asserting here that the result actually comes from the cache)
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
assertTrue(actualForRace.isEmpty());
}
@Test
public void testSimpleCompetitorListOnRegattaLogInFlexibleLeaderboard() {
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog();
for (Competitor c : compLists[0]) {
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), MillisecondsTimePoint.now(), UUID.randomUUID(), c));
}
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRace = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
assertEquals(expected, actualForRace);
}
@Test
public void testSimpleCompetitorListOnOneRaceLogAndRegattaLogInFlexibleLeaderboard() {
flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false);
RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog();
for (Competitor c : compLists[0]) {
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), MillisecondsTimePoint.now(), UUID.randomUUID(), c));
}
RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME);
for (Competitor c : compLists[1]) {
raceLog.add(RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c));
}
Set<Competitor> expected = new HashSet<>(compLists[0]);
expected.addAll(compLists[1]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRace = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace);
assertEquals(expected, actualForRace);
}
@Test
public void testTwoCompetitorListsOnTwoRacesInFlexibleLeaderboard() {
TrackedRace trackedRace1 = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[0]);
flexibleLeaderboard.addRace(trackedRace1, "R1", /* medalRace */ false);
TrackedRace trackedRace2 = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[1]);
flexibleLeaderboard.addRace(trackedRace2, "R2", /* medalRace */ false);
Set<Competitor> expected = new HashSet<>(compLists[0]);
expected.addAll(compLists[1]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRace1 = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R1"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace1);
Set<Competitor> actualForRace2 = new HashSet<>();
Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors(
flexibleLeaderboard.getRaceColumnByName("R2"),
flexibleLeaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), actualForRace2);
assertEquals(new HashSet<>(compLists[0]), actualForRace1);
assertEquals(new HashSet<>(compLists[1]), actualForRace2);
}
@Test
public void testSimpleCompetitorListOnOneRaceInRegattaLeaderboard() {
TrackedRace trackedRace = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[0]);
regattaLeaderboard.getRaceColumnByName("R1").setTrackedRace(regattaLeaderboard.getRaceColumnByName("R1").getFleetByName("Yellow"), trackedRace);
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRaceYellow = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(expected, actualForRaceYellow);
Set<Competitor> actualForRaceBlue = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Blue")), actualForRaceBlue);
assertEquals(Collections.emptySet(), actualForRaceBlue);
}
@Test
public void testTwoCompetitorListsOnTwoRacesInRegattaLeaderboard() {
TrackedRace trackedRace1 = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[0]);
regattaLeaderboard.getRaceColumnByName("R1").setTrackedRace(regattaLeaderboard.getRaceColumnByName("R1").getFleetByName("Yellow"), trackedRace1);
TrackedRace trackedRace2 = new MockedTrackedRaceWithStartTimeAndRanks(MillisecondsTimePoint.now(), compLists[1]);
regattaLeaderboard.getRaceColumnByName("R1").setTrackedRace(regattaLeaderboard.getRaceColumnByName("R1").getFleetByName("Blue"), trackedRace2);
Set<Competitor> expected = new HashSet<>(compLists[0]);
expected.addAll(compLists[1]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRaceYellow = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(new HashSet<>(compLists[0]), actualForRaceYellow);
Set<Competitor> actualForRaceBlue = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Blue")), actualForRaceBlue);
assertEquals(new HashSet<>(compLists[1]), actualForRaceBlue);
}
@Test
public void testSimpleCompetitorListOnOneRaceLogInRegattaLeaderboard() {
RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow");
for (Competitor c : compLists[0]) {
raceLog.add(RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c));
}
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRaceYellow = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(new HashSet<>(compLists[0]), actualForRaceYellow);
}
@Test
public void testSimpleCompetitorListOnRegattaLogInRegattaLeaderboard() throws NotRevokableException {
RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog();
final Map<Competitor, RegattaLogRegisterCompetitorEvent> competitorOnRegattaLogRegistrationEvents = new HashMap<>();
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
for (Competitor c : compLists[0]) {
final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), c);
regattaLog.add(registerCompetitorEvent);
competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent);
}
Set<Competitor> expected = new HashSet<>(compLists[0]);
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualForRaceYellow = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(new HashSet<>(compLists[0]), actualForRaceYellow);
Set<Competitor> actualForRaceBlue = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Blue")), actualForRaceBlue);
assertEquals(new HashSet<>(compLists[0]), actualForRaceBlue);
// now revoke one registration again from the regatta log
final Competitor competitorToRevokeFromRegattaLog = compLists[0].get(2);
regattaLog.revokeEvent(author, competitorOnRegattaLogRegistrationEvents.get(competitorToRevokeFromRegattaLog));
actualForRaceYellow = new HashSet<>(); // try another time; cache should of course yield an equal result (although
// we're not asserting here that the result actually comes from the cache)
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
expected.remove(competitorToRevokeFromRegattaLog);
assertEquals(expected.size(), actualForRaceYellow.size());
assertEquals(expected, actualForRaceYellow);
}
@Test
public void testSimpleCompetitorListOnOneRaceLogAndRegattaLogInRegattaLeaderboard() {
final RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog();
final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0);
for (Competitor c : compLists[0]) {
regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), c));
}
final RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow");
final int passId = 1;
final Map<Competitor, RaceLogRegisterCompetitorEvent> competitorOnRaceLogRegistrationEvents = new HashMap<>();
for (Competitor c : compLists[passId]) {
final RaceLogRegisterCompetitorEvent registerCompetitorEvent = RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), author, passId, c);
raceLog.add(registerCompetitorEvent);
competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent);
}
regattaLeaderboard.setSuppressed(compLists[0].get(compLists[0].size()-passId), /* suppressed */ true);
Set<Competitor> expected = new HashSet<>(compLists[0]);
expected.addAll(compLists[passId]);
Set<Competitor> expectedWithoutSuppressed = new HashSet<>(expected);
expectedWithoutSuppressed.remove(compLists[0].get(compLists[0].size()-passId));
Set<Competitor> actual = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(), actual);
assertEquals(expected, actual);
Set<Competitor> actualWithoutSuppressed = new HashSet<>();
Util.addAll(regattaLeaderboard.getCompetitors(), actualWithoutSuppressed);
assertEquals(expectedWithoutSuppressed, actualWithoutSuppressed);
Set<Competitor> actualForRaceYellow = new HashSet<>();
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(expected, actualForRaceYellow);
actualForRaceYellow = new HashSet<>(); // try another time; cache should of course yield an equal result (although
// we're not asserting here that the result actually comes from the cache)
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
assertEquals(expected, actualForRaceYellow);
// But now it gets interesting: we're revoking a competitor registration on the race log and assert
// that the competitor is gone from the list:
final Competitor competitorToRevokeFromRaceLog = compLists[passId].get(2);
raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking"));
actualForRaceYellow = new HashSet<>(); // try another time; cache should of course yield an equal result (although
// we're not asserting here that the result actually comes from the cache)
Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors(
regattaLeaderboard.getRaceColumnByName("R1"), regattaLeaderboard.getFleet("Yellow")), actualForRaceYellow);
expected.remove(competitorToRevokeFromRaceLog);
assertEquals(expected.size(), actualForRaceYellow.size());
assertEquals(expected, actualForRaceYellow);
}
}
@@ -95,8 +95,8 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
flexibleLeaderboard.addRace(trackedRace, RACECOLUMN_FLEXIBLELEADERBOARD+"2", false);
Wind wind = new WindImpl(new DegreePosition(12, 13), startOfSecondRace.plus(Duration.ONE_MINUTE), new KnotSpeedWithBearingImpl(
/* speedInKnots */18, new DegreeBearingImpl(185)));
assertTrue(previousTrackedRace.takesWindFix(wind)); // previous race has tracking still open and takes the fix
assertTrue(trackedRace.takesWindFix(wind)); // tracked race also needs to take the fix as it falls into the regular tracking interval
assertTrue(previousTrackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // previous race has tracking still open and takes the fix
assertTrue(trackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // tracked race also needs to take the fix as it falls into the regular tracking interval
}
@Test
@@ -117,8 +117,8 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
Wind wind = new WindImpl(new DegreePosition(12, 13),
endOfFirstRace.plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).plus(Duration.ONE_MINUTE), // fix is after the grace period
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)));
assertFalse(previousTrackedRace.takesWindFix(wind)); // previous race has tracking closed one second after it started and doesn't accept the fix
assertTrue(trackedRace.takesWindFix(wind)); // tracked race also needs to take the fix as it falls into the regular tracking interval
assertFalse(previousTrackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // previous race has tracking closed one second after it started and doesn't accept the fix
assertTrue(trackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // tracked race also needs to take the fix as it falls into the regular tracking interval
}
@Test
@@ -134,7 +134,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
Wind wind = new WindImpl(new DegreePosition(12, 13),
endOfFirstRace.plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).plus(Duration.ONE_MINUTE), // fix is after the grace period
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)));
assertTrue(trackedRace.takesWindFix(wind));
assertTrue(trackedRace.takesWindFixWithTimePoint(wind.getTimePoint()));
}
@Test
@@ -154,8 +154,8 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
Wind wind = new WindImpl(new DegreePosition(12, 13),
endOfFirstRace.plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).plus(Duration.ONE_MINUTE), // fix is after the grace period
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)));
assertFalse(previousTrackedRace.takesWindFix(wind)); // fix is after first race's end plus grace period
assertFalse(trackedRace.takesWindFix(wind));
assertFalse(previousTrackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // fix is after first race's end plus grace period
assertFalse(trackedRace.takesWindFixWithTimePoint(wind.getTimePoint()));
}
@Test
@@ -175,8 +175,8 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
Wind wind = new WindImpl(new DegreePosition(12, 13),
startOfFirstRace.plus(Duration.ONE_SECOND), // fix is recorded by previous race
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)));
assertTrue(previousTrackedRace.takesWindFix(wind)); // fix is after first race's end plus grace period
assertFalse(trackedRace.takesWindFix(wind));
assertTrue(previousTrackedRace.takesWindFixWithTimePoint(wind.getTimePoint())); // fix is after first race's end plus grace period
assertFalse(trackedRace.takesWindFixWithTimePoint(wind.getTimePoint()));
}
@Test
@@ -244,9 +244,9 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
r2.setTrackedRace(fleet, tr1);
r3.setTrackedRace(fleet, tr2);
r4.setTrackedRace(fleet, tr3); // produce a cycle because now transitively tr1 has itself as a predecessor
assertTrue(tr3.takesWindFix(new WindImpl(new DegreePosition(12, 13),
assertTrue(tr3.takesWindFixWithTimePoint(new WindImpl(new DegreePosition(12, 13),
startOfThirdRace.minus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.divide(2)),
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)))));
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185))).getTimePoint()));
}
/**
@@ -265,9 +265,9 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest
final TrackedRace tr1 = createTrackedRace("FirstRace", startOfFirstRace, endOfFirstRace);
r1.setTrackedRace(fleet, tr1);
r2.setTrackedRace(fleet, tr1);
assertTrue(tr1.takesWindFix(new WindImpl(new DegreePosition(12, 13),
assertTrue(tr1.takesWindFixWithTimePoint(new WindImpl(new DegreePosition(12, 13),
startOfFirstRace.minus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.divide(2)),
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185)))));
new KnotSpeedWithBearingImpl(/* speedInKnots */18, new DegreeBearingImpl(185))).getTimePoint()));
}
private DynamicTrackedRace createTrackedRace(final String name, final TimePoint startOfRace, final TimePoint endOfRace) {
@@ -49,6 +49,7 @@ import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.ranking.RankingMetric;
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
import com.sap.sailing.domain.regattalike.IsRegattaLike;
import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
import com.sap.sailing.domain.regattalike.RegattaLikeListener;
import com.sap.sailing.domain.tracking.CourseDesignChangedListener;
@@ -471,6 +472,21 @@ public class MockedTrackedRace implements DynamicTrackedRace {
public RaceColumn getRaceColumnByName(String raceColumnName) {
return null;
}
@Override
public IsRegattaLike getRegattaLike() {
return null;
}
@Override
public RaceLog getRacelog(String raceColumnName, String fleetName) {
return null;
}
@Override
public Iterable<? extends RaceColumn> getRaceColumns() {
return null;
}
};
}
@@ -28,7 +28,6 @@ import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.Person;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Sideline;
@@ -105,8 +104,6 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<com.sap.sse.common.Util.Pair<String, UUID>, DynamicPerson> personCache = new HashMap<>();
private final Map<Serializable, DynamicTeam> teamCache = new HashMap<>();
/**
* Caches regattas by their name and their boat class's name
*/
@@ -262,7 +259,7 @@ public class DomainFactoryImpl implements DomainFactory {
nationality = null;
logger.log(Level.SEVERE, "Unknown nationality "+nationalityAsString+" for competitor "+name+"; leaving null", iae);
}
DynamicTeam team = getOrCreateTeam(name, nationality, competitorId);
DynamicTeam team = createTeam(name, nationality, competitorId);
DynamicBoat boat = new BoatImpl(shortName, boatClass, shortName);
result = competitorStore.getOrCreateCompetitor(competitorId, name, null /* displayColor */,
null /* email */, null /* flagImag */, team, boat, (double) timeOnTimeFactor,
@@ -271,27 +268,15 @@ public class DomainFactoryImpl implements DomainFactory {
return result;
}
/**
* If a team called <code>name</code> already is known by this domain factory, it is returned. Otherwise, the team name
* is split along "+" signs with one {@link Person} object created for each part. If an existing team is found, its
* nationality will be updated to match <code>nationality</code>.
*/
private DynamicTeam getOrCreateTeam(String name, Nationality nationality, UUID competitorId) {
synchronized (teamCache) {
DynamicTeam result = teamCache.get(competitorId);
if (result == null) {
String[] sailorNames = name.split("\\b*\\+\\b*");
List<DynamicPerson> sailors = new ArrayList<DynamicPerson>();
for (String sailorName : sailorNames) {
sailors.add(getOrCreatePerson(sailorName.trim(), nationality, competitorId));
}
result = new TeamImpl(name, sailors, /* TODO coach not known */null);
teamCache.put(competitorId, result);
} else {
result.setNationality(nationality);
}
return result;
private DynamicTeam createTeam(String name, Nationality nationality, UUID competitorId) {
DynamicTeam result;
String[] sailorNames = name.split("\\b*\\+\\b*");
List<DynamicPerson> sailors = new ArrayList<DynamicPerson>();
for (String sailorName : sailorNames) {
sailors.add(getOrCreatePerson(sailorName.trim(), nationality, competitorId));
}
result = new TeamImpl(name, sailors, /* TODO coach not known */null);
return result;
}
@Override
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.base;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
@@ -227,4 +228,18 @@ public interface RaceColumn extends Named {
boolean hasSplitFleets();
RaceExecutionOrderProvider getRaceExecutionOrderProvider();
/**
* Provides the combined set of competitors from all {@link #getTrackedRace(Fleet) tracked races attached to this
* column} or, in case a fleet does not have a tracked race attached, the competitors registered through the
* respective {@link RaceLog} {@link #getRaceLog(Fleet) attached to this column for that fleet}. Note that this does
* not include competitors registered through any {@link RegattaLog} on the structure owning (directly or
* transitively) this column.
*/
Iterable<Competitor> getAllCompetitors();
/**
* Same as {@link #getAllCompetitors()}, but restricted to the single race identified by the <code>fleet</code> parameter.
*/
Iterable<Competitor> getAllCompetitors(Fleet fleet);
}
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.RankingMetrics;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
import com.sap.sailing.domain.ranking.RankingMetricsFactory;
@@ -22,7 +23,7 @@ import com.sap.sse.common.WithID;
* @author Axel Uhl (d043530)
*
*/
public interface Regatta extends Named, WithID, IsRegattaLike {
public interface Regatta extends Named, WithID, IsRegattaLike, HasRaceColumnsAndRegattaLike {
ScoringScheme getScoringScheme();
/**
@@ -3,11 +3,14 @@ package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
@@ -117,9 +120,9 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
@Override
public Fleet getFleetOfCompetitor(Competitor competitor) {
for (Map.Entry<Fleet, TrackedRace> e : trackedRaces.entrySet()) {
if (Util.contains(e.getValue().getRace().getCompetitors(), competitor)) {
return e.getKey();
for (final Fleet fleet : getFleets()) {
if (Util.contains(getAllCompetitors(fleet), competitor)) {
return fleet;
}
}
return null;
@@ -206,4 +209,41 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
public void setMasterDataExportOngoingThreadFlag(boolean flagValue) {
trackedRaces.setMasterDataExportOngoingThreadFlag(flagValue);
}
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<>();
for (Fleet fleet : getFleets()) {
TrackedRace trackedRace = getTrackedRace(fleet);
if (trackedRace != null) {
Util.addAll(trackedRace.getRace().getCompetitors(), result);
} else {
// if no tracked race is found, use competitors from race log; this assumes that if a tracked
// race exists, its competitors set takes precedence over what's in the race log. Usually,
// the tracked race will have the same competitors as those in the race log, or more because
// those from the regatta log are added to the tracked race as well.
Set<Competitor> viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze();
result.addAll(viaRaceLog);
}
}
return result;
}
@Override
public Iterable<Competitor> getAllCompetitors(final Fleet fleet) {
final Iterable<Competitor> result;
TrackedRace trackedRace = getTrackedRace(fleet);
if (trackedRace != null) {
result = trackedRace.getRace().getCompetitors();
} else {
// if no tracked race is found, use competitors from race log; this assumes that if a tracked
// race exists, its competitors set takes precedence over what's in the race log. Usually,
// the tracked race will have the same competitors as those in the race log, or more because
// those from the regatta log are added to the tracked race as well.
Set<Competitor> viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze();
result = viaRaceLog;
}
return result;
}
}
@@ -16,9 +16,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
@@ -40,6 +40,7 @@ import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.leaderboard.ResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
@@ -111,6 +112,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
* Defaults to <code>true</code>. See {@link Regatta#useStartTimeInference()}.
*/
private boolean useStartTimeInference;
private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider;
/**
* Constructs a regatta with an empty {@link RaceLogStore}.
@@ -171,7 +174,6 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
* @param series
* all {@link Series} in this iterable will have their {@link Series#setRegatta(Regatta) regatta set} to
* this new regatta.
* @param rankingMetricConstructor TODO
*/
public <S extends Series> RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<S> series, boolean persistent, ScoringScheme scoringScheme,
@@ -363,24 +365,15 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<Competitor>();
if (competitorsProvider == null) {
competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this);
}
Util.addAll(competitorsProvider.getAllCompetitors(), result);
for (RaceDefinition race : getAllRaces()) {
for (Competitor c : race.getCompetitors()) {
result.add(c);
}
}
for (Series series : getSeries()) {
for (RaceColumn rc : series.getRaceColumns()) {
for (Fleet fleet : rc.getFleets()) {
TrackedRace trackedRace = rc.getTrackedRace(fleet);
if (trackedRace != null) {
Util.addAll(trackedRace.getRace().getCompetitors(), result);
}
}
}
}
//consider {@link RegattaLog}
Set<Competitor> viaLog = new RegisteredCompetitorsAnalyzer<>(regattaLikeHelper.getRegattaLog()).analyze();
result.addAll(viaLog);
return result;
}
@@ -700,4 +693,37 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
public RaceColumn getRaceColumnByName(String raceColumnName) {
return regattaLikeHelper.getRaceColumnByName(raceColumnName);
}
@Override
public IsRegattaLike getRegattaLike() {
return this;
}
@Override
public RaceLog getRacelog(String raceColumnName, String fleetName) {
final RaceLog result;
final RaceColumn raceColumn = getRaceColumnByName(raceColumnName);
if (raceColumn == null) {
result = null;
} else {
final Fleet fleet = raceColumn.getFleetByName(fleetName);
if (fleet == null) {
result = null;
} else {
result = raceColumn.getRaceLog(fleet);
}
}
return result;
}
@Override
public Iterable<? extends RaceColumn> getRaceColumns() {
final List<RaceColumnInSeries> result = new ArrayList<>();
for (final Series series : getSeries()) {
for (final RaceColumnInSeries rc : series.getRaceColumns()) {
result.add(rc);
}
}
return result;
}
}
@@ -0,0 +1,12 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
public interface HasRaceColumns {
Iterable<? extends RaceColumn> getRaceColumns();
void addRaceColumnListener(RaceColumnListener listener);
void removeRaceColumnListener(RaceColumnListener listener);
}
@@ -0,0 +1,7 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.regattalike.HasRegattaLike;
public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceColumns {
}
@@ -44,7 +44,7 @@ import com.sap.sse.common.Util;
* @author Axel Uhl (d043530)
*
*/
public interface Leaderboard extends LeaderboardBase {
public interface Leaderboard extends LeaderboardBase, HasRaceColumns {
/**
* If the leaderboard is a "matrix" with the cells being defined by a competitor / race "coordinate,"
* then this interface defines the structure of the "cells."
@@ -93,6 +93,22 @@ public interface Leaderboard extends LeaderboardBase {
* @return all competitors in this leaderboard, including the suppressed ones.
*/
Iterable<Competitor> getAllCompetitors();
/**
* Retrieves all competitors expected to race in the fleet and column specified.
* When a {@link TrackedRace} is {@link RaceColumn#getTrackedRace(Fleet) attached} to the race
* column for the <code>fleet</code> specified, its competitor set is returned. Otherwise,
* the competitors are collected from any other information, such as a regatta log and/or the
* race log for the combination of race column and fleet or, in case of a meta-leaderboard,
* from the leaderboard represented by the race column.
*/
Iterable<Competitor> getAllCompetitors(RaceColumn raceColumn, Fleet fleet);
/**
* Same as {@link #getAllCompetitors(RaceColumn, Fleet)} with competitors from {@link #getSuppressedCompetitors()}
* removed
*/
Iterable<Competitor> getCompetitors(RaceColumn raceColumn, Fleet fleet);
/**
* Convenience method which returns the difference between {@link #getAllCompetitors()} and {@link #getCompetitors()}.
@@ -247,7 +263,7 @@ public interface Leaderboard extends LeaderboardBase {
* Sums up the {@link #getTotalPoints(Competitor, TrackedRace, TimePoint) total points} of <code>competitor</code>
* across all races tracked by this leaderboard, respecting the {@link RaceColumn#isStartsWithZeroScore()} property.
*/
Double getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException;
Double getTotalPoints(Competitor competitor, TimePoint timePoint);
/**
* Sums up the {@link #getTotalPoints(Competitor, RaceColumn, TimePoint) total points} of <code>competitor</code>
@@ -8,7 +8,6 @@ import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorChangeListener;
import com.sap.sailing.domain.base.Fleet;
@@ -16,9 +15,9 @@ import com.sap.sailing.domain.base.Nationality;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.WithNationality;
import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.caching.LeaderboardCache;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
@@ -262,9 +261,14 @@ public class LeaderboardCacheManager {
leaderboard.getScoreCorrection().addScoreCorrectionListener(scoreCorrectionListener);
scoreCorrectionListeners.put(leaderboard, scoreCorrectionListener);
competitorChangeListeners.put(leaderboard, competitorChangeListener);
final RaceColumnListener raceColumnListener = new RaceColumnListener() {
final RaceColumnListener raceColumnListener = new RaceColumnListenerWithDefaultAction() {
private static final long serialVersionUID = 8165124797028386317L;
@Override
public void defaultAction() {
removeFromCache(leaderboard);
}
@Override
public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
removeFromCache(leaderboard);
@@ -278,70 +282,6 @@ public class LeaderboardCacheManager {
public boolean isTransient() {
return true;
}
@Override
public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
removeFromCache(leaderboard); // removes all listeners from invalidationListenersPerLeaderboard and from their TrackedRaces
}
@Override
public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) {
removeFromCache(leaderboard);
}
@Override
public void isStartsWithZeroScoreChanged(RaceColumn raceColumn, boolean newIsStartsWithZeroScore) {
removeFromCache(leaderboard);
}
@Override
public void hasSplitFleetContiguousScoringChanged(RaceColumn raceColumn, boolean hasSplitFleetContiguousScoring) {
removeFromCache(leaderboard);
}
@Override
public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn,
boolean firstColumnIsNonDiscardableCarryForward) {
removeFromCache(leaderboard);
}
@Override
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
removeFromCache(leaderboard);
}
@Override
public void raceColumnRemovedFromContainer(RaceColumn raceColumn) {
removeFromCache(leaderboard);
}
@Override
public void raceColumnMoved(RaceColumn raceColumn, int newIndex) {
removeFromCache(leaderboard);
}
@Override
public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) {
removeFromCache(leaderboard);
}
@Override
public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule,
ResultDiscardingRule newDiscardingRule) {
removeFromCache(leaderboard);
}
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName,
String displayName) {
removeFromCache(leaderboard);
}
@Override
public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier,
RaceLogEvent event) {
removeFromCache(leaderboard);
}
};
leaderboard.addRaceColumnListener(raceColumnListener);
synchronized (raceColumnListeners) {
@@ -12,9 +12,9 @@ import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.leaderboard.ScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.regattalike.HasRegattaLike;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
@@ -28,14 +28,14 @@ import com.sap.sse.common.TimePoint;
* @author Axel Uhl (D043530)
*
*/
public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardImpl implements HasRegattaLike{
public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardImpl implements HasRaceColumnsAndRegattaLike {
private static final long serialVersionUID = -328091952760083438L;
/**
* Cache for the combined competitors of this leaderboard; taken from the {@link TrackedRace#getRace() races of the
* tracked races} associated with this leaderboard. Updated when the set of tracked races changes.
*/
private transient Iterable<Competitor> allCompetitorsCache;
private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider;
/**
* @param scoreComparator the comparator to use to compare basic scores, such as net points
@@ -77,20 +77,21 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
*/
@Override
public Iterable<Competitor> getAllCompetitors() {
if (allCompetitorsCache == null) {
Set<Competitor> result = new HashSet<Competitor>();
synchronized (this) {
for (TrackedRace r : getTrackedRaces()) {
for (Competitor c : r.getRace().getCompetitors()) {
result.add(c);
}
}
}
allCompetitorsCache = result;
}
return allCompetitorsCache;
return getOrCreateCompetitorsProvider().getAllCompetitors();
}
@Override
public Iterable<Competitor> getAllCompetitors(RaceColumn raceColumn, Fleet fleet) {
return getOrCreateCompetitorsProvider().getAllCompetitors(raceColumn, fleet);
}
private CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() {
if (competitorsProvider == null) {
competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this);
}
return competitorsProvider;
}
@Override
public Competitor getCompetitorByIdAsString(String idAsString) {
for (Competitor competitor : getAllCompetitors()) {
@@ -144,18 +145,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
return correctedRank;
}
@Override
public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
allCompetitorsCache = null;
super.trackedRaceLinked(raceColumn, fleet, trackedRace);
}
@Override
public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
allCompetitorsCache = null;
super.trackedRaceUnlinked(raceColumn, fleet, trackedRace);
}
// Note: no need to redefine isMedalRaceChanged because that doesn't affect the competitorsCache
@Override
@@ -182,4 +171,5 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI
Fleet fleet = raceColumn.getFleetByName(fleetName);
return raceColumn.getRaceLog(fleet);
}
}
@@ -12,7 +12,6 @@ import java.util.Set;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -182,8 +181,7 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
}
@Override
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2,
TimePoint timePoint) throws NoWindException {
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint) {
return 0;
}
}
@@ -14,6 +14,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
@@ -516,13 +517,13 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
}
@Override
public Double getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
public Double getTotalPoints(Competitor competitor, TimePoint timePoint) {
return getTotalPoints(competitor, getRaceColumns(), timePoint);
}
@Override
public Double getTotalPoints(Competitor competitor, final Iterable<RaceColumn> raceColumnsToConsider,
TimePoint timePoint) throws NoWindException {
TimePoint timePoint) {
// when a column with isStartsWithZeroScore() is found, only reset score if the competitor scored in any race from there on
boolean needToResetScoreUponNextNonEmptyEntry = false;
double result = getCarriedPoints(competitor);
@@ -720,11 +721,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
public Map<Competitor, Double> call() {
Map<Competitor, Double> totalPointsSumPerCompetitorInColumn = new HashMap<>();
for (Competitor competitor : getCompetitors()) {
try {
totalPointsSumPerCompetitorInColumn.put(competitor, getTotalPoints(competitor, finalRaceColumnsToConsider, timePoint));
} catch (NoWindException e) {
throw new NoWindError(e);
}
totalPointsSumPerCompetitorInColumn.put(competitor, getTotalPoints(competitor, finalRaceColumnsToConsider, timePoint));
}
synchronized (result) {
return totalPointsSumPerCompetitorInColumn;
@@ -1096,31 +1093,69 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
@Override
public Iterable<Competitor> getCompetitors() {
// TODO bug 1348: try to cache result; invalidation would have to listen for columns added and suppression changing;
// for meta-leaderbaords, transitive listening to those events would be necessary.
Set<Competitor> result = new HashSet<>();
for (Competitor competitor : getAllCompetitors()) {
if (!isSuppressed(competitor)) {
result.add(competitor);
}
final Iterable<Competitor> result;
// mostly the set of suppressed competitors is empty; in this case, avoid having to loop over the
// potentially large set of competitors
if (Util.isEmpty(getSuppressedCompetitors())) {
result = getAllCompetitors();
} else {
final Iterable<Competitor> allCompetitors = getAllCompetitors();
final Set<Competitor> suppressed = new HashSet<>();
Util.addAll(getSuppressedCompetitors(), suppressed);
result = getCompetitorIterableSkippingSuppressed(allCompetitors, suppressed);
}
return result;
}
@Override
public Iterable<Competitor> getCompetitors(RaceColumn raceColumn, Fleet fleet) {
return getCompetitorIterableSkippingSuppressed(getAllCompetitors(raceColumn, fleet), getSuppressedCompetitors());
}
/**
* Defines the difference between {@link #getCompetitors} and {@link #getAllCompetitors}. If a competitor is suppressed,
* it won't participate in the scoring process, particularly because it isn't considered by {@link #getCompetitorsFromBestToWorst(TimePoint)}
* nor {@link #getCompetitorsFromBestToWorst(RaceColumn, TimePoint)}.
* return an iterable with a smart iterator that filters out the suppressed elements on demand
*/
private boolean isSuppressed(Competitor competitor) {
LockUtil.lockForRead(suppressedCompetitorsLock);
try {
return suppressedCompetitors.contains(competitor);
} finally {
LockUtil.unlockAfterRead(suppressedCompetitorsLock);
}
protected Iterable<Competitor> getCompetitorIterableSkippingSuppressed(final Iterable<Competitor> allCompetitors,
final Iterable<Competitor> suppressed) {
final Iterable<Competitor> result;
result = new Iterable<Competitor>() {
@Override
public Iterator<Competitor> iterator() {
return new Iterator<Competitor>() {
private final Iterator<Competitor> allIter = allCompetitors.iterator();
private Competitor next = advance();
private Competitor advance() {
next = null;
while (allIter.hasNext() && next == null) {
next = allIter.next();
if (Util.contains(suppressed, next)) {
next = null;
}
}
return next;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public Competitor next() {
if (next == null) {
throw new NoSuchElementException();
}
final Competitor result = next;
advance();
return result;
}
};
}
};
return result;
}
@Override
public Iterable<Competitor> getSuppressedCompetitors() {
LockUtil.lockForRead(suppressedCompetitorsLock);
@@ -0,0 +1,203 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent;
import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor;
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener;
import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction;
import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
/**
* A caching provider of a competitor set, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of
* a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been provided,
* it is cached. The cache is invalidated when one of the following events occurs:
* <ul>
* <li>a competitor is registered with or unregistered from a race log of any of the race columns or the regatta log</li>
* <li>a race column is added or removed</li>
* <li>a tracked race is linked to or unlinked from any of the race columns</li>
* </ul>
*
* @author Axel Uhl (d043530)
*
*/
public class CompetitorProviderFromRaceColumnsAndRegattaLike {
private static final Logger logger = Logger.getLogger(CompetitorProviderFromRaceColumnsAndRegattaLike.class.getName());
private final HasRaceColumnsAndRegattaLike provider;
private final RegattaLogEventVisitor regattaLogCompetitorsCacheInvalidationListener;
private final RaceLogEventVisitor raceLogCompetitorsCacheInvalidationListener;
private final RaceColumnListener raceColumnListener;
private Iterable<Competitor> allCompetitorsCache;
private final ConcurrentHashMap<Pair<RaceColumn, Fleet>, Iterable<Competitor>> allCompetitorsCacheByRace;
public CompetitorProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) {
super();
this.provider = provider;
this.allCompetitorsCacheByRace = new ConcurrentHashMap<>();
// A note regarding listener serializability: RaceLogListener and RegattaLogListener objects
// don't need to be serializable as the log listeners are a transient structure. The race column
// listeners, however, need to explicitly declare that they are transient.
// This enclosing object is intended not to be serialized and shall be re-constructed by
// its users after de-serialization. Therefore, the transient-ness of the log listeners works
// as intended, and the race column listener explicitly returns true from its isTransient()
// method.
regattaLogCompetitorsCacheInvalidationListener = new BaseRegattaLogEventVisitor() {
@Override
public void visit(RegattaLogRegisterCompetitorEvent event) {
invalidateAllCompetitorsCaches();
}
@Override
public void visit(RegattaLogRevokeEvent event) {
try {
if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) {
invalidateAllCompetitorsCaches();
}
} catch (ClassNotFoundException e) {
logger.log(Level.WARNING, "Problem occurred trying to resolve revoked event class "+event.getRevokedEventType(), e);
}
}
};
raceLogCompetitorsCacheInvalidationListener = new BaseRaceLogEventVisitor() {
@Override
public void visit(RaceLogRegisterCompetitorEvent event) {
invalidateAllCompetitorsCaches();
}
@Override
public void visit(RaceLogRevokeEvent event) {
try {
if (RaceLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) {
invalidateAllCompetitorsCaches();
}
} catch (ClassNotFoundException e) {
logger.log(Level.WARNING, "Problem occurred trying to resolve revoked event class "+event.getRevokedEventType(), e);
}
}
};
raceColumnListener = new RaceColumnListenerWithDefaultAction() {
private static final long serialVersionUID = -8678230058730043052L;
@Override
public void defaultAction() {}
/**
* As the entire provider object is considered transient, its listeners are so, too.
*/
@Override
public boolean isTransient() {
return true;
}
@Override
public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
invalidateAllCompetitorsCaches();
}
@Override
public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {
invalidateAllCompetitorsCaches();
}
@Override
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
invalidateAllCompetitorsCaches();
}
@Override
public void raceColumnRemovedFromContainer(RaceColumn raceColumn) {
invalidateAllCompetitorsCaches();
}
};
}
public Iterable<Competitor> getAllCompetitors() {
if (allCompetitorsCache == null) {
final Set<Competitor> result = new HashSet<>();
for (RaceColumn rc : provider.getRaceColumns()) {
Util.addAll(rc.getAllCompetitors(), result);
for (final Fleet fleet : rc.getFleets()) {
rc.getRaceLog(fleet).addListener(raceLogCompetitorsCacheInvalidationListener);
}
}
provider.addRaceColumnListener(raceColumnListener);
// consider {@link RegattaLog}
Set<Competitor> viaLog = getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener();
result.addAll(viaLog);
allCompetitorsCache = result;
}
return allCompetitorsCache;
}
/**
* Obtains competitors from the regatta log and adds those from the tracked race for the
* raceColumn/fleet combination or the race log, if no tracked race is attached for this
* combination. Does <em>not</em> eliminate suppressed competitors.
*/
public Iterable<Competitor> getAllCompetitors(final RaceColumn raceColumn, final Fleet fleet) {
Pair<RaceColumn, Fleet> key = new Pair<>(raceColumn, fleet);
Iterable<Competitor> result = allCompetitorsCacheByRace.get(key);
if (result == null) {
final Set<Competitor> resultSet = new HashSet<>();
Util.addAll(raceColumn.getAllCompetitors(fleet), resultSet);
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the race log's listeners set
raceColumn.getRaceLog(fleet).addListener(raceLogCompetitorsCacheInvalidationListener);
provider.addRaceColumnListener(raceColumnListener);
// consider {@link RegattaLog}
Set<Competitor> viaLog = getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener();
resultSet.addAll(viaLog);
result = resultSet;
allCompetitorsCacheByRace.put(key, result);
}
return result;
}
private Set<Competitor> getCompetitorsFromRegattaLogAndRegisterAsRegattaLogListener() {
Set<Competitor> viaLog = new RegisteredCompetitorsAnalyzer<>(provider.getRegattaLike().getRegattaLog()).analyze();
// note: adding listeners is idempotent; at most one occurrence of this listener exists in the regatta log's listeners set
provider.getRegattaLike().getRegattaLog().addListener(regattaLogCompetitorsCacheInvalidationListener);
return viaLog;
}
private void invalidateAllCompetitorsCaches() {
allCompetitorsCache = null;
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's listeners set
provider.getRegattaLike().getRegattaLog().removeListener(regattaLogCompetitorsCacheInvalidationListener);
for (final RaceColumn rc : provider.getRaceColumns()) {
for (final Fleet fleet : rc.getFleets()) {
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race log's listeners set
rc.getRaceLog(fleet).removeListener(raceLogCompetitorsCacheInvalidationListener);
}
}
// note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column listeners set
provider.removeRaceColumnListener(raceColumnListener);
allCompetitorsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it should be good enough.
// The change frequency of competitors lists on individual races is much lower than the access frequency to this structure.
}
}
@@ -8,14 +8,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Fleet;
@@ -145,8 +142,10 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
private FlexibleRaceColumn addRaceColumn(String name, boolean medalRace, boolean logAlreadyExistingColumn) {
FlexibleRaceColumn column = getRaceColumnByName(name);
if (column != null) {
final String msg = "Trying to create race column with duplicate name "+name+" in leaderboard "+getName();
logger.severe(msg);
if (logAlreadyExistingColumn) {
final String msg = "Trying to create race column with duplicate name " + name + " in leaderboard " + getName();
logger.severe(msg);
}
} else {
column = createRaceColumn(name, medalRace);
column.addRaceColumnListener(this);
@@ -319,18 +318,6 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor);
}
@Override
public Iterable<Competitor> getAllCompetitors() {
Set<Competitor> result = new HashSet<>();
for (Competitor c : super.getAllCompetitors()) {
result.add(c);
}
//consider {@link RegattaLog}
Set<Competitor> viaLog = new RegisteredCompetitorsAnalyzer<>(regattaLikeHelper.getRegattaLog()).analyze();
result.addAll(viaLog);
return result;
}
private class RaceExecutionOrderCache extends AbstractRaceExecutionOrderProvider {
private static final long serialVersionUID = 652833386555762661L;
@@ -107,8 +107,7 @@ public class HighPointExtremeSailingSeriesOverall extends HighPoint {
* @throws NoWindException
*/
@Override
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard,
Competitor o1, Competitor o2, TimePoint timePoint) throws NoWindException {
public int compareByLatestRegattaInMetaLeaderboard(Leaderboard leaderboard, Competitor o1, Competitor o2, TimePoint timePoint) {
assert leaderboard instanceof MetaLeaderboard;
// compare by last regatta if this leaderboard is a meta leaderboard
final int result;
@@ -110,10 +110,11 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
needToResetO1ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore();
needToResetO2ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore();
if (getLeaderboard().getScoringScheme().isValidInTotalScore(getLeaderboard(), raceColumn, o1, timePoint)
&& getLeaderboard().getScoringScheme().isValidInTotalScore(getLeaderboard(), raceColumn, o2, timePoint)) {
int preemptiveColumnResult = 0;
final Double o1Score = totalPointsCache.get(new Util.Pair<Competitor, RaceColumn>(o1, raceColumn));
final boolean o1ValidInTotalScore = getLeaderboard().getScoringScheme().isValidInTotalScore(getLeaderboard(), raceColumn, o1, timePoint);
final boolean o2ValidInTotalScore = getLeaderboard().getScoringScheme().isValidInTotalScore(getLeaderboard(), raceColumn, o2, timePoint);
final Double o1Score;
if (o1ValidInTotalScore) {
o1Score = totalPointsCache.get(new Util.Pair<Competitor, RaceColumn>(o1, raceColumn));
if (o1Score != null) {
o1Scores.add(new Util.Pair<RaceColumn, Double>(raceColumn, o1Score));
if (needToResetO1ScoreUponNextValidResult) {
@@ -122,7 +123,12 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
}
o1ScoreSum += o1Score;
}
final Double o2Score = totalPointsCache.get(new Util.Pair<Competitor, RaceColumn>(o2, raceColumn));
} else {
o1Score = null;
}
final Double o2Score;
if (o2ValidInTotalScore) {
o2Score = totalPointsCache.get(new Util.Pair<Competitor, RaceColumn>(o2, raceColumn));
if (o2Score != null) {
o2Scores.add(new Util.Pair<RaceColumn, Double>(raceColumn, o2Score));
if (needToResetO2ScoreUponNextValidResult) {
@@ -131,6 +137,11 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
}
o2ScoreSum += o2Score;
}
} else {
o2Score = null;
}
if (o1ValidInTotalScore && o2ValidInTotalScore) {
int preemptiveColumnResult = 0;
if (raceColumn.isMedalRace()) {
// only count the score for the medal race score if it wasn't a carry-forward column
if (!raceColumn.isCarryForward()) {
@@ -5,6 +5,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -147,6 +148,17 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI
return result;
}
@Override
public Iterable<Competitor> getAllCompetitors(RaceColumn raceColumn, Fleet fleet) {
final Iterable<Competitor> result;
if (fleet == metaFleet && Util.contains(getRaceColumns(), raceColumn)) {
result = ((MetaLeaderboardColumn) raceColumn).getAllCompetitors();
} else {
result = Collections.emptySet();
}
return result;
}
@Override
public Fleet getFleet(String fleetName) {
return fleetName.equals(metaFleet.getName()) ? metaFleet : null;
@@ -203,4 +203,20 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
public RaceExecutionOrderProvider getRaceExecutionOrderProvider() {
return null;
}
@Override
public Iterable<Competitor> getAllCompetitors() {
return leaderboard.getAllCompetitors();
}
@Override
public Iterable<Competitor> getAllCompetitors(Fleet fleet) {
final Iterable<Competitor> result;
if (fleet == metaFleet) {
result = leaderboard.getAllCompetitors();
} else {
result = Collections.emptySet();
}
return result;
}
}
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.regattalike;
import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike;
import com.sap.sailing.domain.leaderboard.Leaderboard;
public interface LeaderboardThatHasRegattaLike extends Leaderboard, HasRegattaLike {
public interface LeaderboardThatHasRegattaLike extends Leaderboard, HasRaceColumnsAndRegattaLike {
}
@@ -299,11 +299,11 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
* implementations shall override this and provide a meaningful implementation according to the specification given
* above.
*/
default boolean takesWindFix(Wind wind) {
default boolean takesWindFixWithTimePoint(TimePoint timePoint) {
return true;
}
default boolean takesWindFixRecursively(Wind wind, Set<TrackedRace> visited) {
default boolean takesWindFixWithTimePointRecursively(TimePoint windFixTimePoint, Set<TrackedRace> visited) {
return true;
}
@@ -676,7 +676,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
@Override
public boolean recordWind(Wind wind, WindSource windSource) {
final boolean result;
if (takesWindFix(wind)) {
if (takesWindFixWithTimePoint(wind.getTimePoint())) {
result = getOrCreateWindTrack(windSource).add(wind);
updated(/* time point */null); // wind events shouldn't advance race time
triggerManeuverCacheRecalculationForAllCompetitors();
@@ -54,7 +54,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEv
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl;
import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMarkFinder;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogDefinedMarkFinder;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder;
import com.sap.sailing.domain.base.BoatClass;
@@ -1570,10 +1570,10 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
* two is not <code>null</code>.
*/
@Override
public boolean takesWindFix(Wind wind) {
public boolean takesWindFixWithTimePoint(TimePoint timePoint) {
final Set<TrackedRace> visited = new HashSet<>();
visited.add(this);
return takesWindFixRecursively(wind, visited);
return takesWindFixWithTimePointRecursively(timePoint, visited);
}
/**
@@ -1582,7 +1582,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
* {@link RaceExecutionOrderProvider}
*/
@Override
public boolean takesWindFixRecursively(Wind wind, Set<TrackedRace> visited) {
public boolean takesWindFixWithTimePointRecursively(TimePoint windFixTimePoint, Set<TrackedRace> visited) {
final boolean result;
final TimePoint earliestStartTimePoint = Util.getEarliestOfTimePoints(getStartOfRace(), getStartOfTracking());
final TimePoint latestEndTimePoint = Util.getLatestOfTimePoints(getEndOfRace(), getEndOfTracking());
@@ -1590,21 +1590,21 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
// first check if the fix meets the criteria set by the latestEndTimePoint: either the latestEndTimePoint is null, meaning an
// open interval which will continue to accept late wind fixes, or the fix time point is before the latestEndTimePoint plus a grace
// interval:
if (latestEndTimePoint == null || wind.getTimePoint().minus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).before(latestEndTimePoint)) {
if (latestEndTimePoint == null || windFixTimePoint.minus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).before(latestEndTimePoint)) {
// then check, if fix is accepted anyway because it's after earliestStartTimePoint.minus(TIME_BEFORE_START_TO_TRACK_WIND_MILLIS)
// and before latestEndTimePoint.plus(IS_LIVE_GRACE_PERIOD_IN_MILLIS) or latestEndTimePoint is null. In this case, no expensive
// recursive check whether previous races take the fix are required.
if (wind.getTimePoint().plus(TIME_BEFORE_START_TO_TRACK_WIND_MILLIS).after(earliestStartTimePoint)) {
if (windFixTimePoint.plus(TIME_BEFORE_START_TO_TRACK_WIND_MILLIS).after(earliestStartTimePoint)) {
result = true;
} else {
// if the fix is older than even the extended lead interval would accept, don't accept the fix:
if (wind.getTimePoint().plus(EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS).before(earliestStartTimePoint)) {
if (windFixTimePoint.plus(EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS).before(earliestStartTimePoint)) {
result = false;
} else {
// the fix is in the critical interval between EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS and
// TIME_BEFORE_START_TO_TRACK_WIND_MILLIS before the earliestStartTimePoint; the fix shall only be accepted
// if no previous race exists that accepts it
result = noPreviousRaceTakesWind(wind, visited);
result = noPreviousRaceTakesWindFixWithTimePoint(windFixTimePoint, visited);
}
}
} else {
@@ -1616,11 +1616,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
return result;
}
private boolean noPreviousRaceTakesWind(Wind wind, Set<TrackedRace> visited) {
private boolean noPreviousRaceTakesWindFixWithTimePoint(TimePoint timePoint, Set<TrackedRace> visited) {
final boolean result;
Set<TrackedRace> previousRacesInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
if (previousRacesInExecutionOrder == null || !previousRacesInExecutionOrder.stream().filter(tr ->
visited.add(tr) && tr.takesWindFixRecursively(wind, visited)).findAny().isPresent()) {
visited.add(tr) && tr.takesWindFixWithTimePointRecursively(timePoint, visited)).findAny().isPresent()) {
result = true;
} else {
result = false;
@@ -3874,7 +3874,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
new MapWithValueCollectionReducer<>(), allLogs).analyze();
final Set<Mark> result = new HashSet<>();
result.addAll(markMappings.keySet());
final AnalyzerFactory<Collection<Mark>> analyzerFactory = new DefinedMarkFinder.Factory();
final AnalyzerFactory<Collection<Mark>> analyzerFactory = new RaceLogDefinedMarkFinder.Factory();
Set<Mark> marksDefinedInRaceLog = new MultiLogAnalyzer<>(analyzerFactory, new SetReducer<Mark>(), raceLogs).analyze();
result.addAll(marksDefinedInRaceLog);
return result;
@@ -7,10 +7,10 @@ import static org.junit.Assert.assertThat;
import org.junit.Test;
import com.sap.sailing.gwt.home.client.shared.Countdown;
import com.sap.sailing.gwt.home.client.shared.Countdown.CountdownListener;
import com.sap.sailing.gwt.home.client.shared.Countdown.RemainingTime;
import com.sap.sailing.gwt.home.client.shared.Countdown.Unit;
import com.sap.sailing.gwt.home.shared.utils.Countdown;
import com.sap.sailing.gwt.home.shared.utils.Countdown.CountdownListener;
import com.sap.sailing.gwt.home.shared.utils.Countdown.RemainingTime;
import com.sap.sailing.gwt.home.shared.utils.Countdown.Unit;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
+2 -2
View File
@@ -13,8 +13,8 @@
<link rel="stylesheet" type="text/css"
href="/sailing-fontface-1.0.cache.css">
<script src="js/jquery-1.11.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="js/jquery.slick/slick-1.5.5.css"/>
<script type="text/javascript" src="js/jquery.slick/slick-1.5.5.min.js"></script>
<link rel="stylesheet" type="text/css" href="js/jquery.slick/slick-1.5.8.css"/>
<script type="text/javascript" src="js/jquery.slick/slick-1.5.8.min.js"></script>
<link href="js/video-js/video-js.css" rel="stylesheet">
<link href="js/video-js/video-js-sapsailing.css" rel="stylesheet">
<script src="js/video-js/video.js"></script>
@@ -19,44 +19,42 @@
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.polars.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.annotations/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6&quot; javaProject=&quot;com.sap.sailing.gwt.ui&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.gwt.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.googlecode.java-diff-utils/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.json.simple/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.server/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.tractracadapter.persistence/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/org.moxieapps.gwt.highcharts/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.geocoding/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.google.gwt.osgi/lib/gwt-user.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;com.sap.sailing.gwt.ui&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.operationaltransformation/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.replication/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart.html com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart.html com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
</launchConfiguration>
@@ -75,5 +75,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -workDir &quot;${project_loc:com.sap.sailing.gwt.ui}/.tmp/gwt-work&quot; -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9876 -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Desktop com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xms1024m -Xmx3072m"/>
</launchConfiguration>
@@ -10,6 +10,7 @@
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
@@ -44,7 +45,6 @@
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.expeditionconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.declination/resources&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.polars.datamining.shared/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.udpconnector/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.mongodb/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sailing.domain.swisstimingadapter/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
@@ -65,13 +65,12 @@
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.ui/src/main/java&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.gwt.adminconsole/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.security.common/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/com.sap.sse.datamining.annotations/src&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-nosuperDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.home.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XstartOnFirstThread -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
</launchConfiguration>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,20 +0,0 @@
/*
_ _ _ _
___| (_) ___| | __ (_)___
/ __| | |/ __| |/ / | / __|
\__ \ | | (__| < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
|__/
Version: 1.5.0
Author: Ken Wheeler
Website: http://kenwheeler.github.io
Docs: http://kenwheeler.github.io/slick
Repo: http://github.com/kenwheeler/slick
Issues: http://github.com/kenwheeler/slick/issues
*/
/* global window, document, define, jQuery, setInterval, clearInterval */
!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,g,h,e=this;if(e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="previous">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="next">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,g=e.options.responsive||null,g&&g.length>-1){e.respondTo=e.options.respondTo||"window";for(h in g)g.hasOwnProperty(h)&&(e.breakpoints.push(g[h].breakpoint),e.breakpointSettings[g[h].breakpoint]=g[h].settings);e.breakpoints.sort(function(a,b){return e.options.mobileFirst===!0?a-b:b-a})}"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.msHidden?(e.hidden="msHidden",e.visibilityChange="msvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.init(),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=nLine truncated
if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.swipeLeft=b.options.vertical===!1?d+f*g:d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.dragging=!0,void 0)},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&"object"!=typeof b.options.prevArrow&&b.$prevArrow.remove(),b.$nextArrow&&"object"!=typeof b.options.nextArrow&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(){var a=this;a.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.options.infinite!==!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.removeClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;document[a.hidden]?(a.paused=!0,a.autoPlayClear()):(a.paused=!1,a.autoPlay())},a.fn.slick=function(){var g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length,f=0;for(f;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}});
@@ -1,116 +0,0 @@
/* Slider */
.slick-slider
{
position: relative;
display: block;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-khtml-user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list
{
position: relative;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
}
.slick-list:focus
{
outline: none;
}
.slick-list.dragging
{
cursor: pointer;
cursor: hand;
}
.slick-slider .slick-track,
.slick-slider .slick-list
{
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track
{
position: relative;
top: 0;
left: 0;
display: block;
}
.slick-track:before,
.slick-track:after
{
display: table;
content: '';
}
.slick-track:after
{
clear: both;
}
.slick-loading .slick-track
{
visibility: hidden;
}
.slick-slide
{
display: none;
float: left;
height: 100%;
min-height: 1px;
}
[dir='rtl'] .slick-slide
{
float: right;
}
.slick-slide img
{
display: block;
}
.slick-slide.slick-loading img
{
display: none;
}
.slick-slide.dragging img
{
pointer-events: none;
}
.slick-initialized .slick-slide
{
display: block;
}
.slick-loading .slick-slide
{
visibility: hidden;
}
.slick-vertical .slick-slide
{
display: block;
height: auto;
border: 1px solid transparent;
}
File diff suppressed because it is too large. Load diff
@@ -1,18 +0,0 @@
/*
_ _ _ _
___| (_) ___| | __ (_)___
/ __| | |/ __| |/ / | / __|
\__ \ | | (__| < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
|__/
Version: 1.5.5
Author: Ken Wheeler
Website: http://kenwheeler.github.io
Docs: http://kenwheeler.github.io/slick
Repo: http://github.com/kenwheeler/slick
Issues: http://github.com/kenwheeler/slick/issues
*/
!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,g,h,e=this;if(e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="previous">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="next">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,g=e.options.responsive||null,g&&g.length>-1){e.respondTo=e.options.respondTo||"window";for(h in g)g.hasOwnProperty(h)&&(e.breakpoints.push(g[h].breakpoint),e.breakpointSettings[g[h].breakpoint]=g[h].settings);e.breakpoints.sort(function(a,b){return e.options.mobileFirst===!0?a-b:b-a})}"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.init(!0),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=c.options.asNavFor;d&&null!==d&&(d=a(d).not(c.$slider)),null!==d&&"object"==typeof d&&Line truncated
}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.swipeLeft=b.options.vertical===!1?d+f*g:d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.dragging=!0,void 0)},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&"object"!=typeof b.options.prevArrow&&b.$prevArrow.remove(),b.$nextArrow&&"object"!=typeof b.options.nextArrow&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.options.infinite!==!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.removeClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;document[a.hidden]?(a.paused=!0,a.autoPlayClear()):a.options.autoplay===!0&&(a.paused=!1,a.autoPlay())},a.fn.slick=function(){var g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length,f=0;for(f;e>f;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}});
@@ -113,4 +113,7 @@
height: auto;
border: 1px solid transparent;
}
.slick-arrow.slick-hidden {
display: none;
}
@@ -0,0 +1,18 @@
/*
_ _ _ _
___| (_) ___| | __ (_)___
/ __| | |/ __| |/ / | / __|
\__ \ | | (__| < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
|__/
Version: 1.5.8
Author: Ken Wheeler
Website: http://kenwheeler.github.io
Docs: http://kenwheeler.github.io/slick
Repo: http://github.com/kenwheeler/slick
Issues: http://github.com/kenwheeler/slick/issues
*/
!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none" role="button" aria-required="false" tabindex="0">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.hidden="hidden",e.paused=!1,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,f,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0),e.checkResponsive(!0)}var b=0;return c}(),b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-slick-index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?(e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}})):(e.applyTransition(),b=Math.ceil(b),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=c.options.asNavFor;d&&null!==d&&(d=a(d).not(c.$slider)),null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};c[b.transitiLine truncated
})):i.postSlide(e),i.animateHeight(),void 0):(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e),void 0)))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&135>=d?"left":"right":"vertical"},b.prototype.swipeEnd=function(){var c,b=this;if(b.dragging=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe)switch(b.swipeDirection()){case"left":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.slideHandler(c),b.currentDirection=0,b.touchObject={},b.$slider.trigger("swipe",[b,"left"]);break;case"right":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.slideHandler(c),b.currentDirection=1,b.touchObject={},b.$slider.trigger("swipe",[b,"right"])}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||h&&1!==h.length?!1:(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.swipeLeft=b.options.vertical===!1?d+f*g:d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.dragging=!0,void 0)},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass(Line truncated
@@ -1,90 +0,0 @@
@charset 'UTF-8';
/* Dots */
.slick-slider
{
margin-bottom: 30px;
}
.slick-dots
{
position: absolute;
bottom: -45px;
display: block;
width: 100%;
padding: 0;
list-style: none;
text-align: center;
}
.slick-dots li
{
position: relative;
display: inline-block;
width: 20px;
height: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
}
.slick-dots li button
{
font-size: 0;
line-height: 0;
display: block;
width: 20px;
height: 20px;
padding: 5px;
cursor: pointer;
color: transparent;
border: 0;
outline: none;
background: transparent;
}
.slick-dots li button:hover,
.slick-dots li button:focus
{
outline: none;
}
.slick-dots li button:hover:before,
.slick-dots li button:focus:before
{
opacity: 1;
}
.slick-dots li button:before
{
font-family: 'slick';
font-size: 6px;
line-height: 20px;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
content: '•';
text-align: center;
opacity: .25;
color: black;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-dots li.slick-active button:before
{
opacity: .75;
color: black;
}
@@ -1,5 +1,5 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar">
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar" xmlns:b="urn:import:com.sap.sse.gwt.client.controls.busyindicator">
<ui:with field="res"
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
@@ -35,6 +35,10 @@
float: right;
margin-left: 0.5em;
}
.busy {
width: 32px;
margin: 2em auto 10em;
}
</ui:style>
<g:FlowPanel>
<g:HTMLPanel addStyleNames="{style.header}">
@@ -54,6 +58,8 @@
</div>
</g:HTMLPanel>
<g:SimplePanel ui:field="tabContentPanelUi"
addStyleNames="{style.content}" />
addStyleNames="{style.content}">
<b:SimpleBusyIndicator addStyleNames="{style.busy}" busy="true" />
</g:SimplePanel>
</g:FlowPanel>
</ui:UiBinder>
@@ -45,7 +45,7 @@ public interface TextMessages extends Messages {
String sapSailing();
String search();
String startSimulator();
String countdownStartingInDays();
String countdownDays();
String countdownHours();
String countdownMinutes();
@@ -34,7 +34,7 @@ overview=Overview
sapSailing=SAP Sailing
search=Search
startSimulator=Start Simulator
countdownStartingInDays=Days
countdownDays=Days
countdownHours=Hrs
countdownMinutes=Min
@@ -34,7 +34,7 @@ overview=Übersicht
sapSailing=SAP Sailing
search=Suche
startSimulator=Simulator starten
countdownStartingInDays=Tagen
countdownDays=Tage
countdownHours=Std.
countdownMinutes=Min.
@@ -1,183 +1,184 @@
socialFooterShare=Share this on
home=主页
aboutUs=关于我们
contact=联络
sponsoring=赞助商
solutions=解决方案
events=比赛
german=德语
english=英语
officalEventWebsite=官方活动网站
leg=站
races=赛事
moreInfo=更多信息
viewAnalysis=观看分析
overallLeaderboard=总排行榜
pleaseEnterASearchTerm=请输入搜索词
pleaseTryAgain=请再试一次
reloadPage=重新载入页面
errorMessageLoadingData=加载该页的数据时出错
errorMessageNoSuchLeaderboard=无法利用这词寻找排行榜
raceNotScheduled=没有确认时间
regattaDetails=帆船赛细节
regatta=帆船赛
competitorsAnalytics=队伍分析
chooseChart=选择图标类型
series=系列
regattaLeaderboards=帆船赛排行榜
features=功能
releaseNotes=软件更新发布
whatsNew=最新信息
overview=概览
sapSailing=SAP帆船
search=搜索
startSimulator=启动模拟器
live=实时
finished=结束
watchNow=马上观看
lastUpdate=最后更新
leaderboard=排行榜
eventHeaderMedia=媒体
eventHeaderOverview=概览
eventHeaderRaces=赛程
eventHeaderRegattas=帆船赛
seriesHeaderOverview=关于比赛系列
seriesHeaderUpcoming=未来赛事
seriesHeaderRecent=最近赛事
seriesHeaderLeaderboard=排行榜
eventsOverviewRecentEvents=赛事
eventsOverviewRecentCountries=国家
eventsOverviewRecentSailors=运动员
eventsOverviewRecentTrackedRaces=赛事(含比赛分析)
eventResultsHeadline=比赛结果
eventResultsBoatClassesDropDown=所有帆船级别
eventOverviewMoreEvents=更多赛事
eventOverviewRecentEvents=最近赛事
eventOverviewUpcomingDate=日期
eventOverviewUpcomingEvent=赛事
eventOverviewUpcomingLocation=地点
eventOverviewUpcomingSchedule=未来赛程
eventOverviewUpcomingSeries=系列
eventOverviewUpcomingTeaser=更多赛事即将公布
eventQuickfinderTitle=赛事快速查找
eventRegattaHeaderLeaderboard=排行榜
eventRegattaHeaderRaceRaces=赛事
eventRegattaListAllBoatClasses=所有帆船级别
eventRegattaLeaderboardCompetitor=比赛队伍
eventRegattaLeaderboardExtendLeaderboard=详细排行榜
eventRegattaLeaderboardFinishedMessage=没有更多比赛
eventRegattaLeaderboardLastScoreUpdate=最后积分更新
eventRegattaLeaderboardName=队伍名称
eventRegattaLeaderboardRegattaRank=帆船赛排名
eventRegattaLeaderboardTotalPoints=总积分
eventRegattaRaceWatch=实时观看
eventRegattaRaceAnalyse=赛事分析
eventRegattaRaceNotTracked=不含比赛分析
mainEventShowAll=显示所有赛事
mainEventTitle=最新帆船赛事
mainMediaSubtitle=
mainMediaTitle=照片
mainMediaVideosSubtitle=
mainMediaVideosTitle=最新视频
mainSponsorsReadMore=阅读更多
mediaTeaserPhotosTitle=照片
mediaTeaserVideosTitle=视频
regattaCompetitors=比赛队伍\竞争对手
regattaRaces=赛事
regattaTracked=Tracked 
regattaRegattaStarts=帆船比赛即将开始
regattaPts=积分
regattaCourse=帆船赛程
regattaArea=地点
regattaFinishedAt=结束时间为
regattaScheduledAt=开始时间为
regattaStartedAt=开始时间为
regattasResultsTitle=比赛结果
searchResultHeaderButton=搜寻
searchResultHeaderLabel=您的搜寻
searchResultsFound=搜寻结果
searchResultHeaderPlaceholder=输入您的搜寻关键词
searchResultMore=更多
searchResultSearch=搜寻
searchResultSearchAgain=重新搜寻
searchResultSortLabel=排序方式
searchResultSortNewest=最近
searchResultSortOldest=最旧
searchResultSortRelevance=相关性
solutionsSAPNav=SAP帆船比赛分析
solutionsSAPHeadline=SAP帆船比赛分析
countdownDays=Days
countdownHours=Hrs
countdownMinutes=Min
countdownSeconds=Sec
countdownDay=Day
countdownHour=Hour
countdownMinute=Min
countdownSecond=Sec
boxNewsUpdateMoreLink=Report news
boxNewsUpdateTitle=News Update
boxUpcomingRacesCountdownStarted1=Started
boxUpcomingRacesCountdownStarted2=hrs and
boxUpcomingRacesCountdownStarted3=minutes ago
boxUpcomingRacesCountdownStarting1=Starting in
boxUpcomingRacesCountdownStarting2=hrs and
boxUpcomingRacesCountdownStarting3=minutes
boxUpcomingRacesMoreLink=Event Schedule
boxUpcomingRacesTitle=Upcoming Races Today
boxWeather=Weather
boxWeatherUnit=KTS
defaultTitle=SAP帆船
seriesOverviewHeaderRecent=Latest Series Events
seriesOverviewReadMore=More
eventRegattaRaceFinished=Finished at:
eventRegattaRaceStarted=Started at:
eventRegattaRaceScheduled=Scheduled for:
eventRegattaRaceRace=Race
eventRegattaRaceWind=Wind Strength:
eventRegattaRaceWinner=Winner
eventRegattaRaceLeader=Leader
eventRegattaRacesLegendGps=Tracking
eventRegattaRacesLegendWind=Wind Data
eventRegattaRacesLegendVideo=Video
eventRegattaRacesLegendAudio=Audio
eventSponsorsTitle=Event Sponsorships
footerJobs=Jobs
footerCopyright=\u00A9 2015 SAP帆船
footerLanguage=SAP Sailing offered in
footerLegal=Legal Disclosure
footerPrivacy=Privacy
footerFeedback=Feedback
headerEvents=比赛
headerHome=主页
headerLogo=SAP帆船
headerSearch=搜索
headerSearchPlaceholder=搜索
headerSolutions=Solutions
headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
latestRaceResultsIsNew=New
latestRaceResultsIsUpdated=Updated
latestRaceResultsRaceCountLabel=Result after
latestRaceResultsRaceCountUnit=races
latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
searchResultCount=About 2,450 results where found for 'Schnitzel'
sharingEmail=Send an email
sharingFacebook=Share on Facebook
sharingTwitter=Tweet about it
socialFooterTitle=Recommend SAP Sailing Analytics
solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.
solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.
solutionsRaceNav=Race Committee App
solutionsRaceHeadline=Race Committee App
solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.
solutionsPostNav=Post-Race Analytics
solutionsPostHeadline=Post-Race Analytics
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.<br> SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsTrainingNav=Training Diary
solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary
solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.
solutionsSimulatorNav=Strategy Simulator
solutionsSimulatorHeadline=Strategy Simulator
solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
socialFooterShare=Share this on
home=主页
aboutUs=关于我们
contact=联络
sponsoring=赞助商
solutions=解决方案
events=比赛
german=德语
english=英语
officalEventWebsite=官方活动网站
leg=站
races=赛事
moreInfo=更多信息
viewAnalysis=观看分析
overallLeaderboard=总排行榜
pleaseEnterASearchTerm=请输入搜索词
pleaseTryAgain=请再试一次
reloadPage=重新载入页面
errorMessageLoadingData=加载该页的数据时出错
errorMessageNoSuchLeaderboard=无法利用这词寻找排行榜
raceNotScheduled=没有确认时间
regattaDetails=帆船赛细节
regatta=帆船赛
competitorsAnalytics=队伍分析
chooseChart=选择图标类型
series=系列
regattaLeaderboards=帆船赛排行榜
features=功能
releaseNotes=软件更新发布
whatsNew=最新信息
overview=概览
sapSailing=SAP帆船
search=搜索
startSimulator=启动模拟器
live=实时
finished=结束
watchNow=马上观看
lastUpdate=最后更新
leaderboard=排行榜
eventHeaderMedia=媒体
eventHeaderOverview=概览
eventHeaderRaces=赛程
eventHeaderRegattas=帆船赛
seriesHeaderOverview=关于比赛系列
seriesHeaderUpcoming=未来赛事
seriesHeaderRecent=最近赛事
seriesHeaderLeaderboard=排行榜
eventsOverviewRecentEvents=赛事
eventsOverviewRecentCountries=国家
eventsOverviewRecentSailors=运动员
eventsOverviewRecentTrackedRaces=赛事(含比赛分析)
eventResultsHeadline=比赛结果
eventResultsBoatClassesDropDown=所有帆船级别
eventOverviewMoreEvents=更多赛事
eventOverviewRecentEvents=最近赛事
eventOverviewUpcomingDate=日期
eventOverviewUpcomingEvent=赛事
eventOverviewUpcomingLocation=地点
eventOverviewUpcomingSchedule=未来赛程
eventOverviewUpcomingSeries=系列
eventOverviewUpcomingTeaser=更多赛事即将公布
eventQuickfinderTitle=赛事快速查找
eventRegattaHeaderLeaderboard=排行榜
eventRegattaHeaderRaceRaces=赛事
eventRegattaListAllBoatClasses=所有帆船级别
eventRegattaLeaderboardCompetitor=比赛队伍
eventRegattaLeaderboardExtendLeaderboard=详细排行榜
eventRegattaLeaderboardFinishedMessage=没有更多比赛
eventRegattaLeaderboardLastScoreUpdate=最后积分更新
eventRegattaLeaderboardName=队伍名称
eventRegattaLeaderboardRegattaRank=帆船赛排名
eventRegattaLeaderboardTotalPoints=总积分
eventRegattaRaceWatch=实时观看
eventRegattaRaceAnalyse=赛事分析
eventRegattaRaceNotTracked=不含比赛分析
mainEventShowAll=显示所有赛事
mainEventTitle=最新帆船赛事
mainMediaSubtitle=
mainMediaTitle=照片
mainMediaVideosSubtitle=
mainMediaVideosTitle=最新视频
mainSponsorsReadMore=阅读更多
mediaTeaserPhotosTitle=照片
mediaTeaserVideosTitle=视频
regattaCompetitors=比赛队伍\竞争对手
regattaRaces=赛事
regattaTracked=Tracked 
regattaRegattaStarts=帆船比赛即将开始
regattaPts=积分
regattaCourse=帆船赛程
regattaArea=地点
regattaFinishedAt=结束时间为
regattaScheduledAt=开始时间为
regattaStartedAt=开始时间为
regattasResultsTitle=比赛结果
searchResultHeaderButton=搜寻
searchResultHeaderLabel=您的搜寻
searchResultsFound=搜寻结果
searchResultHeaderPlaceholder=输入您的搜寻关键词
searchResultMore=更多
searchResultSearch=搜寻
searchResultSearchAgain=重新搜寻
searchResultSortLabel=排序方式
searchResultSortNewest=最近
searchResultSortOldest=最旧
searchResultSortRelevance=相关性
solutionsSAPNav=SAP帆船比赛分析
solutionsSAPHeadline=SAP帆船比赛分析
countdownStartingInDays=Days
countdownDays=Days
countdownHours=Hrs
countdownMinutes=Min
countdownSeconds=Sec
countdownDay=Day
countdownHour=Hour
countdownMinute=Min
countdownSecond=Sec
boxNewsUpdateMoreLink=Report news
boxNewsUpdateTitle=News Update
boxUpcomingRacesCountdownStarted1=Started
boxUpcomingRacesCountdownStarted2=hrs and
boxUpcomingRacesCountdownStarted3=minutes ago
boxUpcomingRacesCountdownStarting1=Starting in
boxUpcomingRacesCountdownStarting2=hrs and
boxUpcomingRacesCountdownStarting3=minutes
boxUpcomingRacesMoreLink=Event Schedule
boxUpcomingRacesTitle=Upcoming Races Today
boxWeather=Weather
boxWeatherUnit=KTS
defaultTitle=SAP帆船
seriesOverviewHeaderRecent=Latest Series Events
seriesOverviewReadMore=More
eventRegattaRaceFinished=Finished at:
eventRegattaRaceStarted=Started at:
eventRegattaRaceScheduled=Scheduled for:
eventRegattaRaceRace=Race
eventRegattaRaceWind=Wind Strength:
eventRegattaRaceWinner=Winner
eventRegattaRaceLeader=Leader
eventRegattaRacesLegendGps=Tracking
eventRegattaRacesLegendWind=Wind Data
eventRegattaRacesLegendVideo=Video
eventRegattaRacesLegendAudio=Audio
eventSponsorsTitle=Event Sponsorships
footerJobs=Jobs
footerCopyright=\u00A9 2015 SAP帆船
footerLanguage=SAP Sailing offered in
footerLegal=Legal Disclosure
footerPrivacy=Privacy
footerFeedback=Feedback
headerEvents=比赛
headerHome=主页
headerLogo=SAP帆船
headerSearch=搜索
headerSearchPlaceholder=搜索
headerSolutions=Solutions
headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
latestRaceResultsIsNew=New
latestRaceResultsIsUpdated=Updated
latestRaceResultsRaceCountLabel=Result after
latestRaceResultsRaceCountUnit=races
latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
searchResultCount=About 2,450 results where found for 'Schnitzel'
sharingEmail=Send an email
sharingFacebook=Share on Facebook
sharingTwitter=Tweet about it
socialFooterTitle=Recommend SAP Sailing Analytics
solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.
solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.
solutionsRaceNav=Race Committee App
solutionsRaceHeadline=Race Committee App
solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.
solutionsPostNav=Post-Race Analytics
solutionsPostHeadline=Post-Race Analytics
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.<br> SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsTrainingNav=Training Diary
solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary
solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.
solutionsSimulatorNav=Strategy Simulator
solutionsSimulatorHeadline=Strategy Simulator
solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
@@ -1,9 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<g:HTMLPanel>
<s:error.ErrorMessage ui:field='errorMessage'/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,63 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar"
xmlns:tabs="urn:import:com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs"
xmlns:h="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.header">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:style>
.header {
position: relative;
width: 100%;
margin: 0;
padding: 0;
}
.mainHeader {
width: 66.6666666666667%;
}
.sharingHeader {
width: 33.3333333333333%;
float: right;
padding: 0 1rem;
position:
relative;
padding: 1.333333333333333em 0;
text-align: right;
background-color: maroon;
height: 2rem;
}
.breadcrumb, .intro {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.breadcrumb {
font-size: 0.866666666666667em;
font-weight: 600;
}
.intro {
height: 5em;
}
</ui:style>
<g:HTMLPanel>
<c:TabPanel ui:field="tabPanelUi">
<c:header>
<h:EventHeader ui:field="eventHeader" />
</c:header>
<c:tabcontent title="{i18n.overview}">
<tabs:MultiregattaOverviewTabView />
</c:tabcontent>
<c:tabcontent title="{i18n.regattas}">
<tabs:MultiregattaRegattasTabView />
</c:tabcontent>
<c:tabcontent title="{i18n.media}">
<tabs:MultiregattaMediaTabView />
</c:tabcontent>
</c:TabPanel>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,25 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs;
import com.google.gwt.place.shared.Prefix;
import com.sap.sailing.gwt.home.client.place.event.AbstractEventPlace;
import com.sap.sailing.gwt.home.client.place.event.EventContext;
import com.sap.sailing.gwt.home.client.place.event.EventPrefixes;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.AbstractMultiregattaEventPlace;
public class MultiregattaMediaPlace extends AbstractMultiregattaEventPlace {
public MultiregattaMediaPlace(String id) {
super(id);
}
public MultiregattaMediaPlace(EventContext context) {
super(context);
}
@Prefix(EventPrefixes.MultiregattaMedia)
public static class Tokenizer extends AbstractEventPlace.Tokenizer<MultiregattaMediaPlace> {
@Override
protected MultiregattaMediaPlace getRealPlace(EventContext context) {
return new MultiregattaMediaPlace(context);
}
}
}
@@ -1,181 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.MultiregattaTabView;
import com.sap.sailing.gwt.home.client.place.event.overview.EventOverviewStage;
import com.sap.sailing.gwt.home.client.place.event.partials.eventregatta.EventRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter.DropdownFilterList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListStepsLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLive;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshManager;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.home.desktop.partials.statistics.StatisticsBox;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventStatisticsAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
import com.sap.sse.common.Util.Triple;
/**
* Created by pgtaboada on 25.11.14.
*/
public class MultiregattaOverviewTabView extends Composite implements MultiregattaTabView<MultiregattaOverviewPlace> {
private static final MainCss MAIN_CSS = SharedResources.INSTANCE.mainCss();
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaOverviewTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField SimplePanel content;
@UiField(provided = true) EventOverviewStage stage;
@UiField(provided = true) RacesListLive racesListLive;
@UiField DivElement newContentContainerUi;
@UiField DivElement legendAndFilterUi;
@UiField(provided = true) DropdownFilter<String> boatCategoryFilterUi;
@UiField MultiRegattaListStepsLegend regattaProgressLegendUi;
@UiField(provided = true) MultiRegattaList regattaListUi;
@UiField AnchorElement regattaOverviewLinkUi;
@UiField StatisticsBox statisticsBoxUi;
private Presenter currentPresenter;
@Override
public Class<MultiregattaOverviewPlace> getPlaceClassForActivation() {
return MultiregattaOverviewPlace.class;
}
@Override
public void setPresenter(EventMultiregattaView.Presenter currentPresenter) {
this.currentPresenter = currentPresenter;
}
@Override
public TabView.State getState() {
return TabView.State.VISIBLE;
}
@Override
public void start(MultiregattaOverviewPlace myPlace, AcceptsOneWidget contentArea) {
stage = new EventOverviewStage(currentPresenter);
racesListLive = new RacesListLive(currentPresenter, true);
MultiregattaOverviewRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaOverviewRegattasTabViewRegattaFilterList();
boatCategoryFilterUi = new DropdownFilter<String>(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList);
regattaListUi = new MultiRegattaList(currentPresenter, false);
initWidget(ourUiBinder.createAndBindUi(this));
regattaOverviewLinkUi.setHref(currentPresenter.getRegattaOverviewLink());
regattaOverviewLinkUi.addClassName(currentPresenter.isEventOrRegattaLive() ? MAIN_CSS.buttonred() : MAIN_CSS.buttonprimary());
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
stage.setupRefresh(refreshManager);
refreshManager.add(racesListLive.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
if (ExperimentalFeatures.SHOW_NEW_REGATTA_LIST) {
refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId()));
refreshManager.add(statisticsBoxUi, new GetEventStatisticsAction(currentPresenter.getCtx().getEventDTO().getId(), true));
content.removeFromParent();
} else {
boatCategoryFilterUi.removeFromParent();
regattaProgressLegendUi.removeFromParent();
regattaListUi.removeFromParent();
newContentContainerUi.removeFromParent();
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
contentArea.setWidget(this);
}
protected void initView() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> regattaStructure = getRegattaStructure();
EventRegattaList eventRegattaList = new EventRegattaList(regattaStructure, currentPresenter);
content.setWidget(eventRegattaList);
}
private Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> getRegattaStructure() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> result = new HashMap<>();
Map<String, RaceGroupDTO> raceGroupsMap = new HashMap<>();
for (RaceGroupDTO raceGroup : currentPresenter.getCtx().getRaceGroups()) {
raceGroupsMap.put(raceGroup.getName(), raceGroup);
}
for (LeaderboardGroupDTO leaderboardGroup : currentPresenter.getCtx().getLeaderboardGroups()) {
for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.getLeaderboards()) {
String leaderboardName = leaderboard.name;
result.put(leaderboardName, new Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>(
raceGroupsMap.get(leaderboardName), leaderboard, leaderboardGroup));
}
}
return result;
}
@Override
public void stop() {
}
@Override
public MultiregattaOverviewPlace placeToFire() {
return new MultiregattaOverviewPlace(currentPresenter.getCtx());
}
private class MultiregattaOverviewRegattasTabViewRegattaFilterList implements
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
@Override
public void setData(SortedSetResult<RegattaWithProgressDTO> data) {
legendAndFilterUi.getStyle().setDisplay(data.isEmpty() ? Display.NONE : Display.BLOCK);
regattaListUi.setData(data);
boatCategoryFilterUi.updateFilterValues();
}
@Override
public Collection<String> getSelectableValues() {
return regattaListUi.getSelectableBoatCategories();
}
@Override
public void onSelectFilter(String value) {
regattaListUi.setVisibleBoatCategory(value);
}
}
}
@@ -1,37 +0,0 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials"
xmlns:s="urn:import:com.sap.sailing.gwt.home.desktop.partials.statistics"
xmlns:o="urn:import:com.sap.sailing.gwt.home.client.place.event.overview">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:style>
.legend_and_filter {
text-align: right;
}
.legend_and_filter > div, .legend_and_filter > a {
display: inline-block;
vertical-align: middle;
margin-left: 1.5em;
}
</ui:style>
<g:HTMLPanel>
<o:EventOverviewStage ui:field="stage" />
<div class="{res.mediaCss.grid}" ui:field="newContentContainerUi">
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}">
<p:raceListLive.RacesListLive ui:field="racesListLive" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" />
<div class="{res.mainCss.spacermargintopmedium} {style.legend_and_filter}" ui:field="legendAndFilterUi" style="display:none;">
<p:multiRegattaList.MultiRegattaListStepsLegend ui:field="regattaProgressLegendUi" />
<p:listNavigation.DropdownFilter ui:field="boatCategoryFilterUi" />
<a class="{res.mainCss.button} {res.mainCss.buttonstrong} {res.mainCss.buttonarrowrightwhite}"
target="_blank" ui:field="regattaOverviewLinkUi">
<ui:text from="{i18n.racesOverview}" />
</a>
</div>
<p:multiRegattaList.MultiRegattaList ui:field="regattaListUi" />
<s:StatisticsBox addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopmedium}" ui:field="statisticsBoxUi"/>
</div>
</div>
<g:SimplePanel ui:field="content" />
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,178 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.multiregatta.tabs;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.EventMultiregattaView.Presenter;
import com.sap.sailing.gwt.home.client.place.event.multiregatta.MultiregattaTabView;
import com.sap.sailing.gwt.home.client.place.event.partials.eventregatta.EventRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter;
import com.sap.sailing.gwt.home.client.place.event.partials.listNavigation.DropdownFilter.DropdownFilterList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaList;
import com.sap.sailing.gwt.home.client.place.event.partials.multiRegattaList.MultiRegattaListStepsLegend;
import com.sap.sailing.gwt.home.client.place.event.partials.raceListLive.RacesListLive;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshManager;
import com.sap.sailing.gwt.home.client.place.event.regatta.tabs.reload.RefreshableWidget;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction;
import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction;
import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO;
import com.sap.sse.common.Util.Triple;
/**
* Created by pgtaboada on 25.11.14.
*/
public class MultiregattaRegattasTabView extends Composite implements MultiregattaTabView<MultiregattaRegattasPlace> {
private static final MainCss MAIN_CSS = SharedResources.INSTANCE.mainCss();
interface MyBinder extends UiBinder<HTMLPanel, MultiregattaRegattasTabView> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField SimplePanel content;
@UiField DivElement newContentContainerUi;
@UiField(provided = true) RacesListLive racesListLiveUi;
@UiField DivElement legendAndFilterUi;
@UiField(provided = true) DropdownFilter<String> boatCategoryFilterUi;
@UiField MultiRegattaListStepsLegend regattaProgressLegendUi;
@UiField(provided = true) MultiRegattaList regattaListUi;
@UiField AnchorElement regattaOverviewLinkUi;
private Presenter currentPresenter;
@Override
public Class<MultiregattaRegattasPlace> getPlaceClassForActivation() {
return MultiregattaRegattasPlace.class;
}
@Override
public void setPresenter(EventMultiregattaView.Presenter currentPresenter) {
this.currentPresenter = currentPresenter;
}
@Override
public TabView.State getState() {
return TabView.State.VISIBLE;
}
@Override
public void start(final MultiregattaRegattasPlace myPlace, final AcceptsOneWidget contentArea) {
racesListLiveUi = new RacesListLive(currentPresenter, true);
MultiregattaRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaRegattasTabViewRegattaFilterList();
boatCategoryFilterUi = new DropdownFilter<String>(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList);
regattaListUi = new MultiRegattaList(currentPresenter, true);
initWidget(ourUiBinder.createAndBindUi(this));
regattaOverviewLinkUi.setHref(currentPresenter.getRegattaOverviewLink());
regattaOverviewLinkUi.addClassName(currentPresenter.isEventOrRegattaLive() ? MAIN_CSS.buttonred() : MAIN_CSS.buttonprimary());
RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch());
refreshManager.add(racesListLiveUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId()));
if (ExperimentalFeatures.SHOW_NEW_REGATTA_LIST) {
refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId()));
content.removeFromParent();
} else {
boatCategoryFilterUi.removeFromParent();
regattaProgressLegendUi.removeFromParent();
regattaListUi.removeFromParent();
newContentContainerUi.removeFromParent();
// TODO: understand, and than move this into appropiate place (probably context)
currentPresenter.ensureRegattaStructure(new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
if (raceGroups.size() > 0) {
initView();
} else {
// createEventWithoutRegattasView(event, panel);
}
}
@Override
public void onFailure(Throwable caught) {
// createErrorView(
// "Error while loading the regatta structure with service getRegattaStructureOfEvent()",
// caught, panel);
}
});
}
contentArea.setWidget(this);
}
protected void initView() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> regattaStructure = getRegattaStructure();
EventRegattaList eventRegattaList = new EventRegattaList(regattaStructure, currentPresenter);
content.setWidget(eventRegattaList);
}
private Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> getRegattaStructure() {
Map<String, Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>> result = new HashMap<>();
Map<String, RaceGroupDTO> raceGroupsMap = new HashMap<>();
for (RaceGroupDTO raceGroup: currentPresenter.getCtx().getRaceGroups()) {
raceGroupsMap.put(raceGroup.getName(), raceGroup);
}
for (LeaderboardGroupDTO leaderboardGroup : currentPresenter.getCtx().getLeaderboardGroups()) {
for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) {
String leaderboardName = leaderboard.name;
result.put(leaderboardName, new Triple<RaceGroupDTO, StrippedLeaderboardDTO, LeaderboardGroupDTO>(raceGroupsMap.get(leaderboardName),
leaderboard, leaderboardGroup));
}
}
return result;
}
@Override
public void stop() {
}
@Override
public MultiregattaRegattasPlace placeToFire() {
return new MultiregattaRegattasPlace(currentPresenter.getCtx());
}
private class MultiregattaRegattasTabViewRegattaFilterList implements
DropdownFilterList<String>, RefreshableWidget<SortedSetResult<RegattaWithProgressDTO>> {
@Override
public void setData(SortedSetResult<RegattaWithProgressDTO> data) {
legendAndFilterUi.getStyle().setDisplay(data.isEmpty() ? Display.NONE : Display.BLOCK);
regattaListUi.setData(data);
boatCategoryFilterUi.updateFilterValues();
}
@Override
public Collection<String> getSelectableValues() {
return regattaListUi.getSelectableBoatCategories();
}
@Override
public void onSelectFilter(String value) {
regattaListUi.setVisibleBoatCategory(value);
}
}
}
@@ -1,32 +0,0 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.event.partials">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:style>
.legend_and_filter {
text-align: right;
}
.legend_and_filter > div, .legend_and_filter > a {
display: inline-block;
vertical-align: middle;
margin-left: 1.5em;
}
</ui:style>
<g:HTMLPanel>
<div class="{res.mediaCss.grid}" ui:field="newContentContainerUi">
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {res.mainCss.spacermarginbottommedium}">
<p:raceListLive.RacesListLive ui:field="racesListLiveUi" addStyleNames="{res.mainCss.spacermargintopmedium}" />
<div class="{res.mainCss.spacermargintopmedium} {style.legend_and_filter}" ui:field="legendAndFilterUi" style="display:none;">
<p:multiRegattaList.MultiRegattaListStepsLegend ui:field="regattaProgressLegendUi" />
<p:listNavigation.DropdownFilter ui:field="boatCategoryFilterUi" />
<a class="{res.mainCss.button} {res.mainCss.buttonstrong} {res.mainCss.buttonarrowrightwhite}"
target="_blank" ui:field="regattaOverviewLinkUi">
<ui:text from="{i18n.racesOverview}" />
</a>
</div>
<p:multiRegattaList.MultiRegattaList ui:field="regattaListUi" />
</div>
</div>
<g:SimplePanel ui:field="content" />
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,36 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.place.event"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources" />
<ui:style>
.marginFix {
margin-top: 2rem;
}
</ui:style>
<g:HTMLPanel>
<div class="{res.mediaCss.grid} {style.marginFix}" >
<div class="{res.mediaCss.small6} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_scoring}">
<h3><ui:text from="{i18n.competitorsAnalytics}" /></h3>
</div>
<div class="{res.mediaCss.small6} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_settings}">
<ui:text from="{i18n.chooseChart}" />
<g:ListBox ui:field="chartTypeSelectionListBox" />
</div>
<div class="{res.mediaCss.column}" style="margin-bottom: 1em;">
<b><ui:text from="{i18n.chartSelectionHint}" /></b>
</div>
<div ui:field="competitorSelectionStateUi" class="{res.mediaCss.column}" style="margin-bottom: 1em;">
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<g:HTMLPanel ui:field="oldCompetitorChartsPanel">
</g:HTMLPanel>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,39 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.place.event"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources" />
<g:HTMLPanel styleName=" {local_res.css.marginFix}">
<div class="{res.mediaCss.grid}" >
<div class="{res.mediaCss.small7} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_scoring}">
<div ui:field="lastScoringCommentDiv" class="{local_res.css.regattaleaderboard_meta_scoring_comment}"></div>
<div ui:field="hasLiveRaceDiv" class="{local_res.css.regattaleaderboard_meta_liverace}"></div>
<div ui:field="scoringSchemeDiv" class="{local_res.css.regattaleaderboard_meta_scoring_type}"></div>
</div>
<div class="{res.mediaCss.small5} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_settings}">
<div class="{local_res.css.regattaleaderboard_meta_update}">
<div ui:field="lastScoringUpdateTextDiv" class="{local_res.css.regattaleaderboard_meta_update_text}"></div>
<div ui:field="lastScoringUpdateTimeDiv" class="{local_res.css.regattaleaderboard_meta_update_timestamp}"></div>
</div>
<g:Anchor ui:field="autoRefreshAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_reload}"></g:Anchor>
<g:Anchor ui:field="settingsAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_settings_button}"></g:Anchor>
<g:Anchor ui:field="fullscreenAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_fullscreen_button}"></g:Anchor>
</div>
</div>
<div class="{res.mediaCss.grid}" >
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {local_res.css.letItScroll}">
<table class="{local_res.css.regattaleaderboard_table}">
<tr>
<td>
<g:HTMLPanel ui:field="oldLeaderboardPanel">
</g:HTMLPanel>
</td>
</tr>
</table>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,39 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.place.event"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources" />
<ui:with field="local_res2" type="com.sap.sailing.gwt.home.client.place.event.oldmultileaderboard.OldMultiLeaderboardResources" />
<g:HTMLPanel styleName=" {local_res.css.marginFix}">
<div class="{res.mediaCss.grid}" >
<div class="{res.mediaCss.small6} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_scoring}">
<p ui:field="lastScoringCommentDiv" class="{local_res.css.regattaleaderboard_meta_scoring_comment}"></p>
<p ui:field="scoringSchemeDiv" class="{local_res.css.regattaleaderboard_meta_scoring_type}"></p>
</div>
<div class="{res.mediaCss.small6} {res.mediaCss.column} {local_res.css.regattaleaderboard_meta_settings}">
<div class="{local_res.css.regattaleaderboard_meta_update}">
<p ui:field="lastScoringUpdateTextDiv" class="{local_res.css.regattaleaderboard_meta_update_text}"></p>
<p ui:field="lastScoringUpdateTimeDiv" class="{local_res.css.regattaleaderboard_meta_update_timestamp}"></p>
</div>
<g:Anchor ui:field="autoRefreshAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_reload}"></g:Anchor>
<g:Anchor ui:field="settingsAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_settings_button}"></g:Anchor>
<g:Anchor ui:field="fullscreenAnchor" href="javascript:;" styleName="{res.mainCss.button} {local_res.css.regattaleaderboard_meta_fullscreen_button}"></g:Anchor>
</div>
</div>
<div class="{res.mediaCss.grid}" >
<div class="{res.mediaCss.small12} {res.mediaCss.columns} {local_res.css.letItScroll}">
<table class="{local_res.css.regattaleaderboard_table}">
<tr>
<td>
<g:HTMLPanel ui:field="oldMultiLeaderboardPanel" styleName="{local_res2.css.oldMultiLeaderboardPanel}">
</g:HTMLPanel>
</td>
</tr>
</table>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,16 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.oldmultileaderboard;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
public interface OldMultiLeaderboardResources extends ClientBundle {
public static final OldMultiLeaderboardResources INSTANCE = GWT.create(OldMultiLeaderboardResources.class);
@Source("com/sap/sailing/gwt/home/client/place/event/oldmultileaderboard/OldMultiLeaderboard.css")
LocalCss css();
public interface LocalCss extends CssResource {
String oldMultiLeaderboardPanel();
}
}
@@ -1,16 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:m="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.message" xmlns:u="urn:import:com.sap.sailing.gwt.home.client.place.event.partials.updatesBox">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_ubi" type="com.sap.sailing.gwt.common.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<g:HTMLPanel>
<div class="{res.mainCss.spacer} {res.mainCss.spacersmall}"></div>
<m:Message ui:field="message" />
<div class="{res.mediaCss.grid}">
<g:SimplePanel ui:field="stage" addStyleNames="{res.mediaCss.small12} {res.mediaCss.columns}" />
<div ui:field="updatesWrapperUi" class="{res.mediaCss.small12} {res.mediaCss.medium5} {res.mediaCss.large4} {res.mediaCss.columns}" style="display: none;">
<u:UpdatesBox ui:field="updatesUi" addStyleNames="{res.mainCss.spacermargin} {res.mainCss.spacermargintopsmall} {res.mainCss.spacermarginonlyonsmall}" />
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,190 +0,0 @@
.regatta {
font-size: 15px;
/* @alternate */ font-size: 1rem;
border-bottom: 1px solid #d9d9d9;
padding: 1.333333333333333em 0;
}
.regatta[data-rendermode='compact'] {
border-top: 1px solid #ccc;
padding-left: 4em;
padding-right: 4em;
}
.regatta[data-rendermode='compact'] .regatta_intro_details_itemhideoncompact {
display: none;
}
.regatta[data-rendermode='link']:hover,
.regatta[data-rendermode='link']:focus {
background-color: #fcfcfc;
}
.regatta[data-rendermode='link']:nth-child(odd) {
background-color: #f8f8f8;
}
.regatta[data-rendermode='link']:nth-child(odd):hover,
.regatta[data-rendermode='link']:nth-child(odd):focus {
background-color: #f3f3f3;
}
.regatta_intro {
display: block;
padding-left: 10.333333333333334em;
min-height: 9.333333333333334em;
position: relative;
}
.regatta_intro:hover,
.regatta_intro:focus {
text-decoration: none;
}
.regatta_intro_image {
border: 1px solid #ccc;
position: absolute;
top: 0;
left: 0;
}
.regatta_intro_header {
margin-bottom: 0.666666666666667em;
padding-top: 0.333333333333333em;
padding-bottom: 0.666666666666667em;
border-bottom: 1px solid #ccc;
position: relative;
}
.regatta_intro_header_name {
display: inline-block;
font-size: 1.333333333333333em;
margin: 0;
margin-right: 0.266666666666667em;
}
.regatta_intro_header_namelink:hover,
.regatta_intro_header_namelink:focus {
text-decoration: underline;
}
.regatta_intro_header_details {
text-align: right;
}
.regatta_intro_header_details_item {
display: inline-block;
padding: 0.2em 1em 0.2em 0;
margin-right: 1em;
border-right: 1px solid #ccc;
}
.regatta_intro_header_details_item:last-child {
padding-right: 0;
margin-right: 0;
border-right-width: 0;
}
.regatta_intro_header_details_item_value {
color: #008fcc;
font-weight: 700;
}
.regatta_intro_header_details_label {
vertical-align: middle;
margin-top: -0.2em;
}
.regatta_intro_phases {
position: relative;
padding-right: 10em;
border-bottom: 1px solid #ccc;
padding-bottom: 0.666666666666667em;
}
.regatta_intro_phases_phase {
display: block;
margin-right: 1.333333333333333em;
padding: 0.133333333333333em 1.333333333333333em 0.133333333333333em 0;
min-height: 2.666666666666667em;
}
@media (min-width: 50em) {
.regatta_intro_phases_phase {
display: inline-block;
border-right: 1px solid #ccc;
}
}
.regatta_intro_phases_phase_name {
font-size: 0.866666666666667em;
}
.regatta_intro_phases_phase_races {
display: inline-block;
}
.regatta_intro_phases_phase_races_race {
display: inline-block;
background-color: #ccc;
height: 0.666666666666667em;
width: 1.333333333333333em;
margin-right: 3px;
}
.regatta_intro_phases_phase_races_race[data-status='live'] {
background-color: #f00;
}
.regatta_intro_phases_phase_races_race[data-status='finished'] {
background-color: #f0ab00;
}
.regatta_intro_phases_leaderboardlink {
text-transform: uppercase;
z-index: 2;
position: absolute;
top: 0;
right: 0;
background-color: #008FCC;
color: white;
}
.regatta_intro_phases_leaderboardlink:hover {
background-color: #0177ab;
}
.regatta_intro_scheduled {
padding-top: 0.8em;
}
.regatta_intro_results {
padding-top: 0.6em;
}
.regatta_intro_results_competitor {
white-space: nowrap;
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
display: inline-block;
max-width: 32%;
padding: 0.2em 1.333333333333333em;
border-right: 1px solid #ccc;
}
.regatta_intro_results_competitor:first-child {
padding-left: 0;
}
.regatta_intro_results_competitor:last-child {
padding-right: 0;
border-right-width: 0;
}
.regatta_intro_results_competitor_name {
font-weight: 700;
color: #008fcc;
}
.regatta_intro_fleets {
width: 100%;
}
.regatta_intro_fleets_fleet {
border-bottom: 1px solid #ccc;
}
.regatta_intro_fleets_fleet:last-child {
padding-bottom: 0;
}
.regatta_intro_fleets_fleet_item {
margin: 0.4em 0;
padding: 0.4em 1.333333333333333em;
border-left: 1px solid #ccc;
white-space: nowrap;
}
.regatta_intro_fleets_fleet_itemfirst {
margin-left: 0;
padding-left: 0;
border-left-width: 0;
}
.regatta_intro_fleets_fleet_item_value {
font-weight: 700;
color: #008fcc;
}
.regatta_intro_fleets_fleet_item_flag {
width: 2em;
vertical-align: middle;
}
.regatta_intro_fleets_fleet_live {
text-align: right;
width: 100%;
}
@@ -1,169 +0,0 @@
package com.sap.sailing.gwt.home.client.place.event.partials;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.HeadingElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.BoatClassImageResolver;
import com.sap.sailing.gwt.common.client.BoatClassImageResources;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.EventView.Presenter;
import com.sap.sailing.gwt.home.client.shared.LongNamesUtil;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO;
public class Regatta extends Composite {
private static RegattaUiBinder uiBinder = GWT.create(RegattaUiBinder.class);
interface RegattaUiBinder extends UiBinder<Widget, Regatta> {
}
private final EventViewDTO event;
private RaceGroupDTO raceGroup;
private final List<RegattaPhase> phasesElements;
private LeaderboardGroupDTO leaderboardGroup;
private final boolean isSingleView;
@UiField DivElement regattaDiv;
@UiField HeadingElement regattaNameHeading;
@UiField DivElement leaderboardGroupName;
@UiField DivElement leaderboardGroupNameDiv;
// @UiField SpanElement scheduledStart;
@UiField DivElement regattaPhasesPanel;
@UiField DivElement regattaPhasesInfoDiv;
@UiField SpanElement competitorsCount;
@UiField DivElement competitorsCountDiv;
@UiField SpanElement racesCount;
@UiField SpanElement trackedRacesCount;
@UiField DivElement isLiveDiv;
@UiField Anchor regattaDetailsLink;
@UiField Image boatClassImage;
@UiField
AnchorElement boatClassLinkUi;
private Presenter presenter;
private PlaceNavigation<?> regattaNavigation;
public Regatta(boolean isSingleView, EventView.Presenter presenter) {
this.event = presenter.getCtx().getEventDTO();
this.isSingleView = isSingleView;
this.presenter = presenter;
phasesElements = new ArrayList<RegattaPhase>();
RegattaResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
public void setData(LeaderboardGroupDTO leaderboardGroup, boolean hasMultipleLeaderboardGroups, StrippedLeaderboardDTO leaderboard,
RaceGroupDTO raceGroup) {
this.raceGroup = raceGroup;
this.leaderboardGroup = leaderboardGroup;
if(isSingleView) {
regattaDetailsLink.setVisible(false);
} else {
regattaNavigation = presenter.getRegattaNavigation(leaderboard.regattaName != null ? leaderboard.regattaName : leaderboard.name);
regattaDetailsLink.setHref(regattaNavigation.getTargetUrl());
boatClassLinkUi.setHref(regattaNavigation.getTargetUrl());
Event.sinkEvents(boatClassLinkUi, Event.ONCLICK);
Event.setEventListener(boatClassLinkUi, new EventListener() {
@Override
public void onBrowserEvent(Event event) {
if (LinkUtil.handleLinkClick(event)) {
event.preventDefault();
regattaNavigation.goToPlace();
}
}
});
}
boolean hasLiveRace = leaderboard.hasLiveRace(presenter.getTimerForClientServerOffset().getLiveTimePointInMillis());
if(!hasLiveRace) {
isLiveDiv.getStyle().setDisplay(Display.NONE);
}
// boolean isFinished... TODO
if(raceGroup.boatClass != null) {
boatClassImage.setResource(BoatClassImageResolver.getBoatClassIconResource(raceGroup.boatClass));
} else {
boatClassImage.setResource(BoatClassImageResources.INSTANCE.genericBoatClass());
}
String regattaDisplayName = leaderboard.displayName != null ? leaderboard.displayName : leaderboard.name;
regattaNameHeading.setInnerText(regattaDisplayName);
if(hasMultipleLeaderboardGroups && leaderboardGroup.getName() != null) {
leaderboardGroupName.setInnerText(LongNamesUtil.shortenLeaderboardGroupName(event.getDisplayName(), leaderboardGroup.getName()));
leaderboardGroupName.setAttribute("data-labeltype", "group1");
} else {
leaderboardGroupNameDiv.removeFromParent();
}
if(leaderboard.competitorsCount > 0) {
competitorsCount.setInnerText(String.valueOf(leaderboard.competitorsCount));
} else {
competitorsCountDiv.getStyle().setDisplay(Display.NONE);
}
setRegattaProgress(leaderboard);
}
private void setRegattaProgress(StrippedLeaderboardDTO leaderboard) {
// clear first
regattaPhasesPanel.removeAllChildren();
phasesElements.clear();
if(raceGroup != null) {
if(raceGroup.getSeries().size() == 0) {
regattaPhasesInfoDiv.getStyle().setDisplay(Display.NONE);
} else {
for(RaceGroupSeriesDTO series: raceGroup.getSeries()) {
RegattaPhase regattaPhase = new RegattaPhase(series, leaderboardGroup,
leaderboard, raceGroup, presenter);
regattaPhasesPanel.appendChild(regattaPhase.getElement());
phasesElements.add(regattaPhase);
}
}
}
racesCount.setInnerText(String.valueOf(leaderboard.getRacesCount()));
trackedRacesCount.setInnerText(String.valueOf(leaderboard.getTrackedRacesCount()));
}
@UiHandler("regattaDetailsLink")
void regattaDetailsLinkClicked(ClickEvent e) {
handleClickEvent(e, regattaNavigation);
}
private void handleClickEvent(ClickEvent e, PlaceNavigation<?> place) {
if (LinkUtil.handleLinkClick((Event) e.getNativeEvent())) {
place.goToPlace();
e.preventDefault();
}
}
}
Loaded 100 of 826 files, more files were not shown because too many files have changed in this diff. Show more