From 252ef5734d2a6a3deac972a2ad92d119c154194f Mon Sep 17 00:00:00 2001 From: D049941 Date: Mon, 27 May 2013 17:09:06 +0200 Subject: [PATCH 01/13] Basic implementation for CellTable added to be able to delete existing leaderboards. This is needed since we can't drop the database for tests at the moment. Therefore we can't provide a well know state for tests and tests have to perform all necessary steps to establish the preconditions for the test. --- .../adminconsole/LeaderboardConfigPanel.java | 2283 +++++++++-------- .../adminconsole/TestLeaderboardCreation.java | 9 +- .../pages/LeaderboardConfigurationPanel.java | 109 +- .../selenium/test/gwt/widgets/CellTable.java | 129 +- 4 files changed, 1326 insertions(+), 1204 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index b873ac08e14..1aa8771cda5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -1,1142 +1,1143 @@ -package com.sap.sailing.gwt.ui.adminconsole; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.google.gwt.cell.client.AbstractCell; -import com.google.gwt.cell.client.FieldUpdater; -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.safehtml.client.SafeHtmlTemplates; -import com.google.gwt.safehtml.shared.SafeHtml; -import com.google.gwt.safehtml.shared.SafeHtmlBuilder; -import com.google.gwt.safehtml.shared.SafeHtmlUtils; -import com.google.gwt.user.cellview.client.CellTable; -import com.google.gwt.user.cellview.client.Column; -import com.google.gwt.user.cellview.client.ColumnSortEvent; -import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; -import com.google.gwt.user.cellview.client.ColumnSortList; -import com.google.gwt.user.cellview.client.TextColumn; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.CaptionPanel; -import com.google.gwt.user.client.ui.FormPanel; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HasHorizontalAlignment; -import com.google.gwt.user.client.ui.HasVerticalAlignment; -import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.VerticalPanel; -import com.google.gwt.view.client.ListDataProvider; -import com.google.gwt.view.client.SelectionChangeEvent; -import com.google.gwt.view.client.SingleSelectionModel; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.domain.common.impl.Util.Pair; -import com.sap.sailing.gwt.ui.adminconsole.DisablableCheckboxCell.IsEnabled; -import com.sap.sailing.gwt.ui.adminconsole.RaceColumnInLeaderboardDialog.RaceColumnDescriptor; -import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback; -import com.sap.sailing.gwt.ui.client.ErrorReporter; -import com.sap.sailing.gwt.ui.client.MarkedAsyncCallback; -import com.sap.sailing.gwt.ui.client.ParallelExecutionCallback; -import com.sap.sailing.gwt.ui.client.ParallelExecutionHolder; -import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener; -import com.sap.sailing.gwt.ui.client.RaceSelectionModel; -import com.sap.sailing.gwt.ui.client.RaceSelectionProvider; -import com.sap.sailing.gwt.ui.client.RegattaDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.client.URLEncoder; -import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint; -import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; -import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; -import com.sap.sailing.gwt.ui.shared.EventDTO; -import com.sap.sailing.gwt.ui.shared.RegattaDTO; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; - -public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderboardProvider, RegattaDisplayer, RaceSelectionChangeListener, - TrackedRaceChangedListener { - - private final TrackedRacesListComposite trackedRacesListComposite; - - private final StringMessages stringMessages; - - private final SailingServiceAsync sailingService; - - private final ListDataProvider leaderboardList; - - private final ListDataProvider> raceColumnAndFleetList; - - private final ErrorReporter errorReporter; - - private final CellTable leaderboardTable; - - private final CellTable> raceColumnTable; - - private StrippedLeaderboardDTO selectedLeaderboard; - - private Pair selectedRaceInLeaderboard; - - private final Button addRaceColumnsButton; - - private final Button columnMoveUpButton; - private final Button columnMoveDownButton; - - private final CaptionPanel selectedLeaderBoardPanel; - private final CaptionPanel trackedRacesCaptionPanel; - private final List allRegattas; - - private TextBox filterLeaderboardTextbox; - - final SingleSelectionModel> raceColumnTableSelectionModel; - - private List availableLeaderboardList; - - private final SingleSelectionModel leaderboardSelectionModel; - - private final RaceSelectionProvider raceSelectionProvider; - - public static class AnchorCell extends AbstractCell { - - @Override - public void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml safeHtml, SafeHtmlBuilder sb) { - sb.append(safeHtml); - } - } - - interface AnchorTemplates extends SafeHtmlTemplates { - @SafeHtmlTemplates.Template("{1}") - SafeHtml cell(String url, String displayName); - } - - private static AnchorTemplates ANCHORTEMPLATE = GWT.create(AnchorTemplates.class); - - public LeaderboardConfigPanel(SailingServiceAsync sailingService, AdminConsoleEntryPoint adminConsole, - final ErrorReporter errorReporter, StringMessages theStringConstants, final boolean showRaceDetails) { - this.stringMessages = theStringConstants; - this.sailingService = sailingService; - leaderboardList = new ListDataProvider(); - allRegattas = new ArrayList(); - raceColumnAndFleetList = new ListDataProvider>(); - this.errorReporter = errorReporter; - this.availableLeaderboardList = new ArrayList(); - VerticalPanel mainPanel = new VerticalPanel(); - mainPanel.setWidth("100%"); - this.setWidget(mainPanel); - - //Create leaderboards list and functionality - CaptionPanel leaderboardsCaptionPanel = new CaptionPanel(stringMessages.leaderboards()); - leaderboardsCaptionPanel.setStyleName("bold"); - leaderboardsCaptionPanel.setWidth("75%"); - mainPanel.add(leaderboardsCaptionPanel); - - VerticalPanel leaderboardsPanel = new VerticalPanel(); - leaderboardsCaptionPanel.add(leaderboardsPanel); - - Label lblFilterEvents = new Label(stringMessages.filterLeaderboardsByName() + ": "); - HorizontalPanel filterPanel = new HorizontalPanel(); - filterPanel.setSpacing(5); - filterPanel.add(lblFilterEvents); - filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE); - filterLeaderboardTextbox = new TextBox(); - filterLeaderboardTextbox.addKeyUpHandler(new KeyUpHandler() { - @Override - public void onKeyUp(KeyUpEvent event) { - fillRaceListFromAvailableLeaderboardsApplyingFilter(); - } - }); - filterPanel.add(filterLeaderboardTextbox); - leaderboardsPanel.add(filterPanel); - - AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); - leaderboardTable = new CellTable(/* pageSize */10000, tableRes); - ListHandler leaderboardColumnListHandler = new ListHandler( - leaderboardList.getList()); - - AnchorCell anchorCell = new AnchorCell(); - Column linkColumn = new Column(anchorCell) { - @Override - public SafeHtml getValue(StrippedLeaderboardDTO object) { - String debugParam = Window.Location.getParameter("gwt.codesvr"); - String link = URLEncoder.encode("/gwt/Leaderboard.html?name=" + object.name - + (showRaceDetails ? "&showRaceDetails=true" : "") - + (object.displayName != null ? "&displayName="+object.displayName : "") - + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); - return ANCHORTEMPLATE.cell(link, object.name); - } - - }; - linkColumn.setSortable(true); - leaderboardColumnListHandler.setComparator(linkColumn, new Comparator() { - - @Override - public int compare(StrippedLeaderboardDTO o1, StrippedLeaderboardDTO o2) { - boolean ascending = isSortedAscending(); - if (o1.name.equals(o2.name)) { - return 0; - } - int val = -1; - val = (o1 != null && o2 != null && ascending) ? (o1.name.compareTo(o2.name)) : -(o2.name - .compareTo(o1.name)); - return val; - } - - private boolean isSortedAscending() { - ColumnSortList sortList = leaderboardTable.getColumnSortList(); - return sortList.size() > 0 & sortList.get(0).isAscending(); - } - }); - - TextColumn leaderboardDisplayNameColumn = new TextColumn() { - @Override - public String getValue(StrippedLeaderboardDTO leaderboard) { - return leaderboard.getDisplayName() !=null ? leaderboard.getDisplayName() : ""; - } - }; - - TextColumn discardingOptionsColumn = new TextColumn() { - @Override - public String getValue(StrippedLeaderboardDTO leaderboard) { - String result = ""; - if (leaderboard.discardThresholds != null) { - for (int discardThreshold : leaderboard.discardThresholds) { - result += discardThreshold + " "; - } - } - return result; - } - }; - - TextColumn leaderboardTypeColumn = new TextColumn() { - @Override - public String getValue(StrippedLeaderboardDTO leaderboard) { - String result = leaderboard.isRegattaLeaderboard ? "Regatta" : "Flexible"; - if(leaderboard.isMetaLeaderboard) { - result += " , Meta"; - } - return result; - } - }; - - TextColumn scoringSystemColumn = new TextColumn() { - @Override - public String getValue(StrippedLeaderboardDTO leaderboard) { - return leaderboard.scoringScheme == null ? "" : ScoringSchemeTypeFormatter.format(leaderboard.scoringScheme, stringMessages); - } - }; - - TextColumn courseAreaColumn = new TextColumn() { - @Override - public String getValue(StrippedLeaderboardDTO leaderboard) { - return leaderboard.defaultCourseAreaIdAsString == null ? "" : leaderboard.defaultCourseAreaName; - } - }; - - ImagesBarColumn leaderboardActionColumn = new ImagesBarColumn( - new LeaderboardConfigImagesBarCell(stringMessages)); - leaderboardActionColumn.setFieldUpdater(new FieldUpdater() { - @Override - public void update(int index, StrippedLeaderboardDTO leaderboardDTO, String value) { - if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { - if (Window.confirm("Do you really want to remove the leaderboard: '" + leaderboardDTO.name + "' ?")) { - removeLeaderboard(leaderboardDTO); - } - } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { - final String oldLeaderboardName = leaderboardDTO.name; - List otherExistingLeaderboard = new ArrayList(); - otherExistingLeaderboard.addAll(availableLeaderboardList); - otherExistingLeaderboard.remove(leaderboardDTO); - if (leaderboardDTO.isMetaLeaderboard) { - Window.alert("This is a meta leaderboard. It can't be changed here."); - } else { - if (leaderboardDTO.isRegattaLeaderboard) { - LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, - leaderboardDTO.displayName, null, leaderboardDTO.discardThresholds, leaderboardDTO.regattaName, leaderboardDTO.defaultCourseAreaIdAsString); - AbstractLeaderboardDialog dialog = new RegattaLeaderboardEditDialog(Collections - .unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas), - descriptor, stringMessages, errorReporter, - new DialogCallback() { - @Override - public void cancel() { - } - - @Override - public void ok(LeaderboardDescriptor result) { - updateLeaderboard(oldLeaderboardName, result); - } - }); - dialog.show(); - } else { - LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, leaderboardDTO.displayName, leaderboardDTO.scoringScheme, leaderboardDTO.discardThresholds, leaderboardDTO.defaultCourseAreaIdAsString); - openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, leaderboardDTO.name, descriptor); - } - } - } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT_SCORES.equals(value)) { - String debugParam = Window.Location.getParameter("gwt.codesvr"); - Window.open("/gwt/LeaderboardEditing.html?name=" + leaderboardDTO.name - + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""), "_blank", null); - } else if (LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL.equals(value)) { - openLeaderboardUrlConfigDialog(leaderboardDTO, stringMessages); - } - } - }); - leaderboardTable.addColumn(linkColumn, stringMessages.name()); - leaderboardTable.addColumn(leaderboardDisplayNameColumn, stringMessages.displayName()); - leaderboardTable.addColumn(discardingOptionsColumn, stringMessages.discarding()); - leaderboardTable.addColumn(leaderboardTypeColumn, stringMessages.type()); - leaderboardTable.addColumn(scoringSystemColumn, stringMessages.scoringSystem()); - leaderboardTable.addColumn(courseAreaColumn, stringMessages.courseArea()); - leaderboardTable.addColumn(leaderboardActionColumn, stringMessages.actions()); - leaderboardTable.addColumnSortHandler(leaderboardColumnListHandler); - leaderboardTable.setWidth("100%"); - leaderboardSelectionModel = new SingleSelectionModel(); - leaderboardTable.setSelectionModel(leaderboardSelectionModel); - leaderboardSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { - public void onSelectionChange(SelectionChangeEvent event) { - setSelectedLeaderboard(leaderboardSelectionModel.getSelectedObject()); - leaderboardSelectionChanged(); - } - }); - leaderboardList.addDataDisplay(leaderboardTable); - leaderboardsPanel.add(leaderboardTable); - HorizontalPanel leaderboardButtonPanel = new HorizontalPanel(); - leaderboardButtonPanel.setSpacing(5); - leaderboardsPanel.add(leaderboardButtonPanel); - Button createFlexibleLeaderboardBtn = new Button(stringMessages.createFlexibleLeaderboard() + "..."); - createFlexibleLeaderboardBtn.ensureDebugId("CreateFlexibleLeaderboardButton"); - leaderboardButtonPanel.add(createFlexibleLeaderboardBtn); - createFlexibleLeaderboardBtn.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent clickEvent) { - createFlexibleLeaderboard(); - } - }); - - Button createRegattaLeaderboardBtn = new Button(stringMessages.createRegattaLeaderboard() + "..."); - createRegattaLeaderboardBtn.ensureDebugId("CreateRegattaLeaderboardButton"); - leaderboardButtonPanel.add(createRegattaLeaderboardBtn); - createRegattaLeaderboardBtn.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent clickEvent) { - createRegattaLeaderboard(); - } - }); - - mainPanel.add(new Grid(1, 1)); - - // caption panels for the selected leaderboard and tracked races - HorizontalPanel splitPanel = new HorizontalPanel(); - mainPanel.add(splitPanel); - - selectedLeaderBoardPanel = new CaptionPanel(stringMessages.leaderboard()); - selectedLeaderBoardPanel.setWidth("50%"); - splitPanel.add(selectedLeaderBoardPanel); - - VerticalPanel vPanel = new VerticalPanel(); - vPanel.setWidth("100%"); - selectedLeaderBoardPanel.setContentWidget(vPanel); - - trackedRacesCaptionPanel = new CaptionPanel(stringMessages.trackedRaces()); - trackedRacesCaptionPanel.setWidth("50%"); - splitPanel.add(trackedRacesCaptionPanel); - - VerticalPanel trackedRacesPanel = new VerticalPanel(); - trackedRacesPanel.setWidth("100%"); - trackedRacesCaptionPanel.setContentWidget(trackedRacesPanel); - trackedRacesCaptionPanel.setStyleName("bold"); - - raceSelectionProvider = new RaceSelectionModel(); - trackedRacesListComposite = new TrackedRacesListComposite(sailingService, errorReporter, adminConsole, - raceSelectionProvider, stringMessages, /* multiselection */false); - trackedRacesPanel.add(trackedRacesListComposite); - trackedRacesListComposite.addTrackedRaceChangeListener(this); - raceSelectionProvider.addRaceSelectionChangeListener(this); - - HorizontalPanel hPanel = new HorizontalPanel(); - hPanel.setSpacing(5); - vPanel.add(hPanel); - - // ------------ races of the selected leaderboard ---------------- - AnchorCell raceAnchorCell = new AnchorCell(); - Column, SafeHtml> raceLinkColumn = new Column, SafeHtml>(raceAnchorCell) { - @Override - public SafeHtml getValue(Pair raceInLeaderboardDTOAndFleetName) { - if (raceInLeaderboardDTOAndFleetName.getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB()) != null) { - RegattaNameAndRaceName raceIdentifier = (RegattaNameAndRaceName) raceInLeaderboardDTOAndFleetName - .getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB()); - String debugParam = Window.Location.getParameter("gwt.codesvr"); - String link = URLEncoder.encode("/gwt/RaceBoard.html?leaderboardName=" - + getSelectedLeaderboard().name + "&raceName=" + raceIdentifier.getRaceName() + "®attaName=" - + raceIdentifier.getRegattaName() - + "&"+RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES+"=true" - + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); - return ANCHORTEMPLATE.cell(link, raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName()); - } else { - return SafeHtmlUtils.fromString(raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName()); - } - } - }; - TextColumn> fleetNameColumn = new TextColumn>() { - @Override - public String getValue(Pair object) { - return object.getB().name; - } - }; - TextColumn> explicitFactorColumn = new TextColumn>() { - @Override - public String getValue(Pair object) { - return object.getA().getExplicitFactor() == null ? "" : object.getA().getExplicitFactor().toString(); - } - }; - - Column, Boolean> isMedalRaceCheckboxColumn = new Column, Boolean>( - new DisablableCheckboxCell(new IsEnabled() { - @Override - public boolean isEnabled() { - return getSelectedLeaderboard() != null && !getSelectedLeaderboard().isRegattaLeaderboard; - } - })) { - @Override - public Boolean getValue(Pair race) { - return race.getA().isMedalRace(); - } - }; - isMedalRaceCheckboxColumn.setFieldUpdater(new FieldUpdater, Boolean>() { - @Override - public void update(int index, Pair object, Boolean value) { - setIsMedalRace(getSelectedLeaderboard().name, object.getA(), value); - } - }); - isMedalRaceCheckboxColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - - TextColumn> isLinkedRaceColumn = new TextColumn>() { - @Override - public String getValue(Pair raceColumnAndFleetName) { - boolean isTrackedRace = raceColumnAndFleetName.getA().isTrackedRace(raceColumnAndFleetName.getB()); - return isTrackedRace ? stringMessages.yes() : stringMessages.no(); - } - }; - ImagesBarColumn, LeaderboardRaceConfigImagesBarCell> raceActionColumn = - new ImagesBarColumn, LeaderboardRaceConfigImagesBarCell>( - new LeaderboardRaceConfigImagesBarCell(this, stringMessages)); - raceActionColumn.setFieldUpdater(new FieldUpdater, String>() { - @Override - public void update(int index, Pair object, String value) { - if (LeaderboardRaceConfigImagesBarCell.ACTION_REMOVE.equals(value)) { - if (Window.confirm(stringMessages.reallyRemoveRace(object.getA().getRaceColumnName()))) { - removeRaceColumn(object.getA()); - } - } else if (LeaderboardRaceConfigImagesBarCell.ACTION_EDIT.equals(value)) { - editRaceColumnOfLeaderboard(object); - } else if (LeaderboardRaceConfigImagesBarCell.ACTION_UNLINK.equals(value)) { - unlinkRaceColumnFromTrackedRace(object.getA().getRaceColumnName(), object.getB()); - } - } - }); - Label lblRaceNamesIn = new Label(stringMessages.races()); - vPanel.add(lblRaceNamesIn); - raceColumnTable = new CellTable>(/* pageSize */200, tableRes); - raceColumnTable.addColumn(raceLinkColumn, stringMessages.name()); - raceColumnTable.addColumn(fleetNameColumn, stringMessages.fleet()); - raceColumnTable.addColumn(isMedalRaceCheckboxColumn, stringMessages.medalRace()); - raceColumnTable.addColumn(isLinkedRaceColumn, stringMessages.islinked()); - raceColumnTable.addColumn(explicitFactorColumn, stringMessages.factor()); - raceColumnTable.addColumn(raceActionColumn, stringMessages.actions()); - raceColumnAndFleetList.addDataDisplay(raceColumnTable); - raceColumnTable.setWidth("500px"); - raceColumnTableSelectionModel = new SingleSelectionModel>(); - raceColumnTable.setSelectionModel(raceColumnTableSelectionModel); - raceColumnTableSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { - public void onSelectionChange(SelectionChangeEvent event) { - leaderboardRaceColumnSelectionChanged(); - } - }); - vPanel.add(raceColumnTable); - - HorizontalPanel selectedLeaderboardRaceButtonPanel = new HorizontalPanel(); - selectedLeaderboardRaceButtonPanel.setSpacing(5); - vPanel.add(selectedLeaderboardRaceButtonPanel); - - addRaceColumnsButton = new Button(stringMessages.actionAddRaces() + "..."); - selectedLeaderboardRaceButtonPanel.add(addRaceColumnsButton); - addRaceColumnsButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - if (getSelectedLeaderboard().isRegattaLeaderboard) { - Window.alert(stringMessages.cannotAddRacesToRegattaLeaderboardButOnlyToRegatta()); - } else { - addRaceColumnsToLeaderboard(); - } - } - }); - - columnMoveUpButton = new Button(stringMessages.columnMoveUp()); - selectedLeaderboardRaceButtonPanel.add(columnMoveUpButton); - columnMoveUpButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - moveSelectedRaceColumnUp(); - } - }); - columnMoveDownButton = new Button(stringMessages.columnMoveDown()); - selectedLeaderboardRaceButtonPanel.add(columnMoveDownButton); - columnMoveDownButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - moveSelectedRaceColumnDown(); - } - }); - - loadAndRefreshLeaderboards(); - } - - protected void openUpdateFlexibleLeaderboardDialog(final StrippedLeaderboardDTO leaderboardDTO, final List otherExistingLeaderboard, - final String oldLeaderboardName, final LeaderboardDescriptor descriptor) { - sailingService.getEvents(new AsyncCallback>() { - @Override - public void onSuccess(List result) { - openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, - descriptor, result); - } - - @Override - public void onFailure(Throwable caught) { - openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, - descriptor, new ArrayList()); - } - }); - } - - protected void openUpdateFlexibleLeaderboardDialog(StrippedLeaderboardDTO leaderboardDTO, List otherExistingLeaderboard, - final String oldLeaderboardName, LeaderboardDescriptor descriptor, List existingEvents) { - FlexibleLeaderboardEditDialog dialog = new FlexibleLeaderboardEditDialog( - Collections.unmodifiableCollection(otherExistingLeaderboard), descriptor, stringMessages, - Collections.unmodifiableList(existingEvents), errorReporter, - new DialogCallback() { - @Override - public void cancel() { - } - - @Override - public void ok(LeaderboardDescriptor result) { - updateLeaderboard(oldLeaderboardName, result); - } - }); - dialog.show(); - } - - /** - * Allow the user to combine the various URL parameters that exist for the {@link LeaderboardEntryPoint} and obtain the - * resulting URL in a link. The link's reference target is updated dynamically as the user adjusts the settings. Therefore, - * the link can be clicked, bookmarked or copied to the clipboard at any time. The OK / Cancel actions for the dialog shown - * are no-ops. - */ - private void openLeaderboardUrlConfigDialog(AbstractLeaderboardDTO leaderboard, StringMessages stringMessages) { - LeaderboardEntryPoint.getUrlConfigurationDialog(leaderboard, stringMessages).show(); - } - - public void loadAndRefreshLeaderboards() { - sailingService.getLeaderboards(new AsyncCallback>() { - @Override - public void onSuccess(List leaderboards) { - leaderboardList.getList().clear(); - availableLeaderboardList.clear(); - leaderboardList.getList().addAll(leaderboards); - availableLeaderboardList.addAll(leaderboards); - fillRaceListFromAvailableLeaderboardsApplyingFilter(); - leaderboardSelectionChanged(); - leaderboardRaceColumnSelectionChanged(); - } - - @Override - public void onFailure(Throwable t) { - LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to obtain list of leaderboards: " - + t.getMessage()); - } - }); - } - - /** - * @param nameOfRaceColumnToSelect - * if not null, selects the first race column name with this name found in the leaderboard - * after the refresh has successfully completed. See {@link #selectRaceColumn(String)}. - */ - public void loadAndRefreshLeaderboard(final String leaderboardName, final String nameOfRaceColumnToSelect) { - leaderboardSelectionModel.setSelected(null, true); - sailingService.getLeaderboard(leaderboardName, new AsyncCallback() { - @Override - public void onSuccess(StrippedLeaderboardDTO leaderboard) { - replaceLeaderboardInList(leaderboardList.getList(), leaderboardName, leaderboard); - replaceLeaderboardInList(availableLeaderboardList, leaderboardName, leaderboard); - leaderboardSelectionModel.setSelected(leaderboard, true); - if (nameOfRaceColumnToSelect != null) { - selectRaceColumn(nameOfRaceColumnToSelect); - } - } - - @Override - public void onFailure(Throwable t) { - LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to update leaderboard with name " + leaderboardName +" : " - + t.getMessage()); - } - }); - } - - private void replaceLeaderboardInList(List leaderboardList, String leaderboardToReplace, StrippedLeaderboardDTO newLeaderboard) { - int index = -1; - for (StrippedLeaderboardDTO existingLeaderboard : leaderboardList) { - index++; - if (existingLeaderboard.name.equals(leaderboardToReplace)) { - break; - } - } - if (index >= 0) { - leaderboardList.set(index, newLeaderboard); - } - } - - private void unlinkRaceColumnFromTrackedRace(final String raceColumnName, final FleetDTO fleet) { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, fleet.name, - new AsyncCallback() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumnName - + " from leaderboard " + selectedLeaderboardName + ": " + t.getMessage()); - } - - @Override - public void onSuccess(Void arg0) { - trackedRacesListComposite.clearSelection(); - getSelectedRaceColumnWithFleet().getA().setRaceIdentifier(fleet, null); - raceColumnAndFleetList.refresh(); - } - }); - } - - private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - final String raceColumnString = raceColumnDTO.getRaceColumnName(); - sailingService.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString, - new AsyncCallback() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumnDTO - + " in leaderboard " + getSelectedLeaderboardName() + ": " + t.getMessage()); - } - - @Override - public void onSuccess(Void arg0) { - loadAndRefreshLeaderboard(selectedLeaderboardName, /* raceColumnNameToSelect */ null); - } - }); - } - - /** - * The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case, - * move all fleet-based rows of the same RaceColumn down. - */ - private void moveSelectedRaceColumnDown() { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); - sailingService.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to move leaderboard race column " - + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() - + " down: " + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); - } - }); - } - - /** - * The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case, - * move all fleet-based rows of the same RaceColumn down. - */ - private void moveSelectedRaceColumnUp() { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); - sailingService.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to move leaderboard race column " - + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + " up: " - + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); - } - }); - } - - private void leaderboardRaceColumnSelectionChanged() { - selectedRaceInLeaderboard = getSelectedRaceColumnWithFleet(); - if (selectedRaceInLeaderboard != null) { - columnMoveUpButton.setEnabled(true); - columnMoveDownButton.setEnabled(true); - selectTrackedRaceInRaceList(); - } else { - columnMoveUpButton.setEnabled(false); - columnMoveDownButton.setEnabled(false); - trackedRacesListComposite.clearSelection(); - } - } - - private void selectRaceColumn(String raceCoumnName) { - List> list = raceColumnAndFleetList.getList(); - for (Pair pair : list) { - if (pair.getA().name.equals(raceCoumnName)) { - raceColumnTableSelectionModel.setSelected(pair, true); - break; - } - } - } - - private void selectTrackedRaceInRaceList() { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - final Pair selectedRaceColumnAndFleetNameInLeaderboard = getSelectedRaceColumnWithFleet(); - final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA().getRaceColumnName(); - final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().name; - sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName, - selectedRaceColumnName, new AsyncCallback>() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to determine tracked race linked to race column " - + selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " - + t.getMessage()); - } - - @Override - public void onSuccess(Map regattaAndRaceNamesPerFleet) { - if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) { - RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet.get(selectedFleetName); - if (raceIdentifier != null) { - selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()); - } else { - trackedRacesListComposite.clearSelection(); - } - } else { - trackedRacesListComposite.clearSelection(); - } - } - }); - } - - private void selectRaceInList(String regattaName, String raceName) { - RegattaNameAndRaceName raceIdentifier = new RegattaNameAndRaceName(regattaName, raceName); - trackedRacesListComposite.selectRaceByIdentifier(raceIdentifier); - } - - private Pair getSelectedRaceColumnWithFleet() { - Pair raceInLeaderboardAndFleetName = raceColumnTableSelectionModel.getSelectedObject(); - return raceInLeaderboardAndFleetName; - } - - private void editRaceColumnOfLeaderboard(final Pair raceColumnWithFleet) { - final String selectedLeaderboardName = getSelectedLeaderboardName(); - final boolean oldIsMedalRace = raceColumnWithFleet.getA().isMedalRace(); - final String oldRaceColumnName = raceColumnWithFleet.getA().getRaceColumnName(); - final Double oldExplicitFactor = raceColumnWithFleet.getA().getExplicitFactor(); - // use a set to avoid duplicates in the case of regatta leaderboards with multiple fleets per column - Set existingRacesWithoutThisRace = new HashSet(); - for (Pair pair : raceColumnAndFleetList.getList()) { - existingRacesWithoutThisRace.add(pair.getA()); - } - existingRacesWithoutThisRace.remove(raceColumnWithFleet.getA()); - final RaceColumnInLeaderboardDialog raceDialog = new RaceColumnInLeaderboardDialog(existingRacesWithoutThisRace, - raceColumnWithFleet.getA(), getSelectedLeaderboard().isRegattaLeaderboard, stringMessages, new DialogCallback() { - @Override - public void cancel() { - } - - @Override - public void ok(final RaceColumnDescriptor result) { - boolean rename = !oldRaceColumnName.equals(result.getName()); - boolean updateIsMedalRace = oldIsMedalRace != result.isMedalRace(); - boolean updateFactor = oldExplicitFactor != result.getExplicitFactor(); - List> callbacks = new ArrayList>(); - final ParallelExecutionCallback renameLeaderboardColumnCallback = new ParallelExecutionCallback(); - if (rename) { - callbacks.add(renameLeaderboardColumnCallback); - } - final ParallelExecutionCallback updateIsMedalRaceCallback = new ParallelExecutionCallback(); - if (updateIsMedalRace) { - callbacks.add(updateIsMedalRaceCallback); - } - final ParallelExecutionCallback updateLeaderboardColumnFactorCallback = new ParallelExecutionCallback(); - if (updateFactor) { - callbacks.add(updateLeaderboardColumnFactorCallback); - } - new ParallelExecutionHolder(callbacks.toArray(new ParallelExecutionCallback[0])) { - @Override - public void handleSuccess() { - loadAndRefreshLeaderboard(selectedLeaderboardName, result.getName()); - } - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to update data of race column " - + oldRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " - + t.getMessage()); - } - }; - if (rename) { - sailingService.renameLeaderboardColumn(selectedLeaderboardName, oldRaceColumnName, - result.getName(), renameLeaderboardColumnCallback); - } - if (updateIsMedalRace) { - sailingService.updateIsMedalRace(selectedLeaderboardName, result.getName(), - result.isMedalRace(), updateIsMedalRaceCallback); - } - if (updateFactor) { - sailingService.updateLeaderboardColumnFactor(selectedLeaderboardName, result.getName(), - result.getExplicitFactor(), updateLeaderboardColumnFactorCallback); - } - } - }); - raceDialog.show(); - } - - private void setIsMedalRace(String leaderboardName, final RaceColumnDTO raceInLeaderboard, - final boolean isMedalRace) { - sailingService.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError(stringMessages.errorUpdatingIsMedalRace(caught.getMessage())); - } - @Override - public void onSuccess(Void result) { - getSelectedLeaderboard().setIsMedalRace(raceInLeaderboard.getRaceColumnName(), isMedalRace); - } - }); - } - - private void addRaceColumnsToLeaderboard() { - final String leaderboardName = getSelectedLeaderboardName(); - final List existingRaceColumns = new ArrayList(); - for (Pair pair : raceColumnAndFleetList.getList()) { - existingRaceColumns.add(pair.getA()); - } - final RaceColumnsInLeaderboardDialog raceDialog = new RaceColumnsInLeaderboardDialog(existingRaceColumns, - stringMessages, new DialogCallback>() { - @Override - public void cancel() { - } - - @Override - public void ok(final List result) { - updateRaceColumnsOfLeaderboard(leaderboardName, existingRaceColumns, result); - } - }); - raceDialog.show(); - } - - private void updateRaceColumnsOfLeaderboard(final String leaderboardName, List existingRaceColumns, List newRaceColumns) { - final List> raceColumnsToAdd = new ArrayList>(); - - for(RaceColumnDTO newRaceColumn: newRaceColumns) { - if(!existingRaceColumns.contains(newRaceColumn)) { - raceColumnsToAdd.add(new Pair(newRaceColumn.name, newRaceColumn.isMedalRace())); - } - } - - sailingService.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to add race columns to leaderboard " + leaderboardName - + ": " + caught.getMessage()); - } - - @Override - public void onSuccess(Void v) { - loadAndRefreshLeaderboard(leaderboardName, /* nameOfRaceColumnToSelect */ null); - } - }); - } - - private String getSelectedLeaderboardName() { - return getSelectedLeaderboard() != null ? getSelectedLeaderboard().name : null; - } - - private void leaderboardSelectionChanged() { - // make sure that clearing the selection doesn't cause an unlinking of the selected tracked race - raceSelectionProvider.removeRaceSelectionChangeListener(this); - trackedRacesListComposite.clearSelection(); - // add listener again using a scheduled command which is executed when the browser's event loop re-gains - // control; we assume that at that point in time the selection updates have already been performed - Scheduler.get().scheduleFinally(new ScheduledCommand() { - @Override - public void execute() { - raceSelectionProvider.addRaceSelectionChangeListener(LeaderboardConfigPanel.this); - } - }); - if (getSelectedLeaderboard() != null) { - raceColumnAndFleetList.getList().clear(); - for (RaceColumnDTO raceColumn : getSelectedLeaderboard().getRaceList()) { - for (FleetDTO fleet : raceColumn.getFleets()) { - raceColumnAndFleetList.getList().add(new Pair(raceColumn, fleet)); - } - } - selectedLeaderBoardPanel.setVisible(true); - selectedLeaderBoardPanel.setCaptionText("Details of leaderboard '" + getSelectedLeaderboard().name + "'"); - if (!getSelectedLeaderboard().isMetaLeaderboard) { - trackedRacesCaptionPanel.setVisible(true); - } - addRaceColumnsButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); - columnMoveUpButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); - columnMoveDownButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); - } else { - selectedLeaderBoardPanel.setVisible(false); - trackedRacesCaptionPanel.setVisible(false); - setSelectedLeaderboard(null); - selectedRaceInLeaderboard = null; - } - } - - @Override - public void fillRegattas(List regattas) { - trackedRacesListComposite.fillRegattas(regattas); - - allRegattas.clear(); - allRegattas.addAll(regattas); - } - - @Override - public void changeTrackingRace(Iterable regattaAndRaceIdentifiers, boolean isTracked) { - for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { - for (Pair raceColumnAndFleetName : raceColumnAndFleetList.getList()) { - if (raceColumnAndFleetName.getA().getRaceColumnName().equals(regattaAndRaceIdentifier.getRaceName())) { - raceColumnAndFleetName.getA().setRaceIdentifier(raceColumnAndFleetName.getB(), - regattaAndRaceIdentifier); - } - } - raceColumnAndFleetList.refresh(); - } - } - - private void createFlexibleLeaderboard() { - sailingService.getEvents(new MarkedAsyncCallback>() { - - @Override - public void handleSuccess(List result) { - createFlexibleLeaderboard(result); - } - - @Override - public void handleFailure(Throwable caught) { - createFlexibleLeaderboard(new ArrayList()); - } - }); - } - - private void createFlexibleLeaderboard(List existingEvents) { - - AbstractLeaderboardDialog dialog = new FlexibleLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList), - stringMessages, Collections.unmodifiableCollection(existingEvents), errorReporter, new DialogCallback() { - @Override - public void cancel() { - } - - @Override - public void ok(final LeaderboardDescriptor newLeaderboard) { - sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), - newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaIdAsString(), - new MarkedAsyncCallback() { - @Override - public void handleFailure(Throwable t) { - errorReporter.reportError("Error trying to create the new flexible leaderboard " + newLeaderboard.getName() - + ": " + t.getMessage()); - } - - @Override - public void handleSuccess(StrippedLeaderboardDTO result) { - addLeaderboard(result); - } - }); - } - }); - dialog.ensureDebugId("CreateFlexibleLeaderboardDialog"); - dialog.show(); - } - - private void createRegattaLeaderboard() { - RegattaLeaderboardCreateDialog dialog = new RegattaLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList), - Collections.unmodifiableCollection(allRegattas), stringMessages, errorReporter, new DialogCallback() { - @Override - public void cancel() { - } - - @Override - public void ok(final LeaderboardDescriptor newLeaderboard) { - RegattaIdentifier regattaIdentifier = new RegattaName(newLeaderboard.getRegattaName()); - sailingService.createRegattaLeaderboard(regattaIdentifier, newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), - new AsyncCallback() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to create the new regatta leaderboard " + newLeaderboard.getName() - + ": " + t.getMessage()); - } - - @Override - public void onSuccess(StrippedLeaderboardDTO result) { - addLeaderboard(result); - } - }); - } - }); - dialog.show(); - } - - private void addLeaderboard(StrippedLeaderboardDTO result) { - leaderboardList.getList().add(result); - availableLeaderboardList.add(result); - setSelectedLeaderboard(result); - leaderboardSelectionChanged(); - } - - private void updateLeaderboard(final String oldLeaderboardName, final LeaderboardDescriptor leaderboardToUpdate) { - sailingService.updateLeaderboard(oldLeaderboardName, leaderboardToUpdate.getName(), leaderboardToUpdate.getDisplayName(), - leaderboardToUpdate.getDiscardThresholds(), new AsyncCallback() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": " - + t.getMessage()); - } - - @Override - public void onSuccess(Void result) { - for (int i = 0; i < leaderboardList.getList().size(); i++) { - StrippedLeaderboardDTO dao = leaderboardList.getList().get(i); - if (dao.name.equals(oldLeaderboardName)) { - dao.name = leaderboardToUpdate.getName(); - dao.displayName = leaderboardToUpdate.getDisplayName(); - dao.discardThresholds = leaderboardToUpdate.getDiscardThresholds(); - break; - } - } - leaderboardList.refresh(); - } - }); - } - - private void removeLeaderboard(final StrippedLeaderboardDTO leaderBoard) { - sailingService.removeLeaderboard(leaderBoard.name, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to remove leaderboard " + leaderBoard.name + ": " - + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - // check if the removed leaderboard was the selected one - leaderboardList.getList().remove(leaderBoard); - availableLeaderboardList.remove(leaderBoard); - - if (getSelectedLeaderboard() != null && getSelectedLeaderboard().name.equals(leaderBoard.name)) { - setSelectedLeaderboard(null); - leaderboardSelectionChanged(); - } - } - }); - } - - @Override - public void onRaceSelectionChange(List selectedRaces) { - // if no leaderboard column is selected, ignore the race selection change - Pair selectedRaceColumnAndFleetName = getSelectedRaceColumnWithFleet(); - if (selectedRaceColumnAndFleetName != null) { - if (selectedRaces.isEmpty()) { - unlinkRaceColumnFromTrackedRace(selectedRaceColumnAndFleetName.getA().getRaceColumnName(), selectedRaceColumnAndFleetName.getB()); - } else { - linkTrackedRaceToSelectedRaceColumn(selectedRaceColumnAndFleetName.getA(), selectedRaceColumnAndFleetName.getB(), - selectedRaces.iterator().next()); - } - } - } - - private void linkTrackedRaceToSelectedRaceColumn(final RaceColumnDTO selectedRaceInLeaderboard, - final FleetDTO fleet, final RegattaAndRaceIdentifier selectedRace) { - sailingService.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), selectedRaceInLeaderboard - .getRaceColumnName(), fleet.name, selectedRace, - new AsyncCallback() { - @Override - public void onFailure(Throwable t) { - errorReporter.reportError("Error trying to link tracked race " + selectedRace + " to race column named " - + selectedRaceInLeaderboard.getRaceColumnName() + " of leaderboard " - + getSelectedLeaderboardName() + ": " + t.getMessage()); - trackedRacesListComposite.clearSelection(); - } - - @Override - public void onSuccess(Boolean success) { - if (success) { - // TODO consider enabling the Unlink button - selectedRaceInLeaderboard.setRaceIdentifier(fleet, selectedRace); - raceColumnAndFleetList.refresh(); - } - } - }); - } - - private void fillRaceListFromAvailableLeaderboardsApplyingFilter() { - String text = filterLeaderboardTextbox.getText(); - List wordsToFilter = Arrays.asList(text.split(" ")); - leaderboardList.getList().clear(); - if (text != null && !text.isEmpty()) { - for (StrippedLeaderboardDTO dao : availableLeaderboardList) { - boolean failed = false; - for (String word : wordsToFilter) { - String textAsUppercase = word.toUpperCase().trim(); - if (!dao.name.toUpperCase().contains(textAsUppercase)) { - failed = true; - break; - } - } - if (!failed) { - leaderboardList.getList().add(dao); - } - } - } else { - leaderboardList.getList().addAll(availableLeaderboardList); - } - // now sort again according to selected criterion - ColumnSortEvent.fire(leaderboardTable, leaderboardTable.getColumnSortList()); - } - - @Override - public StrippedLeaderboardDTO getSelectedLeaderboard() { - return selectedLeaderboard; - } - - private void setSelectedLeaderboard(StrippedLeaderboardDTO selectedLeaderboard) { - this.selectedLeaderboard = selectedLeaderboard; - } +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.gwt.cell.client.AbstractCell; +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.safehtml.client.SafeHtmlTemplates; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.ColumnSortList; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CaptionPanel; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.google.gwt.view.client.SingleSelectionModel; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.gwt.ui.adminconsole.DisablableCheckboxCell.IsEnabled; +import com.sap.sailing.gwt.ui.adminconsole.RaceColumnInLeaderboardDialog.RaceColumnDescriptor; +import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback; +import com.sap.sailing.gwt.ui.client.ErrorReporter; +import com.sap.sailing.gwt.ui.client.MarkedAsyncCallback; +import com.sap.sailing.gwt.ui.client.ParallelExecutionCallback; +import com.sap.sailing.gwt.ui.client.ParallelExecutionHolder; +import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener; +import com.sap.sailing.gwt.ui.client.RaceSelectionModel; +import com.sap.sailing.gwt.ui.client.RaceSelectionProvider; +import com.sap.sailing.gwt.ui.client.RegattaDisplayer; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.URLEncoder; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint; +import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; +import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.RegattaDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; + +public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderboardProvider, RegattaDisplayer, RaceSelectionChangeListener, + TrackedRaceChangedListener { + + private final TrackedRacesListComposite trackedRacesListComposite; + + private final StringMessages stringMessages; + + private final SailingServiceAsync sailingService; + + private final ListDataProvider leaderboardList; + + private final ListDataProvider> raceColumnAndFleetList; + + private final ErrorReporter errorReporter; + + private final CellTable leaderboardTable; + + private final CellTable> raceColumnTable; + + private StrippedLeaderboardDTO selectedLeaderboard; + + private Pair selectedRaceInLeaderboard; + + private final Button addRaceColumnsButton; + + private final Button columnMoveUpButton; + private final Button columnMoveDownButton; + + private final CaptionPanel selectedLeaderBoardPanel; + private final CaptionPanel trackedRacesCaptionPanel; + private final List allRegattas; + + private TextBox filterLeaderboardTextbox; + + final SingleSelectionModel> raceColumnTableSelectionModel; + + private List availableLeaderboardList; + + private final SingleSelectionModel leaderboardSelectionModel; + + private final RaceSelectionProvider raceSelectionProvider; + + public static class AnchorCell extends AbstractCell { + + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml safeHtml, SafeHtmlBuilder sb) { + sb.append(safeHtml); + } + } + + interface AnchorTemplates extends SafeHtmlTemplates { + @SafeHtmlTemplates.Template("{1}") + SafeHtml cell(String url, String displayName); + } + + private static AnchorTemplates ANCHORTEMPLATE = GWT.create(AnchorTemplates.class); + + public LeaderboardConfigPanel(SailingServiceAsync sailingService, AdminConsoleEntryPoint adminConsole, + final ErrorReporter errorReporter, StringMessages theStringConstants, final boolean showRaceDetails) { + this.stringMessages = theStringConstants; + this.sailingService = sailingService; + leaderboardList = new ListDataProvider(); + allRegattas = new ArrayList(); + raceColumnAndFleetList = new ListDataProvider>(); + this.errorReporter = errorReporter; + this.availableLeaderboardList = new ArrayList(); + VerticalPanel mainPanel = new VerticalPanel(); + mainPanel.setWidth("100%"); + this.setWidget(mainPanel); + + //Create leaderboards list and functionality + CaptionPanel leaderboardsCaptionPanel = new CaptionPanel(stringMessages.leaderboards()); + leaderboardsCaptionPanel.setStyleName("bold"); + leaderboardsCaptionPanel.setWidth("75%"); + mainPanel.add(leaderboardsCaptionPanel); + + VerticalPanel leaderboardsPanel = new VerticalPanel(); + leaderboardsCaptionPanel.add(leaderboardsPanel); + + Label lblFilterEvents = new Label(stringMessages.filterLeaderboardsByName() + ": "); + HorizontalPanel filterPanel = new HorizontalPanel(); + filterPanel.setSpacing(5); + filterPanel.add(lblFilterEvents); + filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE); + filterLeaderboardTextbox = new TextBox(); + filterLeaderboardTextbox.addKeyUpHandler(new KeyUpHandler() { + @Override + public void onKeyUp(KeyUpEvent event) { + fillRaceListFromAvailableLeaderboardsApplyingFilter(); + } + }); + filterPanel.add(filterLeaderboardTextbox); + leaderboardsPanel.add(filterPanel); + + AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); + leaderboardTable = new CellTable(/* pageSize */10000, tableRes); + leaderboardTable.ensureDebugId("AvailableLeaderboardsTable"); + ListHandler leaderboardColumnListHandler = new ListHandler( + leaderboardList.getList()); + + AnchorCell anchorCell = new AnchorCell(); + Column linkColumn = new Column(anchorCell) { + @Override + public SafeHtml getValue(StrippedLeaderboardDTO object) { + String debugParam = Window.Location.getParameter("gwt.codesvr"); + String link = URLEncoder.encode("/gwt/Leaderboard.html?name=" + object.name + + (showRaceDetails ? "&showRaceDetails=true" : "") + + (object.displayName != null ? "&displayName="+object.displayName : "") + + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); + return ANCHORTEMPLATE.cell(link, object.name); + } + + }; + linkColumn.setSortable(true); + leaderboardColumnListHandler.setComparator(linkColumn, new Comparator() { + + @Override + public int compare(StrippedLeaderboardDTO o1, StrippedLeaderboardDTO o2) { + boolean ascending = isSortedAscending(); + if (o1.name.equals(o2.name)) { + return 0; + } + int val = -1; + val = (o1 != null && o2 != null && ascending) ? (o1.name.compareTo(o2.name)) : -(o2.name + .compareTo(o1.name)); + return val; + } + + private boolean isSortedAscending() { + ColumnSortList sortList = leaderboardTable.getColumnSortList(); + return sortList.size() > 0 & sortList.get(0).isAscending(); + } + }); + + TextColumn leaderboardDisplayNameColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + return leaderboard.getDisplayName() !=null ? leaderboard.getDisplayName() : ""; + } + }; + + TextColumn discardingOptionsColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + String result = ""; + if (leaderboard.discardThresholds != null) { + for (int discardThreshold : leaderboard.discardThresholds) { + result += discardThreshold + " "; + } + } + return result; + } + }; + + TextColumn leaderboardTypeColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + String result = leaderboard.isRegattaLeaderboard ? "Regatta" : "Flexible"; + if(leaderboard.isMetaLeaderboard) { + result += " , Meta"; + } + return result; + } + }; + + TextColumn scoringSystemColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + return leaderboard.scoringScheme == null ? "" : ScoringSchemeTypeFormatter.format(leaderboard.scoringScheme, stringMessages); + } + }; + + TextColumn courseAreaColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + return leaderboard.defaultCourseAreaIdAsString == null ? "" : leaderboard.defaultCourseAreaName; + } + }; + + ImagesBarColumn leaderboardActionColumn = new ImagesBarColumn( + new LeaderboardConfigImagesBarCell(stringMessages)); + leaderboardActionColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, StrippedLeaderboardDTO leaderboardDTO, String value) { + if (LeaderboardConfigImagesBarCell.ACTION_REMOVE.equals(value)) { + if (Window.confirm("Do you really want to remove the leaderboard: '" + leaderboardDTO.name + "' ?")) { + removeLeaderboard(leaderboardDTO); + } + } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT.equals(value)) { + final String oldLeaderboardName = leaderboardDTO.name; + List otherExistingLeaderboard = new ArrayList(); + otherExistingLeaderboard.addAll(availableLeaderboardList); + otherExistingLeaderboard.remove(leaderboardDTO); + if (leaderboardDTO.isMetaLeaderboard) { + Window.alert("This is a meta leaderboard. It can't be changed here."); + } else { + if (leaderboardDTO.isRegattaLeaderboard) { + LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, + leaderboardDTO.displayName, null, leaderboardDTO.discardThresholds, leaderboardDTO.regattaName, leaderboardDTO.defaultCourseAreaIdAsString); + AbstractLeaderboardDialog dialog = new RegattaLeaderboardEditDialog(Collections + .unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas), + descriptor, stringMessages, errorReporter, + new DialogCallback() { + @Override + public void cancel() { + } + + @Override + public void ok(LeaderboardDescriptor result) { + updateLeaderboard(oldLeaderboardName, result); + } + }); + dialog.show(); + } else { + LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, leaderboardDTO.displayName, leaderboardDTO.scoringScheme, leaderboardDTO.discardThresholds, leaderboardDTO.defaultCourseAreaIdAsString); + openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, leaderboardDTO.name, descriptor); + } + } + } else if (LeaderboardConfigImagesBarCell.ACTION_EDIT_SCORES.equals(value)) { + String debugParam = Window.Location.getParameter("gwt.codesvr"); + Window.open("/gwt/LeaderboardEditing.html?name=" + leaderboardDTO.name + + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""), "_blank", null); + } else if (LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL.equals(value)) { + openLeaderboardUrlConfigDialog(leaderboardDTO, stringMessages); + } + } + }); + leaderboardTable.addColumn(linkColumn, stringMessages.name()); + leaderboardTable.addColumn(leaderboardDisplayNameColumn, stringMessages.displayName()); + leaderboardTable.addColumn(discardingOptionsColumn, stringMessages.discarding()); + leaderboardTable.addColumn(leaderboardTypeColumn, stringMessages.type()); + leaderboardTable.addColumn(scoringSystemColumn, stringMessages.scoringSystem()); + leaderboardTable.addColumn(courseAreaColumn, stringMessages.courseArea()); + leaderboardTable.addColumn(leaderboardActionColumn, stringMessages.actions()); + leaderboardTable.addColumnSortHandler(leaderboardColumnListHandler); + leaderboardTable.setWidth("100%"); + leaderboardSelectionModel = new SingleSelectionModel(); + leaderboardTable.setSelectionModel(leaderboardSelectionModel); + leaderboardSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + setSelectedLeaderboard(leaderboardSelectionModel.getSelectedObject()); + leaderboardSelectionChanged(); + } + }); + leaderboardList.addDataDisplay(leaderboardTable); + leaderboardsPanel.add(leaderboardTable); + HorizontalPanel leaderboardButtonPanel = new HorizontalPanel(); + leaderboardButtonPanel.setSpacing(5); + leaderboardsPanel.add(leaderboardButtonPanel); + Button createFlexibleLeaderboardBtn = new Button(stringMessages.createFlexibleLeaderboard() + "..."); + createFlexibleLeaderboardBtn.ensureDebugId("CreateFlexibleLeaderboardButton"); + leaderboardButtonPanel.add(createFlexibleLeaderboardBtn); + createFlexibleLeaderboardBtn.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent clickEvent) { + createFlexibleLeaderboard(); + } + }); + + Button createRegattaLeaderboardBtn = new Button(stringMessages.createRegattaLeaderboard() + "..."); + createRegattaLeaderboardBtn.ensureDebugId("CreateRegattaLeaderboardButton"); + leaderboardButtonPanel.add(createRegattaLeaderboardBtn); + createRegattaLeaderboardBtn.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent clickEvent) { + createRegattaLeaderboard(); + } + }); + + mainPanel.add(new Grid(1, 1)); + + // caption panels for the selected leaderboard and tracked races + HorizontalPanel splitPanel = new HorizontalPanel(); + mainPanel.add(splitPanel); + + selectedLeaderBoardPanel = new CaptionPanel(stringMessages.leaderboard()); + selectedLeaderBoardPanel.setWidth("50%"); + splitPanel.add(selectedLeaderBoardPanel); + + VerticalPanel vPanel = new VerticalPanel(); + vPanel.setWidth("100%"); + selectedLeaderBoardPanel.setContentWidget(vPanel); + + trackedRacesCaptionPanel = new CaptionPanel(stringMessages.trackedRaces()); + trackedRacesCaptionPanel.setWidth("50%"); + splitPanel.add(trackedRacesCaptionPanel); + + VerticalPanel trackedRacesPanel = new VerticalPanel(); + trackedRacesPanel.setWidth("100%"); + trackedRacesCaptionPanel.setContentWidget(trackedRacesPanel); + trackedRacesCaptionPanel.setStyleName("bold"); + + raceSelectionProvider = new RaceSelectionModel(); + trackedRacesListComposite = new TrackedRacesListComposite(sailingService, errorReporter, adminConsole, + raceSelectionProvider, stringMessages, /* multiselection */false); + trackedRacesPanel.add(trackedRacesListComposite); + trackedRacesListComposite.addTrackedRaceChangeListener(this); + raceSelectionProvider.addRaceSelectionChangeListener(this); + + HorizontalPanel hPanel = new HorizontalPanel(); + hPanel.setSpacing(5); + vPanel.add(hPanel); + + // ------------ races of the selected leaderboard ---------------- + AnchorCell raceAnchorCell = new AnchorCell(); + Column, SafeHtml> raceLinkColumn = new Column, SafeHtml>(raceAnchorCell) { + @Override + public SafeHtml getValue(Pair raceInLeaderboardDTOAndFleetName) { + if (raceInLeaderboardDTOAndFleetName.getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB()) != null) { + RegattaNameAndRaceName raceIdentifier = (RegattaNameAndRaceName) raceInLeaderboardDTOAndFleetName + .getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB()); + String debugParam = Window.Location.getParameter("gwt.codesvr"); + String link = URLEncoder.encode("/gwt/RaceBoard.html?leaderboardName=" + + getSelectedLeaderboard().name + "&raceName=" + raceIdentifier.getRaceName() + "®attaName=" + + raceIdentifier.getRegattaName() + + "&"+RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES+"=true" + + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); + return ANCHORTEMPLATE.cell(link, raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName()); + } else { + return SafeHtmlUtils.fromString(raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName()); + } + } + }; + TextColumn> fleetNameColumn = new TextColumn>() { + @Override + public String getValue(Pair object) { + return object.getB().name; + } + }; + TextColumn> explicitFactorColumn = new TextColumn>() { + @Override + public String getValue(Pair object) { + return object.getA().getExplicitFactor() == null ? "" : object.getA().getExplicitFactor().toString(); + } + }; + + Column, Boolean> isMedalRaceCheckboxColumn = new Column, Boolean>( + new DisablableCheckboxCell(new IsEnabled() { + @Override + public boolean isEnabled() { + return getSelectedLeaderboard() != null && !getSelectedLeaderboard().isRegattaLeaderboard; + } + })) { + @Override + public Boolean getValue(Pair race) { + return race.getA().isMedalRace(); + } + }; + isMedalRaceCheckboxColumn.setFieldUpdater(new FieldUpdater, Boolean>() { + @Override + public void update(int index, Pair object, Boolean value) { + setIsMedalRace(getSelectedLeaderboard().name, object.getA(), value); + } + }); + isMedalRaceCheckboxColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); + + TextColumn> isLinkedRaceColumn = new TextColumn>() { + @Override + public String getValue(Pair raceColumnAndFleetName) { + boolean isTrackedRace = raceColumnAndFleetName.getA().isTrackedRace(raceColumnAndFleetName.getB()); + return isTrackedRace ? stringMessages.yes() : stringMessages.no(); + } + }; + ImagesBarColumn, LeaderboardRaceConfigImagesBarCell> raceActionColumn = + new ImagesBarColumn, LeaderboardRaceConfigImagesBarCell>( + new LeaderboardRaceConfigImagesBarCell(this, stringMessages)); + raceActionColumn.setFieldUpdater(new FieldUpdater, String>() { + @Override + public void update(int index, Pair object, String value) { + if (LeaderboardRaceConfigImagesBarCell.ACTION_REMOVE.equals(value)) { + if (Window.confirm(stringMessages.reallyRemoveRace(object.getA().getRaceColumnName()))) { + removeRaceColumn(object.getA()); + } + } else if (LeaderboardRaceConfigImagesBarCell.ACTION_EDIT.equals(value)) { + editRaceColumnOfLeaderboard(object); + } else if (LeaderboardRaceConfigImagesBarCell.ACTION_UNLINK.equals(value)) { + unlinkRaceColumnFromTrackedRace(object.getA().getRaceColumnName(), object.getB()); + } + } + }); + Label lblRaceNamesIn = new Label(stringMessages.races()); + vPanel.add(lblRaceNamesIn); + raceColumnTable = new CellTable>(/* pageSize */200, tableRes); + raceColumnTable.addColumn(raceLinkColumn, stringMessages.name()); + raceColumnTable.addColumn(fleetNameColumn, stringMessages.fleet()); + raceColumnTable.addColumn(isMedalRaceCheckboxColumn, stringMessages.medalRace()); + raceColumnTable.addColumn(isLinkedRaceColumn, stringMessages.islinked()); + raceColumnTable.addColumn(explicitFactorColumn, stringMessages.factor()); + raceColumnTable.addColumn(raceActionColumn, stringMessages.actions()); + raceColumnAndFleetList.addDataDisplay(raceColumnTable); + raceColumnTable.setWidth("500px"); + raceColumnTableSelectionModel = new SingleSelectionModel>(); + raceColumnTable.setSelectionModel(raceColumnTableSelectionModel); + raceColumnTableSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + leaderboardRaceColumnSelectionChanged(); + } + }); + vPanel.add(raceColumnTable); + + HorizontalPanel selectedLeaderboardRaceButtonPanel = new HorizontalPanel(); + selectedLeaderboardRaceButtonPanel.setSpacing(5); + vPanel.add(selectedLeaderboardRaceButtonPanel); + + addRaceColumnsButton = new Button(stringMessages.actionAddRaces() + "..."); + selectedLeaderboardRaceButtonPanel.add(addRaceColumnsButton); + addRaceColumnsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + if (getSelectedLeaderboard().isRegattaLeaderboard) { + Window.alert(stringMessages.cannotAddRacesToRegattaLeaderboardButOnlyToRegatta()); + } else { + addRaceColumnsToLeaderboard(); + } + } + }); + + columnMoveUpButton = new Button(stringMessages.columnMoveUp()); + selectedLeaderboardRaceButtonPanel.add(columnMoveUpButton); + columnMoveUpButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + moveSelectedRaceColumnUp(); + } + }); + columnMoveDownButton = new Button(stringMessages.columnMoveDown()); + selectedLeaderboardRaceButtonPanel.add(columnMoveDownButton); + columnMoveDownButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + moveSelectedRaceColumnDown(); + } + }); + + loadAndRefreshLeaderboards(); + } + + protected void openUpdateFlexibleLeaderboardDialog(final StrippedLeaderboardDTO leaderboardDTO, final List otherExistingLeaderboard, + final String oldLeaderboardName, final LeaderboardDescriptor descriptor) { + sailingService.getEvents(new AsyncCallback>() { + @Override + public void onSuccess(List result) { + openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, + descriptor, result); + } + + @Override + public void onFailure(Throwable caught) { + openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, + descriptor, new ArrayList()); + } + }); + } + + protected void openUpdateFlexibleLeaderboardDialog(StrippedLeaderboardDTO leaderboardDTO, List otherExistingLeaderboard, + final String oldLeaderboardName, LeaderboardDescriptor descriptor, List existingEvents) { + FlexibleLeaderboardEditDialog dialog = new FlexibleLeaderboardEditDialog( + Collections.unmodifiableCollection(otherExistingLeaderboard), descriptor, stringMessages, + Collections.unmodifiableList(existingEvents), errorReporter, + new DialogCallback() { + @Override + public void cancel() { + } + + @Override + public void ok(LeaderboardDescriptor result) { + updateLeaderboard(oldLeaderboardName, result); + } + }); + dialog.show(); + } + + /** + * Allow the user to combine the various URL parameters that exist for the {@link LeaderboardEntryPoint} and obtain the + * resulting URL in a link. The link's reference target is updated dynamically as the user adjusts the settings. Therefore, + * the link can be clicked, bookmarked or copied to the clipboard at any time. The OK / Cancel actions for the dialog shown + * are no-ops. + */ + private void openLeaderboardUrlConfigDialog(AbstractLeaderboardDTO leaderboard, StringMessages stringMessages) { + LeaderboardEntryPoint.getUrlConfigurationDialog(leaderboard, stringMessages).show(); + } + + public void loadAndRefreshLeaderboards() { + sailingService.getLeaderboards(new AsyncCallback>() { + @Override + public void onSuccess(List leaderboards) { + leaderboardList.getList().clear(); + availableLeaderboardList.clear(); + leaderboardList.getList().addAll(leaderboards); + availableLeaderboardList.addAll(leaderboards); + fillRaceListFromAvailableLeaderboardsApplyingFilter(); + leaderboardSelectionChanged(); + leaderboardRaceColumnSelectionChanged(); + } + + @Override + public void onFailure(Throwable t) { + LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to obtain list of leaderboards: " + + t.getMessage()); + } + }); + } + + /** + * @param nameOfRaceColumnToSelect + * if not null, selects the first race column name with this name found in the leaderboard + * after the refresh has successfully completed. See {@link #selectRaceColumn(String)}. + */ + public void loadAndRefreshLeaderboard(final String leaderboardName, final String nameOfRaceColumnToSelect) { + leaderboardSelectionModel.setSelected(null, true); + sailingService.getLeaderboard(leaderboardName, new AsyncCallback() { + @Override + public void onSuccess(StrippedLeaderboardDTO leaderboard) { + replaceLeaderboardInList(leaderboardList.getList(), leaderboardName, leaderboard); + replaceLeaderboardInList(availableLeaderboardList, leaderboardName, leaderboard); + leaderboardSelectionModel.setSelected(leaderboard, true); + if (nameOfRaceColumnToSelect != null) { + selectRaceColumn(nameOfRaceColumnToSelect); + } + } + + @Override + public void onFailure(Throwable t) { + LeaderboardConfigPanel.this.errorReporter.reportError("Error trying to update leaderboard with name " + leaderboardName +" : " + + t.getMessage()); + } + }); + } + + private void replaceLeaderboardInList(List leaderboardList, String leaderboardToReplace, StrippedLeaderboardDTO newLeaderboard) { + int index = -1; + for (StrippedLeaderboardDTO existingLeaderboard : leaderboardList) { + index++; + if (existingLeaderboard.name.equals(leaderboardToReplace)) { + break; + } + } + if (index >= 0) { + leaderboardList.set(index, newLeaderboard); + } + } + + private void unlinkRaceColumnFromTrackedRace(final String raceColumnName, final FleetDTO fleet) { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, fleet.name, + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumnName + + " from leaderboard " + selectedLeaderboardName + ": " + t.getMessage()); + } + + @Override + public void onSuccess(Void arg0) { + trackedRacesListComposite.clearSelection(); + getSelectedRaceColumnWithFleet().getA().setRaceIdentifier(fleet, null); + raceColumnAndFleetList.refresh(); + } + }); + } + + private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final String raceColumnString = raceColumnDTO.getRaceColumnName(); + sailingService.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString, + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumnDTO + + " in leaderboard " + getSelectedLeaderboardName() + ": " + t.getMessage()); + } + + @Override + public void onSuccess(Void arg0) { + loadAndRefreshLeaderboard(selectedLeaderboardName, /* raceColumnNameToSelect */ null); + } + }); + } + + /** + * The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case, + * move all fleet-based rows of the same RaceColumn down. + */ + private void moveSelectedRaceColumnDown() { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); + sailingService.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName, + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to move leaderboard race column " + + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + + " down: " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); + } + }); + } + + /** + * The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case, + * move all fleet-based rows of the same RaceColumn down. + */ + private void moveSelectedRaceColumnUp() { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName(); + sailingService.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName, + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to move leaderboard race column " + + selectedRaceColumnName + " in leaderboard " + getSelectedLeaderboardName() + " up: " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(selectedLeaderboardName, selectedRaceColumnName); + } + }); + } + + private void leaderboardRaceColumnSelectionChanged() { + selectedRaceInLeaderboard = getSelectedRaceColumnWithFleet(); + if (selectedRaceInLeaderboard != null) { + columnMoveUpButton.setEnabled(true); + columnMoveDownButton.setEnabled(true); + selectTrackedRaceInRaceList(); + } else { + columnMoveUpButton.setEnabled(false); + columnMoveDownButton.setEnabled(false); + trackedRacesListComposite.clearSelection(); + } + } + + private void selectRaceColumn(String raceCoumnName) { + List> list = raceColumnAndFleetList.getList(); + for (Pair pair : list) { + if (pair.getA().name.equals(raceCoumnName)) { + raceColumnTableSelectionModel.setSelected(pair, true); + break; + } + } + } + + private void selectTrackedRaceInRaceList() { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final Pair selectedRaceColumnAndFleetNameInLeaderboard = getSelectedRaceColumnWithFleet(); + final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA().getRaceColumnName(); + final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().name; + sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName, + selectedRaceColumnName, new AsyncCallback>() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to determine tracked race linked to race column " + + selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " + + t.getMessage()); + } + + @Override + public void onSuccess(Map regattaAndRaceNamesPerFleet) { + if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) { + RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet.get(selectedFleetName); + if (raceIdentifier != null) { + selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()); + } else { + trackedRacesListComposite.clearSelection(); + } + } else { + trackedRacesListComposite.clearSelection(); + } + } + }); + } + + private void selectRaceInList(String regattaName, String raceName) { + RegattaNameAndRaceName raceIdentifier = new RegattaNameAndRaceName(regattaName, raceName); + trackedRacesListComposite.selectRaceByIdentifier(raceIdentifier); + } + + private Pair getSelectedRaceColumnWithFleet() { + Pair raceInLeaderboardAndFleetName = raceColumnTableSelectionModel.getSelectedObject(); + return raceInLeaderboardAndFleetName; + } + + private void editRaceColumnOfLeaderboard(final Pair raceColumnWithFleet) { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final boolean oldIsMedalRace = raceColumnWithFleet.getA().isMedalRace(); + final String oldRaceColumnName = raceColumnWithFleet.getA().getRaceColumnName(); + final Double oldExplicitFactor = raceColumnWithFleet.getA().getExplicitFactor(); + // use a set to avoid duplicates in the case of regatta leaderboards with multiple fleets per column + Set existingRacesWithoutThisRace = new HashSet(); + for (Pair pair : raceColumnAndFleetList.getList()) { + existingRacesWithoutThisRace.add(pair.getA()); + } + existingRacesWithoutThisRace.remove(raceColumnWithFleet.getA()); + final RaceColumnInLeaderboardDialog raceDialog = new RaceColumnInLeaderboardDialog(existingRacesWithoutThisRace, + raceColumnWithFleet.getA(), getSelectedLeaderboard().isRegattaLeaderboard, stringMessages, new DialogCallback() { + @Override + public void cancel() { + } + + @Override + public void ok(final RaceColumnDescriptor result) { + boolean rename = !oldRaceColumnName.equals(result.getName()); + boolean updateIsMedalRace = oldIsMedalRace != result.isMedalRace(); + boolean updateFactor = oldExplicitFactor != result.getExplicitFactor(); + List> callbacks = new ArrayList>(); + final ParallelExecutionCallback renameLeaderboardColumnCallback = new ParallelExecutionCallback(); + if (rename) { + callbacks.add(renameLeaderboardColumnCallback); + } + final ParallelExecutionCallback updateIsMedalRaceCallback = new ParallelExecutionCallback(); + if (updateIsMedalRace) { + callbacks.add(updateIsMedalRaceCallback); + } + final ParallelExecutionCallback updateLeaderboardColumnFactorCallback = new ParallelExecutionCallback(); + if (updateFactor) { + callbacks.add(updateLeaderboardColumnFactorCallback); + } + new ParallelExecutionHolder(callbacks.toArray(new ParallelExecutionCallback[0])) { + @Override + public void handleSuccess() { + loadAndRefreshLeaderboard(selectedLeaderboardName, result.getName()); + } + @Override + public void handleFailure(Throwable t) { + errorReporter.reportError("Error trying to update data of race column " + + oldRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " + + t.getMessage()); + } + }; + if (rename) { + sailingService.renameLeaderboardColumn(selectedLeaderboardName, oldRaceColumnName, + result.getName(), renameLeaderboardColumnCallback); + } + if (updateIsMedalRace) { + sailingService.updateIsMedalRace(selectedLeaderboardName, result.getName(), + result.isMedalRace(), updateIsMedalRaceCallback); + } + if (updateFactor) { + sailingService.updateLeaderboardColumnFactor(selectedLeaderboardName, result.getName(), + result.getExplicitFactor(), updateLeaderboardColumnFactorCallback); + } + } + }); + raceDialog.show(); + } + + private void setIsMedalRace(String leaderboardName, final RaceColumnDTO raceInLeaderboard, + final boolean isMedalRace) { + sailingService.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace, + new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError(stringMessages.errorUpdatingIsMedalRace(caught.getMessage())); + } + @Override + public void onSuccess(Void result) { + getSelectedLeaderboard().setIsMedalRace(raceInLeaderboard.getRaceColumnName(), isMedalRace); + } + }); + } + + private void addRaceColumnsToLeaderboard() { + final String leaderboardName = getSelectedLeaderboardName(); + final List existingRaceColumns = new ArrayList(); + for (Pair pair : raceColumnAndFleetList.getList()) { + existingRaceColumns.add(pair.getA()); + } + final RaceColumnsInLeaderboardDialog raceDialog = new RaceColumnsInLeaderboardDialog(existingRaceColumns, + stringMessages, new DialogCallback>() { + @Override + public void cancel() { + } + + @Override + public void ok(final List result) { + updateRaceColumnsOfLeaderboard(leaderboardName, existingRaceColumns, result); + } + }); + raceDialog.show(); + } + + private void updateRaceColumnsOfLeaderboard(final String leaderboardName, List existingRaceColumns, List newRaceColumns) { + final List> raceColumnsToAdd = new ArrayList>(); + + for(RaceColumnDTO newRaceColumn: newRaceColumns) { + if(!existingRaceColumns.contains(newRaceColumn)) { + raceColumnsToAdd.add(new Pair(newRaceColumn.name, newRaceColumn.isMedalRace())); + } + } + + sailingService.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to add race columns to leaderboard " + leaderboardName + + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void v) { + loadAndRefreshLeaderboard(leaderboardName, /* nameOfRaceColumnToSelect */ null); + } + }); + } + + private String getSelectedLeaderboardName() { + return getSelectedLeaderboard() != null ? getSelectedLeaderboard().name : null; + } + + private void leaderboardSelectionChanged() { + // make sure that clearing the selection doesn't cause an unlinking of the selected tracked race + raceSelectionProvider.removeRaceSelectionChangeListener(this); + trackedRacesListComposite.clearSelection(); + // add listener again using a scheduled command which is executed when the browser's event loop re-gains + // control; we assume that at that point in time the selection updates have already been performed + Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override + public void execute() { + raceSelectionProvider.addRaceSelectionChangeListener(LeaderboardConfigPanel.this); + } + }); + if (getSelectedLeaderboard() != null) { + raceColumnAndFleetList.getList().clear(); + for (RaceColumnDTO raceColumn : getSelectedLeaderboard().getRaceList()) { + for (FleetDTO fleet : raceColumn.getFleets()) { + raceColumnAndFleetList.getList().add(new Pair(raceColumn, fleet)); + } + } + selectedLeaderBoardPanel.setVisible(true); + selectedLeaderBoardPanel.setCaptionText("Details of leaderboard '" + getSelectedLeaderboard().name + "'"); + if (!getSelectedLeaderboard().isMetaLeaderboard) { + trackedRacesCaptionPanel.setVisible(true); + } + addRaceColumnsButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); + columnMoveUpButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); + columnMoveDownButton.setVisible(!getSelectedLeaderboard().isRegattaLeaderboard); + } else { + selectedLeaderBoardPanel.setVisible(false); + trackedRacesCaptionPanel.setVisible(false); + setSelectedLeaderboard(null); + selectedRaceInLeaderboard = null; + } + } + + @Override + public void fillRegattas(List regattas) { + trackedRacesListComposite.fillRegattas(regattas); + + allRegattas.clear(); + allRegattas.addAll(regattas); + } + + @Override + public void changeTrackingRace(Iterable regattaAndRaceIdentifiers, boolean isTracked) { + for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { + for (Pair raceColumnAndFleetName : raceColumnAndFleetList.getList()) { + if (raceColumnAndFleetName.getA().getRaceColumnName().equals(regattaAndRaceIdentifier.getRaceName())) { + raceColumnAndFleetName.getA().setRaceIdentifier(raceColumnAndFleetName.getB(), + regattaAndRaceIdentifier); + } + } + raceColumnAndFleetList.refresh(); + } + } + + private void createFlexibleLeaderboard() { + sailingService.getEvents(new MarkedAsyncCallback>() { + + @Override + public void handleSuccess(List result) { + createFlexibleLeaderboard(result); + } + + @Override + public void handleFailure(Throwable caught) { + createFlexibleLeaderboard(new ArrayList()); + } + }); + } + + private void createFlexibleLeaderboard(List existingEvents) { + + AbstractLeaderboardDialog dialog = new FlexibleLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList), + stringMessages, Collections.unmodifiableCollection(existingEvents), errorReporter, new DialogCallback() { + @Override + public void cancel() { + } + + @Override + public void ok(final LeaderboardDescriptor newLeaderboard) { + sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), + newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaIdAsString(), + new MarkedAsyncCallback() { + @Override + public void handleFailure(Throwable t) { + errorReporter.reportError("Error trying to create the new flexible leaderboard " + newLeaderboard.getName() + + ": " + t.getMessage()); + } + + @Override + public void handleSuccess(StrippedLeaderboardDTO result) { + addLeaderboard(result); + } + }); + } + }); + dialog.ensureDebugId("CreateFlexibleLeaderboardDialog"); + dialog.show(); + } + + private void createRegattaLeaderboard() { + RegattaLeaderboardCreateDialog dialog = new RegattaLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList), + Collections.unmodifiableCollection(allRegattas), stringMessages, errorReporter, new DialogCallback() { + @Override + public void cancel() { + } + + @Override + public void ok(final LeaderboardDescriptor newLeaderboard) { + RegattaIdentifier regattaIdentifier = new RegattaName(newLeaderboard.getRegattaName()); + sailingService.createRegattaLeaderboard(regattaIdentifier, newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to create the new regatta leaderboard " + newLeaderboard.getName() + + ": " + t.getMessage()); + } + + @Override + public void onSuccess(StrippedLeaderboardDTO result) { + addLeaderboard(result); + } + }); + } + }); + dialog.show(); + } + + private void addLeaderboard(StrippedLeaderboardDTO result) { + leaderboardList.getList().add(result); + availableLeaderboardList.add(result); + setSelectedLeaderboard(result); + leaderboardSelectionChanged(); + } + + private void updateLeaderboard(final String oldLeaderboardName, final LeaderboardDescriptor leaderboardToUpdate) { + sailingService.updateLeaderboard(oldLeaderboardName, leaderboardToUpdate.getName(), leaderboardToUpdate.getDisplayName(), + leaderboardToUpdate.getDiscardThresholds(), new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": " + + t.getMessage()); + } + + @Override + public void onSuccess(Void result) { + for (int i = 0; i < leaderboardList.getList().size(); i++) { + StrippedLeaderboardDTO dao = leaderboardList.getList().get(i); + if (dao.name.equals(oldLeaderboardName)) { + dao.name = leaderboardToUpdate.getName(); + dao.displayName = leaderboardToUpdate.getDisplayName(); + dao.discardThresholds = leaderboardToUpdate.getDiscardThresholds(); + break; + } + } + leaderboardList.refresh(); + } + }); + } + + private void removeLeaderboard(final StrippedLeaderboardDTO leaderBoard) { + sailingService.removeLeaderboard(leaderBoard.name, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to remove leaderboard " + leaderBoard.name + ": " + + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + // check if the removed leaderboard was the selected one + leaderboardList.getList().remove(leaderBoard); + availableLeaderboardList.remove(leaderBoard); + + if (getSelectedLeaderboard() != null && getSelectedLeaderboard().name.equals(leaderBoard.name)) { + setSelectedLeaderboard(null); + leaderboardSelectionChanged(); + } + } + }); + } + + @Override + public void onRaceSelectionChange(List selectedRaces) { + // if no leaderboard column is selected, ignore the race selection change + Pair selectedRaceColumnAndFleetName = getSelectedRaceColumnWithFleet(); + if (selectedRaceColumnAndFleetName != null) { + if (selectedRaces.isEmpty()) { + unlinkRaceColumnFromTrackedRace(selectedRaceColumnAndFleetName.getA().getRaceColumnName(), selectedRaceColumnAndFleetName.getB()); + } else { + linkTrackedRaceToSelectedRaceColumn(selectedRaceColumnAndFleetName.getA(), selectedRaceColumnAndFleetName.getB(), + selectedRaces.iterator().next()); + } + } + } + + private void linkTrackedRaceToSelectedRaceColumn(final RaceColumnDTO selectedRaceInLeaderboard, + final FleetDTO fleet, final RegattaAndRaceIdentifier selectedRace) { + sailingService.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), selectedRaceInLeaderboard + .getRaceColumnName(), fleet.name, selectedRace, + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to link tracked race " + selectedRace + " to race column named " + + selectedRaceInLeaderboard.getRaceColumnName() + " of leaderboard " + + getSelectedLeaderboardName() + ": " + t.getMessage()); + trackedRacesListComposite.clearSelection(); + } + + @Override + public void onSuccess(Boolean success) { + if (success) { + // TODO consider enabling the Unlink button + selectedRaceInLeaderboard.setRaceIdentifier(fleet, selectedRace); + raceColumnAndFleetList.refresh(); + } + } + }); + } + + private void fillRaceListFromAvailableLeaderboardsApplyingFilter() { + String text = filterLeaderboardTextbox.getText(); + List wordsToFilter = Arrays.asList(text.split(" ")); + leaderboardList.getList().clear(); + if (text != null && !text.isEmpty()) { + for (StrippedLeaderboardDTO dao : availableLeaderboardList) { + boolean failed = false; + for (String word : wordsToFilter) { + String textAsUppercase = word.toUpperCase().trim(); + if (!dao.name.toUpperCase().contains(textAsUppercase)) { + failed = true; + break; + } + } + if (!failed) { + leaderboardList.getList().add(dao); + } + } + } else { + leaderboardList.getList().addAll(availableLeaderboardList); + } + // now sort again according to selected criterion + ColumnSortEvent.fire(leaderboardTable, leaderboardTable.getColumnSortList()); + } + + @Override + public StrippedLeaderboardDTO getSelectedLeaderboard() { + return selectedLeaderboard; + } + + private void setSelectedLeaderboard(StrippedLeaderboardDTO selectedLeaderboard) { + this.selectedLeaderboard = selectedLeaderboard; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardCreation.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardCreation.java index 9b40820f40e..852f290f3aa 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardCreation.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardCreation.java @@ -19,15 +19,16 @@ import com.sap.sailing.selenium.test.adminconsole.pages.LeaderboardConfiguration * D049941 */ public class TestLeaderboardCreation extends AbstractSeleniumTest { - @Before - public void clearDatabase() { - DatabaseHelper.dropDatabase(); - } +// @Before +// public void clearDatabase() { +// DatabaseHelper.dropDatabase(); +// } @Test public void testCreateFlexibleLeaderboardWithDuplicateName() { AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); LeaderboardConfigurationPanel leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + leaderboardConfiguration.deleteLeaderboard("Humba Humba"); { FlexibleLeaderboardCreationDialog dialog = leaderboardConfiguration.startCreatingFlexibleLeaderboard(); dialog.setName("Humba Humba"); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/pages/LeaderboardConfigurationPanel.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/pages/LeaderboardConfigurationPanel.java index d6f6d6d716f..a3588736b17 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/pages/LeaderboardConfigurationPanel.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/pages/LeaderboardConfigurationPanel.java @@ -1,28 +1,81 @@ -package com.sap.sailing.selenium.test.adminconsole.pages; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import com.sap.sailing.selenium.core.BySeleniumId; -import com.sap.sailing.selenium.core.FindBy; -import com.sap.sailing.selenium.test.PageArea; - -public class LeaderboardConfigurationPanel extends PageArea { - @FindBy(how = BySeleniumId.class, using = "CreateFlexibleLeaderboardButton") - private WebElement createFlexibleLeaderboardButton; - - @FindBy(how = BySeleniumId.class, using = "CreateRegattaLeaderboardButton") - private WebElement createRegattaLeaderboardButton; - - protected LeaderboardConfigurationPanel(WebDriver driver, WebElement element) { - super(driver, element); - } - - public FlexibleLeaderboardCreationDialog startCreatingFlexibleLeaderboard() { - this.createFlexibleLeaderboardButton.click(); - // Wait, since we trigger an AJAX-request to get the available events - waitForAjaxRequests(); - WebElement dialog = findElementBySeleniumId(this.driver, "CreateFlexibleLeaderboardDialog"); - return new FlexibleLeaderboardCreationDialog(this.driver, dialog); - } -} +package com.sap.sailing.selenium.test.adminconsole.pages; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.test.PageArea; +import com.sap.sailing.selenium.test.gwt.widgets.CellTable; + +public class LeaderboardConfigurationPanel extends PageArea { + @FindBy(how = BySeleniumId.class, using = "CreateFlexibleLeaderboardButton") + private WebElement createFlexibleLeaderboardButton; + + @FindBy(how = BySeleniumId.class, using = "CreateRegattaLeaderboardButton") + private WebElement createRegattaLeaderboardButton; + + @FindBy(how = BySeleniumId.class, using = "AvailableLeaderboardsTable") + private WebElement availableLeaderboardsTable; + + protected LeaderboardConfigurationPanel(WebDriver driver, WebElement element) { + super(driver, element); + } + + + public List getAvailableLeaderboards() { + List leaderboards = new ArrayList<>(); + + CellTable table = getLeaderboardTable(); + List rows = table.getRows(); + + for(WebElement row : rows) { + WebElement name = row.findElement(By.xpath(".//td/div/a")); + + leaderboards.add(name.getText()); + } + + return leaderboards; + } + + public void deleteLeaderboard(String leaderboard) { + CellTable table = getLeaderboardTable(); + List rows = table.getRows(); + + for(WebElement row : rows) { + WebElement name = row.findElement(By.xpath(".//td/div/a")); + + if(!leaderboard.equals(name.getText())) + continue; + + WebElement removeAction = row.findElement(By.xpath(".//td/div/div[@title='Remove']/img")); + + removeAction.click(); + + this.driver.switchTo().alert().accept(); + } + } + + public FlexibleLeaderboardCreationDialog startCreatingFlexibleLeaderboard() { + this.createFlexibleLeaderboardButton.click(); + // Wait, since we trigger an AJAX-request to get the available events + waitForAjaxRequests(); + WebElement dialog = findElementBySeleniumId(this.driver, "CreateFlexibleLeaderboardDialog"); + return new FlexibleLeaderboardCreationDialog(this.driver, dialog); + } + + private CellTable getLeaderboardTable() { + return new CellTable(this.driver, this.availableLeaderboardsTable); + } + + protected void initElements() { + super.initElements(); + + //this.availableLeaderboardsTable = new CellTable(this.driver, findElementBySeleniumId("AvailableLeaderboardsTable")); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/gwt/widgets/CellTable.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/gwt/widgets/CellTable.java index 35640c79549..610bdedb686 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/gwt/widgets/CellTable.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/gwt/widgets/CellTable.java @@ -1,31 +1,98 @@ -package com.sap.sailing.selenium.test.gwt.widgets; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import com.sap.sailing.selenium.test.PageObject; - -/** - *

- * - * @author - * D049941 - */ -public class CellTable extends PageObject { - /** - *

- * - * @param driver - * - * @param element - * - */ - public CellTable(WebDriver driver, WebElement element) { - super(driver, element); - } - - @Override - protected void verify() { - // TODO: Verify that the context represents a GWT CellTable - } -} +package com.sap.sailing.selenium.test.gwt.widgets; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.test.PageObject; + +/** + *

+ * + * @author + * D049941 + */ +public class CellTable extends PageObject { + /** + *

+ * + * @param driver + * + * @param element + * + */ + public CellTable(WebDriver driver, WebElement element) { + super(driver, element); + } + + public List getHeaders() { + List headers = new ArrayList<>(); + + for(WebElement header : findHeaders()) { + headers.add(header.getText()); + } + + return headers; + } + + public void clickHeader(String name) { + for(WebElement header : findHeaders()) { + if(name.equals(header.getText())) + header.click(); + } + } + + public List getRows() { + List bodies = this.context.findElements(By.tagName("tbody")); + + for(WebElement body : bodies) { + if(!body.isDisplayed()) + continue; + + List rows = body.findElements(By.tagName("tr")); + + Iterator iterator = rows.iterator(); + + while(iterator.hasNext()) { + WebElement row = iterator.next(); + + if(isRowForLoadingAnimation(row)) + iterator.remove(); + } + + return rows; + } + + return Collections.emptyList(); + } + + @Override + protected void verify() { + // TODO: Verify that the context represents a GWT CellTable + String tagName = ((WebElement) this.context).getTagName(); + + if(!tagName.equalsIgnoreCase("table")) + throw new IllegalArgumentException("WebElement does not represent a table"); + } + + private List findHeaders() { + return this.context.findElements(By.tagName("th")); + } + + private boolean isRowForLoadingAnimation(WebElement row) { + List images = row.findElements(By.xpath(".//td/div/div/div/img")); + + if(images.isEmpty() || images.size() > 1) + return false; + + WebElement image = images.get(0); + System.out.println(image.getCssValue("background-image")); + + return true; + } +} From 5f7217ed29b99c269311a9f0711a3213b020b204 Mon Sep 17 00:00:00 2001 From: Frederik Petersen Date: Wed, 29 May 2013 09:43:08 +0200 Subject: [PATCH 02/13] Polar sheets now correctly resize according to client view size --- .../ui/polarsheets/PolarSheetsChartPanel.java | 33 +++++++----- .../ui/polarsheets/PolarSheetsEntryPoint.java | 13 +---- .../PolarSheetsHistogramPanel.java | 26 +++++++--- .../gwt/ui/polarsheets/PolarSheetsPanel.java | 52 +++++++------------ 4 files changed, 59 insertions(+), 65 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java index 4db8488c226..420db3cd786 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java @@ -15,12 +15,13 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.LinePlotOptions; import org.moxieapps.gwt.highcharts.client.plotOptions.Marker; import org.moxieapps.gwt.highcharts.client.plotOptions.SeriesPlotOptions; -import com.google.gwt.user.client.ui.RequiresResize; -import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.DockLayoutPanel; import com.sap.sailing.domain.common.PolarSheetsData; import com.sap.sailing.gwt.ui.client.StringMessages; -public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize { +public class PolarSheetsChartPanel extends DockLayoutPanel { private StringMessages stringMessages; private Chart chart; @@ -29,17 +30,18 @@ public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize private Map nameForSeries = new HashMap(); public PolarSheetsChartPanel(StringMessages stringMessages) { + super(Unit.PCT); this.stringMessages = stringMessages; - setPixelSize(800, 800); + setSize("100%", "100%"); chart = createPolarSheetChart(); seriesMap = new HashMap(); - setWidget(chart); + add(chart); } private Chart createPolarSheetChart() { Chart polarSheetChart = new Chart().setType(Series.Type.LINE) .setLinePlotOptions(new LinePlotOptions().setLineWidth(1)).setZoomType(Chart.ZoomType.X_AND_Y) - .setPolar(true).setSize(800, 800); + .setPolar(true).setHeight100().setWidth100(); polarSheetChart.setChartTitleText(stringMessages.polarSheetChart()); polarSheetChart.getYAxis().setMin(0); return polarSheetChart; @@ -167,12 +169,6 @@ public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize chart.setSeriesPlotOptions(new SeriesPlotOptions().setPointMouseOverEventHandler(pointMouseOverHandler)); } - @Override - public void onResize() { - chart.setSizeToMatchContainer(); - chart.redraw(); - } - public Series[] getSeriesPerWindspeedForName(String name) { return seriesMap.get(name); } @@ -180,5 +176,18 @@ public class PolarSheetsChartPanel extends SimplePanel implements RequiresResize public String getNameForSeries(Series series) { return nameForSeries.get(series); } + + @Override + protected void onLoad() { + Timer timer = new Timer() { + + @Override + public void run() { + chart.setSizeToMatchContainer(); + } + }; + timer.schedule(200); + super.onLoad(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsEntryPoint.java index ce0a38c8fb7..e85da62b23b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsEntryPoint.java @@ -4,12 +4,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.DockLayoutPanel; import com.google.gwt.user.client.ui.RootLayoutPanel; -import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.ScrollPanel; import com.sap.sailing.gwt.ui.client.AbstractEntryPoint; import com.sap.sailing.gwt.ui.client.RegattaDisplayer; import com.sap.sailing.gwt.ui.client.RegattaRefresher; @@ -31,16 +27,11 @@ public class PolarSheetsEntryPoint extends AbstractEntryPoint implements Regatta } private void createUI() { - RootPanel rootPanel = RootPanel.get(); - DockLayoutPanel mainPanel = new DockLayoutPanel(Unit.PX); - RootLayoutPanel.get().add(mainPanel); - ScrollPanel contentScrollPanel = new ScrollPanel(); + RootLayoutPanel rootPanel = RootLayoutPanel.get(); PolarSheetsPanel polarSheetsPanel = new PolarSheetsPanel(sailingService, this, stringMessages, this); polarSheetsPanel.addStyleName(PolarSheetsPanel.POLARSHEETS_STYLE); regattaDisplayers.add(polarSheetsPanel); - contentScrollPanel.setWidget(polarSheetsPanel); - mainPanel.add(contentScrollPanel); - rootPanel.add(mainPanel); + rootPanel.add(polarSheetsPanel); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java index c1db7cba4c0..cb6c8a93aab 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java @@ -10,26 +10,28 @@ import org.moxieapps.gwt.highcharts.client.Series; import org.moxieapps.gwt.highcharts.client.Series.Type; import org.moxieapps.gwt.highcharts.client.labels.XAxisLabels; -import com.google.gwt.user.client.ui.RequiresResize; -import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.DockLayoutPanel; import com.sap.sailing.domain.common.PolarSheetsHistogramData; import com.sap.sailing.gwt.ui.client.StringMessages; -public class PolarSheetsHistogramPanel extends SimplePanel implements RequiresResize{ +public class PolarSheetsHistogramPanel extends DockLayoutPanel { private final Chart chart; private final StringMessages stringMessages; public PolarSheetsHistogramPanel(StringMessages stringMessages) { + super(Unit.PCT); this.stringMessages = stringMessages; setSize("100%", "100%"); chart = createHistogramChart(); chart.getElement().setAttribute("align", "top"); - setWidget(chart); + add(chart); } private Chart createHistogramChart() { - Chart histogramChart = new Chart().setType(Type.COLUMN).setZoomType(Chart.ZoomType.X).setWidth(800); + Chart histogramChart = new Chart().setType(Type.COLUMN).setZoomType(Chart.ZoomType.X).setHeight100().setWidth100(); histogramChart.setChartTitleText(stringMessages.histogram()); histogramChart.getYAxis().setMin(0).setAxisTitle(new AxisTitle().setText(stringMessages.numberOfDataPoints())); histogramChart.getXAxis().setLabels(new XAxisLabels().setRotation(-90f).setY(10)).setAxisTitle(new AxisTitle().setText( @@ -59,9 +61,17 @@ public class PolarSheetsHistogramPanel extends SimplePanel implements RequiresRe } @Override - public void onResize() { - chart.setSizeToMatchContainer(); - chart.redraw(); + protected void onLoad() { + Timer timer = new Timer() { + + @Override + public void run() { + chart.setSizeToMatchContainer(); + } + }; + timer.schedule(200); + super.onLoad(); } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java index e40971b4015..5ed30d75749 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java @@ -10,6 +10,7 @@ import org.moxieapps.gwt.highcharts.client.Series; import org.moxieapps.gwt.highcharts.client.events.PointMouseOverEvent; import org.moxieapps.gwt.highcharts.client.events.PointMouseOverEventHandler; +import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.NumberFormat; @@ -17,11 +18,10 @@ import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.FormPanel; -import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.DockLayoutPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.PolarSheetGenerationTriggerResponse; import com.sap.sailing.domain.common.PolarSheetsData; @@ -37,12 +37,11 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; -public class PolarSheetsPanel extends FormPanel implements RaceSelectionChangeListener, RegattaDisplayer { +public class PolarSheetsPanel extends DockLayoutPanel implements RaceSelectionChangeListener, RegattaDisplayer { // TODO UI stuff public static final String POLARSHEETS_STYLE = "polarSheets"; - private FlowPanel mainPanel; private SailingServiceAsync sailingService; private PolarSheetsTrackedRacesList polarSheetsTrackedRacesList; private ErrorReporter errorReporter; @@ -66,6 +65,7 @@ public class PolarSheetsPanel extends FormPanel implements RaceSelectionChangeLi public PolarSheetsPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, StringMessages stringMessages, PolarSheetsEntryPoint polarSheetsEntryPoint) { + super(Unit.PCT); this.polarSheetsEntryPoint = polarSheetsEntryPoint; this.sailingService = sailingService; this.errorReporter = errorReporter; @@ -73,28 +73,27 @@ public class PolarSheetsPanel extends FormPanel implements RaceSelectionChangeLi idNameMapping = new HashMap(); nameIdMapping = new HashMap(); - - this.mainPanel = new FlowPanel(); setSize("100%", "100%"); - mainPanel.setSize("100%", "100%"); - setWidget(mainPanel); - HorizontalPanel splitPanel = createSplitPanel(); - VerticalPanel leftPanel = addFilteredTrackedRacesList(splitPanel); + VerticalPanel leftPanel = addFilteredTrackedRacesList(); + ScrollPanel leftScrollPanel = new ScrollPanel(leftPanel); + addWest(leftScrollPanel, 40); polarSheetsGenerationLabel = createPolarSheetGenerationStatusLabel(); leftPanel.add(polarSheetsGenerationLabel); dataCountLabel = new Label(); leftPanel.add(dataCountLabel); - VerticalPanel rightPanel = addPolarSheetsChartPanel(splitPanel); + DockLayoutPanel rightPanel = new DockLayoutPanel(Unit.PCT); + PolarSheetsChartPanel polarSheetsChartPanel = createPolarSheetsChartPanel(); + rightPanel.addNorth(polarSheetsChartPanel, 70); histogramPanel = new PolarSheetsHistogramPanel(stringMessages); histogramPanel.getElement().setAttribute("align", "top"); - rightPanel.add(histogramPanel); + rightPanel.addSouth(histogramPanel, 30); nameListBox = new ListBox(); - rightPanel.add(nameListBox); + leftPanel.add(nameListBox); Button exportButton = new Button("Export"); setExportButtonListener(exportButton); - rightPanel.add(exportButton); - mainPanel.add(splitPanel); + leftPanel.add(exportButton); + add(rightPanel); asyncActionsExecutor = new AsyncActionsExecutor(); setEventListenersForPolarSheetChart(); @@ -221,32 +220,17 @@ public class PolarSheetsPanel extends FormPanel implements RaceSelectionChangeLi return polarSheetsGenerationStatusLabel; } - private VerticalPanel addPolarSheetsChartPanel(HorizontalPanel splitPanel) { - VerticalPanel verticalPanel = new VerticalPanel(); - verticalPanel.setSize("100%", "100%"); + private PolarSheetsChartPanel createPolarSheetsChartPanel() { chartPanel = new PolarSheetsChartPanel(stringMessages); - verticalPanel.add(chartPanel); - verticalPanel.setCellHeight(chartPanel, "800px"); - splitPanel.add(verticalPanel); - splitPanel.setCellWidth(verticalPanel, "50%"); - return verticalPanel; + return chartPanel; } - private HorizontalPanel createSplitPanel() { - HorizontalPanel splitPanel = new HorizontalPanel(); - splitPanel.setSize("100%", "100%"); - return splitPanel; - } - - private VerticalPanel addFilteredTrackedRacesList(HorizontalPanel splitPanel) { + private VerticalPanel addFilteredTrackedRacesList() { VerticalPanel trackedRacesPanel = new VerticalPanel(); trackedRacesPanel.setWidth("100%"); createPolarSheetsTrackedRacesList(); trackedRacesPanel.add(polarSheetsTrackedRacesList); - - splitPanel.add(trackedRacesPanel); - splitPanel.setCellWidth(trackedRacesPanel, "50%"); return trackedRacesPanel; } From 60aba0fc15623786b88a8c2c3bc8195e958c2b27 Mon Sep 17 00:00:00 2001 From: Frederik Petersen Date: Wed, 29 May 2013 10:19:27 +0200 Subject: [PATCH 03/13] Changed polarsheetspanel from docklayoutpanel to splitlayoutpanel --- .../ui/polarsheets/PolarSheetsChartPanel.java | 6 ++++ .../PolarSheetsHistogramPanel.java | 6 ++++ .../gwt/ui/polarsheets/PolarSheetsPanel.java | 32 ++++++++++++++++--- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java index 420db3cd786..4d6c15e18cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsChartPanel.java @@ -189,5 +189,11 @@ public class PolarSheetsChartPanel extends DockLayoutPanel { timer.schedule(200); super.onLoad(); } + + @Override + public void onResize() { + chart.setSizeToMatchContainer(); + super.onResize(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java index cb6c8a93aab..a2b64b7c7e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsHistogramPanel.java @@ -73,5 +73,11 @@ public class PolarSheetsHistogramPanel extends DockLayoutPanel { super.onLoad(); } + @Override + public void onResize() { + chart.setSizeToMatchContainer(); + super.onResize(); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java index 5ed30d75749..d20cf6ea375 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/polarsheets/PolarSheetsPanel.java @@ -22,6 +22,7 @@ import com.google.gwt.user.client.ui.DockLayoutPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.SplitLayoutPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.PolarSheetGenerationTriggerResponse; import com.sap.sailing.domain.common.PolarSheetsData; @@ -37,7 +38,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; -public class PolarSheetsPanel extends DockLayoutPanel implements RaceSelectionChangeListener, RegattaDisplayer { +public class PolarSheetsPanel extends SplitLayoutPanel implements RaceSelectionChangeListener, RegattaDisplayer { // TODO UI stuff public static final String POLARSHEETS_STYLE = "polarSheets"; @@ -63,9 +64,10 @@ public class PolarSheetsPanel extends DockLayoutPanel implements RaceSelectionCh private ListBox nameListBox; + private ScrollPanel leftScrollPanel; + public PolarSheetsPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, StringMessages stringMessages, PolarSheetsEntryPoint polarSheetsEntryPoint) { - super(Unit.PCT); this.polarSheetsEntryPoint = polarSheetsEntryPoint; this.sailingService = sailingService; this.errorReporter = errorReporter; @@ -76,8 +78,8 @@ public class PolarSheetsPanel extends DockLayoutPanel implements RaceSelectionCh setSize("100%", "100%"); VerticalPanel leftPanel = addFilteredTrackedRacesList(); - ScrollPanel leftScrollPanel = new ScrollPanel(leftPanel); - addWest(leftScrollPanel, 40); + leftScrollPanel = new ScrollPanel(leftPanel); + addWest(leftScrollPanel, 400); polarSheetsGenerationLabel = createPolarSheetGenerationStatusLabel(); leftPanel.add(polarSheetsGenerationLabel); dataCountLabel = new Label(); @@ -335,4 +337,26 @@ public class PolarSheetsPanel extends DockLayoutPanel implements RaceSelectionCh polarSheetsTrackedRacesList.fillRegattas(regattas); } + + @Override + protected void onLoad() { + Timer timer = new Timer() { + + @Override + public void run() { + setWidgetSize(leftScrollPanel, polarSheetsTrackedRacesList.getOffsetWidth() + 30); + Timer timer = new Timer() { + + @Override + public void run() { + chartPanel.onResize(); + histogramPanel.onResize(); + } + }; + timer.schedule(200); + } + }; + timer.schedule(600); + super.onLoad(); + } } From 8b03accf6648e07242b53a0efb5973602aef1144 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Mon, 27 May 2013 17:57:55 +0200 Subject: [PATCH 04/13] File must be in unix format --- configuration/tmuxManagementConsole.sh | 88 +++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/configuration/tmuxManagementConsole.sh b/configuration/tmuxManagementConsole.sh index 7f829e2c0c6..4d4370a1a56 100755 --- a/configuration/tmuxManagementConsole.sh +++ b/configuration/tmuxManagementConsole.sh @@ -1,44 +1,44 @@ -#!/bin/bash - -command -v tmux >/dev/null 2>&1 || { echo "I require tmux but it's not installed. Aborting." >&2; exit 1; } - -sn=sailing - -SERVERS_DIR=/home/trac/servers - -TMUX_ACTIVE=`tmux has-session -t $sn 2>/dev/null` -if [ $? -eq 0 ]; then - echo "Session exists...not configuring a new one" -else - echo "Session does not exist...creating a new one with name $sn" - cd /home/trac/git - tmux new-session -s "$sn" -n "BUILD" -d - - counter=1 - for dir in dev test prod1 prod2; do - cd $SERVERS_DIR/$dir - tmux new-window -t "$sn:$counter" -n `basename $dir` "bash -c './start'; bash" - counter=$[counter + 1] - done - - cd /home/trac/servers/prod1 - tmux new-window -t "$sn:$counter" -n "UDP" "bash -c './udpmirror -v 2012 localhost 2010 localhost 2011 localhost 2013 localhost 2014'; bash" - - cd /opt/mongodb/bin - tmux new-window -t "$sn:$[counter+1]" -n "GOAccess" "bash -c 'goaccess -f /var/log/httpd/access_log'; bash" - - cd /opt/ - tmux new-window -t "$sn:$[counter+2]" -n "ATop" "bash -c 'apachetop -f /var/log/httpd/access_log'; bash" - - cd /home/trac/servers - tmux new-window -t "$sn:$[counter+3]" -n "Logs" "bash -c 'ls -lah'; bash" - - cd /home/trac/servers/prod1 - tmux new-window -t "$sn:$[counter+4]" -n "STListener" "bash -c './swisstiminglistener 3500 3501'; bash" - - tmux select-window -t "$sn:0" -fi - -if [[ "$1" != "unattended" ]]; then - tmux -2 attach-session -t "$sn" -fi +#!/bin/bash + +command -v tmux >/dev/null 2>&1 || { echo "I require tmux but it's not installed. Aborting." >&2; exit 1; } + +sn=sailing + +SERVERS_DIR=/home/trac/servers + +TMUX_ACTIVE=`tmux has-session -t $sn 2>/dev/null` +if [ $? -eq 0 ]; then + echo "Session exists...not configuring a new one" +else + echo "Session does not exist...creating a new one with name $sn" + cd /home/trac/git + tmux new-session -s "$sn" -n "BUILD" -d + + counter=1 + for dir in dev test prod1 prod2; do + cd $SERVERS_DIR/$dir + tmux new-window -t "$sn:$counter" -n `basename $dir` "bash -c './start'; bash" + counter=$[counter + 1] + done + + cd /home/trac/servers/prod1 + tmux new-window -t "$sn:$counter" -n "UDP" "bash -c './udpmirror -v 2012 localhost 2010 localhost 2011 localhost 2013 localhost 2014'; bash" + + cd /opt/mongodb/bin + tmux new-window -t "$sn:$[counter+1]" -n "GOAccess" "bash -c 'goaccess -f /var/log/httpd/access_log'; bash" + + cd /opt/ + tmux new-window -t "$sn:$[counter+2]" -n "ATop" "bash -c 'apachetop -f /var/log/httpd/access_log'; bash" + + cd /home/trac/servers + tmux new-window -t "$sn:$[counter+3]" -n "Logs" "bash -c 'ls -lah'; bash" + + cd /home/trac/servers/prod1 + tmux new-window -t "$sn:$[counter+4]" -n "STListener" "bash -c './swisstiminglistener 3500 3501'; bash" + + tmux select-window -t "$sn:0" +fi + +if [[ "$1" != "unattended" ]]; then + tmux -2 attach-session -t "$sn" +fi From 44502f6c34ee08a5cf0eb075605275697a3f129f Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Mon, 3 Jun 2013 15:30:22 +0200 Subject: [PATCH 05/13] Do not overwrite start and stop --- configuration/buildAndUpdateProduct.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index e697a672c96..58e1e9301d7 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -347,8 +347,12 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/realm.properties configuration/jetty/etc cp -v $PROJECT_HOME/java/target/configuration/monitoring.properties configuration/ cp -v $PROJECT_HOME/configuration/mongodb.cfg $ACDIR/ - cp -v $PROJECT_HOME/java/target/start $ACDIR/ - cp -v $PROJECT_HOME/java/target/stop $ACDIR/ + + # avoid overwriting start configuration if it exists + if [ ! -f $ACDIR/start ]; then + cp -v $PROJECT_HOME/java/target/start $ACDIR/ + cp -v $PROJECT_HOME/java/target/stop $ACDIR/ + fi fi cp -r -v $p2PluginRepository/configuration/org.eclipse.equinox.simpleconfigurator configuration/ From 7cb85b117c87aee6bd32beca3cc3612a66d6b397 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Mon, 3 Jun 2013 15:53:36 +0200 Subject: [PATCH 06/13] Do not remove start,stop --- configuration/buildAndUpdateProduct.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index 58e1e9301d7..77746b913a5 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -338,9 +338,6 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then rm -rf $ACDIR/configuration/org.eclipse.* if [[ $HAS_OVERWRITTEN_TARGET -eq 0 ]]; then - rm -rf $ACDIR/start - rm -rf $ACDIR/stop - cp -v $p2PluginRepository/configuration/config.ini configuration/ mkdir -p configuration/jetty/etc cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/jetty.xml configuration/jetty/etc From 86c976c0cc4c17bd4893b519784b954cea2a1b6a Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 14:21:36 +0200 Subject: [PATCH 07/13] bug 1418: support high point scoring scheme where winner receives one point --- .../domain/common/ScoringSchemeType.java | 2 +- .../domain/base/impl/DomainFactoryImpl.java | 3 +++ .../HighPointFirstGets1LastBreaksTie.java | 25 +++++++++++++++++++ .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../ScoringSchemeTypeFormatter.java | 2 ++ 7 files changed, 34 insertions(+), 1 deletion(-) create mode 100755 java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java index 491b5be22da..b49b524d5cb 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java @@ -2,5 +2,5 @@ package com.sap.sailing.domain.common; public enum ScoringSchemeType { LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, - HIGH_POINT_FIRST_GETS_TEN, LOW_POINT_WINNER_GETS_ZERO + HIGH_POINT_FIRST_GETS_TEN, HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 375e7a9c9dc..fba4a42561e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -56,6 +56,7 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero; @@ -320,6 +321,8 @@ public class DomainFactoryImpl implements DomainFactory { return new HighPointExtremeSailingSeriesOverall(); case HIGH_POINT_LAST_BREAKS_TIE: return new HighPointLastBreaksTie(); + case HIGH_POINT_FIRST_GETS_ONE: + return new HighPointFirstGets1LastBreaksTie(); case HIGH_POINT_FIRST_GETS_TEN: return new HighPointFirstGets10LastBreaksTie(); case LOW_POINT_WINNER_GETS_ZERO: diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java new file mode 100755 index 00000000000..05a4f0fa5cd --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java @@ -0,0 +1,25 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.List; + +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.impl.Util.Pair; + +public class HighPointFirstGets1LastBreaksTie extends HighPointFirstGetsFixedScore { + private static final long serialVersionUID = 1L; + + public HighPointFirstGets1LastBreaksTie() { + super(10.0); + } + + @Override + public ScoringSchemeType getType() { + return ScoringSchemeType.HIGH_POINT_FIRST_GETS_ONE; + } + + @Override + public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + return 0; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 50bca9a4a3a..f1eb54b6ebe 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -449,6 +449,7 @@ public interface StringMessages extends Messages { String sideToWhichMarkAtLegStartWasRounded(); String raceIsLive(String raceName); String racesAreLive(String raceNames); + String scoringSchemeHighPointFirstGetsOne(); String scoringSchemeHighPointFirstGetsTen(); String knotsUnit(); String averageJibeLossInMetersTooltip(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index a0e4a4e07cc..5ea9061dbdf 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -490,6 +490,7 @@ sideToWhichMarkAtLegStartWasRoundedTooltip=Side to which the mark at leg start w raceIsLive=Race {0} is live racesAreLive=Races {0} are live knotsUnit=kts +scoringSchemeHighPointFirstGetsTen=High Point, winner gets 1 point scoringSchemeHighPointFirstGetsTen=High Point, winner gets 10 points knotsUnit=kts generatePolarSheet=Generate Polar Sheet diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 52a54d147cb..1151dbed673 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -490,6 +490,7 @@ sideToWhichMarkAtLegStartWasRounded=Tonne gerundet an sideToWhichMarkAtLegStartWasRoundedTooltip=Seite, an der die Bahnmarke am Schenkelstart gerundet wurde raceIsLive=Rennen {0} ist live racesAreLive=Rennen {0} sind live +scoringSchemeHighPointFirstGetsOne=High Point System, Gewinner erhält 1 Punkt scoringSchemeHighPointFirstGetsTen=High Point System, Gewinner erhält 10 Punkte knotsUnit=kn generatePolarSheet=Polardiagramm erstellen diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java index 18b39cf4e12..d3a2d0fc004 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java @@ -14,6 +14,8 @@ public class ScoringSchemeTypeFormatter { return stringMessages.scoringSchemeHighPointEssOverall(); case HIGH_POINT_LAST_BREAKS_TIE: return stringMessages.scoringSchemeHighPointLastBreaksTie(); + case HIGH_POINT_FIRST_GETS_ONE: + return stringMessages.scoringSchemeHighPointFirstGetsOne(); case HIGH_POINT_FIRST_GETS_TEN: return stringMessages.scoringSchemeHighPointFirstGetsTen(); case LOW_POINT_WINNER_GETS_ZERO: From 37a659c5dd733552606a1fb43bd0abf05c70cf3d Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 14:22:54 +0200 Subject: [PATCH 08/13] penalty for high-point scoring scheme where winner gets one point is -1 --- .../impl/HighPointFirstGets1LastBreaksTie.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java index 05a4f0fa5cd..7e545cb0d2b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java @@ -2,15 +2,18 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.List; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; public class HighPointFirstGets1LastBreaksTie extends HighPointFirstGetsFixedScore { private static final long serialVersionUID = 1L; public HighPointFirstGets1LastBreaksTie() { - super(10.0); + super(1.0); } @Override @@ -18,6 +21,12 @@ public class HighPointFirstGets1LastBreaksTie extends HighPointFirstGetsFixedSco return ScoringSchemeType.HIGH_POINT_FIRST_GETS_ONE; } + @Override + public Double getPenaltyScore(RaceColumn raceColumn, Competitor competitor, MaxPointsReason maxPointsReason, Integer numberOfCompetitorsInRace, + NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher) { + return -1.0; + } + @Override public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { return 0; From 62686a9808b1e417fb893abc49b6bce6d7c24c44 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 15:50:24 +0200 Subject: [PATCH 09/13] fixed AbstractRaceColumn so that it properly notifies listeners when releaseTrackedRace is called --- .../domain/test/LeaderboardOfflineTest.java | 49 +++++++++++++++++++ .../domain/test/mock/MockedTrackedRace.java | 4 +- .../mock/MockedTrackedRaceWithFixedRank.java | 10 +++- .../domain/base/impl/AbstractRaceColumn.java | 2 +- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 312d7bfbfed..640a7ae9e67 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -2,10 +2,13 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -13,17 +16,22 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; @@ -33,7 +41,9 @@ import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; public class LeaderboardOfflineTest extends AbstractLeaderboardTest { private Set testRaces; @@ -100,6 +110,45 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { leaderboard.addRace(testRaces.iterator().next(), columnName, /* medalRace */ false, defaultFleet); assertTrue(leaderboard.getRaceColumnByName(columnName).isMedalRace()); } + + @Test + public void testRepeatedLeaderboardDTOCacheInvalidation() throws NoWindException, InterruptedException, ExecutionException { + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( + new int[] { 5, 8 }), new LowPoint(), null); + Fleet defaultFleet = leaderboard.getFleet(null); + final String columnName = "abc"; + setupRaces(1, 0); + leaderboard.addRaceColumn(columnName, /* medalRace */ true); + leaderboard.addRace(testRaces.iterator().next(), columnName, /* medalRace */ false, defaultFleet); + final Set emptySet = Collections.emptySet(); + final MillisecondsTimePoint now = MillisecondsTimePoint.now(); + final TrackedRegattaRegistry trackedRegattaRegistry = new TrackedRegattaRegistry() { + @Override + public DynamicTrackedRegatta getOrCreateTrackedRegatta(Regatta regatta) { + return null; + } + @Override + public DynamicTrackedRegatta getTrackedRegatta(Regatta regatta) { + return null; + } + @Override + public void removeTrackedRegatta(Regatta regatta) {} + + @Override + public Regatta getRememberedRegattaForRace(Serializable raceID) { + return null; + } + @Override + public boolean isRaceBeingTracked(RaceDefinition r) { + return true; + } + }; + LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE); + assertNotNull(leaderboardDTO); + assertSame(leaderboardDTO, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); // assert it's cached + leaderboard.getRaceColumnByName(columnName).releaseTrackedRace(defaultFleet); // this should clear the cache + assertNotSame(leaderboardDTO, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); + } @Test public void testMaxPointsDiscard() throws NoWindException { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index c0816107934..e4e4f97cb06 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; import java.util.List; import java.util.NavigableSet; +import java.util.TreeSet; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -191,8 +192,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public NavigableSet getMarkPassings(Competitor competitor) { - // TODO Auto-generated method stub - return null; + return new TreeSet(); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java index a39362bb385..18ee0bc4be7 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -8,6 +9,8 @@ import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; @@ -33,6 +36,11 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { private class MockedRaceDefinition implements RaceDefinition { private static final long serialVersionUID = 6812543850545870357L; + private final Course course; + + public MockedRaceDefinition() { + course = new CourseImpl("Test Course", Arrays.asList(new Waypoint[0])); + } @Override public String getName() { @@ -41,7 +49,7 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { @Override public Course getCourse() { - return null; + return course; } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index 893059bbfb5..a625bd8469a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -101,7 +101,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public synchronized void releaseTrackedRace(Fleet fleet) { - trackedRaces.remove(fleet); + setTrackedRace(fleet, null); } @Override From 7f638de7d929909204607372b05ed04c14ad099e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 15:57:36 +0200 Subject: [PATCH 10/13] fixed bug 1421 and provided a test case --- .../domain/test/LeaderboardOfflineTest.java | 8 +- .../leaderboard/LeaderboardCacheManager.java | 153 +++++++++--------- .../caching/LeaderboardDTOCache.java | 2 +- 3 files changed, 88 insertions(+), 75 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 640a7ae9e67..b2a12be2795 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -147,7 +147,13 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { assertNotNull(leaderboardDTO); assertSame(leaderboardDTO, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); // assert it's cached leaderboard.getRaceColumnByName(columnName).releaseTrackedRace(defaultFleet); // this should clear the cache - assertNotSame(leaderboardDTO, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); + LeaderboardDTO leaderboardDTO2 = leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE); + assertNotSame(leaderboardDTO, leaderboardDTO2); + assertSame(leaderboardDTO2, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); // and cached again + leaderboard.getRaceColumnByName(columnName).setTrackedRace(defaultFleet, testRaces.iterator().next()); // clear cache again; requires listener(s) to still be attached + LeaderboardDTO leaderboardDTO3 = leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE); + assertNotSame(leaderboardDTO2, leaderboardDTO3); + assertSame(leaderboardDTO3, leaderboard.getLeaderboardDTO(now, emptySet, trackedRegattaRegistry, DomainFactory.INSTANCE)); // and cached again } @Test diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index a09b9a63e5e..dccab7703f0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -180,94 +180,101 @@ public class LeaderboardCacheManager { * is updated accordingly. */ private void registerAsListener(final Leaderboard leaderboard) { - for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) { - registerListener(leaderboard, trackedRace); - } - final CacheInvalidationUponScoreCorrectionListener scoreCorrectionListener = new CacheInvalidationUponScoreCorrectionListener(leaderboard); - leaderboard.getScoreCorrection().addScoreCorrectionListener(scoreCorrectionListener); - synchronized (scoreCorrectionListeners) { - scoreCorrectionListeners.put(leaderboard, scoreCorrectionListener); - } - final RaceColumnListener raceColumnListener = new RaceColumnListener() { - private static final long serialVersionUID = 8165124797028386317L; - - @Override - public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - removeFromCache(leaderboard); + // only add as listener again if not yet added + if (!scoreCorrectionListeners.containsKey(leaderboard)) { + for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) { registerListener(leaderboard, trackedRace); } - - /** - * This listener must not be serialized. See also bug 952. - */ - @Override - public boolean isTransient() { - return true; + final CacheInvalidationUponScoreCorrectionListener scoreCorrectionListener = new CacheInvalidationUponScoreCorrectionListener( + leaderboard); + leaderboard.getScoreCorrection().addScoreCorrectionListener(scoreCorrectionListener); + synchronized (scoreCorrectionListeners) { + scoreCorrectionListeners.put(leaderboard, scoreCorrectionListener); } - - @Override - public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - removeFromCache(leaderboard); - Map> listenersMap = invalidationListenersPerLeaderboard.get(leaderboard); - if (listenersMap != null) { - Set listeners = listenersMap.get(trackedRace); - if (listeners != null) { - for (CacheInvalidationListener listener : listeners) { - listener.removeFromTrackedRace(); + final RaceColumnListener raceColumnListener = new RaceColumnListener() { + private static final long serialVersionUID = 8165124797028386317L; + + @Override + public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + removeFromCache(leaderboard); + registerListener(leaderboard, trackedRace); + } + + /** + * This listener must not be serialized. See also bug 952. + */ + @Override + public boolean isTransient() { + return true; + } + + @Override + public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + removeFromCache(leaderboard); + Map> listenersMap = invalidationListenersPerLeaderboard + .get(leaderboard); + if (listenersMap != null) { + Set listeners = listenersMap.get(trackedRace); + if (listeners != null) { + for (CacheInvalidationListener listener : listeners) { + listener.removeFromTrackedRace(); + } } } } - } - @Override - public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) { - removeFromCache(leaderboard); - } + @Override + public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) { + removeFromCache(leaderboard); + } - @Override - public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) { - return true; - } + @Override + public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) { + return true; + } - @Override - public void raceColumnAddedToContainer(RaceColumn raceColumn) { - removeFromCache(leaderboard); - } + @Override + public void raceColumnAddedToContainer(RaceColumn raceColumn) { + removeFromCache(leaderboard); + } - @Override - public void raceColumnRemovedFromContainer(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 raceColumnMoved(RaceColumn raceColumn, int newIndex) { + removeFromCache(leaderboard); + } - @Override - public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { - removeFromCache(leaderboard); - } + @Override + public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { + removeFromCache(leaderboard); + } - @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { - removeFromCache(leaderboard); - } + @Override + public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, + ThresholdBasedResultDiscardingRule newDiscardingRule) { + removeFromCache(leaderboard); + } - @Override - public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) { - 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) { + raceColumnListeners.put(leaderboard, raceColumnListener); } - - @Override - public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) { - removeFromCache(leaderboard); - } - }; - leaderboard.addRaceColumnListener(raceColumnListener); - synchronized (raceColumnListeners) { - raceColumnListeners.put(leaderboard, raceColumnListener); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCache.java index 9c8fae22556..383c51cb4ef 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCache.java @@ -88,7 +88,6 @@ public class LeaderboardDTOCache implements LeaderboardCache { } }; this.leaderboardCacheManager = new LeaderboardCacheManager(this); - this.leaderboardCacheManager.add(leaderboard); } @Override @@ -159,6 +158,7 @@ public class LeaderboardDTOCache implements LeaderboardCache { } }); computeLeadearboardByNameExecutor.execute(future); + this.leaderboardCacheManager.add(leaderboard); // ensure the leaderboard is tracked for changes to invalidate leaderboardCache.put(key, future); } else { cacheHit = true; From e4766d9445e69b3a22761c4d782e79688a4e42f9 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 4 Jun 2013 16:56:38 +0200 Subject: [PATCH 11/13] renaming of RegattaRaceStatesJsonGetServlet to EventRaceStatesJsonGetServlet --- .../WEB-INF/web.xml | 18 +++++++++--------- ...java => EventRaceStatesJsonGetServlet.java} | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) rename java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/{rc/RegattaRaceStatesJsonGetServlet.java => EventRaceStatesJsonGetServlet.java} (97%) diff --git a/java/com.sap.sailing.server.gateway/WEB-INF/web.xml b/java/com.sap.sailing.server.gateway/WEB-INF/web.xml index 7d1ba633b4d..46d528f9ecc 100644 --- a/java/com.sap.sailing.server.gateway/WEB-INF/web.xml +++ b/java/com.sap.sailing.server.gateway/WEB-INF/web.xml @@ -58,15 +58,6 @@ RCCompetitors /rc/competitors - - - RCRegattaRaceStates - com.sap.sailing.server.gateway.impl.rc.RegattaRaceStatesJsonGetServlet - - - RCRegattaRaceStates - /rc/regattaRaceStates - @@ -97,6 +88,15 @@ /events + + EventRaceStatesServlet + com.sap.sailing.server.gateway.impl.EventRaceStatesJsonGetServlet + + + EventRaceStatesServlet + /eventRaceStates + + RegattasJsonGetServlet com.sap.sailing.server.gateway.impl.RegattasJsonGetServlet diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RegattaRaceStatesJsonGetServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java similarity index 97% rename from java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RegattaRaceStatesJsonGetServlet.java rename to java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java index 5dfd893a104..d3defd9d998 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RegattaRaceStatesJsonGetServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java @@ -1,4 +1,4 @@ -package com.sap.sailing.server.gateway.impl.rc; +package com.sap.sailing.server.gateway.impl; import java.io.IOException; import java.util.Calendar; @@ -32,10 +32,10 @@ import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer; import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder; import com.sap.sailing.server.gateway.AbstractJsonHttpServlet; -public class RegattaRaceStatesJsonGetServlet extends AbstractJsonHttpServlet { +public class EventRaceStatesJsonGetServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = -4820965681871902242L; - private final static Logger logger = Logger.getLogger(RegattaRaceStatesJsonGetServlet.class.getName()); + private final static Logger logger = Logger.getLogger(EventRaceStatesJsonGetServlet.class.getName()); private static final String PARAM_NAME_EVENTID = "eventId"; private static final String PARAM_NAME_FILTER_BY_COURSEAREA = "filterByCourseArea"; From 218b9747a9e06ae014c128aab99daad0f826dc2b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 17:09:28 +0200 Subject: [PATCH 12/13] fixed string messages for new scoring scheme --- .../com/sap/sailing/gwt/ui/client/StringMessages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 5ea9061dbdf..17f5959788c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -490,7 +490,7 @@ sideToWhichMarkAtLegStartWasRoundedTooltip=Side to which the mark at leg start w raceIsLive=Race {0} is live racesAreLive=Races {0} are live knotsUnit=kts -scoringSchemeHighPointFirstGetsTen=High Point, winner gets 1 point +scoringSchemeHighPointFirstGetsOne=High Point, winner gets 1 point scoringSchemeHighPointFirstGetsTen=High Point, winner gets 10 points knotsUnit=kts generatePolarSheet=Generate Polar Sheet From 84e6a6d98f5858e482f3247b862b4875af055542 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 4 Jun 2013 22:15:04 +0200 Subject: [PATCH 13/13] made detaching of a race log null safe --- .../sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java | 4 +++- .../domain/tracking/impl/DynamicTrackedRaceLogListener.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index b658309d6f4..bd81bb318d9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -670,7 +670,9 @@ DynamicTrackedRace, GPSTrackListener { @Override public void detachRaceLog() { - logListener.removeFrom(attachedRaceLog); + if (attachedRaceLog != null) { + logListener.removeFrom(attachedRaceLog); + } super.detachRaceLog(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java index f4f83a1e7ad..2676d8a4570 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java @@ -49,7 +49,9 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor { // Maybe something like this is needed: // TODO: // ??? trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.PREPARED, 0.0)); - raceLog.removeListener(this); + if (raceLog != null) { + raceLog.removeListener(this); + } } private void analyze() {