diff --git a/configuration/sailing.sh b/configuration/sailing.sh index 7efa3b8a5b7..a6e048ffb25 100644 --- a/configuration/sailing.sh +++ b/configuration/sailing.sh @@ -8,6 +8,7 @@ export EC2_HOME=/opt/amazon/ec2-api-tools-1.6.8.0 export EC2_URL=https://ec2.eu-west-1.amazonaws.com export JAVA_HOME=/opt/jdk1.8.0_45 export JAVA_1_7_HOME=/opt/jdk1.7.0_75 +export ANDROID_HOME=/opt/android-sdk-linux export PATH=$PATH:$JAVA_HOME/bin:/opt/amazon/ec2-api-tools-1.6.8.0/bin:/opt/amazon/bin diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java index 494597a73b9..ba267b82e89 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java @@ -1,5 +1,8 @@ package com.sap.sailing.domain.common; +import java.util.ArrayList; +import java.util.List; + import com.sap.sailing.domain.common.impl.MeterDistance; @@ -157,4 +160,16 @@ public enum BoatClassMasterdata { return hasAdditionalDownwindSail; } + public static Iterable getAllBoatClassNames(boolean includeAlternativeNames) { + final List result = new ArrayList<>(); + for (BoatClassMasterdata bcmd : values()) { + result.add(bcmd.getDisplayName()); + if (includeAlternativeNames) { + for (String alternativeName : bcmd.getAlternativeNames()) { + result.add(alternativeName); + } + } + } + return result; + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index 540255f034e..747f938f666 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -24,6 +24,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; @@ -136,6 +137,11 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { public void visit(RaceLogDeviceMarkMappingEvent event) { RaceLogRaceTracker.this.onDeviceMarkMappingEvent(event); } + + @Override + public void visit(RaceLogDefineMarkEvent event) { + RaceLogRaceTracker.this.onDefineMarkEvent(event); + } @Override public void visit(RaceLogStartTrackingEvent event) { @@ -321,6 +327,7 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { } private void updateMarkMappings(boolean loadIfNotCovered) { + assert trackedRace != null; // TODO remove fixes, if mappings have been removed // check if there are new time ranges not covered so far Map>> newMappings = getNewMarkMappings(); @@ -359,6 +366,18 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { gpsFixStore.addListener(this, event.getDevice()); } } + + /** + * When a log is attached to it, the tracked race creates mark tracks for all marks either defined or with a device + * mapped to it. When this tracker is running for a tracked race it has to mimic this behavior dynamically. When a + * {@link RaceLogDefineMarkEvent} is received, the existence of the track for that mark in the {@link TrackedRace} + * has to be ensured, also ensuring that the mark will exist in the mark tracks map key set. + */ + private void onDefineMarkEvent(RaceLogDefineMarkEvent event) { + if (trackedRace != null) { + trackedRace.getOrCreateTrack(event.getMark()); + } + } private void onDeviceCompetitorMappingEvent(DeviceCompetitorMappingEvent event) { if (trackedRace != null) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/MultiLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/MultiLogAnalyzer.java index 76f7df12b78..a2b6ac90feb 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/MultiLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/MultiLogAnalyzer.java @@ -10,6 +10,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import com.sap.sse.common.Util; + /** * Apply one kind of analyzer to multiple logs, and combine (reduce) their output into one result value. */ @@ -31,7 +33,7 @@ public class MultiLogAnalyzer public static abstract class CollectionReducer> implements ResultReducer, C> { @Override public C reduce(Collection interimResult, C reducedFinalResult) { - reducedFinalResult.addAll(interimResult); + Util.addAll(interimResult, reducedFinalResult); return reducedFinalResult; } } @@ -71,7 +73,7 @@ public class MultiLogAnalyzer } - public MultiLogAnalyzer(AnalyzerFactory< InterimResultT> analyzerFactory, + public MultiLogAnalyzer(AnalyzerFactory analyzerFactory, ResultReducer resultReducer, AbstractLog... logs) { this(analyzerFactory, resultReducer, Arrays.asList(logs)); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/DefinedMarkFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/DefinedMarkFinder.java index 7e2ea5a69d7..15de65022db 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/DefinedMarkFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/DefinedMarkFinder.java @@ -1,22 +1,33 @@ package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.LogAnalyzer; +import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.base.Mark; -public class DefinedMarkFinder extends RaceLogAnalyzer> { +public class DefinedMarkFinder extends RaceLogAnalyzer> { public DefinedMarkFinder(RaceLog raceLog) { super(raceLog); } + public static class Factory implements AnalyzerFactory> { + @Override + public LogAnalyzer> createAnalyzer(AbstractLog log) { + return new DefinedMarkFinder((RaceLog) log); + } + } + @Override - protected Iterable performAnalysis() { - List< Mark> result = new ArrayList(); + protected Collection performAnalysis() { + List result = new ArrayList(); for (RaceLogEvent event : getLog().getUnrevokedEvents()) { if (event instanceof RaceLogDefineMarkEvent) { RaceLogDefineMarkEvent dME = (RaceLogDefineMarkEvent) event; @@ -25,5 +36,4 @@ public class DefinedMarkFinder extends RaceLogAnalyzer> { } return result; } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/DeviceMarkMappingFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/DeviceMarkMappingFinder.java index 97ac6b477fd..c8ef195833f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/DeviceMarkMappingFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/DeviceMarkMappingFinder.java @@ -21,7 +21,6 @@ public class DeviceMarkMappingFinder, public LogAnalyzer>>> createAnalyzer(AbstractLog log) { return new DeviceMarkMappingFinder(log); } - } public DeviceMarkMappingFinder(LogT log) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/WaypointImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/WaypointImpl.java index 6e28e3b3edb..7c262b59976 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/WaypointImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/WaypointImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.base.impl; +import java.util.UUID; + import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.SharedDomainFactory; @@ -10,8 +12,7 @@ import com.sap.sailing.domain.common.PassingInstruction; public class WaypointImpl implements Waypoint { private static final long serialVersionUID = 1600863368078653897L; private final ControlPoint controlPoint; - private static int idCounter = 1; - private final int id; + private final UUID id; private final PassingInstruction passingInstructions; private final Bearing fixedBearing; @@ -30,7 +31,7 @@ public class WaypointImpl implements Waypoint { this.controlPoint = controlPoint; this.passingInstructions = passingInstructions; this.fixedBearing = fixedBearing; - id = idCounter++; + id = UUID.randomUUID(); } @Override @@ -54,7 +55,7 @@ public class WaypointImpl implements Waypoint { } @Override - public Integer getId() { + public UUID getId() { return id; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 4cb14ec95c9..8c5bfaca6df 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -870,4 +870,12 @@ public interface TrackedRace extends Serializable, IsManagedByCache getMarksFromRaceAndLogs() { + return getMarks(); + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 18d8bccc62c..bc0a9a72841 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -6,6 +6,7 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.ConcurrentModificationException; @@ -35,6 +36,10 @@ import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer; +import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.AnalyzerFactory; +import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.MapWithValueCollectionReducer; +import com.sap.sailing.domain.abstractlog.MultiLogAnalyzer.SetReducer; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; @@ -49,7 +54,9 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEv import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMarkFinder; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -3161,10 +3168,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } logger.info("Finished loading competitor tracks for " + getRace().getName()); logger.info("Started loading mark tracks for " + getRace().getName()); - for (Mark mark : getMarks()) { + for (Mark mark : getMarksFromRaceAndLogs()) { try { - gpsFixStore.loadMarkTrack((DynamicGPSFixTrack) markTracks.get(mark), log, - mark); + gpsFixStore.loadMarkTrack((DynamicGPSFixTrack) getOrCreateTrack(mark), log, mark); } catch (TransformationException | NoCorrespondingServiceRegisteredException e) { logger.log(Level.WARNING, "Could not load track for " + mark, e); } @@ -3777,4 +3783,21 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl this.raceLogResolver = domainFactory.getRaceLogResolver(); return this; } + + @Override + public Iterable getMarksFromRaceAndLogs() { + final List> allLogs = new ArrayList>(); + final List> raceLogs = new ArrayList<>(); + raceLogs.addAll(attachedRaceLogs.values()); + allLogs.addAll(raceLogs); + allLogs.addAll(attachedRegattaLogs.values()); + final Map>> markMappings = new MultiLogAnalyzer<>(new DeviceMarkMappingFinder.Factory(), + new MapWithValueCollectionReducer<>(), allLogs).analyze(); + final Set result = new HashSet<>(); + result.addAll(markMappings.keySet()); + final AnalyzerFactory> analyzerFactory = new DefinedMarkFinder.Factory(); + Set marksDefinedInRaceLog = new MultiLogAnalyzer<>(analyzerFactory, new SetReducer(), raceLogs).analyze(); + result.addAll(marksDefinedInRaceLog); + return result; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java index c8203b76bd1..b18109f4e2f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaWithSeriesAndFleetsDialog.java @@ -1,5 +1,8 @@ package com.sap.sailing.gwt.ui.adminconsole; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.UUID; @@ -181,7 +184,15 @@ public abstract class AbstractRegattaWithSeriesAndFleetsDialog extends DataEn private void setupEventAndCourseAreaListBoxes(StringMessages stringMessages) { sailingEventsListBox.addItem(stringMessages.selectSailingEvent()); - for (EventDTO event : existingEvents) { + final List sortedEvents = new ArrayList<>(); + sortedEvents.addAll(existingEvents); + Collections.sort(sortedEvents, new Comparator() { + @Override + public int compare(EventDTO o1, EventDTO o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + for (EventDTO event : sortedEvents) { sailingEventsListBox.addItem(event.getName()); if (isCourseAreaInEvent(event, regatta.defaultCourseAreaUuid)) { sailingEventsListBox.setSelectedIndex(sailingEventsListBox.getItemCount() - 1); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 571177f4adc..a19ce368dae 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -9,6 +9,7 @@ import com.google.gwt.user.client.ui.DoubleBox; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.BoatClassMasterdata; @@ -37,7 +38,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class CompetitorEditDialog extends DataEntryDialog { private final CompetitorDTO competitorToEdit; private final TextBox name; - private final ListBox boatClassName; + private final SuggestBox boatClassName; private final TextBox displayColorTextBox; private final ListBox threeLetterIocCountryCode; private final TextBox sailId; @@ -73,25 +74,12 @@ public class CompetitorEditDialog extends DataEntryDialog { this.stringMessages = stringMessages; this.competitorToEdit = competitorToEdit; - this.boatClassName = createListBox(/* isMultipleSelect */ false); + this.boatClassName = createSuggestBox(BoatClassMasterdata.getAllBoatClassNames(/* includeAlternativeNames */ true)); int i=0; List boatClassNamesList = new ArrayList(); for (BoatClassMasterdata t : BoatClassMasterdata.values()) { boatClassNamesList.add(t.getDisplayName()); } - String competitorsBoatClassName = competitorToEdit.getBoatClass() != null ? competitorToEdit.getBoatClass().getName() : null; - Collections.sort(boatClassNamesList); - for (String name : boatClassNamesList) { - boatClassName.addItem(name); - if (name.equals(competitorsBoatClassName)) { - boatClassName.setSelectedIndex(i); - } - i++; - } - if (boatClassName.getSelectedIndex() == -1 && competitorsBoatClassName != null) { - boatClassName.addItem(competitorsBoatClassName); - boatClassName.setSelectedIndex(i); - } if (competitorToEdit.getBoatClass() != null) { boatClassName.setEnabled(false); } @@ -185,7 +173,7 @@ public class CompetitorEditDialog extends DataEntryDialog { color = new InvalidColor(iae); } } - BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(boatClassName.getSelectedIndex()), 0); + BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); CompetitorDTO result = new CompetitorDTOImpl(name.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java index fbbf533fe7f..dc4db1d817f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java @@ -4,8 +4,10 @@ import java.util.List; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; @@ -16,7 +18,7 @@ import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWithSeriesAndFleetsDialog { protected TextBox nameEntryField; - protected TextBox boatClassEntryField; + protected SuggestBox boatClassEntryField; public RegattaWithSeriesAndFleetsDialog(RegattaDTO regatta, Iterable series, List existingEvents, String title, String okButton, StringMessages stringMessages, @@ -27,9 +29,8 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi nameEntryField.ensureDebugId("NameTextBox"); nameEntryField.setVisibleLength(40); nameEntryField.setText(regatta.getName()); - boatClassEntryField = createTextBox(null); - boatClassEntryField.ensureDebugId("BoatClassTextBox"); - boatClassEntryField.setVisibleLength(20); + boatClassEntryField = createSuggestBox(BoatClassMasterdata.getAllBoatClassNames(/* include alternative names */ true)); + boatClassEntryField.getValueBox().ensureDebugId("BoatClassTextBox"); if (regatta.boatClass != null) { boatClassEntryField.setText(regatta.boatClass.getName()); } @@ -45,7 +46,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi @Override protected RegattaDTO getResult() { RegattaDTO result = getRegattaDTO(); - result.setName(nameEntryField.getText()); + result.setName(nameEntryField.getText().trim()); // trim to particularly avoid trailing slashes result.boatClass = new BoatClassDTO(boatClassEntryField.getText(), 0.0); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java index 411331c30cd..8540d7fa24b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashSet; @@ -474,13 +475,17 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { public void onSuccess(List result) { TracTracEventManagementPanel.this.previousConfigurations.clear(); TracTracEventManagementPanel.this.connectionsHistoryListBox.clear(); - + Collections.sort(result, new Comparator() { + @Override + public int compare(TracTracConfigurationDTO c1, TracTracConfigurationDTO c2) { + return c1.name.compareTo(c2.name); + } + }); for (TracTracConfigurationDTO config : result) { TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config); TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name); } - if (!result.isEmpty()) { updatePanelFromSelectedStoredConfiguration(); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java index 8b108f5c4fb..6b6ae9eff60 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java @@ -1,6 +1,8 @@ package com.sap.sailing.server.gateway.impl.rc; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import javax.servlet.ServletException; @@ -9,6 +11,7 @@ import javax.servlet.http.HttpServletResponse; import org.json.simple.JSONArray; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMarkFinder; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumn; @@ -24,62 +27,59 @@ public class MarksJsonExportServlet extends AbstractJsonHttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String leaderboardName = request.getParameter(RaceLogServletConstants.PARAMS_LEADERBOARD_NAME); if (leaderboardName == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_LEADERBOARD_NAME)); return; } - String raceColumnName = request.getParameter(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME); if (raceColumnName == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME)); return; } - String fleetName = request.getParameter(RaceLogServletConstants.PARAMS_RACE_FLEET_NAME); if (fleetName == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_RACE_FLEET_NAME)); return; } - RacingEventService service = getService(); - Leaderboard leaderboard = service.getLeaderboardByName(leaderboardName); if (leaderboard == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); return; } - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such race column found."); return; } - Fleet fleet = raceColumn.getFleetByName(fleetName); if (fleet == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such fleet found."); return; } - TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - JSONArray result = new JSONArray(); - + final Iterable marks; if (trackedRace != null) { - MarkJsonSerializer serializer = new MarkJsonSerializer(); - - for (Mark mark : trackedRace.getMarks()) { - if (toUUID(mark.getId().toString()) != null) { - result.add(serializer.serialize(mark)); - } + marks = trackedRace.getMarks(); + } else { + final List marksList = new ArrayList<>(); + // no tracked race associated yet; grab the mark definitions from the race log: + for (Mark markDefinitionFromRaceLog : new DefinedMarkFinder(raceColumn.getRaceLog(fleet)).analyze()) { + marksList.add(markDefinitionFromRaceLog); + } + marks = marksList; + } + MarkJsonSerializer serializer = new MarkJsonSerializer(); + for (Mark mark : marks) { + if (toUUID(mark.getId().toString()) != null) { + result.add(serializer.serialize(mark)); } } - setJsonResponseHeader(response); result.writeJSONString(response.getWriter()); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java index 5e1d8f59c76..56a23608b20 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringListEditorComposite.java @@ -1,5 +1,8 @@ package com.sap.sse.gwt.client.controls.listedit; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyUpEvent; @@ -82,6 +85,9 @@ public class StringListEditorComposite extends ListEditorComposite { for (String suggestValue : suggestValues) { inputOracle.add(suggestValue); } + List defaultSuggestions = new ArrayList<>(); + Util.addAll(suggestValues, defaultSuggestions); + this.inputOracle.setDefaultSuggestionsFromText(defaultSuggestions); } @Override diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java index 810114a8362..4f72a25d7ff 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java @@ -1,6 +1,8 @@ package com.sap.sse.gwt.client.dialog; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; @@ -24,12 +26,15 @@ import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.LongBox; +import com.google.gwt.user.client.ui.MultiWordSuggestOracle; import com.google.gwt.user.client.ui.PasswordTextBox; import com.google.gwt.user.client.ui.RadioButton; +import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.datepicker.client.DateBox; +import com.sap.sse.common.Util; import com.sap.sse.gwt.client.controls.GenericListBox; import com.sap.sse.gwt.client.controls.GenericListBox.ValueBuilder; import com.sap.sse.gwt.client.controls.IntegerBox; @@ -163,6 +168,24 @@ public abstract class DataEntryDialog { return createTextBoxInternal(initialValue, 30); } + public SuggestBox createSuggestBox(Iterable suggestValues) { + List suggestValuesAsCollection = new ArrayList<>(); + Util.addAll(suggestValues, suggestValuesAsCollection); + final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle(); + oracle.addAll(suggestValuesAsCollection); + oracle.setDefaultSuggestionsFromText(suggestValuesAsCollection); + final SuggestBox result = new SuggestBox(oracle); + result.getValueBox().addChangeHandler(new ChangeHandler() { + @Override + public void onChange(ChangeEvent event) { + validate(); + } + }); + DialogUtils.linkEnterToButton(getOkButton(), result.getValueBox()); + DialogUtils.linkEscapeToButton(getCancelButton(), result.getValueBox()); + return result; + } + /** * Creates a text box with a key-up listener attached which ensures the value is updated after each * key-up event and the entire dialog is {@link #validate() validated} in this case. diff --git a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/NetworkHelper.java b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/NetworkHelper.java index e4cf0882372..67129183e45 100644 --- a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/NetworkHelper.java +++ b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/util/NetworkHelper.java @@ -36,7 +36,6 @@ public class NetworkHelper { public void executeHttpJsonRequestAsnchronously(HttpRequest request, NetworkHelperSuccessListener successListener, NetworkHelperFailureListener failureListener) { - NetworkRequestTask task = new NetworkRequestTask(successListener, failureListener); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, request); } @@ -62,13 +61,10 @@ public class NetworkHelper { try { stream = request.execute(); String responseStr = readStream(stream); - response = null; - if (responseStr.length() > 0) { response = new JSONObject(responseStr); } - isSuccess = true; } catch (IOException e) { error = new NetworkHelperError(e.getMessage()); @@ -76,7 +72,6 @@ public class NetworkHelper { error = new NetworkHelperError(e.getMessage()); ExLog.e(mContext, TAG, "Failed to parse JSON: " + e.getMessage()); } - return null; } diff --git a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java index 363b06b57e9..6edd2786fcc 100644 --- a/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java +++ b/mobile/com.sap.sailing.buoy.positioning/src/com/sap/sailing/android/buoy/positioning/app/util/CheckinManager.java @@ -58,13 +58,11 @@ public class CheckinManager { public void callServerAndGenerateCheckinData() { Uri uri = Uri.parse(url); - // TODO: assuming scheme is http, is this valid? String scheme = uri.getScheme(); if (scheme != "http" && scheme != "https") { scheme = "http"; } - final URLData urlData = extractRequestParametersFromUri(uri, scheme); if (urlData == null) { setCheckinData(null); @@ -76,7 +74,6 @@ public class CheckinManager { try { HttpGetRequest getLeaderboardRequest = new HttpGetRequest(new URL(urlData.getLeaderboardUrl), mContext); getLeaderBoardFromServer(urlData, getLeaderboardRequest); - } catch (MalformedURLException e) { ExLog.e(mContext, TAG, "Error: Failed to perform checking due to a MalformedURLException: " + e.getMessage()); @@ -115,13 +112,9 @@ public class CheckinManager { private void getLeaderBoardFromServer(final URLData urlData, HttpGetRequest getLeaderboardRequest) { NetworkHelper.getInstance(mContext).executeHttpJsonRequestAsnchronously(getLeaderboardRequest, new NetworkHelper.NetworkHelperSuccessListener() { - @Override public void performAction(JSONObject response) { - // TODO Auto-generated method stub - final String leaderboardName; - try { leaderboardName = response.getString("name"); urlData.getMarkUrl = urlData.hostWithPort + prefs.getServerMarkPath(leaderboardName); @@ -143,9 +136,7 @@ public class CheckinManager { ExLog.e(mContext, TAG, "Error: Failed to perform checking due to a MalformedURLException: " + e1.getMessage()); } } - }, new NetworkHelper.NetworkHelperFailureListener() { - @Override public void performAction(NetworkHelper.NetworkHelperError e) { ExLog.e(mContext, TAG, "Failed to get event from API: " + e.getMessage()); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/DependentRaceSpinnerAdapter.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/DependentRaceSpinnerAdapter.java index 18e3d005ee3..fdcc42419e2 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/DependentRaceSpinnerAdapter.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/DependentRaceSpinnerAdapter.java @@ -116,7 +116,7 @@ public class DependentRaceSpinnerAdapter implements SpinnerAdapter { @Override public int getViewTypeCount() { - return 2; + return 1; } @Override