From 3fd911764c93558c5c8d2fa716e8a9f804c996aa Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 29 Aug 2011 17:59:24 +0200 Subject: [PATCH] factored commonalitied between Expedition and SwissTiming UDP receivers --- .../META-INF/MANIFEST.MF | 3 +- .../META-INF/MANIFEST.MF | 3 +- .../SwissTimingFormatException.java | 2 +- .../SwissTimingListener.java | 5 + .../SwissTimingMessage.java | 3 +- .../SwissTimingMessageListener.java | 6 + .../SwissTimingMessageParser.java | 3 +- .../impl/SwissTimingMessageImpl.java | 5 + .../impl/SwissTimingMessageParserImpl.java | 7 + .../impl/SwissTimingUDPReceiverImpl.java | 24 +++ .../SailingDomainTest (Proxy).launch | 2 +- .../domain/test/KielWeek2011BasedTest.java | 18 --- .../test/LeaderboardForKielWeekTest.java | 14 ++ .../domain/test/StoredTrackBasedTest.java | 16 -- .../WindEstimationOnStoredTracksTest.java | 20 ++- .../META-INF/MANIFEST.MF | 3 +- .../META-INF/MANIFEST.MF | 3 +- .../ExpeditionListener.java | 5 +- .../ExpeditionMessage.java | 3 +- .../UDPExpeditionReceiver.java | 153 ++---------------- .../impl/ExpeditionMessageParser.java | 81 ++++++++++ java/com.sap.sailing.gwt.ui/SailingGWT.launch | 2 +- .../ui/client/EditableLeaderboardPanel.java | 29 ++++ .../gwt/ui/client/LeaderboardConfigPanel.java | 2 +- .../gwt/ui/client/LeaderboardPanel.java | 78 +++++---- java/com.sap.sailing.gwt.ui/war/.gitignore | 2 - .../rpcPolicyManifest/manifest.txt | 2 - .../SailingServer (Proxy).launch | 2 +- java/com.sap.sailing.udpconnector/.classpath | 7 + java/com.sap.sailing.udpconnector/.project | 28 ++++ .../.settings/org.eclipse.jdt.core.prefs | 8 + .../.settings/org.eclipse.pde.core.prefs | 4 + .../META-INF/MANIFEST.MF | 8 + java/com.sap.sailing.udpconnector/pom.xml | 13 ++ .../sap/sailing/udpconnector/UDPMessage.java | 5 + .../udpconnector/UDPMessageListener.java | 5 + .../udpconnector/UDPMessageParser.java | 7 + .../sap/sailing/udpconnector/UDPReceiver.java | 105 ++++++++++++ java/pom.xml | 1 + 39 files changed, 460 insertions(+), 227 deletions(-) create mode 100755 java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingListener.java create mode 100755 java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageListener.java create mode 100755 java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingUDPReceiverImpl.java create mode 100755 java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageParser.java create mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java delete mode 100644 java/com.sap.sailing.gwt.ui/war/.gitignore delete mode 100644 java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.Leaderboard/rpcPolicyManifest/manifest.txt create mode 100755 java/com.sap.sailing.udpconnector/.classpath create mode 100755 java/com.sap.sailing.udpconnector/.project create mode 100755 java/com.sap.sailing.udpconnector/.settings/org.eclipse.jdt.core.prefs create mode 100755 java/com.sap.sailing.udpconnector/.settings/org.eclipse.pde.core.prefs create mode 100755 java/com.sap.sailing.udpconnector/META-INF/MANIFEST.MF create mode 100644 java/com.sap.sailing.udpconnector/pom.xml create mode 100755 java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessage.java create mode 100755 java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageListener.java create mode 100755 java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageParser.java create mode 100755 java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPReceiver.java diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF index 9c0794b16e5..66929b12d6e 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/META-INF/MANIFEST.MF @@ -7,6 +7,7 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: com.sap.sailing.domain.swisstimingadapter, com.sap.sailing.domain, - org.junit4 + org.junit4, + com.sap.sailing.udpconnector Bundle-ClassPath: resources/, . diff --git a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF index a0d6af4f52b..7af3be0a264 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF @@ -5,5 +5,6 @@ Bundle-SymbolicName: com.sap.sailing.domain.swisstimingadapter Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Require-Bundle: com.sap.sailing.domain +Require-Bundle: com.sap.sailing.domain, + com.sap.sailing.udpconnector Export-Package: com.sap.sailing.domain.swisstimingadapter diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFormatException.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFormatException.java index ea5f4825e1d..886be653284 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFormatException.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFormatException.java @@ -1,6 +1,6 @@ package com.sap.sailing.domain.swisstimingadapter; -public class SwissTimingFormatException extends Exception { +public class SwissTimingFormatException extends RuntimeException { private static final long serialVersionUID = -1210353206288437237L; private final byte[] swissTimingMessage; diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingListener.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingListener.java new file mode 100755 index 00000000000..f48f0ad43b9 --- /dev/null +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingListener.java @@ -0,0 +1,5 @@ +package com.sap.sailing.domain.swisstimingadapter; + +public interface SwissTimingListener { + void received(SwissTimingMessage message); +} diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessage.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessage.java index e1fa5acf333..47b59496f6b 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessage.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessage.java @@ -3,8 +3,9 @@ package com.sap.sailing.domain.swisstimingadapter; import com.sap.sailing.domain.base.Position; import com.sap.sailing.domain.base.Speed; import com.sap.sailing.domain.base.TimePoint; +import com.sap.sailing.udpconnector.UDPMessage; -public interface SwissTimingMessage { +public interface SwissTimingMessage extends UDPMessage { String getRaceID(); int getPacketID(); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageListener.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageListener.java new file mode 100755 index 00000000000..ba54bb17d14 --- /dev/null +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageListener.java @@ -0,0 +1,6 @@ +package com.sap.sailing.domain.swisstimingadapter; + +import com.sap.sailing.udpconnector.UDPMessageListener; + +public interface SwissTimingMessageListener extends UDPMessageListener { +} diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageParser.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageParser.java index 00db6ed4ac9..2112d41ac0e 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageParser.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingMessageParser.java @@ -1,8 +1,9 @@ package com.sap.sailing.domain.swisstimingadapter; import com.sap.sailing.domain.swisstimingadapter.impl.SwissTimingMessageParserImpl; +import com.sap.sailing.udpconnector.UDPMessageParser; -public interface SwissTimingMessageParser { +public interface SwissTimingMessageParser extends UDPMessageParser { SwissTimingMessageParser INSTANCE = new SwissTimingMessageParserImpl(); SwissTimingMessage parse(byte[] message) throws SwissTimingFormatException; diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageImpl.java index cf52609a955..cf0d9190104 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageImpl.java @@ -29,6 +29,11 @@ public class SwissTimingMessageImpl implements SwissTimingMessage { this.batteryPercent = batteryPercent; this.length = length; } + + @Override + public boolean isValid() { + return true; + } @Override public String getRaceID() { diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageParserImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageParserImpl.java index ef692ee0fe2..3850040560d 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageParserImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingMessageParserImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.swisstimingadapter.impl; +import java.net.DatagramPacket; + import com.sap.sailing.domain.base.impl.DegreeBearingImpl; import com.sap.sailing.domain.base.impl.DegreePosition; import com.sap.sailing.domain.base.impl.KilometersPerHourSpeedWithBearingImpl; @@ -84,4 +86,9 @@ public class SwissTimingMessageParserImpl implements SwissTimingMessageParser { return result; } + @Override + public SwissTimingMessage parse(DatagramPacket p) throws SwissTimingFormatException { + return parse(p.getData(), p.getOffset()); + } + } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingUDPReceiverImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingUDPReceiverImpl.java new file mode 100755 index 00000000000..b111a1894ec --- /dev/null +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingUDPReceiverImpl.java @@ -0,0 +1,24 @@ +package com.sap.sailing.domain.swisstimingadapter.impl; + +import java.net.SocketException; + +import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessage; +import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessageListener; +import com.sap.sailing.udpconnector.UDPMessageParser; +import com.sap.sailing.udpconnector.UDPReceiver; + +public class SwissTimingUDPReceiverImpl extends UDPReceiver { + + private final SwissTimingMessageParserImpl parser; + + public SwissTimingUDPReceiverImpl(int port) throws SocketException { + super(port); + parser = new SwissTimingMessageParserImpl(); + } + + @Override + protected UDPMessageParser getParser() { + return parser; + } + +} diff --git a/java/com.sap.sailing.domain.test/SailingDomainTest (Proxy).launch b/java/com.sap.sailing.domain.test/SailingDomainTest (Proxy).launch index 99a688ba679..4455ce75a78 100755 --- a/java/com.sap.sailing.domain.test/SailingDomainTest (Proxy).launch +++ b/java/com.sap.sailing.domain.test/SailingDomainTest (Proxy).launch @@ -16,5 +16,5 @@ - + diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/KielWeek2011BasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/KielWeek2011BasedTest.java index b129e08fa85..f543d63386c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/KielWeek2011BasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/KielWeek2011BasedTest.java @@ -23,17 +23,13 @@ import com.sap.sailing.domain.base.Position; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.TimePoint; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.DegreeBearingImpl; import com.sap.sailing.domain.base.impl.DegreePosition; -import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.tracking.DynamicTrackedEvent; import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.WindSource; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.GPSFixImpl; import com.sap.sailing.domain.tracking.impl.TrackedLegImpl; -import com.sap.sailing.domain.tracking.impl.WindImpl; import com.sap.sailing.domain.tractracadapter.Receiver; import com.sap.sailing.domain.tractracadapter.ReceiverType; import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl; @@ -167,11 +163,6 @@ public abstract class KielWeek2011BasedTest extends AbstractTracTracLiveTest { return trackedRace; } - - protected void setTrackedRace(DynamicTrackedRace trackedRace) { - this.trackedRace = trackedRace; - } - /** * When all stored data has been transmitted, notify the semaphor for tests to start processing */ @@ -208,13 +199,4 @@ public abstract class KielWeek2011BasedTest extends AbstractTracTracLiveTest { return storedDataLoaded; } - protected void loadRace(String raceId) throws MalformedURLException, IOException, InterruptedException, - URISyntaxException { - setUp(raceId, ReceiverType.RACECOURSE, ReceiverType.RACESTARTFINISH, ReceiverType.MARKPASSINGS); - getTrackedRace().setWindSource(WindSource.WEB); - getTrackedRace().recordWind( - new WindImpl(/* position */null, MillisecondsTimePoint.now(), new KnotSpeedWithBearingImpl(12, - new DegreeBearingImpl(70))), WindSource.WEB); - fixApproximateMarkPositionsForWindReadOut(getTrackedRace()); - } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java index 2c62e255390..f378bd81150 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java @@ -9,12 +9,17 @@ import java.net.URISyntaxException; import org.junit.Test; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.DegreeBearingImpl; +import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.leaderboard.RaceInLeaderboard; import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.tracking.NoWindException; +import com.sap.sailing.domain.tracking.WindSource; +import com.sap.sailing.domain.tracking.impl.WindImpl; +import com.sap.sailing.domain.tractracadapter.ReceiverType; import com.sap.sailing.util.Util.Pair; public class LeaderboardForKielWeekTest extends KielWeek2011BasedTest { @@ -51,4 +56,13 @@ public class LeaderboardForKielWeekTest extends KielWeek2011BasedTest { assertEquals(11, leaderboard.getContent(now).get(key).getTotalPoints()); assertEquals(11, leaderboard.getEntry(hasso, column, now).getTotalPoints()); } + + private void loadRace(String raceId) throws MalformedURLException, IOException, InterruptedException, + URISyntaxException { + setUp(raceId, ReceiverType.RACECOURSE, ReceiverType.RACESTARTFINISH, ReceiverType.MARKPASSINGS); + getTrackedRace().setWindSource(WindSource.WEB); + getTrackedRace().recordWind(new WindImpl(/* position */ null, MillisecondsTimePoint.now(), + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(70))), WindSource.WEB); + fixApproximateMarkPositionsForWindReadOut(getTrackedRace()); + } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 6b2364426ee..14baeb061ef 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -48,7 +48,6 @@ import com.sap.sailing.domain.base.impl.WaypointImpl; import com.sap.sailing.domain.tracking.DynamicTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.GPSFixMoving; -import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedEvent; import com.sap.sailing.domain.tracking.WindSource; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; @@ -56,7 +55,6 @@ import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.GPSFixImpl; import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TrackedEventImpl; import com.sap.sailing.domain.tracking.impl.WindImpl; @@ -81,20 +79,6 @@ public abstract class StoredTrackBasedTest { return track; } - protected void copyTracks(Map> tracks, DynamicTrackedRace trackedRace) { - for (Map.Entry> e : tracks.entrySet()) { - DynamicTrack track = trackedRace.getTrack(e.getKey()); - for (GPSFixMoving fix : e.getValue().getRawFixes()) { - track.addGPSFix(fix); - } - List markPassings = new ArrayList(); - // add a mark passing for the start gate at the very beginning to make sure everyone is on a valid leg - markPassings.add(new MarkPassingImpl(track.getFirstRawFix().getTimePoint(), trackedRace.getRace() - .getCourse().getWaypoints().iterator().next(), e.getKey())); - trackedRace.updateMarkPassings(e.getKey(), markPassings); - } - } - /** * Creates a simple two-lap upwind-downwind course for a race/event with given name and boat class name with the * competitors specified. The marks are laid out such that the upwind/downwind leg detection should be alright. diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnStoredTracksTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnStoredTracksTest.java index 96f1f8b9efa..89f0abc90f0 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnStoredTracksTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnStoredTracksTest.java @@ -5,6 +5,8 @@ import static org.junit.Assert.assertNotNull; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.junit.Before; @@ -17,8 +19,10 @@ import com.sap.sailing.domain.tracking.DynamicTrack; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.NoWindException; import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.util.Util; public class WindEstimationOnStoredTracksTest extends StoredTrackBasedTest { @@ -28,9 +32,23 @@ public class WindEstimationOnStoredTracksTest extends StoredTrackBasedTest { public void setUp() throws FileNotFoundException, IOException { Map> tracks = loadTracks(); trackedRace = createTestTrackedRace("Kieler Woche", "505 Race 2", "505", tracks.keySet()); - copyTracks(tracks, trackedRace); + copyTracks(tracks); } + private void copyTracks(Map> tracks) { + for (Map.Entry> e : tracks.entrySet()) { + DynamicTrack track = trackedRace.getTrack(e.getKey()); + for (GPSFixMoving fix : e.getValue().getRawFixes()) { + track.addGPSFix(fix); + } + List markPassings = new ArrayList(); + // add a mark passing for the start gate at the very beginning to make sure everyone is on a valid leg + markPassings.add(new MarkPassingImpl(track.getFirstRawFix().getTimePoint(), trackedRace.getRace() + .getCourse().getWaypoints().iterator().next(), e.getKey())); + trackedRace.updateMarkPassings(e.getKey(), markPassings); + } + } + @Test public void testSuccessfulTrackedRaceCreation() throws FileNotFoundException, IOException { assertNotNull(trackedRace); diff --git a/java/com.sap.sailing.expeditionconnector.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.expeditionconnector.test/META-INF/MANIFEST.MF index c06edf0e7fe..545efb33c25 100755 --- a/java/com.sap.sailing.expeditionconnector.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.expeditionconnector.test/META-INF/MANIFEST.MF @@ -10,4 +10,5 @@ Require-Bundle: org.junit4;bundle-version="4.8.1", com.sap.sailing.expeditionconnector, com.sap.sailing.domain, com.sap.sailing.declination, - com.sap.sailing.domain.test + com.sap.sailing.domain.test, + com.sap.sailing.udpconnector diff --git a/java/com.sap.sailing.expeditionconnector/META-INF/MANIFEST.MF b/java/com.sap.sailing.expeditionconnector/META-INF/MANIFEST.MF index cc3db4828a7..9197475aab9 100755 --- a/java/com.sap.sailing.expeditionconnector/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.expeditionconnector/META-INF/MANIFEST.MF @@ -8,5 +8,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: com.sap.sailing.expeditionconnector Require-Bundle: com.sap.sailing.domain, com.sap.sailing.declination, - org.eclipse.osgi;visibility:=reexport + org.eclipse.osgi;visibility:=reexport, + com.sap.sailing.udpconnector Bundle-ActivationPolicy: lazy diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionListener.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionListener.java index 9f7cff5ed34..957a488f6a1 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionListener.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionListener.java @@ -1,5 +1,6 @@ package com.sap.sailing.expeditionconnector; -public interface ExpeditionListener { - void received(ExpeditionMessage message); +import com.sap.sailing.udpconnector.UDPMessageListener; + +public interface ExpeditionListener extends UDPMessageListener { } diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionMessage.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionMessage.java index 4ef44d9026f..c12382c0e74 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionMessage.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionMessage.java @@ -7,8 +7,9 @@ import com.sap.sailing.domain.base.SpeedWithBearing; import com.sap.sailing.domain.base.TimePoint; import com.sap.sailing.domain.tracking.GPSFix; import com.sap.sailing.domain.tracking.GPSFixMoving; +import com.sap.sailing.udpconnector.UDPMessage; -public interface ExpeditionMessage { +public interface ExpeditionMessage extends UDPMessage { /** * variable ID for the GPS-measured latitude, in decimal degrees */ diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/UDPExpeditionReceiver.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/UDPExpeditionReceiver.java index 44c5bac6fec..1a16b415f70 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/UDPExpeditionReceiver.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/UDPExpeditionReceiver.java @@ -1,18 +1,12 @@ package com.sap.sailing.expeditionconnector; import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; import java.net.SocketException; import java.util.HashMap; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import com.sap.sailing.domain.base.TimePoint; -import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; -import com.sap.sailing.expeditionconnector.impl.ExpeditionMessageImpl; +import com.sap.sailing.expeditionconnector.impl.ExpeditionMessageParser; +import com.sap.sailing.udpconnector.UDPReceiver; /** * When run, starts receiving UDP packets expected to be in the format Expedition writes and notifies registered @@ -21,28 +15,14 @@ import com.sap.sailing.expeditionconnector.impl.ExpeditionMessageImpl; * @author Axel Uhl (d043530) * */ -public class UDPExpeditionReceiver implements Runnable { - private boolean stopped = false; - - private final int listeningOnPort; - - private final DatagramSocket udpSocket; - - /** - * For each listener remembers if the listener is only interested in valid messages. - */ - private final Map listeners; - - /** - * Maximum IP packet length - */ - private static final int MAX_PACKET_SIZE = 65536; - +public class UDPExpeditionReceiver extends UDPReceiver { /** * Remembers, per boat ID, the milliseconds difference between the time the message was received * and the GPS time stamp provided by the message. */ private final Map timeStampOfLastMessageReceived; + + private final ExpeditionMessageParser parser; /** * Launches a listener and dumps messages received to the console @@ -66,128 +46,17 @@ public class UDPExpeditionReceiver implements Runnable { * start this object in a new thread. */ public UDPExpeditionReceiver(int listeningOnPort) throws SocketException { - udpSocket = new DatagramSocket(listeningOnPort); - listeners = new HashMap(); - this.listeningOnPort = listeningOnPort; + super(listeningOnPort); this.timeStampOfLastMessageReceived = new HashMap(); - } - - public void stop() throws SocketException, IOException { - stopped = true; - byte[] buf = new byte[0]; - DatagramPacket stopPacket = new DatagramPacket(buf, 0, InetAddress.getLocalHost(), listeningOnPort); - new DatagramSocket().send(stopPacket); - if (!udpSocket.isConnected()) { - udpSocket.close(); - } + parser = new ExpeditionMessageParser(this); } - /** - * If there are currently no listeners subscribed (see {@link #addListener(ExpeditionListener, boolean)} and - * {@link #removeListener(ExpeditionListener)}), this receiver is {@link #stop() stopped} and true - * is returned; otherwise, false is returned. - */ - public synchronized boolean stopIfNoListeners() throws SocketException, IOException { - boolean result = listeners.isEmpty(); - if (result) { - stop(); - } - return result; + public Map getTimeStampOfLastMessageReceived() { + return timeStampOfLastMessageReceived; } - public boolean isStopped() { - return stopped; - } - - public void run() { - byte[] buf = new byte[MAX_PACKET_SIZE]; - DatagramPacket p = new DatagramPacket(buf, buf.length); - while (!stopped) { - try { - udpSocket.receive(p); - String packetAsString = new String(p.getData(), p.getOffset(), p.getLength()).trim(); - if (packetAsString.length() > 0) { - ExpeditionMessage msg = parse(packetAsString); - if (msg != null) { - for (ExpeditionListener listener : listeners.keySet()) { - if (!listeners.get(listener) || msg.isValid()) { - listener.received(msg); - } - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - udpSocket.close(); - if (udpSocket.isConnected()) { - udpSocket.disconnect(); - } - } - - private ExpeditionMessage parse(String packetAsString) { - Pattern completeLinePattern = Pattern - .compile("#([0-9]*)(( *,([0-9][0-9]*) *, *(-?[0-9]*(\\.[0-9]*)?))*)\\*([0-9a-fA-F][0-9a-fA-F]*)"); - Matcher m = completeLinePattern.matcher(packetAsString); - boolean valid = m.matches(); - if (valid) { - int boatID = Integer.valueOf(m.group(1)); - String variableValuePairs = m.group(2).trim().substring(",".length()); // skip the leading "," - Map values = new HashMap(); - String[] variablesAndValuesInterleaved = variableValuePairs.split(","); - long now = System.currentTimeMillis(); - Long diff = timeStampOfLastMessageReceived.get(boatID); - TimePoint defaultForMessageTimePoint; - if (diff != null) { - // compute a reasonable default for a time stamp in case message doesn't provide one - // by subtracting the last diff from now - defaultForMessageTimePoint = new MillisecondsTimePoint(now - diff); - } else { - defaultForMessageTimePoint = null; - } - for (int i = 0; i < variablesAndValuesInterleaved.length; i++) { - int variableID = Integer.valueOf(variablesAndValuesInterleaved[i++]); - double variableValue = Double.valueOf(variablesAndValuesInterleaved[i]); - values.put(variableID, variableValue); - } - int checksum = Integer.valueOf(m.group(m.groupCount()), 16); - valid = valid && checksumOk(checksum, packetAsString); - ExpeditionMessageImpl result; - if (defaultForMessageTimePoint == null) { - result = new ExpeditionMessageImpl(boatID, values, valid); - } else { - result = new ExpeditionMessageImpl(boatID, values, valid, defaultForMessageTimePoint); - } - if (result.hasValue(ExpeditionMessage.ID_GPS_TIME)) { - // an original GPS time stamp; then remember the difference between now and the time stamp - timeStampOfLastMessageReceived.put(boatID, now-result.getTimePoint().asMillis()); - } - return result; - } else { - System.err.println("Unparsable expedition message: " + packetAsString); - return null; // couldn't even parse - } - } - - private boolean checksumOk(int checksum, String packetAsString) { - int b = 0; - for (byte stringByte : packetAsString.substring(0, packetAsString.lastIndexOf('*')).getBytes()) { - b ^= stringByte; - } - return b == checksum; - } - - public synchronized void addListener(ExpeditionListener listener, boolean validMessagesOnly) { - listeners.put(listener, validMessagesOnly); - } - - public synchronized void removeListener(ExpeditionListener listener) { - listeners.remove(listener); - } - - public int getPort() { - return listeningOnPort; + protected ExpeditionMessageParser getParser() { + return parser; } } diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageParser.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageParser.java new file mode 100755 index 00000000000..c57167672ea --- /dev/null +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/ExpeditionMessageParser.java @@ -0,0 +1,81 @@ +package com.sap.sailing.expeditionconnector.impl; + +import java.net.DatagramPacket; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.sap.sailing.domain.base.TimePoint; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.expeditionconnector.ExpeditionMessage; +import com.sap.sailing.expeditionconnector.UDPExpeditionReceiver; +import com.sap.sailing.udpconnector.UDPMessageParser; + +public class ExpeditionMessageParser implements UDPMessageParser { + + private UDPExpeditionReceiver receiver; + + public ExpeditionMessageParser(UDPExpeditionReceiver receiver) { + this.receiver = receiver; + } + + @Override + public ExpeditionMessage parse(DatagramPacket p) { + String packetAsString = new String(p.getData(), p.getOffset(), p.getLength()).trim(); + if (packetAsString.length() > 0) { + Pattern completeLinePattern = Pattern + .compile("#([0-9]*)(( *,([0-9][0-9]*) *, *(-?[0-9]*(\\.[0-9]*)?))*)\\*([0-9a-fA-F][0-9a-fA-F]*)"); + Matcher m = completeLinePattern.matcher(packetAsString); + boolean valid = m.matches(); + if (valid) { + int boatID = Integer.valueOf(m.group(1)); + String variableValuePairs = m.group(2).trim().substring(",".length()); // skip the leading "," + Map values = new HashMap(); + String[] variablesAndValuesInterleaved = variableValuePairs.split(","); + long now = System.currentTimeMillis(); + Long diff = receiver.getTimeStampOfLastMessageReceived().get(boatID); + TimePoint defaultForMessageTimePoint; + if (diff != null) { + // compute a reasonable default for a time stamp in case message doesn't provide one + // by subtracting the last diff from now + defaultForMessageTimePoint = new MillisecondsTimePoint(now - diff); + } else { + defaultForMessageTimePoint = null; + } + for (int i = 0; i < variablesAndValuesInterleaved.length; i++) { + int variableID = Integer.valueOf(variablesAndValuesInterleaved[i++]); + double variableValue = Double.valueOf(variablesAndValuesInterleaved[i]); + values.put(variableID, variableValue); + } + int checksum = Integer.valueOf(m.group(m.groupCount()), 16); + valid = valid && checksumOk(checksum, packetAsString); + ExpeditionMessageImpl result; + if (defaultForMessageTimePoint == null) { + result = new ExpeditionMessageImpl(boatID, values, valid); + } else { + result = new ExpeditionMessageImpl(boatID, values, valid, defaultForMessageTimePoint); + } + if (result.hasValue(ExpeditionMessage.ID_GPS_TIME)) { + // an original GPS time stamp; then remember the difference between now and the time stamp + receiver.getTimeStampOfLastMessageReceived().put(boatID, now - result.getTimePoint().asMillis()); + } + return result; + } else { + System.err.println("Unparsable expedition message: " + packetAsString); + return null; // couldn't even parse + } + } else { + return null; // empty package + } + } + + private boolean checksumOk(int checksum, String packetAsString) { + int b = 0; + for (byte stringByte : packetAsString.substring(0, packetAsString.lastIndexOf('*')).getBytes()) { + b ^= stringByte; + } + return b == checksum; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index adcdf2d46d5..deee168622c 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -12,7 +12,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java new file mode 100755 index 00000000000..1239e6522d3 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EditableLeaderboardPanel.java @@ -0,0 +1,29 @@ +package com.sap.sailing.gwt.ui.client; + +import com.sap.sailing.gwt.ui.shared.LeaderboardDAO; + +/** + * An editable version of the {@link LeaderboardPanel} which allows a user to enter carried / accumulated + * points and fix individual race scores. + * + * @author Axel Uhl (d043530) + * + */ +public class EditableLeaderboardPanel extends LeaderboardPanel { + + public EditableLeaderboardPanel(SailingServiceAsync sailingService, String leaderboardName, + ErrorReporter errorReporter, StringConstants stringConstants) { + super(sailingService, leaderboardName, errorReporter, stringConstants); + } + + /** + * Always ensures that there is a carry column displayed because in the editable version + * of the leaderboard the carried / accumulated values must always be editable and therefore + * the column must always be shown. + */ + @Override + protected void updateCarryColumn(LeaderboardDAO leaderboard) { + ensureCarryColumn(); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java index 96b5dea595f..2b603721af2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardConfigPanel.java @@ -162,7 +162,7 @@ public class LeaderboardConfigPanel extends FormPanel implements EventDisplayer, grid.setWidget(3, 0, selectedLeaderboardPanel); columnNamesInSelectedLeaderboardListBox = new ListBox(); selectedLeaderboardPanel.add(columnNamesInSelectedLeaderboardListBox); - columnNamesInSelectedLeaderboardListBox.setVisibleItemCount(5); + columnNamesInSelectedLeaderboardListBox.setVisibleItemCount(10); columnNamesInSelectedLeaderboardListBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent e) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java index 56b55ac0fbb..bc725435805 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LeaderboardPanel.java @@ -47,7 +47,7 @@ public class LeaderboardPanel extends FormPanel { private final StringConstants stringConstants; - private CellTable leaderboardTable; + private final CellTable leaderboardTable; private ListDataProvider data; @@ -196,7 +196,7 @@ public class LeaderboardPanel extends FormPanel { } } - private class CarryColumn extends SortableColumn { + protected class CarryColumn extends SortableColumn { public CarryColumn() { setSortable(true); } @@ -229,12 +229,12 @@ public class LeaderboardPanel extends FormPanel { this.errorReporter = errorReporter; this.stringConstants = stringConstants; leaderboardTable = new CellTable(/* pageSize */ 100); - leaderboardTable.setWidth("100%"); - leaderboardTable.setSelectionModel(new MultiSelectionModel() {}); + getLeaderboardTable().setWidth("100%"); + getLeaderboardTable().setSelectionModel(new MultiSelectionModel() {}); data = new ListDataProvider(); - data.addDataDisplay(leaderboardTable); + data.addDataDisplay(getLeaderboardTable()); listHandler = new ListHandler(data.getList()); - leaderboardTable.addColumnSortHandler(listHandler); + getLeaderboardTable().addColumnSortHandler(listHandler); loadCompleteLeaderboard(new Date()); VerticalPanel vp = new VerticalPanel(); HorizontalPanel hp = new HorizontalPanel(); @@ -249,12 +249,12 @@ public class LeaderboardPanel extends FormPanel { } }); vp.add(hp); - vp.add(leaderboardTable); + vp.add(getLeaderboardTable()); setWidget(vp); } - private void addColumn(SortableColumn column) { - leaderboardTable.addColumn(column, column.getHeader()); + protected void addColumn(SortableColumn column) { + getLeaderboardTable().addColumn(column, column.getHeader()); listHandler.setComparator(column, column.getComparator()); } @@ -294,8 +294,8 @@ public class LeaderboardPanel extends FormPanel { private void createMissingRaceColumns(LeaderboardDAO leaderboard) { for (Map.Entry raceNameAndMedalRace : leaderboard.raceNamesAndMedalRace.entrySet()) { boolean foundRaceColumn = false; - for (int i=0; !foundRaceColumn && i c = leaderboardTable.getColumn(i); + for (int i=0; !foundRaceColumn && i c = getLeaderboardTable().getColumn(i); if (c instanceof RaceColumn && ((RaceColumn) c).getRaceName().equals(raceNameAndMedalRace.getKey())) { foundRaceColumn = true; } @@ -308,14 +308,14 @@ public class LeaderboardPanel extends FormPanel { private void removeUnusedRaceColumns(LeaderboardDAO leaderboard) { List> columnsToRemove = new ArrayList>(); - for (int i=0; i c = leaderboardTable.getColumn(i); + for (int i=0; i c = getLeaderboardTable().getColumn(i); if (c instanceof RaceColumn && (leaderboard == null || !leaderboard.raceNamesAndMedalRace.keySet().contains(((RaceColumn) c).getRaceName()))) { columnsToRemove.add(c); } } for (Column c : columnsToRemove) { - leaderboardTable.removeColumn(c); + getLeaderboardTable().removeColumn(c); } } @@ -323,47 +323,61 @@ public class LeaderboardPanel extends FormPanel { * If the last column is the totals column, remove it. Add the race column as the last column. */ private void addRaceColumn(RaceColumn raceColumn) { - if (leaderboardTable.getColumn(leaderboardTable.getColumnCount()-1) instanceof TotalsColumn) { - leaderboardTable.removeColumn(leaderboardTable.getColumnCount()-1); + if (getLeaderboardTable().getColumn(getLeaderboardTable().getColumnCount()-1) instanceof TotalsColumn) { + getLeaderboardTable().removeColumn(getLeaderboardTable().getColumnCount()-1); } addColumn(raceColumn); } private void ensureCompetitorColumn() { - if (leaderboardTable.getColumnCount() == 0) { + if (getLeaderboardTable().getColumnCount() == 0) { addColumn(new CompetitorColumn()); } else { - if (!(leaderboardTable.getColumn(0) instanceof CompetitorColumn)) { + if (!(getLeaderboardTable().getColumn(0) instanceof CompetitorColumn)) { throw new RuntimeException("The first column must always be the competitor column but it was of type "+ - leaderboardTable.getColumn(0).getClass().getName()); + getLeaderboardTable().getColumn(0).getClass().getName()); } } } private void ensureTotalsColumn() { // add a totals column on the right - if (leaderboardTable.getColumnCount() == 0 || !(leaderboardTable.getColumn(leaderboardTable.getColumnCount()-1) instanceof TotalsColumn)) { + if (getLeaderboardTable().getColumnCount() == 0 || !(getLeaderboardTable().getColumn(getLeaderboardTable().getColumnCount()-1) instanceof TotalsColumn)) { addColumn(new TotalsColumn()); } } /** - * If column #1 (second column, right of the competitor column) does not exist or is not of type {@link CarryColumn}, - * all columns starting from #1 will be removed and a {@link CarryColumn} will be added. + * If the leaderboard {@link LeaderboardDAO#hasCarriedPoints has carried points} and if column #1 + * (second column, right of the competitor column) does not exist or is not of type {@link CarryColumn}, all columns + * starting from #1 will be removed and a {@link CarryColumn} will be added. If the leaderboard has no carried points + * but the display still shows a carry column, the column is removed. */ - private void updateCarryColumn(LeaderboardDAO leaderboard) { + protected void updateCarryColumn(LeaderboardDAO leaderboard) { if (leaderboard != null && leaderboard.hasCarriedPoints) { - if (!(leaderboardTable.getColumn(1) instanceof CarryColumn)) { - while (leaderboardTable.getColumnCount() > 1) { - leaderboardTable.removeColumn(1); - } - addColumn(new CarryColumn()); - } + ensureCarryColumn(); } else { - if (leaderboardTable.getColumnCount() >= 2 && leaderboardTable.getColumn(1) instanceof CarryColumn) { - leaderboardTable.removeColumn(1); - } + ensureNoCarryColumn(); } } + private void ensureNoCarryColumn() { + if (getLeaderboardTable().getColumnCount() >= 2 && getLeaderboardTable().getColumn(1) instanceof CarryColumn) { + getLeaderboardTable().removeColumn(1); + } + } + + protected void ensureCarryColumn() { + if (!(getLeaderboardTable().getColumn(1) instanceof CarryColumn)) { + while (getLeaderboardTable().getColumnCount() > 1) { + getLeaderboardTable().removeColumn(1); + } + addColumn(new CarryColumn()); + } + } + + protected CellTable getLeaderboardTable() { + return leaderboardTable; + } + } diff --git a/java/com.sap.sailing.gwt.ui/war/.gitignore b/java/com.sap.sailing.gwt.ui/war/.gitignore deleted file mode 100644 index af8c69b2794..00000000000 --- a/java/com.sap.sailing.gwt.ui/war/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/com.sap.sailing.gwt.ui.AdminConsole -/com.sap.sailing.gwt.ui.Leaderboard diff --git a/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.Leaderboard/rpcPolicyManifest/manifest.txt b/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.Leaderboard/rpcPolicyManifest/manifest.txt deleted file mode 100644 index b787c54a338..00000000000 --- a/java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/com.sap.sailing.gwt.ui.Leaderboard/rpcPolicyManifest/manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Module com.sap.sailing.gwt.ui.Leaderboard -# RPC service class, partial path of RPC policy file diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index 85a2ea94dbb..ee678b5b8df 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -24,5 +24,5 @@ - + diff --git a/java/com.sap.sailing.udpconnector/.classpath b/java/com.sap.sailing.udpconnector/.classpath new file mode 100755 index 00000000000..8a8f1668cdc --- /dev/null +++ b/java/com.sap.sailing.udpconnector/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/com.sap.sailing.udpconnector/.project b/java/com.sap.sailing.udpconnector/.project new file mode 100755 index 00000000000..e87bc1d86fb --- /dev/null +++ b/java/com.sap.sailing.udpconnector/.project @@ -0,0 +1,28 @@ + + + com.sap.sailing.udpconnector + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sailing.udpconnector/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.udpconnector/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 00000000000..371baff39fb --- /dev/null +++ b/java/com.sap.sailing.udpconnector/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Mon Aug 29 13:20:38 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/java/com.sap.sailing.udpconnector/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.udpconnector/.settings/org.eclipse.pde.core.prefs new file mode 100755 index 00000000000..42ee077170e --- /dev/null +++ b/java/com.sap.sailing.udpconnector/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Mon Aug 29 13:20:38 CEST 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sailing.udpconnector/META-INF/MANIFEST.MF b/java/com.sap.sailing.udpconnector/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..24987da74e5 --- /dev/null +++ b/java/com.sap.sailing.udpconnector/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Udpconnector +Bundle-SymbolicName: com.sap.sailing.udpconnector +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Export-Package: com.sap.sailing.udpconnector diff --git a/java/com.sap.sailing.udpconnector/pom.xml b/java/com.sap.sailing.udpconnector/pom.xml new file mode 100644 index 00000000000..33ea8e956a9 --- /dev/null +++ b/java/com.sap.sailing.udpconnector/pom.xml @@ -0,0 +1,13 @@ + + + 4.0.0 + + root + com.sap.sailing + 0.0.1-SNAPSHOT + + com.sap.sailing.udpconnector + 1.0.0-SNAPSHOT + eclipse-plugin + diff --git a/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessage.java b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessage.java new file mode 100755 index 00000000000..312beb6358e --- /dev/null +++ b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessage.java @@ -0,0 +1,5 @@ +package com.sap.sailing.udpconnector; + +public interface UDPMessage { + boolean isValid(); +} diff --git a/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageListener.java b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageListener.java new file mode 100755 index 00000000000..1845ac1b8c0 --- /dev/null +++ b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageListener.java @@ -0,0 +1,5 @@ +package com.sap.sailing.udpconnector; + +public interface UDPMessageListener { + void received(MessageType message); +} diff --git a/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageParser.java b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageParser.java new file mode 100755 index 00000000000..839e704a093 --- /dev/null +++ b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPMessageParser.java @@ -0,0 +1,7 @@ +package com.sap.sailing.udpconnector; + +import java.net.DatagramPacket; + +public interface UDPMessageParser { + MessageType parse(DatagramPacket p); +} diff --git a/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPReceiver.java b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPReceiver.java new file mode 100755 index 00000000000..a7cae656349 --- /dev/null +++ b/java/com.sap.sailing.udpconnector/src/com/sap/sailing/udpconnector/UDPReceiver.java @@ -0,0 +1,105 @@ +package com.sap.sailing.udpconnector; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.util.HashMap; +import java.util.Map; + +public abstract class UDPReceiver> implements Runnable { + private boolean stopped = false; + + private final int listeningOnPort; + + private final DatagramSocket udpSocket; + + /** + * For each listener remembers if the listener is only interested in valid messages. + */ + private final Map listeners; + + /** + * Maximum IP packet length + */ + private static final int MAX_PACKET_SIZE = 65536; + + /** + * You need call {@link #run} to actually start receiving events. To do this asynchronously, + * start this object in a new thread. + */ + public UDPReceiver(int listeningOnPort) throws SocketException { + udpSocket = new DatagramSocket(listeningOnPort); + listeners = new HashMap(); + this.listeningOnPort = listeningOnPort; + } + + public void stop() throws SocketException, IOException { + stopped = true; + byte[] buf = new byte[0]; + DatagramPacket stopPacket = new DatagramPacket(buf, 0, InetAddress.getLocalHost(), listeningOnPort); + new DatagramSocket().send(stopPacket); + if (!udpSocket.isConnected()) { + udpSocket.close(); + } + } + + /** + * If there are currently no listeners subscribed (see {@link #addListener(ListenerType, boolean)} and + * {@link #removeListener(ListenerType)}), this receiver is {@link #stop() stopped} and true + * is returned; otherwise, false is returned. + */ + public synchronized boolean stopIfNoListeners() throws SocketException, IOException { + boolean result = listeners.isEmpty(); + if (result) { + stop(); + } + return result; + } + + public boolean isStopped() { + return stopped; + } + + public void run() { + byte[] buf = new byte[MAX_PACKET_SIZE]; + DatagramPacket p = new DatagramPacket(buf, buf.length); + while (!stopped) { + try { + udpSocket.receive(p); + String packetAsString = new String(p.getData(), p.getOffset(), p.getLength()).trim(); + if (packetAsString.length() > 0) { + MessageType msg = getParser().parse(p); + if (msg != null) { + for (ListenerType listener : listeners.keySet()) { + if (!listeners.get(listener) || msg.isValid()) { + listener.received(msg); + } + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + udpSocket.close(); + if (udpSocket.isConnected()) { + udpSocket.disconnect(); + } + } + + public synchronized void addListener(ListenerType listener, boolean validMessagesOnly) { + listeners.put(listener, validMessagesOnly); + } + + public synchronized void removeListener(ListenerType listener) { + listeners.remove(listener); + } + + public int getPort() { + return listeningOnPort; + } + + protected abstract UDPMessageParser getParser(); +} diff --git a/java/pom.xml b/java/pom.xml index 60adef50522..bf1c83863a3 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -21,6 +21,7 @@ com.sap.sailing.domain.swisstimingadapter.test com.sap.sailing.declination com.sap.sailing.declination.test + com.sap.sailing.udpconnector com.sap.sailing.expeditionconnector com.sap.sailing.expeditionconnector.test com.sap.sailing.server