diff --git a/doc/SAP_Race_Manager_App_Leaflet_v3_no_Bleed.pdf b/doc/SAP_Race_Manager_App_Leaflet_v3_no_Bleed.pdf new file mode 100644 index 00000000000..e0f4ccbdbc6 Binary files /dev/null and b/doc/SAP_Race_Manager_App_Leaflet_v3_no_Bleed.pdf differ diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/card/StartAnalysisCard.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/card/StartAnalysisCard.java index f9cf4529613..258a0a33106 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/card/StartAnalysisCard.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/card/StartAnalysisCard.java @@ -151,16 +151,28 @@ public class StartAnalysisCard extends Composite implements HasWidgets, StartAna timer.setTime(startAnalysisDTO.timeOfStartInMilliSeconds); zoomTypes.add(ZoomTypes.BUOYS); } + RaceMapZoomSettings raceMapZoomSettings = new RaceMapZoomSettings(zoomTypes, false); + AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); - RaceMapSettings raceMapSettings = RaceMapSettings.readSettingsFromURL(); + RaceMapSettings defaultRaceMapSettings = RaceMapSettings.readSettingsFromURL( + /* defaultForShowMapControls */ true, /* defaultForShowCourseGeometry */ false, + /* defaultForMapOrientationWindUp */ false, /* defaultForViewShowStreamlets */ false, + /* defaultForViewShowStreamletColors */ false, /* defaultForViewShowSimulation */ false); + final RaceMapSettings raceMapSettings = new RaceMapSettings(raceMapZoomSettings, getHelpLineSettings(), + defaultRaceMapSettings.getTransparentHoverlines(), defaultRaceMapSettings.getHoverlineStrokeWeight(), + startAnalysisDTO.tailLenghtInMilliseconds, defaultRaceMapSettings.isWindUp(), + defaultRaceMapSettings.getBuoyZoneRadiusInMeters(), defaultRaceMapSettings.isShowOnlySelectedCompetitors(), + defaultRaceMapSettings.isShowSelectedCompetitorsInfo(), defaultRaceMapSettings.isShowWindStreamletColors(), + defaultRaceMapSettings.isShowWindStreamletOverlay(), defaultRaceMapSettings.isShowSimulationOverlay(), + defaultRaceMapSettings.isShowMapControls(), defaultRaceMapSettings.getManeuverTypesToShow(), + defaultRaceMapSettings.isShowDouglasPeuckerPoints()); + + RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingServiceAsync, asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */); raceMap = new RaceMap(new RaceMapLifecycle(StringMessages.INSTANCE), raceMapSettings, sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel, StringMessages.INSTANCE, startAnalysisDTO.regattaAndRaceIdentifier, raceMapResources, /* isSimulationEnabled */ false, /* showHeaderPanel */ true); - raceMap.getSettings().setZoomSettings(new RaceMapZoomSettings(zoomTypes, false)); - raceMap.getSettings().setHelpLinesSettings(getHelpLineSettings()); - raceMap.getSettings().setTailLengthInMilliseconds(startAnalysisDTO.tailLenghtInMilliseconds); raceTimesInfoProvider.addRaceTimesInfoProviderListener(raceMap); raceMap.setSize("100%", "100%"); card_map_container.getElement().getStyle().setHeight(getHeightForRaceMapInPixels(), Unit.PX); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index a4c2ffa6b72..ac770b47302 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -2084,4 +2084,137 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertTrue(leaderboard.isDiscarded(rankedCompetitor, qColumn, later)); } } + + + /** + * See bug 3752: when the medal race participants do not race in a "Last Race" gold fleet and the "Last Race" column comes before the + * medal race column, medal race participants must still rank better than all others; participants not in the medal race and not in + * any of the gold and silver fleet of the last race may rank between gold and silver fleet based on the "extreme fleet" idea. + */ + @Test + public void testTotalRankComparatorForOrderedSplitFleetsWithMedalRaceParticipantsNotRacingInLastRaceGoldFleet() throws NoWindException { + series = new ArrayList(); + // -------- qualification series ------------ + { + List qualificationFleets = new ArrayList(); + for (String qualificationFleetName : new String[] { "Yellow", "Blue" }) { + qualificationFleets.add(new FleetImpl(qualificationFleetName)); + } + List qualificationRaceColumnNames = new ArrayList(); + qualificationRaceColumnNames.add("Q"); + Series qualificationSeries = new SeriesImpl("Qualification", /* isMedal */false, /* isFleetsCanRunInParallel */ true, qualificationFleets, qualificationRaceColumnNames, /* trackedRegattaRegistry */ null); + // discard the one and only qualification race; it doesn't score + qualificationSeries.setResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(new int[] { 1 })); + series.add(qualificationSeries); + } + + // -------- final series ------------ + { + List finalFleets = new ArrayList(); + int fleetOrdering = 1; + for (String finalFleetName : new String[] { "Gold", "Silver" }) { + finalFleets.add(new FleetImpl(finalFleetName, fleetOrdering++)); + } + List finalRaceColumnNames = new ArrayList(); + finalRaceColumnNames.add("F"); + Series finalSeries = new SeriesImpl("Final", /* isMedal */false, /* isFleetsCanRunInParallel */ true, finalFleets, finalRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(finalSeries); + } + // -------- last race series ------------ + { + List lastRaceFleets = new ArrayList(); + int fleetOrdering = 1; + for (String finalFleetName : new String[] { "Gold", "Silver" }) { + lastRaceFleets.add(new FleetImpl(finalFleetName, fleetOrdering++)); + } + List lastRaceColumnNames = new ArrayList(); + lastRaceColumnNames.add("L"); + Series lastRaceSeries = new SeriesImpl("Last Race", /* isMedal */false, /* isFleetsCanRunInParallel */ true, lastRaceFleets, lastRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(lastRaceSeries); + } + // -------- medal series ------------ + { + Set medalFleets = Collections.singleton(new FleetImpl("Default")); + List medalRaceColumnNames = new ArrayList(); + medalRaceColumnNames.add("M"); + Series medalSeries = new SeriesImpl("Medal", /* isMedal */true, /* isFleetsCanRunInParallel */ true, medalFleets, medalRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(medalSeries); + } + final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true); + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* course area */null, OneDesignRankingMetric::new); + List competitors = createCompetitors(12); + final int firstYellowCompetitorIndex = 3; + List yellow = new ArrayList<>(competitors.subList(firstYellowCompetitorIndex, firstYellowCompetitorIndex+6)); + List blue = new ArrayList<>(competitors); + blue.removeAll(yellow); + Collections.shuffle(yellow); + Collections.shuffle(blue); + final int firstGoldCompetitorIndex = 5; + List gold = new ArrayList<>(competitors.subList(firstGoldCompetitorIndex, firstGoldCompetitorIndex+6)); + List silver = new ArrayList<>(competitors); + silver.removeAll(gold); + Collections.shuffle(gold); + Collections.shuffle(silver); + List lastRaceSilver = new ArrayList<>(silver); + final Competitor theUntrackedCompetitorInLastRace = lastRaceSilver.get(lastRaceSilver.size()-1); + lastRaceSilver.remove(theUntrackedCompetitorInLastRace); // one participant accidentally not tracked; expected to end up between silver and gold + List medal = new ArrayList<>(gold.subList(0, 2)); // take two gold race participants as medal race participants + List lastRaceGold = new ArrayList<>(gold); + lastRaceGold.removeAll(medal); // no medal race participant participates in the last race's gold fleet + + Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]); + TimePoint now = MillisecondsTimePoint.now(); + TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); + RaceColumn qColumn = series.get(0).getRaceColumnByName("Q"); + TrackedRace qYellow = new MockedTrackedRaceWithStartTimeAndRanks(now, yellow); + qColumn.setTrackedRace(qColumn.getFleetByName("Yellow"), qYellow); + TrackedRace qBlue = new MockedTrackedRaceWithStartTimeAndRanks(now, blue); + qColumn.setTrackedRace(qColumn.getFleetByName("Blue"), qBlue); + RaceColumn fColumn = series.get(1).getRaceColumnByName("F"); + TrackedRace f1Gold = new MockedTrackedRaceWithStartTimeAndRanks(now, gold); + fColumn.setTrackedRace(fColumn.getFleetByName("Gold"), f1Gold); + TrackedRace f1Silver = new MockedTrackedRaceWithStartTimeAndRanks(now, silver); + fColumn.setTrackedRace(fColumn.getFleetByName("Silver"), f1Silver); + RaceColumn lastRaceColumn = series.get(2).getRaceColumnByName("L"); + TrackedRace lGold = new MockedTrackedRaceWithStartTimeAndRanks(now, lastRaceGold); + lastRaceColumn.setTrackedRace(lastRaceColumn.getFleetByName("Gold"), lGold); + TrackedRace lSilver = new MockedTrackedRaceWithStartTimeAndRanks(now, lastRaceSilver); + lastRaceColumn.setTrackedRace(lastRaceColumn.getFleetByName("Silver"), lSilver); + RaceColumn medalColumn = series.get(3).getRaceColumnByName("M"); + TrackedRace mDefault = new MockedTrackedRaceWithStartTimeAndRanks(now, medal); + medalColumn.setTrackedRace(medalColumn.getFleetByName("Default"), mDefault); + + List rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later); + Map netPoints = new LinkedHashMap<>(); + for (Competitor rankedCompetitor : rankedCompetitors) { + netPoints.put(rankedCompetitor, leaderboard.getNetPoints(rankedCompetitor, later)); + } + // assert that all medal participants rank better than all other participants + for (final Competitor medalCompetitor : medal) { + for (final Competitor c : competitors) { + if (!medal.contains(c)) { + assertTrue(rankedCompetitors.indexOf(medalCompetitor) < rankedCompetitors.indexOf(c)); + } + } + } + // assert that all last race's gold participants rank better than all silver participants + for (final Competitor lastRaceGoldParticipant : lastRaceGold) { + for (final Competitor silverParticipant : silver) { + assertTrue(rankedCompetitors.indexOf(lastRaceGoldParticipant) < rankedCompetitors.indexOf(silverParticipant)); + } + } + // assert that theUntrackedCompetitorInLastRace ended up between the last race's silver and gold fleet participants + // based on the "extreme fleet" rule: + for (final Competitor c : competitors) { + if (c != theUntrackedCompetitorInLastRace) { + if (lastRaceGold.contains(c) || medal.contains(c)) { + assertTrue(rankedCompetitors.indexOf(c) < rankedCompetitors.indexOf(theUntrackedCompetitorInLastRace)); + } else { + assertTrue(silver.contains(c)); + assertTrue(rankedCompetitors.indexOf(c) > rankedCompetitors.indexOf(theUntrackedCompetitorInLastRace)); + } + } + } + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java index b2d40b3bb9e..311be94761c 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java @@ -113,6 +113,7 @@ public class LeaderboardTotalRankComparator implements Comparator { // the competitor scored in this or any subsequent columns boolean needToResetO1ScoreUponNextValidResult = false; boolean needToResetO2ScoreUponNextValidResult = false; + int defaultFleetBasedComparisonResult = 0; // relevant if no authoritative fleet-based comparison result was determined; based on extreme fleet vs. no fleet comparison for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) { needToResetO1ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore(); needToResetO2ScoreUponNextValidResult = raceColumn.isStartsWithZeroScore(); @@ -173,13 +174,20 @@ public class LeaderboardTotalRankComparator implements Comparator { preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score); } if (preemptiveColumnResult == 0 && raceColumn.isTotalOrderDefinedByFleet()) { - preemptiveColumnResult = compareByFleet(raceColumn, o1, o2); + final FleetComparisonResult compareByFleetResult = compareByFleet(raceColumn, o1, o2); + preemptiveColumnResult = compareByFleetResult.getAuthoritativeFleetComparisonResult(); + if (defaultFleetBasedComparisonResult == 0) { + defaultFleetBasedComparisonResult = compareByFleetResult.getDefaultFleetComparisonResultBasedOnUnknownFleetAssignment(); + } } if (preemptiveColumnResult != 0) { return preemptiveColumnResult; } } } + if (defaultFleetBasedComparisonResult != 0) { + return defaultFleetBasedComparisonResult; + } // now count the races in which they scored; if they scored in a different number of races, prefer the // competitor who scored more often; otherwise, prefer the competitor who has a better score sum; if score sums are equal, // break tie by sorting scores and looking for the first score difference. @@ -220,27 +228,63 @@ public class LeaderboardTotalRankComparator implements Comparator { } } - private int compareByFleet(RaceColumn raceColumn, Competitor o1, Competitor o2) { + private static class FleetComparisonResult { + /** + * Is non-{@code 0} if the two competitors have been identified as having raced in different fleets in + * {@code raceColumn} with those fleets having different {@link Fleet#getOrdering() orderings}. + * Evaluation of further comparison criteria is not necessary in this case. + */ + private final int authoritativeFleetComparisonResult; + + /** + * When for one of the two competitors compared the fleet in which she raced in a race column + * could not be determined and the other competitor can be identified as having competed in the + * best or in the worst fleet in that column, a default comparison result is derived from this + * such that the competitor with the unknown fleet assignment would be considered worse than + * a participant of the best, and better than a participant of the worst fleet.

+ * + * This result only has relevance if no non-{@code 0} authoritative result can be acquired across + * all columns of the leaderboard. + */ + private final int defaultFleetComparisonResultBasedOnUnknownFleetAssignment; + + public FleetComparisonResult(int authoritativeFleetComparisonResult, + int defaultFleetComparisonResultBasedOnUnknownFleetAssignment) { + super(); + this.authoritativeFleetComparisonResult = authoritativeFleetComparisonResult; + this.defaultFleetComparisonResultBasedOnUnknownFleetAssignment = defaultFleetComparisonResultBasedOnUnknownFleetAssignment; + } + + public int getAuthoritativeFleetComparisonResult() { + return authoritativeFleetComparisonResult; + } + + public int getDefaultFleetComparisonResultBasedOnUnknownFleetAssignment() { + return defaultFleetComparisonResultBasedOnUnknownFleetAssignment; + } + } + + private FleetComparisonResult compareByFleet(RaceColumn raceColumn, Competitor o1, Competitor o2) { Fleet o1f = raceColumn.getFleetOfCompetitor(o1); Fleet o2f = raceColumn.getFleetOfCompetitor(o2); // if the fleet for both was identified because both were tracked in this column, then if the fleets // don't compare equal, return the fleet comparison as result immediately. Example: o1 competed in Gold fleet, // o2 in Silver fleet; Gold compares better to Silver, so o1 is compared better to o2. - int result = 0; + final FleetComparisonResult result; if (o1f != null) { if (o2f != null) { - if (o1f.compareTo(o2f) != 0) { - result = o1f.compareTo(o2f); - } + result = new FleetComparisonResult(o1f.compareTo(o2f), 0); } else { // check if o1's fleet is best or worst in column; in that case, o1's membership in this fleet and the fact // that o2 is not part of that fleet determines the result - result = extremeFleetComparison(raceColumn, o1f); + result = new FleetComparisonResult(0, extremeFleetComparison(raceColumn, o1f)); } } else if (o2f != null) { - // check if o1's fleet is best or worst in column; in that case, o1's membership in this fleet and the fact - // that o2 is not part of that fleet determines the result - result = -extremeFleetComparison(raceColumn, o2f); + // check if o2's fleet is best or worst in column; in that case, o2's membership in this fleet and the fact + // that o1 is not part of that fleet determines the result + result = new FleetComparisonResult(0, -extremeFleetComparison(raceColumn, o2f)); + } else { + result = new FleetComparisonResult(0, 0); } return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java index 2ff462f7067..f5584b9d32f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java @@ -329,7 +329,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe private RaceMapImageManager raceMapImageManager; - private final RaceMapSettings settings; + private RaceMapSettings settings; private final RaceMapLifecycle raceMapLifecycle; private final StringMessages stringMessages; @@ -557,7 +557,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe if (!autoZoomIn && !autoZoomOut && !orientationChangeInProgress) { // stop automatic zoom after a manual zoom event; automatic zoom in zoomMapToNewBounds will restore old settings final List emptyList = Collections.emptyList(); - settings.getZoomSettings().setTypesToConsiderOnZoom(emptyList); + RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors()); + settings = new RaceMapSettings(settings, clearedZoomSettings); } // TODO bug489 when in wind-up mode, avoid zooming out too far; perhaps zoom back in if zoomed out too far } @@ -569,7 +570,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe autoZoomIn = false; autoZoomOut = false; final List emptyList = Collections.emptyList(); - settings.getZoomSettings().setTypesToConsiderOnZoom(emptyList); + RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors()); + settings = new RaceMapSettings(settings, clearedZoomSettings); } }); map.addIdleHandler(new IdleMapHandler() { @@ -650,7 +652,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe */ protected void showAdditionalControls(MapWidget map) { } - + private void setHasPolar() { GetPolarAction getPolar = new GetPolarAction(sailingService, raceIdentifier); asyncActionsExecutor.execute(getPolar, GET_POLAR_CATEGORY, @@ -1799,7 +1801,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe || !BoundsUtil.contains((currentMapBounds = map.getBounds()), newBounds) || graticuleAreaRatio(currentMapBounds, newBounds) > 10) { // only change bounds if the new bounds don't fit into the current map zoom - Iterable oldZoomSettings = settings.getZoomSettings().getTypesToConsiderOnZoom(); + Iterable oldZoomTypesToConsiderSettings = settings.getZoomSettings().getTypesToConsiderOnZoom(); setAutoZoomInProgress(true); autoZoomLatLngBounds = newBounds; int newZoomLevel = getZoomLevel(autoZoomLatLngBounds); @@ -1821,7 +1823,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe } else { map.panTo(autoZoomLatLngBounds.getCenter()); } - settings.getZoomSettings().setTypesToConsiderOnZoom(oldZoomSettings); + RaceMapZoomSettings restoredZoomSettings = new RaceMapZoomSettings(oldZoomTypesToConsiderSettings, settings.getZoomSettings().isZoomToSelectedCompetitors()); + settings = new RaceMapSettings(settings, restoredZoomSettings); setAutoZoomInProgress(false); } } @@ -2445,11 +2448,12 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe @Override public void updateSettings(RaceMapSettings newSettings) { boolean maneuverTypeSelectionChanged = false; - boolean requiredRedraw = false; + boolean requiresRedraw = false; + boolean requiresUpdateCoordinateSystem = false; + for (ManeuverType maneuverType : ManeuverType.values()) { if (newSettings.isShowManeuverType(maneuverType) != settings.isShowManeuverType(maneuverType)) { maneuverTypeSelectionChanged = true; - settings.showManeuverType(maneuverType, newSettings.isShowManeuverType(maneuverType)); } } if (maneuverTypeSelectionChanged) { @@ -2460,65 +2464,52 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe } if (newSettings.isShowDouglasPeuckerPoints() != settings.isShowDouglasPeuckerPoints()) { if (!(timer.getPlayState() == PlayStates.Playing) && lastDouglasPeuckerResult != null && newSettings.isShowDouglasPeuckerPoints()) { - settings.setShowDouglasPeuckerPoints(true); removeAllMarkDouglasPeuckerpoints(); showMarkDouglasPeuckerPoints(lastDouglasPeuckerResult); } else if (!newSettings.isShowDouglasPeuckerPoints()) { - settings.setShowDouglasPeuckerPoints(false); removeAllMarkDouglasPeuckerpoints(); } } if (newSettings.getTailLengthInMilliseconds() != settings.getTailLengthInMilliseconds()) { - settings.setTailLengthInMilliseconds(newSettings.getTailLengthInMilliseconds()); - requiredRedraw = true; + requiresRedraw = true; } if (newSettings.getBuoyZoneRadiusInMeters() != settings.getBuoyZoneRadiusInMeters()) { - settings.setBuoyZoneRadiusInMeters(newSettings.getBuoyZoneRadiusInMeters()); - requiredRedraw = true; + requiresRedraw = true; } if (newSettings.isShowOnlySelectedCompetitors() != settings.isShowOnlySelectedCompetitors()) { - settings.setShowOnlySelectedCompetitors(newSettings.isShowOnlySelectedCompetitors()); - requiredRedraw = true; + requiresRedraw = true; } if (newSettings.isShowSelectedCompetitorsInfo() != settings.isShowSelectedCompetitorsInfo()) { - settings.setShowSelectedCompetitorsInfo(newSettings.isShowSelectedCompetitorsInfo()); - requiredRedraw = true; + requiresRedraw = true; } if (!newSettings.getZoomSettings().equals(settings.getZoomSettings())) { - settings.setZoomSettings(newSettings.getZoomSettings()); - if (!settings.getZoomSettings().containsZoomType(ZoomTypes.NONE)) { + if (!newSettings.getZoomSettings().containsZoomType(ZoomTypes.NONE)) { removeTransitions(); - zoomMapToNewBounds(settings.getZoomSettings().getNewBounds(this)); + zoomMapToNewBounds(newSettings.getZoomSettings().getNewBounds(this)); } } if (!newSettings.getHelpLinesSettings().equals(settings.getHelpLinesSettings())) { - settings.setHelpLinesSettings(newSettings.getHelpLinesSettings()); - requiredRedraw = true; + requiresRedraw = true; } if (newSettings.isShowWindStreamletOverlay() != settings.isShowWindStreamletOverlay()) { - settings.setShowWindStreamletOverlay(newSettings.isShowWindStreamletOverlay()); streamletOverlay.setVisible(newSettings.isShowWindStreamletOverlay()); } if (newSettings.isShowWindStreamletColors() != settings.isShowWindStreamletColors()) { - settings.setShowWindStreamletColors(newSettings.isShowWindStreamletColors()); streamletOverlay.setColors(newSettings.isShowWindStreamletColors()); } if (newSettings.isShowSimulationOverlay() != settings.isShowSimulationOverlay()) { - settings.setShowSimulationOverlay(newSettings.isShowSimulationOverlay()); showSimulationOverlay(newSettings.isShowSimulationOverlay()); } if (newSettings.isWindUp() != settings.isWindUp()) { - settings.setWindUp(newSettings.isWindUp()); + requiresUpdateCoordinateSystem = true; + requiresRedraw = true; + } + this.settings = newSettings; + + if (requiresUpdateCoordinateSystem) { updateCoordinateSystemFromSettings(); - requiredRedraw = true; } - if (newSettings.getTransparentHoverlines() != settings.getTransparentHoverlines()) { - settings.setTransparentHoverlines(newSettings.getTransparentHoverlines()); - } - if (newSettings.getHoverlineStrokeWeight() != settings.getHoverlineStrokeWeight()) { - settings.setHoverlineStrokeWeight(newSettings.getHoverlineStrokeWeight()); - } - if (requiredRedraw) { + if (requiresRedraw) { redraw(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java index 35ef398ca12..ac9929cc983 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettings.java @@ -6,39 +6,45 @@ import java.util.Set; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.Position; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes; +import com.sap.sse.common.Util; import com.sap.sse.common.settings.AbstractSettings; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; public class RaceMapSettings extends AbstractSettings { public static final String PARAM_SHOW_MAPCONTROLS = "showMapControls"; - - private boolean showDouglasPeuckerPoints = false; + public static final String PARAM_SHOW_COURSE_GEOMETRY = "showCourseGeometry"; + public static final String PARAM_MAP_ORIENTATION_WIND_UP = "windUp"; + public static final String PARAM_VIEW_SHOW_STREAMLETS = "viewShowStreamlets"; + public static final String PARAM_VIEW_SHOW_STREAMLET_COLORS = "viewShowStreamletColors"; + public static final String PARAM_VIEW_SHOW_SIMULATION = "viewShowSimulation"; + + private final boolean showDouglasPeuckerPoints; private final Set maneuverTypesToShow; - private boolean showOnlySelectedCompetitors = false; + private final boolean showOnlySelectedCompetitors; - private RaceMapZoomSettings zoomSettings; + private final RaceMapZoomSettings zoomSettings; - private RaceMapHelpLinesSettings helpLinesSettings; + private final RaceMapHelpLinesSettings helpLinesSettings; - private boolean transparentHoverlines = false; // as discussed with Stefan on 2015-12-08 + private final boolean transparentHoverlines; - private int hoverlineStrokeWeight = 15; // as discussed with Stefan on 2015-12-08 + private final int hoverlineStrokeWeight; - private long tailLengthInMilliseconds = 100000l; + private final long tailLengthInMilliseconds; - private double buoyZoneRadiusInMeters = 0.0; + private final double buoyZoneRadiusInMeters; - private boolean showSelectedCompetitorsInfo = true; + private final boolean showSelectedCompetitorsInfo; - private boolean showWindStreamletColors = false; + private final boolean showWindStreamletColors; - private boolean showWindStreamletOverlay = false; + private final boolean showWindStreamletOverlay; - private boolean showSimulationOverlay = false; + private final boolean showSimulationOverlay; - private boolean showMapControls = true; + private final boolean showMapControls; /** * If true, all map contents will be transformed to a water-only environment, rotating all directions / @@ -48,23 +54,85 @@ public class RaceMapSettings extends AbstractSettings { * positions to any other coordinate space that is translated and rotated compared to the original * coordinate space. */ - private boolean windUp = false; + private final boolean windUp; public RaceMapSettings() { - this.maneuverTypesToShow = getDefaultManeuvers(); - this.zoomSettings = new RaceMapZoomSettings(); - this.helpLinesSettings = new RaceMapHelpLinesSettings(); + this( + /* showMapControls */ true, + new RaceMapHelpLinesSettings(), + /* windUp */ false, + /* showWindStreamletOverlay */ false, + /* showWindStreamletColors */ false, + /* showSimulationOverlay */ false); } - public RaceMapSettings(boolean showMapCcontrol) { - this(); - this.showMapControls = showMapCcontrol; + public RaceMapSettings(RaceMapZoomSettings zoomSettings, RaceMapHelpLinesSettings helpLinesSettings, + boolean transparentHoverlines, int hoverlineStrokeWeight, long tailLengthInMilliseconds, boolean windUp, + double buoyZoneRadiusInMeters, boolean showOnlySelectedCompetitors, boolean showSelectedCompetitorsInfo, + boolean showWindStreamletColors, boolean showWindStreamletOverlay, boolean showSimulationOverlay, + boolean showMapControls, Set maneuverTypesToShow, boolean showDouglasPeuckerPoints) { + this.zoomSettings = zoomSettings; + this.helpLinesSettings = helpLinesSettings; + this.transparentHoverlines = transparentHoverlines; + this.hoverlineStrokeWeight = hoverlineStrokeWeight; + this.tailLengthInMilliseconds = tailLengthInMilliseconds; + this.windUp = windUp; + this.buoyZoneRadiusInMeters = buoyZoneRadiusInMeters; + this.showOnlySelectedCompetitors = showOnlySelectedCompetitors; + this.showSelectedCompetitorsInfo = showSelectedCompetitorsInfo; + this.showWindStreamletColors = showWindStreamletColors; + this.showWindStreamletOverlay = showWindStreamletOverlay; + this.showSimulationOverlay = showSimulationOverlay; + this.showMapControls = showMapControls; + this.maneuverTypesToShow = maneuverTypesToShow; + this.showDouglasPeuckerPoints = showDouglasPeuckerPoints; + } + + private RaceMapSettings(boolean showMapControls, boolean showCourseGeometry, boolean windUp, boolean showWindStreamletOverlay, boolean showWindStreamletColors, boolean showSimulationOverlay) { + this(showMapControls, new RaceMapHelpLinesSettings(createHelpLineSettings(showCourseGeometry)), windUp, showWindStreamletOverlay, showWindStreamletColors, showSimulationOverlay); + } + + private RaceMapSettings(boolean showMapControls, RaceMapHelpLinesSettings helpLineSettings, boolean windUp, boolean showWindStreamletOverlay, boolean showWindStreamletColors, boolean showSimulationOverlay) { + this( + new RaceMapZoomSettings(), + helpLineSettings, + /* transparentHoverlines as discussed with Stefan on 2015-12-08 */ false, + /* hoverlineStrokeWeight as discussed with Stefan on 2015-12-08 */ 15, + /* tailLengthInMilliseconds */ 100000l, + /* windUp */ windUp, + /* buoyZoneRadiusInMeters */ 0.0, + /* showOnlySelectedCompetitors */ false, + /* showSelectedCompetitorsInfo */ true, + /* showWindStreamletColors */ showWindStreamletColors, + /* showWindStreamletOverlay */ showWindStreamletOverlay, + /* showSimulationOverlay */ showSimulationOverlay, + /* showMapControls */ showMapControls, + /* maneuverTypesToShow */ getDefaultManeuvers(), + /* showDouglasPeuckerPoints */ false); + } + + private static Set createHelpLineSettings(boolean showCourseGeometry) { + final Set helpLineTypes = new HashSet<>(); + Util.addAll(new RaceMapHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes); + if (showCourseGeometry) { + helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY); + } else { + helpLineTypes.remove(HelpLineTypes.COURSEGEOMETRY); + } + return helpLineTypes; } /** - * "Copy constructor" that produces a new settings object that equals the one passed as argument + * copy constructor that produces a new settings object that equals the one passed as argument */ public RaceMapSettings(RaceMapSettings settings) { + this(settings, new RaceMapZoomSettings(settings.zoomSettings.getTypesToConsiderOnZoom(), settings.zoomSettings.isZoomToSelectedCompetitors())); + } + + /** + * copy constructor that produces a new settings object that equals the one passed as argument but takes the zoom settings from the second parameter + */ + public RaceMapSettings(RaceMapSettings settings, RaceMapZoomSettings zoomSettings) { this.buoyZoneRadiusInMeters = settings.buoyZoneRadiusInMeters; this.helpLinesSettings = new RaceMapHelpLinesSettings(settings.getHelpLinesSettings().getVisibleHelpLineTypes()); this.transparentHoverlines = settings.transparentHoverlines; @@ -79,9 +147,9 @@ public class RaceMapSettings extends AbstractSettings { this.showMapControls = settings.showMapControls; this.tailLengthInMilliseconds = settings.tailLengthInMilliseconds; this.windUp = settings.windUp; - this.zoomSettings = new RaceMapZoomSettings(settings.zoomSettings.getTypesToConsiderOnZoom(), settings.zoomSettings.isZoomToSelectedCompetitors()); + this.zoomSettings = zoomSettings; } - + /** * @return 0 if the tails are not visible {@link #getTailLengthInMilliseconds()} otherwise */ @@ -97,50 +165,22 @@ public class RaceMapSettings extends AbstractSettings { return tailLengthInMilliseconds; } - public void setTailLengthInMilliseconds(long tailLengthInMilliseconds) { - this.tailLengthInMilliseconds = tailLengthInMilliseconds; - } - public boolean isShowDouglasPeuckerPoints() { return showDouglasPeuckerPoints; } - public void setShowDouglasPeuckerPoints(boolean showDouglasPeuckerPoints) { - this.showDouglasPeuckerPoints = showDouglasPeuckerPoints; - } - public boolean isShowWindStreamletOverlay() { return showWindStreamletOverlay; } - public void setShowWindStreamletOverlay(boolean showWindStreamletOverlay) { - this.showWindStreamletOverlay = showWindStreamletOverlay; - } - public boolean isShowWindStreamletColors() { return showWindStreamletColors; } - public void setShowWindStreamletColors(boolean showWindStreamletColors) { - this.showWindStreamletColors = showWindStreamletColors; - } - public boolean isShowSimulationOverlay() { return showSimulationOverlay; } - public void setShowSimulationOverlay(boolean showSimulationOverlay) { - this.showSimulationOverlay = showSimulationOverlay; - } - - public void showManeuverType(ManeuverType maneuverType, boolean show) { - if (show) { - maneuverTypesToShow.add(maneuverType); - } else { - maneuverTypesToShow.remove(maneuverType); - } - } - public boolean isShowManeuverType(ManeuverType maneuverType) { return maneuverTypesToShow.contains(maneuverType); } @@ -149,75 +189,39 @@ public class RaceMapSettings extends AbstractSettings { return showOnlySelectedCompetitors; } - public void setShowOnlySelectedCompetitors(boolean showOnlySelectedCompetitors) { - this.showOnlySelectedCompetitors = showOnlySelectedCompetitors; - } - public RaceMapZoomSettings getZoomSettings() { return zoomSettings; } - public void setZoomSettings(RaceMapZoomSettings zoomSettings) { - this.zoomSettings = zoomSettings; - } - public RaceMapHelpLinesSettings getHelpLinesSettings() { return helpLinesSettings; } - public void setHelpLinesSettings(RaceMapHelpLinesSettings helpLinesSettings) { - this.helpLinesSettings = helpLinesSettings; - } - public boolean getTransparentHoverlines() { return this.transparentHoverlines; } - public void setTransparentHoverlines(boolean transparentHoverlines) { - this.transparentHoverlines = transparentHoverlines; - } - public int getHoverlineStrokeWeight() { return this.hoverlineStrokeWeight; } - public void setHoverlineStrokeWeight(int hoverlineStrokeWeight) { - this.hoverlineStrokeWeight = hoverlineStrokeWeight; - } - public boolean isShowSelectedCompetitorsInfo() { return showSelectedCompetitorsInfo; } - public void setShowSelectedCompetitorsInfo(boolean showSelectedCompetitorsInfo) { - this.showSelectedCompetitorsInfo = showSelectedCompetitorsInfo; - } - public double getBuoyZoneRadiusInMeters() { return buoyZoneRadiusInMeters; } - public void setBuoyZoneRadiusInMeters(double buoyZoneRadiusInMeters) { - this.buoyZoneRadiusInMeters = buoyZoneRadiusInMeters; - } - public boolean isWindUp() { return windUp; } - public void setWindUp(boolean windUp) { - this.windUp = windUp; - } - public boolean isShowMapControls() { return showMapControls; } - public void setShowMapControls(boolean showMapControls) { - this.showMapControls = showMapControls; - } - - private HashSet getDefaultManeuvers() { + private static HashSet getDefaultManeuvers() { HashSet types = new HashSet(); types.add(ManeuverType.JIBE); types.add(ManeuverType.TACK); @@ -225,8 +229,20 @@ public class RaceMapSettings extends AbstractSettings { return types; } - public static RaceMapSettings readSettingsFromURL() { - final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_MAPCONTROLS, true /* default */); - return new RaceMapSettings(showMapControls); + public static RaceMapSettings readSettingsFromURL(boolean defaultForShowMapControls, + boolean defaultForShowCourseGeometry, boolean defaultForMapOrientationWindUp, + boolean defaultForViewShowStreamlets, boolean defaultForViewShowStreamletColors, + boolean defaultForViewShowSimulation) { + final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_MAPCONTROLS, defaultForShowMapControls /* default */); + final boolean showCourseGeometry = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_COURSE_GEOMETRY, defaultForShowCourseGeometry /* default */); + final boolean windUp = GwtHttpRequestUtils.getBooleanParameter(PARAM_MAP_ORIENTATION_WIND_UP, defaultForMapOrientationWindUp /* default */); + final boolean showWindStreamletOverlay = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_STREAMLETS, defaultForViewShowStreamlets /* default */); + final boolean showWindStreamletColors = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_STREAMLET_COLORS, defaultForViewShowStreamletColors /* default */); + final boolean showSimulationOverlay = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_SIMULATION, defaultForViewShowSimulation /* default */); + return new RaceMapSettings(showMapControls, showCourseGeometry, windUp, showWindStreamletOverlay, showWindStreamletColors, showSimulationOverlay); + } + + public Set getManeuverTypesToShow() { + return maneuverTypesToShow; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettingsDialogComponent.java index 91c3ddf42b5..6d7b97f8a10 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapSettingsDialogComponent.java @@ -257,37 +257,31 @@ public class RaceMapSettingsDialogComponent implements SettingsDialogComponent maneuverTypesToShow = new HashSet(); for (Util.Pair p : checkboxAndManeuverType) { - result.showManeuverType(p.getB(), p.getA().getValue()); - } - RaceMapHelpLinesSettings helpLinesSettings = getHelpLinesSettings(); - result.setZoomSettings(getZoomSettings()); - result.setHelpLinesSettings(helpLinesSettings); - result.setShowDouglasPeuckerPoints(showDouglasPeuckerPointsCheckBox.getValue()); - result.setShowOnlySelectedCompetitors(showOnlySelectedCompetitorsCheckBox.getValue()); - result.setShowWindStreamletOverlay(showWindStreamletOverlayCheckbox.getValue()); - result.setShowWindStreamletColors(showWindStreamletColorsCheckbox.getValue()); - result.setShowMapControls(initialSettings.isShowMapControls()); - if (isSimulationEnabled) { - result.setShowSimulationOverlay(showSimulationOverlayCheckbox.getValue()); - } else { - result.setShowSimulationOverlay(false); - } - result.setWindUp(windUpCheckbox.getValue()); - result.setShowSelectedCompetitorsInfo(showSelectedCompetitorsInfoCheckBox.getValue()); - if (helpLinesSettings.isVisible(HelpLineTypes.BOATTAILS)) { - result.setTailLengthInMilliseconds(tailLengthBox.getValue() == null ? -1 : tailLengthBox.getValue() * 1000l); - } - if (helpLinesSettings.isVisible(HelpLineTypes.BUOYZONE)) { - final Double value = buoyZoneRadiusBox.getValue(); - if (value != null) { - result.setBuoyZoneRadiusInMeters(value); + if (p.getA().getValue() == true) { + maneuverTypesToShow.add(p.getB()); } } - result.setTransparentHoverlines(transparentHoverlines.getValue()); - result.setHoverlineStrokeWeight(hoverlineStrokeWeight.getValue()); - return result; + RaceMapHelpLinesSettings helpLinesSettings = getHelpLinesSettings(); + RaceMapZoomSettings zoomSettings = getZoomSettings(); + + boolean showSimulationOverlay = isSimulationEnabled ? showSimulationOverlayCheckbox.getValue() : false; + long tailLengthInMilliseconds = initialSettings.getTailLengthInMilliseconds(); + if (helpLinesSettings.isVisible(HelpLineTypes.BOATTAILS)) { + tailLengthInMilliseconds = tailLengthBox.getValue() == null ? -1 : tailLengthBox.getValue() * 1000l; + } + + double buoyZoneRadiusInMeters = initialSettings.getBuoyZoneRadiusInMeters(); + if (helpLinesSettings.isVisible(HelpLineTypes.BUOYZONE) && buoyZoneRadiusBox.getValue() != null) { + buoyZoneRadiusInMeters = buoyZoneRadiusBox.getValue(); + } + + return new RaceMapSettings(zoomSettings, helpLinesSettings, + transparentHoverlines.getValue(), hoverlineStrokeWeight.getValue(), tailLengthInMilliseconds, windUpCheckbox.getValue(), + buoyZoneRadiusInMeters, showOnlySelectedCompetitorsCheckBox.getValue(), showSelectedCompetitorsInfoCheckBox.getValue(), + showWindStreamletColorsCheckbox.getValue(), showWindStreamletOverlayCheckbox.getValue(), showSimulationOverlay, + initialSettings.isShowMapControls(), maneuverTypesToShow, showDouglasPeuckerPointsCheckBox.getValue()); } private RaceMapZoomSettings getZoomSettings() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapZoomSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapZoomSettings.java index 8a6bcd5a361..24074ed7538 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapZoomSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMapZoomSettings.java @@ -30,23 +30,23 @@ public class RaceMapZoomSettings { } }; - private Iterable typesToConsiderOnZoom; - private boolean zoomToSelectedCompetitors; + private final List typesToConsiderOnZoom; + private final boolean zoomToSelectedCompetitors; /** - * Creates new RaceMapZoomSettings with the {@link ZoomTypes} BOATS and TAILS.
+ * Creates default RaceMapZoomSettings with the {@link ZoomTypes} BUOYS.
* The attribute zoomToSelectedCompetitors will be false. */ public RaceMapZoomSettings() { - final List myTypesToConsiderOnZoom = new ArrayList<>(); - typesToConsiderOnZoom = myTypesToConsiderOnZoom; + typesToConsiderOnZoom = new ArrayList<>(); // Other zoom types such as BOATS, TAILS or WINDSENSORS are not currently used as default zoom types. - myTypesToConsiderOnZoom.add(ZoomTypes.BUOYS); + typesToConsiderOnZoom.add(ZoomTypes.BUOYS); zoomToSelectedCompetitors = false; } - public RaceMapZoomSettings(Iterable typesToConsiderOnZoom, boolean zoomToSelected) { - this.typesToConsiderOnZoom = typesToConsiderOnZoom; + public RaceMapZoomSettings(Iterable typesToConsider, boolean zoomToSelected) { + this.typesToConsiderOnZoom = new ArrayList<>(); + Util.addAll(typesToConsider, this.typesToConsiderOnZoom); this.zoomToSelectedCompetitors = zoomToSelected; } @@ -73,16 +73,6 @@ public class RaceMapZoomSettings { return typesToConsiderOnZoom; } - public void setTypesToConsiderOnZoom(Iterable typesToConsiderOnZoom) { - List newTypesToConsiderOnZoom = new ArrayList<>(); - Util.addAll(typesToConsiderOnZoom, newTypesToConsiderOnZoom); - this.typesToConsiderOnZoom = newTypesToConsiderOnZoom; - } - - public void setZoomToSelectedCompetitors(boolean zoomToSelectedCompetitors) { - this.zoomToSelectedCompetitors = zoomToSelectedCompetitors; - } - public boolean isZoomToSelectedCompetitors() { return zoomToSelectedCompetitors; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/TrueNorthIndicatorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/TrueNorthIndicatorPanel.java index ef7cd8e80a3..099cc503058 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/TrueNorthIndicatorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/TrueNorthIndicatorPanel.java @@ -7,7 +7,6 @@ import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sse.gwt.client.dialog.DataEntryDialog; /** * A true north indicator that can be added as a control to the map. Clicking / tapping the control toggles @@ -44,18 +43,18 @@ public class TrueNorthIndicatorPanel extends FlowPanel { canvas.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - // a bit clumsy, but there is no copy constructor on RaceMapSettings, and the RaceMapSettingsDialogComponent - // class has all we need to clone a RaceMapSettings object, without showing it - final RaceMapSettingsDialogComponent settingsCloner = new RaceMapSettingsDialogComponent(map.getSettings(), stringMessages, /* showViewSimulation */true); - settingsCloner.getAdditionalWidget(new DataEntryDialog("dummy", "dummy", "OK", "Cancel", /* validator */null, /* callback */null) { - @Override - protected RaceMapSettings getResult() { - return null; - } - }); - final RaceMapSettings newSettings = settingsCloner.getResult(); - newSettings.setWindUp(!newSettings.isWindUp()); - map.updateSettings(newSettings); + RaceMapSettings oldRaceMapSettings = map.getSettings(); + boolean newWindUpSettings = !oldRaceMapSettings.isWindUp(); + + final RaceMapSettings newRaceMapSettings = new RaceMapSettings(oldRaceMapSettings.getZoomSettings(), + oldRaceMapSettings.getHelpLinesSettings(), oldRaceMapSettings.getTransparentHoverlines(), + oldRaceMapSettings.getHoverlineStrokeWeight(), oldRaceMapSettings.getTailLengthInMilliseconds(), newWindUpSettings, + oldRaceMapSettings.getBuoyZoneRadiusInMeters(), oldRaceMapSettings.isShowOnlySelectedCompetitors(), + oldRaceMapSettings.isShowSelectedCompetitorsInfo(), oldRaceMapSettings.isShowWindStreamletColors(), + oldRaceMapSettings.isShowWindStreamletOverlay(), oldRaceMapSettings.isShowSimulationOverlay(), + oldRaceMapSettings.isShowMapControls(), oldRaceMapSettings.getManeuverTypesToShow(), + oldRaceMapSettings.isShowDouglasPeuckerPoints()); + map.updateSettings(newRaceMapSettings); } }); textLabel = new Label(""); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java index 62134c62c30..930a64b7717 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java @@ -63,8 +63,6 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint private static final String PARAM_FLEET_NAME = "fleetName"; private static final String PARAM_SHOW_COMPETITORS = "showCompetitors"; private static final String PARAM_PLAY = "play"; - private static final String PARAM_SHOW_COURSE_GEOMETRY = "showCourseGeometry"; - private static final String PARAM_MAP_ORIENTATION_WIND_UP = "windUp"; private String regattaLikeName; private String raceColumnName; @@ -88,12 +86,36 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint } // read optional parameters - final RaceBoardPerspectiveSettings raceboardPerspectiveSettings = RaceBoardPerspectiveSettings.readSettingsFromURL(); - final RaceMapSettings raceMapSettings = RaceMapSettings.readSettingsFromURL(); + final RaceBoardPerspectiveSettings raceboardPerspectiveSettings = RaceBoardPerspectiveSettings + .readSettingsFromURL(/* defaultForViewShowLeaderboard */ true, /* defaultForViewShowWindchart */ true, + /* defaultForViewSimulationEnabled */ false, /* defaultForViewShowCompetitorsChart */ false, + /* defaultForViewCompetitorFilter */ null, /* defaultForCanReplayDuringLiveRaces */ false); + final RaceMapSettings defaultRaceMapSettings = RaceMapSettings.readSettingsFromURL( + /* defaultForShowMapControls */ true, /* defaultForShowCourseGeometry */ true, + /* defaultForMapOrientationWindUp */ true, /* defaultForViewShowStreamlets */ false, + /* defaultForViewShowStreamletColors */ false, /* defaultForViewShowSimulation */ false); final boolean showCompetitors = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_COMPETITORS, false /* default */); final boolean play = GwtHttpRequestUtils.getBooleanParameter(PARAM_PLAY, false /* default */); - final boolean showCourseGeometry = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_COURSE_GEOMETRY, true /* default */); - final boolean windUp = GwtHttpRequestUtils.getBooleanParameter(PARAM_MAP_ORIENTATION_WIND_UP, true /* default */); + final boolean showCourseGeometry = GwtHttpRequestUtils.getBooleanParameter(RaceMapSettings.PARAM_SHOW_COURSE_GEOMETRY, true /* default */); + final boolean windUp = GwtHttpRequestUtils.getBooleanParameter(RaceMapSettings.PARAM_MAP_ORIENTATION_WIND_UP, true /* default */); + + RaceMapZoomSettings raceMapZoomSettings = new RaceMapZoomSettings(Arrays.asList(ZoomTypes.BUOYS), /* zoom to selection */ false); + Set helpLineTypes = new HashSet<>(); + Util.addAll(defaultRaceMapSettings.getHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes); + if (showCourseGeometry) { + helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY); + } + RaceMapHelpLinesSettings raceMapHelpLinesSettings = new RaceMapHelpLinesSettings(helpLineTypes); + + final RaceMapSettings raceMapSettings = new RaceMapSettings(raceMapZoomSettings, raceMapHelpLinesSettings, + defaultRaceMapSettings.getTransparentHoverlines(), defaultRaceMapSettings.getHoverlineStrokeWeight(), + defaultRaceMapSettings.getTailLengthInMilliseconds(), windUp, + defaultRaceMapSettings.getBuoyZoneRadiusInMeters(), defaultRaceMapSettings.isShowOnlySelectedCompetitors(), + defaultRaceMapSettings.isShowSelectedCompetitorsInfo(), defaultRaceMapSettings.isShowWindStreamletColors(), + defaultRaceMapSettings.isShowWindStreamletOverlay(), defaultRaceMapSettings.isShowSimulationOverlay(), + defaultRaceMapSettings.isShowMapControls(), defaultRaceMapSettings.getManeuverTypesToShow(), + defaultRaceMapSettings.isShowDouglasPeuckerPoints()); + sailingService.getRaceIdentifier(regattaLikeName, raceColumnName, fleetName, new AsyncCallback() { @Override public void onSuccess(final RegattaAndRaceIdentifier selectedRaceIdentifier) { @@ -104,7 +126,7 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint @Override public void onSuccess(Map result) { createEmbeddedMap(selectedRaceIdentifier, result, raceboardPerspectiveSettings, raceMapSettings, - showCompetitors, play, showCourseGeometry, windUp); + showCompetitors, play); } @Override @@ -133,7 +155,7 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint private void createEmbeddedMap(final RegattaAndRaceIdentifier selectedRaceIdentifier, Map competitorBoats, final RaceBoardPerspectiveSettings raceboardPerspectiveSettings, final RaceMapSettings raceMapSettings, - final boolean showCompetitors, final boolean play, final boolean showCourseGeometry, final boolean windUp) { + final boolean showCompetitors, final boolean play) { final StringBuilder title = new StringBuilder(regattaLikeName); title.append('/'); title.append(raceColumnName); @@ -184,16 +206,6 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint map.setControls(ControlPosition.RIGHT_BOTTOM, backToLivePlayButton); } }; - final RaceMapSettings mapSettings = new RaceMapSettings(raceMap.getSettings()); - mapSettings.setZoomSettings(new RaceMapZoomSettings(Arrays.asList(ZoomTypes.BUOYS), /* zoom to selection */ false)); - if (showCourseGeometry) { - Set helpLineTypes = new HashSet<>(); - Util.addAll(mapSettings.getHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes); - helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY); - mapSettings.setHelpLinesSettings(new RaceMapHelpLinesSettings(helpLineTypes)); - } - mapSettings.setWindUp(windUp); - raceMap.updateSettings(mapSettings); final WindChart windChart; if (raceboardPerspectiveSettings.isShowWindChart()) { windChart = new WindChart(new WindChartLifecycle(getStringMessages()), sailingService, selectedRaceIdentifier, timer, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java index 40a28743b54..7834f952c89 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java @@ -75,7 +75,10 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { } // read perspective settings parameters from URL - final RaceBoardPerspectiveSettings perspectiveSettings = RaceBoardPerspectiveSettings.readSettingsFromURL(); + final RaceBoardPerspectiveSettings perspectiveSettings = RaceBoardPerspectiveSettings.readSettingsFromURL( + /* defaultForViewShowLeaderboard */ true, /* defaultForViewShowWindchart */ false, + /* defaultForViewSimulationEnabled */ false, /* defaultForViewShowCompetitorsChart */ false, + /* defaultForViewCompetitorFilter */ null, /* defaultForCanReplayDuringLiveRaces */ false); // Determine if the charts, such as the competitor chart or the wind chart, the edit marks // panels, such as mark passing and mark position editors and manage media buttons should be shown. // Automatic selection of attached video (if any) also depends on this flag. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPerspectiveSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPerspectiveSettings.java index f9f69f9851b..e77cff13c2c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPerspectiveSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPerspectiveSettings.java @@ -74,13 +74,16 @@ public class RaceBoardPerspectiveSettings extends AbstractSettings { return canReplayDuringLiveRaces; } - public static RaceBoardPerspectiveSettings readSettingsFromURL() { - final boolean showLeaderboard = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_LEADERBOARD, true /* default */); - final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_WINDCHART, false /* default */); - final boolean simulationEnabled = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SIMULATION_ENABLED, false /* default */); - final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default */); - String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(PARAM_VIEW_COMPETITOR_FILTER, null /* default */); - final boolean canReplayWhileLiveIsPossible = GwtHttpRequestUtils.getBooleanParameter(PARAM_CAN_REPLAY_DURING_LIVE_RACES, false /* default */); + public static RaceBoardPerspectiveSettings readSettingsFromURL(boolean defaultForViewShowLeaderboard, + boolean defaultForViewShowWindchart, boolean defaultForViewSimulationEnabled, + boolean defaultForViewShowCompetitorsChart, String defaultForViewCompetitorFilter, + boolean defaultForCanReplayDuringLiveRaces) { + final boolean showLeaderboard = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_LEADERBOARD, defaultForViewShowLeaderboard /* default */); + final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_WINDCHART, defaultForViewShowWindchart /* default */); + final boolean simulationEnabled = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SIMULATION_ENABLED, defaultForViewSimulationEnabled /* default */); + final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(PARAM_VIEW_SHOW_COMPETITORSCHART, defaultForViewShowCompetitorsChart /* default */); + String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(PARAM_VIEW_COMPETITOR_FILTER, defaultForViewCompetitorFilter /* default */); + final boolean canReplayWhileLiveIsPossible = GwtHttpRequestUtils.getBooleanParameter(PARAM_CAN_REPLAY_DURING_LIVE_RACES, defaultForCanReplayDuringLiveRaces /* default */); final Duration initialDurationAfterRaceStartInReplay = parseDuration(GwtHttpRequestUtils.getStringParameter( PARAM_TIME_AFTER_RACE_START_AS_HOURS_COLON_MILLIS_COLON_SECONDS, null /* default */)); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/WindFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/WindFragment.java index a89e6e03a88..09a561214a9 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/WindFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/WindFragment.java @@ -389,7 +389,7 @@ public class WindFragment extends BaseFragment implements CompassDirectionListen WebSettings settings = mMapWebView.getSettings(); if (showMap) { settings.setJavaScriptEnabled(true); - loadRaceMap(true, false, false, true); + loadRaceMap(/* showWindCharts */ true, /* showStreamlets */ false, /* showSimulation */ false, /* showMapControls */ true); mMapLayout.setVisibility(View.VISIBLE); } else { mMapWebView.loadUrl("about:blank"); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/WindHelper.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/WindHelper.java index b31f8bdbf77..efbbb522983 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/WindHelper.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/utils/WindHelper.java @@ -99,7 +99,7 @@ public class WindHelper { return isTracked; } - public static String generateMapURL(Context context, ManagedRace race ,boolean showWindCharts, boolean showStreamlets, boolean showSimulation, boolean showMapControls){ + public static String generateMapURL(Context context, ManagedRace race, boolean showWindCharts, boolean showStreamlets, boolean showSimulation, boolean showMapControls) { ReadonlyDataManager dataManager = OnlineDataManager.create(context); return dataManager.getMapUrl(AppPreferences.on(context).getServerBaseURL(), race, getEventId(context), showWindCharts, showStreamlets, showSimulation, showMapControls); }