From f7dff83a043012cf5250221647da91b01d59e982 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 18 Jun 2015 19:57:43 +0200 Subject: [PATCH 01/27] proposal for bug 2977: X-ray down time based on race start time, not on X-ray up --- .../impl/BaseRacingProcedure.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java index ea11b0f6666..8abf94f3b3a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java @@ -16,6 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IndividualRecallRe import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsFinishedAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsInFinishingPhaseAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsIndividualRecallDisplayedAnalyzer; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEventScheduler; @@ -27,6 +28,7 @@ import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProce import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureChangedListener; import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; /** @@ -39,7 +41,10 @@ import com.sap.sse.common.TimePoint; public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener implements RacingProcedure, RaceLogChangedListener { - private final static long individualRecallRemovalTimeout = 4 * 60 * 1000; // minutes * seconds * milliseconds + /** + * The time since race start after which the X-ray flag has to go down + */ + private final static Duration individualRecallRemovalTimeout = Duration.ONE_MINUTE.times(4); private RaceStateEventScheduler scheduler; @@ -55,9 +60,11 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i private final FinishingTimeFinder finishingTimeFinder; private final FinishedTimeFinder finishedTimeFinder; private final RaceLogEventVisitor raceLogListener; + private final StartTimeFinder startTimeFinder; private boolean cachedIsIndividualRecallDisplayed; + /** * When calling me, call {@link BaseRacingProcedure#update()} afterwards! */ @@ -78,6 +85,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i this.recallRemovedFinder = new IndividualRecallRemovedFinder(raceLog); this.finishingTimeFinder = new FinishingTimeFinder(raceLog); this.finishedTimeFinder = new FinishedTimeFinder(raceLog); + this.startTimeFinder = new StartTimeFinder(raceLog); this.raceLogListener = new RaceLogChangedVisitor(this); this.raceLog.addListener(raceLogListener); @@ -125,7 +133,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i break; case RUNNING: if (isIndividualRecallDisplayed()) { - rescheduleIndividualRecallTimeout(recallDisplayedFinder.analyze()); + rescheduleIndividualRecallTimeout(startTimeFinder.analyze()); } break; default: @@ -156,17 +164,17 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i @Override public TimePoint getIndividualRecallRemovalTime() { - TimePoint displayed = getIndividualRecallDisplayedTime(); - if (hasIndividualRecall()) { - TimePoint removedEvent = recallRemovedFinder.analyze(); - if (removedEvent != null && (displayed == null || removedEvent.after(displayed))) { - return removedEvent; - } + final TimePoint result; + final TimePoint raceStartTime = startTimeFinder.analyze(); + final TimePoint removedEvent; + if (hasIndividualRecall() && (removedEvent = recallRemovedFinder.analyze()) != null && (raceStartTime == null || removedEvent.after(raceStartTime))) { + result = removedEvent; + } else if (raceStartTime != null) { + result = raceStartTime.plus(individualRecallRemovalTimeout); + } else { + result = null; } - if (displayed != null) { - return displayed.plus(individualRecallRemovalTimeout); - } - return null; + return result; } @Override @@ -210,7 +218,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i cachedIsIndividualRecallDisplayed = isRecallDisplayed; if (cachedIsIndividualRecallDisplayed) { changedListeners.onIndividualRecallDisplayed(this); - rescheduleIndividualRecallTimeout(recallDisplayedFinder.analyze()); + rescheduleIndividualRecallTimeout(startTimeFinder.analyze()); } else { changedListeners.onIndividualRecallRemoved(this); unscheduleStateEvent(RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT); @@ -223,9 +231,9 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i changedListeners.onActiveFlagsChanged(this); } - private void rescheduleIndividualRecallTimeout(TimePoint displayTime) { + private void rescheduleIndividualRecallTimeout(TimePoint raceStartTime) { unscheduleStateEvent(RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT); - scheduleStateEvents(new RaceStateEventImpl(displayTime.plus(individualRecallRemovalTimeout), RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT)); + scheduleStateEvents(new RaceStateEventImpl(raceStartTime.plus(individualRecallRemovalTimeout), RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT)); } protected void scheduleStateEvents(RaceStateEvent stateEvent) { From 9e908b5cb5f3fb3e2bd5e44243f4e4e846c56b2f Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Fri, 19 Jun 2015 14:16:40 +0200 Subject: [PATCH 02/27] Bug 2817 - By Marks Coursdesigner - Not Working change from onLongClick to onClick --- .../coursedesign/CourseMarkAdapter.java | 25 ++++++++----------- .../raceinfo/CourseFragmentMarks.java | 6 ++--- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/CourseMarkAdapter.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/CourseMarkAdapter.java index bfb314eccfd..9459a71de36 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/CourseMarkAdapter.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/coursedesign/CourseMarkAdapter.java @@ -1,8 +1,5 @@ package com.sap.sailing.racecommittee.app.ui.adapters.coursedesign; -import java.util.ArrayList; -import java.util.List; - import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -10,17 +7,19 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; - import com.sap.sailing.domain.base.Mark; import com.sap.sailing.racecommittee.app.R; import com.sap.sailing.racecommittee.app.ui.utils.MarkImageHelper; +import java.util.ArrayList; +import java.util.List; + public class CourseMarkAdapter extends RecyclerView.Adapter { private Context mContext; private List mMarks; private MarkImageHelper mImageHelper; - private MarkLongClick mListener; + private MarkClick mListener; public CourseMarkAdapter(Context context, ArrayList marks, MarkImageHelper imageHelper) { mContext = context; @@ -52,15 +51,15 @@ public class CourseMarkAdapter extends RecyclerView.Adapter Date: Fri, 19 Jun 2015 16:26:02 +0200 Subject: [PATCH 03/27] fixed bug 2981 and added test case; null wind caching was faulty --- ...aderboardDTOCalculationReuseCacheTest.java | 33 +++++++++++++++++++ .../LeaderboardDTOCalculationReuseCache.java | 14 ++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardDTOCalculationReuseCacheTest.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardDTOCalculationReuseCacheTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardDTOCalculationReuseCacheTest.java new file mode 100644 index 00000000000..dcd6db04ab5 --- /dev/null +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardDTOCalculationReuseCacheTest.java @@ -0,0 +1,33 @@ +package com.sap.sailing.domain.test; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class LeaderboardDTOCalculationReuseCacheTest { + @Test + public void testNullWindCaching() { + final MillisecondsTimePoint now = MillisecondsTimePoint.now(); + final LeaderboardDTOCalculationReuseCache cache = new LeaderboardDTOCalculationReuseCache(now); + final Competitor competitor = mock(Competitor.class); + @SuppressWarnings("unchecked") + final GPSFixTrack track = mock(GPSFixTrack.class); + final Position p = new DegreePosition(123, 12); + when(track.getEstimatedPosition(now, false)).thenReturn(p); + final TrackedRace trackedRace = mock(TrackedRace.class); + when(trackedRace.getTrack(competitor)).thenReturn(track); + when(trackedRace.getWind(p, now)).thenReturn(null); + assertNull(cache.getWind(trackedRace, competitor, now)); + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java index b46080d690f..07a1ffff640 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java @@ -8,6 +8,10 @@ import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.leaderboard.impl.AbstractSimpleLeaderboardImpl; import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.TrackedLeg; @@ -16,6 +20,7 @@ import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.impl.MillisecondsTimePoint; /** * A cache structure that is used for a single call to @@ -47,10 +52,13 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea /** - * the wind at competitor's position at timePoint + * the wind at competitor's position at timePoint; null values are represented by {@link #NULL_WIND}. */ final ConcurrentHashMap, Wind> windCache; + private static final Wind NULL_WIND = new WindImpl(/* position */ new DegreePosition(0, 0), + /* time point */ MillisecondsTimePoint.now(), /* windSpeedWithBearing */ new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); + /** * the leg's bearing at timePoint */ @@ -100,7 +108,9 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea Wind result = windCache.get(cacheKey); if (result == null) { result = trackedRace.getWind(trackedRace.getTrack(competitor).getEstimatedPosition(timePoint, false), timePoint); - windCache.put(cacheKey, result); + windCache.put(cacheKey, result == null ? NULL_WIND : result); + } else if (result == NULL_WIND) { + result = null; } return result; } From a8449200defa408fa2ebe1dd441f1fd162ce2769 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 19 Jun 2015 14:57:38 +0000 Subject: [PATCH 04/27] Updated kieler woche 2015 (markdown) --- wiki/kieler-woche-2015.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/wiki/kieler-woche-2015.md b/wiki/kieler-woche-2015.md index 54afdcc9d74..7093d721191 100644 --- a/wiki/kieler-woche-2015.md +++ b/wiki/kieler-woche-2015.md @@ -3,38 +3,44 @@ ## Server Landscape We run four servers for the event: -- on EC2: **Master**, **Replika 1** and **2** with an **ELB** in front, +- on EC2: **Master 1**, **Master 2**, **Replica 1** and **Replica 2** with an **ELB** in front, +- ELB canonical name is KW2015-553831863.eu-west-1.elb.amazonaws.com - locally: **Cube-Server** -For fast and available switching. The DB they use is called `KW2015`, and so is the replication channel. The git branch we use to merge the features we want to deploy to the event servers is called `kielerwoche2015` and the git tag used to build a release for it is called `XXX-release`. See http://hudson.sapsailing.com/job/SAPSailingAnalytics-XXX/ and http://hudson.sapsailing.com/job/SAPSailingAnalytics-XXX-release/, respectively, for their Hudson jobs. +for fast and available switching. The DB they use is called `KW2015`, and so is the replication channel. The git branch we use to merge the features we want to deploy to the event servers is called `kielerwoche2015` and the git tag used to build a release for it is called `kielerwoche2015-release`. See http://hudson.sapsailing.com/job/SAPSailingAnalytics-kielerwoche2015/ and http://hudson.sapsailing.com/job/SAPSailingAnalytics-kielerwoche2015-release/, respectively, for their Hudson jobs. -### Master Server +### Master 1 Server - Admin Console at http://ec2-54-154-151-10.eu-west-1.compute.amazonaws.com:8888/gwt/AdminConsole.html - External IP: 54.154.151.10 - Internal IP: 172.31.24.187 -### Replika 1 server +### Master 2 Server +- Admin Console at http://ec2-54-76-169-213.eu-west-1.compute.amazonaws.com:8888/gwt/AdminConsole.html +- External IP: 54.76.169.213 +- Internal IP: 172.31.30.73 + +### Replica 1 server - Admin Console at http://ec2-54-72-226-124.eu-west-1.compute.amazonaws.com:8888/gwt/AdminConsole.html - External IP: 54.72.226.124 - Internal IP: 172.31.20.11 -### Replika 2 server +### Replica 2 server - Admin Console at http://ec2-54-154-175-180.eu-west-1.compute.amazonaws.com:8888/gwt/AdminConsole.html - External IP: 54.154.175.180 - Internal IP: 172.31.20.12 ## TracTrac URL -- http://xxx.traclive.dk/events/event_xxx/jsonservice.php +- http://event.tractrac.com/events/event_20150616_KielerWoch/jsonservice.php for the Olympic Week ## Replication - RabbitMQ server for replication: 52.16.112.6 (Web: http://52.16.112.6:15672/) - Replication Exchange Name: KW2015 ## Other links -- Regatta Overview: http://kielerwoche2015ro.sapsailing.com -- Manage2Sail Event URL: http://manage2sail.com/api/public/links/event/ID?accesstoken=TOKEN&mediaType=json +- Regatta Overview: http://kielerwoche2015ro.sapsailing.com (currently not yet established) +- Manage2Sail Event URL: http://manage2sail.com/api/public/links/event/d56f7fea-0ca1-4972-83a4-d71d79f26b93?accesstoken=bDAv8CwsTM94ujZ&mediaType=json ## Local network setup basically see [[Set up local network with replication server|wiki/event-network-with-replica]] operating with a Meraki and a local replica server using 1 physical WAN interface on the Meraki. Meraki network config for this event can be found under [[Meraki Dashboard|https://n142.meraki.com/KiWo-TraWo/n/Rzu9tdoc]] -- Accessing replica server from `sailing-demo.sapsailing.com`via ssh or http from `ADMIN` network \ No newline at end of file +- Accessing replica server from `sailing-demo.sapsailing.com` via ssh or http from `ADMIN` network \ No newline at end of file From cb85e9d25a577e20e0edbe0e72b8bb47605bd24b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 19 Jun 2015 14:58:58 +0000 Subject: [PATCH 05/27] Updated kieler woche 2015 (markdown) --- wiki/kieler-woche-2015.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wiki/kieler-woche-2015.md b/wiki/kieler-woche-2015.md index 7093d721191..062235409a7 100644 --- a/wiki/kieler-woche-2015.md +++ b/wiki/kieler-woche-2015.md @@ -19,6 +19,9 @@ for fast and available switching. The DB they use is called `KW2015`, and so is - External IP: 54.76.169.213 - Internal IP: 172.31.30.73 +### "Current" Master +Whichever master is current, we map the main Apache URL http://kielerwoche2015-master.sapsailing.com to it. This is also the URL to use for Tablet and Smartphone configurations. + ### Replica 1 server - Admin Console at http://ec2-54-72-226-124.eu-west-1.compute.amazonaws.com:8888/gwt/AdminConsole.html - External IP: 54.72.226.124 From b11f9aeaba48485f0f426f810ce71c7146b17152 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 19 Jun 2015 15:14:18 +0000 Subject: [PATCH 06/27] Updated kieler woche 2015 (markdown) --- wiki/kieler-woche-2015.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/wiki/kieler-woche-2015.md b/wiki/kieler-woche-2015.md index 062235409a7..19d03533140 100644 --- a/wiki/kieler-woche-2015.md +++ b/wiki/kieler-woche-2015.md @@ -39,6 +39,25 @@ Whichever master is current, we map the main Apache URL http://kielerwoche2015-m - RabbitMQ server for replication: 52.16.112.6 (Web: http://52.16.112.6:15672/) - Replication Exchange Name: KW2015 +## Switching from one Master to Another + - switch Cube Replica's Apache server to direct http://kielerwoche2015.sapsailing.com to the cloud by editing its `/etc/apache2/sites-enabled/001-events.conf`, then as user `root` running `service apache2 reload`. + - upgrade the new master to the release you want, using the `refreshInstance.sh` script + - prepare switching in sapsailing.com:/etc/httpd/conf.d/001-events.conf so that in particular http://kielerwoche2015-master.sapsailing.com points to the new master's IP; save the file but don't do `service httpd reload` as yet + - remove the replicas from the ELB + - cleanly stop replication for all replicas currently active on the master you want to take offline. (Exception: if your current master is really broken and cannot serve requests anymore, in order to keep up at least some form of availability you may leave the replicas running until the new master is up.) + - stop replication on the Cube Replica + - start the new master + - track all the races that need to be tracked + - add the new master to the ELB and remove the old master from the ELB + - immediately afterwards do `service httpd reload` as user `root` on sapsailing.com to activate the new master + - validate that you haven't lost any RCApp events, ideally by comparing the RegattaOverview.html page for the old and the new master; in case you lost events, reload the race logs for those leaderboards in the new master's AdminConsole. + - upgrade the replicas (including the Cube Replica) to the new master if the new master runs a different release than the old master, using `refreshInstance.sh` + - adjust the replicas' (including the Cube Replica) `env.sh` to point to the new master with their `REPLICATE_MASTER_SERVLET_HOST` setting + - restart the Java server instance on the replicas (including the Cube Replica), using the usual `./stop; ./start` sequence. This will automatically re-start the replication + - when the replicas have finished their initial load (can be verified by looking at the RabbitMQ queues at http://ec2-52-16-112-6.eu-west-1.compute.amazonaws.com:15672/#/queues which should no longer have any "initialLoad" queues), add them again to the load balancer + - in the Cube server's Apache configuration let http://kielerwoche2015.sapsailing.com point again to the local replica by editing `/etc/apache2/sites-enabled/001-events.conf`, then as user `root` run `service httpd reload` + - shut down the other master server to avoid confusion with database writes + ## Other links - Regatta Overview: http://kielerwoche2015ro.sapsailing.com (currently not yet established) - Manage2Sail Event URL: http://manage2sail.com/api/public/links/event/d56f7fea-0ca1-4972-83a4-d71d79f26b93?accesstoken=bDAv8CwsTM94ujZ&mediaType=json From e3b4f45ceae0921944fc669654194bc709832553 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Sat, 20 Jun 2015 10:50:56 +0200 Subject: [PATCH 07/27] RCApp: show time since finishing start --- .../res/layout/race_finishing.xml | 11 ++++++- .../res/values-de/strings.xml | 3 +- .../res/values/strings.xml | 3 +- .../raceinfo/RaceFinishingFragment.java | 30 ++++++++++++++----- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/race_finishing.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/race_finishing.xml index 48fce4c2749..a22e4c8a74b 100644 --- a/mobile/com.sap.sailing.racecommittee.app/res/layout/race_finishing.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/race_finishing.xml @@ -24,10 +24,19 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_margin="@dimen/default_margin_half" + android:layout_marginTop="@dimen/default_margin_half" android:text="@string/finishing_started" android:textAppearance="?textNormal"/> + + aus %.0f° Durchschnittliche Windgeschwindigkeit Stimme aufzeichnen - Erstes Schiff im Ziel um #TIME# + Erstes Schiff im Ziel um %s + (%s) Jetzt runter Liste bearbeiten Zielliste diff --git a/mobile/com.sap.sailing.racecommittee.app/res/values/strings.xml b/mobile/com.sap.sailing.racecommittee.app/res/values/strings.xml index 289a2b034df..520cee67dbd 100644 --- a/mobile/com.sap.sailing.racecommittee.app/res/values/strings.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/values/strings.xml @@ -369,7 +369,8 @@ Individual Recalls %s min Record Voice - First vessel in finish at #TIME# + First vessel in finish at %s + (%s) Down now Recording diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceFinishingFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceFinishingFragment.java index 6a2775ee360..c97f03dbecc 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceFinishingFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/RaceFinishingFragment.java @@ -1,7 +1,5 @@ package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo; -import java.text.SimpleDateFormat; - import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; @@ -10,14 +8,21 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; - import com.sap.sailing.android.shared.util.ViewHolder; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.racecommittee.app.R; import com.sap.sailing.racecommittee.app.ui.utils.FlagsResources; +import com.sap.sailing.racecommittee.app.utils.TimeUtils; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +import java.text.SimpleDateFormat; public class RaceFinishingFragment extends BaseFragment { + private SimpleDateFormat mDateFormat; + private TextView mFinishingSince; + public static RaceFinishingFragment newInstance() { RaceFinishingFragment fragment = new RaceFinishingFragment(); Bundle args = new Bundle(); @@ -30,6 +35,9 @@ public class RaceFinishingFragment extends BaseFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.race_finishing, container, false); + mDateFormat = new SimpleDateFormat("HH:mm:ss", getResources().getConfiguration().locale); + mFinishingSince = ViewHolder.get(layout, R.id.first_vessel_since); + ImageView flag = ViewHolder.get(layout, R.id.flag); if (flag != null) { flag.setImageDrawable(FlagsResources.getFlagDrawable(getActivity(), Flags.BLUE.name(), 96)); @@ -55,11 +63,19 @@ public class RaceFinishingFragment extends BaseFragment { if (getView() != null) { TextView first_vessel = ViewHolder.get(getView(), R.id.first_vessel); if (first_vessel != null && getRaceState() != null && getRaceState().getFinishingTime() != null) { - String vessel_time = getString(R.string.finishing_started); - SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", getResources().getConfiguration().locale); - vessel_time = vessel_time.replace("#TIME#", dateFormat.format(getRaceState().getFinishingTime().asDate())); - first_vessel.setText(vessel_time); + first_vessel.setText(getString(R.string.finishing_started, mDateFormat.format(getRaceState().getFinishingTime().asDate()))); } } + notifyTick(MillisecondsTimePoint.now()); + } + + @Override + public void notifyTick(TimePoint now) { + super.notifyTick(now); + + if (mFinishingSince != null) { + String timeDiff = TimeUtils.formatDurationSince(now.minus(getRaceState().getFinishingTime().asMillis()).asMillis()); + mFinishingSince.setText(getString(R.string.finishing_started_since, timeDiff)); + } } } From 35105ca801be884174a11471b06fd8cb07145583 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Sat, 20 Jun 2015 13:57:23 +0200 Subject: [PATCH 08/27] sorting flags by name in preferences --- .../preference/RegattaPreferenceFragment.java | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/RegattaPreferenceFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/RegattaPreferenceFragment.java index 1fca5d0465f..7e2f96a7103 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/RegattaPreferenceFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/RegattaPreferenceFragment.java @@ -16,6 +16,7 @@ import com.sap.sailing.racecommittee.app.ui.activities.PreferenceActivity; import com.sap.sailing.racecommittee.app.ui.activities.SettingsActivity; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -109,54 +110,58 @@ public class RegattaPreferenceFragment extends BasePreferenceFragment { private void setupRacingProcedureTypePreference() { final ListPreference startProcedurePreference = findPreference(R.string.preference_racing_procedure_override_key); - List entries = new ArrayList(); - List entryValues = new ArrayList(); + List entries = new ArrayList<>(); + List entryValues = new ArrayList<>(); for (RacingProcedureType type : RacingProcedureType.validValues()) { entries.add(type.toString()); entryValues.add(type.name()); } - startProcedurePreference.setEntries(entries.toArray(new CharSequence[entries.size()])); - startProcedurePreference.setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()])); + startProcedurePreference.setEntries(entries.toArray(new String[entries.size()])); + startProcedurePreference.setEntryValues(entryValues.toArray(new String[entryValues.size()])); bindPreferenceSummaryToValue(startProcedurePreference); } private void setupCourseDesignerTypePreference() { - final ListPreference courseDesignerPreference = findPreference(R.string.preference_course_designer_override_key); + final ListPreference preference = findPreference(R.string.preference_course_designer_override_key); - List entries = new ArrayList(); - List entryValues = new ArrayList(); + List entries = new ArrayList<>(); + List entryValues = new ArrayList<>(); for (CourseDesignerMode type : CourseDesignerMode.validValues()) { entries.add(type.toString()); entryValues.add(type.name()); } - courseDesignerPreference.setEntries(entries.toArray(new CharSequence[0])); - courseDesignerPreference.setEntryValues(entryValues.toArray(new CharSequence[0])); + preference.setEntries(entries.toArray(new String[entries.size()])); + preference.setEntryValues(entryValues.toArray(new String[entryValues.size()])); - bindPreferenceSummaryToValue(courseDesignerPreference); + bindPreferenceSummaryToValue(preference); } private void setupRRS26StartmodeFlagsList() { - MultiSelectListPreference listPreference = findPreference(R.string.preference_racing_procedure_rrs26_startmode_flags_key); - List flags = new ArrayList(); + MultiSelectListPreference preference = findPreference(R.string.preference_racing_procedure_rrs26_startmode_flags_key); + List flags = new ArrayList<>(); for (Flags flag : Flags.validValues()) { flags.add(flag.name()); } - listPreference.setEntries(flags.toArray(new String[flags.size()])); - listPreference.setEntryValues(flags.toArray(new String[flags.size()])); + + Collections.sort(flags); + preference.setEntries(flags.toArray(new String[flags.size()])); + preference.setEntryValues(flags.toArray(new String[flags.size()])); } private void setupClassFlagList(ListPreference preference) { - List entries = new ArrayList(); - List entryValues = new ArrayList(); + List entries = new ArrayList<>(); + List entryValues = new ArrayList<>(); for (Flags flag : Flags.validValues()) { entries.add(flag.toString()); entryValues.add(flag.name()); } - preference.setEntries(entries.toArray(new CharSequence[entries.size()])); - preference.setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()])); + Collections.sort(entries); + Collections.sort(entryValues); + preference.setEntries(entries.toArray(new String[entries.size()])); + preference.setEntryValues(entryValues.toArray(new String[entryValues.size()])); } } From bbdf95ceb23268bccd90807c806c7abb54f4b8ae Mon Sep 17 00:00:00 2001 From: fmittag Date: Sat, 20 Jun 2015 14:06:36 +0200 Subject: [PATCH 09/27] fix for bug 2983 Confusing live race state after restartConfusing live race state after restart --- .../sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java index f9165ee6d91..a3212eee738 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java @@ -350,8 +350,7 @@ public class RaceContext { } else if (finishTime != null && now.after(finishTime)) { raceState = RaceViewState.FINISHED; } else if(raceLog != null) { - AbortingFlagFinder abortingFlagFinder = new AbortingFlagFinder(raceLog); - RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.analyze(); + RaceLogFlagEvent abortingFlagEvent = checkForAbortFlagEvent(); if (abortingFlagEvent != null) { Flags upperFlag = abortingFlagEvent.getUpperFlag(); if(upperFlag.equals(Flags.AP)) { From ae27b4e3a2e5d47d930847a4b52906f9da744e1d Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 14:15:45 +0200 Subject: [PATCH 10/27] fix for bug 2986: making TrackedRaceImpl.gpsFixStore transient and initialize it to EmptyGPSFixStore.INSTANCE in readObject --- .../com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 399d4a7625d..24c9af3ee5c 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 @@ -104,6 +104,7 @@ import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; +import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; import com.sap.sailing.domain.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.racelogtracking.DeviceMapping; import com.sap.sailing.domain.ranking.OneDesignRankingMetric; @@ -315,7 +316,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl private transient CrossTrackErrorCache crossTrackErrorCache; - private final GPSFixStore gpsFixStore; + private transient GPSFixStore gpsFixStore; /** * Wind and loading is started in a background thread during object construction. If a client needs to @@ -585,6 +586,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2); cacheInvalidationTimerLock = new Object(); windStore = EmptyWindStore.INSTANCE; + gpsFixStore = EmptyGPSFixStore.INSTANCE; competitorRankings = createCompetitorRankingsCache(); competitorRankingsLocks = createCompetitorRankingsLockMap(); directionFromStartToNextMarkCache = new HashMap>(); From ef5811e6bb7c2a0821ea534d05860bbf57fece43 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Sat, 20 Jun 2015 13:51:07 +0100 Subject: [PATCH 11/27] Fixed time window that determines the live race; also fixed strings --- .../dashboards/gwt/server/RibDashboardServiceImpl.java | 8 +++++++- .../sap/sailing/gwt/ui/client/StringMessages.properties | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java index 6a988f36ffd..6eb7e85b295 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java @@ -29,6 +29,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.RacingEventService; +import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -152,8 +153,13 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib for (RaceColumn column : lb.getRaceColumns()) { for (Fleet fleet : column.getFleets()) { TrackedRace race = column.getTrackedRace(fleet); - if (race != null && race.isLive(new MillisecondsTimePoint(new Date()))) { + TimePoint startOfRace = race.getStartOfRace(); + // not relying on isLive() because the time window is too short + // to retrieve wind information we need to extend the time window + if (race != null && startOfRace != null && race.getEndOfRace() == null && + MillisecondsTimePoint.now().after(startOfRace.minus(Duration.ONE_MINUTE.times(20)))) { result = race; + // no break here as we want to have the last race that is deemed to be live } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 5031095902d..fd4534d0798 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -1199,8 +1199,8 @@ group=Group valueAscending=Value (Ascending) valueDescending=Value (Descending) sortBy=Sort by -dashboardWindBotLoadingText=Loading wind bot data ... -dashboardWindBotLoadingMessage=Depending on your connection this operation might take some minutes to complete the first time. +dashboardWindBotLoadingText=Waiting for wind bot data... +dashboardWindBotLoadingMessage=Depending on your connection this operation might take some minutes to complete the first time. It can also take some time if there is no data available right now. dashboardWindBotNotAvailable=Wind bot not available. dashboardWindBot=Wind Bot dashboardTrueWindSpeed=TWS From bff98361d02bd4d095a72d98f58196a4c28d1ef8 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 15:04:57 +0200 Subject: [PATCH 12/27] added a test case for bug 2986 --- .../TrackedRaceContentsReplicationTest.java | 24 ++- ...ithGPSFixStoreContentsReplicationTest.java | 149 ++++++++++++++++++ .../AbstractServerReplicationTestSetUp.java | 24 ++- ...erverWithSingleServiceReplicationTest.java | 9 +- 4 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java index 1c3728ba8cb..b9f67ccbd04 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceContentsReplicationTest.java @@ -45,6 +45,7 @@ import com.sap.sailing.domain.persistence.MongoWindStore; import com.sap.sailing.domain.persistence.MongoWindStoreFactory; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; +import com.sap.sailing.domain.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFixTrack; @@ -67,6 +68,11 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio @Before public void setUp() throws Exception { + final EmptyGPSFixStore gpsFixStore = EmptyGPSFixStore.INSTANCE; + setUp(gpsFixStore); + } + + protected void setUp(final GPSFixStore gpsFixStore) throws Exception, UnknownHostException, InterruptedException { super.setUp(); final String boatClassName = "49er"; // FIXME use master DomainFactory; see bug 592 @@ -95,11 +101,27 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio trackedRegatta = master.apply(new TrackRegatta(raceIdentifier)); trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, MongoWindStoreFactory.INSTANCE.getMongoWindStore(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), - PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory()), EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 5000, + PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory()), gpsFixStore, /* delayToLiveInMillis */ 5000, /* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000)); trackedRace.waitUntilLoadingFromWindStoreComplete(); } + protected Competitor getCompetitor() { + return competitor; + } + + protected DynamicTrackedRace getTrackedRace() { + return trackedRace; + } + + protected RegattaNameAndRaceName getRaceIdentifier() { + return raceIdentifier; + } + + protected DynamicTrackedRegatta getTrackedRegatta() { + return trackedRegatta; + } + @Test public void testGPSFixReplication() throws InterruptedException { final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(1, 2), new MillisecondsTimePoint(12345), diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java new file mode 100644 index 00000000000..00a9cbd536f --- /dev/null +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackedRaceWithGPSFixStoreContentsReplicationTest.java @@ -0,0 +1,149 @@ +package com.sap.sailing.server.replication.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.persistence.MongoWindStoreFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStore; +import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFactory; +import com.sap.sailing.domain.racelog.tracking.GPSFixStore; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; +import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; +import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; +import com.sap.sailing.server.operationaltransformation.TrackRegatta; +import com.sap.sse.common.Color; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.replication.ReplicationMasterDescriptor; +import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp.ReplicationServiceTestImpl; + +/** + * Runs the same tests as {@link TrackedRaceContentsReplicationTest}, but with a non-empty {@link MongoGPSFixStore} that + * has special serialization requirements. + * + * @author Axel Uhl (d043530) + * + */ +public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractServerReplicationTest { + private Competitor competitor; + private DynamicTrackedRace trackedRace; + private RegattaNameAndRaceName raceIdentifier; + private DynamicTrackedRegatta trackedRegatta; + + @Before + public void setUp() throws Exception, UnknownHostException, InterruptedException { + final GPSFixStore gpsFixStore = MongoGPSFixStoreFactory.INSTANCE.getMongoGPSFixStore(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), + PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), /* serviceFinderFactory */ null); + Pair, ReplicationMasterDescriptor> replicationDescriptors = super.basicSetUp( + /* dropDB */true, /* master=null means create a new one */null, + /* replica=null means create a new one */null); + final String boatClassName = "49er"; + // FIXME use master DomainFactory; see bug 592 + final DomainFactory masterDomainFactory = DomainFactory.INSTANCE; + BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); + competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", Color.RED, "someone@nowhere.de", null, new TeamImpl("Tina Lutz + Susann Beucke", + (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null), + new PersonImpl("Tina Lutz", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null) }), + new PersonImpl("Rigo de Mas", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), + new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + final String baseEventName = "Test Event"; + AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, + /*startDate*/ null, /*endDate*/ null, UUID.randomUUID()); + Regatta regatta = master.apply(addEventOperation); + final String raceName = "Test Race"; + final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor)); + AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); + master.apply(addRaceOperation); + masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); + masterCourse.addWaypoint(1, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark2"), /*passingInstruction*/ null)); + masterCourse.addWaypoint(2, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark3"), /*passingInstruction*/ null)); + masterCourse.removeWaypoint(1); + raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), raceName); + trackedRegatta = master.apply(new TrackRegatta(raceIdentifier)); + trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, + MongoWindStoreFactory.INSTANCE.getMongoWindStore(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), + PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory()), gpsFixStore, /* delayToLiveInMillis */ 5000, + /* millisecondsOverWhichToAverageWind */ 10000, /* millisecondsOverWhichToAverageSpeed */10000)); + trackedRace.waitUntilLoadingFromWindStoreComplete(); + // set up the tracked race on the master with a non-empty GPS fix store before starting replication; this shall + // test serialization with a non-empty GPS fix store set on the tracked race. See also bug 2986. + replicationDescriptors.getA().startToReplicateFrom(replicationDescriptors.getB()); + } + + protected Competitor getCompetitor() { + return competitor; + } + + protected DynamicTrackedRace getTrackedRace() { + return trackedRace; + } + + protected RegattaNameAndRaceName getRaceIdentifier() { + return raceIdentifier; + } + + protected DynamicTrackedRegatta getTrackedRegatta() { + return trackedRegatta; + } + + @Test + public void testGPSFixReplication() throws InterruptedException { + final GPSFixMovingImpl fix = new GPSFixMovingImpl(new DegreePosition(1, 2), new MillisecondsTimePoint(12345), + new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + trackedRace.recordFix(competitor, fix); + Thread.sleep(1000); + TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier); + Competitor replicaCompetitor = replicaTrackedRace.getRace().getCompetitors().iterator().next(); + assertNotNull(replicaCompetitor); + GPSFixTrack competitorTrack = replicaTrackedRace.getTrack(replicaCompetitor); + competitorTrack.lockForRead(); + try { + assertEquals(1, Util.size(competitorTrack.getRawFixes())); + assertEquals(fix, competitorTrack.getRawFixes().iterator().next()); + assertNotSame(fix, competitorTrack.getRawFixes().iterator().next()); + } finally { + competitorTrack.unlockAfterRead(); + } + } + + +} diff --git a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java index 137a383d16d..ef32d4e00c7 100644 --- a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java +++ b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerReplicationTestSetUp.java @@ -72,11 +72,33 @@ public abstract class AbstractServerReplicationTestSetUp, ReplicationMasterDescriptor> result = setUpWithoutStartingToReplicateYet(); + result.getA().startToReplicateFrom(result.getB()); + } catch (Exception e) { + tearDown(); + throw e; + } + } + + /** + * Sets up master and replica, starts the JMS message broker and registers the replica with the master. If you want + * to drop the DB in your particular test case first, override {@link #persistenceSetUp(boolean)}. If you don't want + * replication to start right away for your test, override this method, execute only + * {@link #basicSetUp(boolean, Replicable, Replicable)}, do what you need to do and then explicitly call + * {@link ReplicationServiceTestImpl#startToReplicateFrom(ReplicationMasterDescriptor)} or + * {@link ReplicationServiceTestImpl#startToReplicateFromButDontYetFetchInitialLoad(ReplicationMasterDescriptor, boolean)} + * on the first component returned by {@link #basicSetUp(boolean, Replicable, Replicable)}. + * + * @return callers may call result.getA().startToReplicateFrom(result.getB()) on the result to actually + * start replication, e.g., after having done more set-up on the master + */ + protected Pair, ReplicationMasterDescriptor> setUpWithoutStartingToReplicateYet() throws Exception { try { Pair, ReplicationMasterDescriptor> result = basicSetUp( /* dropDB */true, /* master=null means create a new one */null, /* replica=null means create a new one */null); - result.getA().startToReplicateFrom(result.getB()); + return result; } catch (Exception e) { tearDown(); throw e; diff --git a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java index 2e20ed3ee1c..8d07094f647 100755 --- a/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java +++ b/java/com.sap.sse.replication.testsupport/src/com/sap/sse/replication/testsupport/AbstractServerWithSingleServiceReplicationTest.java @@ -25,6 +25,10 @@ public abstract class AbstractServerWithSingleServiceReplicationTest, ReplicationMasterDescriptor> basicSetUp(boolean dropDB, ReplicableImpl master, ReplicableImpl replica) throws Exception { - return testSetUp.basicSetUp(dropDB, master, replica); + final Pair, ReplicationMasterDescriptor> result = testSetUp + .basicSetUp(dropDB, master, replica); + setUpDescriptorsFromTestSetup(); + return result; } @After From 268204d5dfff119cf493cffc0bf91858e98971ba Mon Sep 17 00:00:00 2001 From: fmittag Date: Sat, 20 Jun 2015 15:55:53 +0200 Subject: [PATCH 13/27] fixed launch config --- java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index a00d6c0ff91..7435c9ab64d 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -16,11 +16,9 @@ - - + - @@ -73,7 +71,7 @@ - + From 145e5ab8f22740a93bf673c171c5e672eebf6008 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Sat, 20 Jun 2015 15:04:46 +0100 Subject: [PATCH 14/27] Lowering time where minutes are displayed on regatta overview --- .../gwt/regattaoverview/client/RegattaRaceStatesComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java index 9760e171076..e089c73e226 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java @@ -114,7 +114,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component private TextColumn startTimeColumn; private SimplePanel tableHolder = new SimplePanel(); private final long _1_HOUR = 60 /* seconds */* 60 /* minutes */* 60 /* hour */; - private final long HIDE_COL_TIME_THRESHOLD = _1_HOUR * 12; + private final long HIDE_COL_TIME_THRESHOLD = _1_HOUR; private TextColumn lastUpdateColumn; private TextColumn endOfProtestTime; private TextColumn raceAdditionalInformationColumn; From a4b2f9ef1a3b7be318fc4379d609441b78bd9044 Mon Sep 17 00:00:00 2001 From: fmittag Date: Sat, 20 Jun 2015 16:10:51 +0200 Subject: [PATCH 15/27] fix for deserialization problem with RaceLogFixedMarkPassingEventDeserializer --- .../racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java index 246b13ebe93..7c622a08551 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java @@ -25,8 +25,9 @@ public class RaceLogFixedMarkPassingEventDeserializer extends BaseRaceLogEventDe TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { TimePoint ofPassing = new MillisecondsTimePoint( (Long) object.get(RaceLogFixedMarkPassingEventSerializer.FIELD_TIMEPOINT_OF_MARKPASSING)); - Integer zeroBasedIndexOfPassedWaypoint = (Integer) object + Number zeroBasedIndexOfPassedWaypointObj = (Number) object .get(RaceLogFixedMarkPassingEventSerializer.FIELD_INDEX_OF_PASSED_WAYPOINT); + Integer zeroBasedIndexOfPassedWaypoint = zeroBasedIndexOfPassedWaypointObj != null ? zeroBasedIndexOfPassedWaypointObj.intValue() : null; return factory.createFixedMarkPassingEvent(timePoint, author, id, competitors, passId, ofPassing, zeroBasedIndexOfPassedWaypoint); } From 0dff22a168d4922457f59ebc55195ef1996afa7d Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Sat, 20 Jun 2015 16:23:44 +0100 Subject: [PATCH 16/27] Fixed NPE when race is null --- .../gwt/server/RibDashboardServiceImpl.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java index 6eb7e85b295..1e92e506221 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java @@ -153,13 +153,15 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib for (RaceColumn column : lb.getRaceColumns()) { for (Fleet fleet : column.getFleets()) { TrackedRace race = column.getTrackedRace(fleet); - TimePoint startOfRace = race.getStartOfRace(); - // not relying on isLive() because the time window is too short - // to retrieve wind information we need to extend the time window - if (race != null && startOfRace != null && race.getEndOfRace() == null && - MillisecondsTimePoint.now().after(startOfRace.minus(Duration.ONE_MINUTE.times(20)))) { - result = race; - // no break here as we want to have the last race that is deemed to be live + if (race != null) { + TimePoint startOfRace = race.getStartOfRace(); + // not relying on isLive() because the time window is too short + // to retrieve wind information we need to extend the time window + if (startOfRace != null && race.getEndOfRace() == null && + MillisecondsTimePoint.now().after(startOfRace.minus(Duration.ONE_MINUTE.times(20)))) { + result = race; + // no break here as we want to have the last race that is deemed to be live + } } } } From 798bb77978a21d49d5f869efef8125d4cc36055b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 17:29:59 +0200 Subject: [PATCH 17/27] fix for bug 2988: NPE in LeaderboardDTOCalculationReuseCache --- .../caching/LeaderboardDTOCalculationReuseCache.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java index 07a1ffff640..bc113bca457 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java @@ -50,7 +50,6 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea */ final ConcurrentHashMap legTypeCache; - /** * the wind at competitor's position at timePoint; null values are represented by {@link #NULL_WIND}. */ @@ -60,9 +59,11 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea /* time point */ MillisecondsTimePoint.now(), /* windSpeedWithBearing */ new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); /** - * the leg's bearing at timePoint + * the leg's bearing at timePoint; null values are represented by {@link #NULL_BEARING}. */ final ConcurrentHashMap legBearingCache; + + private static final Bearing NULL_BEARING = new DegreeBearingImpl(0); public LeaderboardDTOCalculationReuseCache(TimePoint timePoint) { legTypeCache = new ConcurrentHashMap<>(); @@ -91,7 +92,9 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea result = legBearingCache.get(trackedLeg.getLeg()); if (result == null) { result = trackedLeg.getLegBearing(timePoint); - legBearingCache.put(trackedLeg.getLeg(), result); + legBearingCache.put(trackedLeg.getLeg(), result == null ? NULL_BEARING : result); + } else if (result == NULL_BEARING) { + result = null; } } else { result = trackedLeg.getLegBearing(timePoint); // different time point; don't cache From a78d7cd56a83e2b96a9ed037f5c42f09260ee0df Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 18:45:18 +0200 Subject: [PATCH 18/27] fixed isIndividualRecallDisplayed() for bug2977 --- .../IsIndividualRecallDisplayedAnalyzer.java | 38 -------------- .../state/impl/ReadonlyRaceStateImpl.java | 2 +- .../RacingProcedureFactory.java | 3 +- .../ReadonlyRacingProcedure.java | 4 +- .../basic/impl/BasicRacingProcedureImpl.java | 5 +- .../ess/impl/ESSRacingProcedureImpl.java | 5 +- .../impl/GateStartRacingProcedureImpl.java | 5 +- .../impl/BaseRacingProcedure.java | 49 ++++++++++--------- .../impl/RacingProcedureFactoryImpl.java | 5 +- .../impl/ReadonlyRacingProcedureFactory.java | 17 ++++--- .../impl/LeagueRacingProcedureImpl.java | 5 +- .../rrs26/impl/RRS26RacingProcedureImpl.java | 5 +- .../analyzing/ServerSideRaceLogResolver.java | 3 +- .../domain/tracking/impl/TrackedRaceImpl.java | 1 - 14 files changed, 61 insertions(+), 86 deletions(-) delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/IsIndividualRecallDisplayedAnalyzer.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/IsIndividualRecallDisplayedAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/IsIndividualRecallDisplayedAnalyzer.java deleted file mode 100644 index ef15f88cfd0..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/IsIndividualRecallDisplayedAnalyzer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race.analyzing.impl; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sse.common.TimePoint; - -public class IsIndividualRecallDisplayedAnalyzer extends RaceLogAnalyzer { - - private final IndividualRecallFinder displayedFinder; - private final IndividualRecallFinder removedFinder; - - public IsIndividualRecallDisplayedAnalyzer(RaceLog raceLog) { - this(raceLog, null); - } - - public IsIndividualRecallDisplayedAnalyzer(RaceLog raceLog, TimePoint at) { - this(raceLog, new IndividualRecallDisplayedFinder(raceLog, at), new IndividualRecallRemovedFinder(raceLog, at), at); - } - - public IsIndividualRecallDisplayedAnalyzer(RaceLog raceLog, IndividualRecallDisplayedFinder displayedFinder, - IndividualRecallRemovedFinder removedFinder, TimePoint at) { - super(raceLog); - this.displayedFinder = displayedFinder; - this.removedFinder = removedFinder; - } - - @Override - protected Boolean performAnalysis() { - TimePoint displayedAt = displayedFinder.analyze(); - TimePoint removedAt = removedFinder.analyze(); - if (displayedAt != null) { - if (removedAt == null || displayedAt.after(removedAt)) { - return true; - } - } - return false; - } - -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java index 4099e79d41d..349b0daa495 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/ReadonlyRaceStateImpl.java @@ -428,7 +428,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL removeChangedListener(racingProcedure); racingProcedure.detach(); } - racingProcedure = procedureFactory.createRacingProcedure(cachedRacingProcedureType, raceLog); + racingProcedure = procedureFactory.createRacingProcedure(cachedRacingProcedureType, raceLog, raceLogResolver); racingProcedure.setStateEventScheduler(scheduler); addChangedListener(racingProcedure); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/RacingProcedureFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/RacingProcedureFactory.java index afa15033192..3654dc22312 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/RacingProcedureFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/RacingProcedureFactory.java @@ -1,12 +1,13 @@ package com.sap.sailing.domain.abstractlog.race.state.racingprocedure; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.configuration.RegattaConfiguration; import com.sap.sailing.domain.common.racelog.RacingProcedureType; public interface RacingProcedureFactory { - ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog); + ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog, RaceLogResolver raceLogResolver); RegattaConfiguration getConfiguration(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ReadonlyRacingProcedure.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ReadonlyRacingProcedure.java index cc743dfc056..f50c3b936ca 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ReadonlyRacingProcedure.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ReadonlyRacingProcedure.java @@ -79,7 +79,9 @@ public interface ReadonlyRacingProcedure extends RaceStateEventProcessor, RaceSt TimePoint getIndividualRecallDisplayedTime(); /** - * Gets the time the individual recall flag was removed (or null). + * Gets the time the individual recall flag was or shall be removed (or null if it hasn't been set or no + * race start time is known). When the flag is currently set, the removal time can either be specified by an explicit + * race log event or is automatically triggered four minutes after the race start time. */ TimePoint getIndividualRecallRemovalTime(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java index 12c064844a6..909c4f138f7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java @@ -7,6 +7,7 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents; @@ -25,8 +26,8 @@ import com.sap.sse.common.TimePoint; public class BasicRacingProcedureImpl extends BaseRacingProcedure { public BasicRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, - RacingProcedureConfiguration configuration) { - super(raceLog, author, factory, configuration); + RacingProcedureConfiguration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, factory, configuration, raceLogResolver); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java index 6ffb0b7d881..08cff9f9fdd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents; @@ -37,8 +38,8 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa private final ESSConfiguration configuration; public ESSRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, ESSConfiguration configuration) { - super(raceLog, author, factory, configuration); + RaceLogEventFactory factory, ESSConfiguration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, factory, configuration, raceLogResolver); this.configuration = configuration; update(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java index 0165aa169cd..2bcafb0f08a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent.GateLineOpeningTimes; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.GateLineOpeningTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.PathfinderFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; @@ -43,8 +44,8 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements private String cachedPathfinder; public GateStartRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, - GateStartConfiguration configuration) { - super(raceLog, author, factory, configuration); + GateStartConfiguration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, factory, configuration, raceLogResolver); this.gateLineOpeningTimeAnalyzer = new GateLineOpeningTimeFinder(raceLog); this.pathfinderAnalyzer = new PathfinderFinder(raceLog); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java index 8abf94f3b3a..8b7101c1cbe 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java @@ -15,7 +15,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IndividualRecallDi import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IndividualRecallRemovedFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsFinishedAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsInFinishingPhaseAnalyzer; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsIndividualRecallDisplayedAnalyzer; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; @@ -30,6 +30,7 @@ import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; /** * Base class for all your {@link RacingProcedure}s. @@ -54,7 +55,6 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i private final RacingProcedureConfiguration configuration; private final RacingProcedureChangedListeners changedListeners; - private final IsIndividualRecallDisplayedAnalyzer isRecallDisplayedAnalyzer; private final IndividualRecallDisplayedFinder recallDisplayedFinder; private final IndividualRecallRemovedFinder recallRemovedFinder; private final FinishingTimeFinder finishingTimeFinder; @@ -64,28 +64,26 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i private boolean cachedIsIndividualRecallDisplayed; - /** * When calling me, call {@link BaseRacingProcedure#update()} afterwards! + * @param raceLogResolver TODO */ public BaseRacingProcedure(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, - RacingProcedureConfiguration configuration) { + RacingProcedureConfiguration configuration, RaceLogResolver raceLogResolver) { if (configuration == null) { throw new IllegalArgumentException("configuration must not be null"); } - this.raceLog = raceLog; this.author = author; this.factory = factory; this.configuration = configuration; this.changedListeners = createChangedListenerContainer(); - this.isRecallDisplayedAnalyzer = new IsIndividualRecallDisplayedAnalyzer(raceLog); this.recallDisplayedFinder = new IndividualRecallDisplayedFinder(raceLog); this.recallRemovedFinder = new IndividualRecallRemovedFinder(raceLog); this.finishingTimeFinder = new FinishingTimeFinder(raceLog); this.finishedTimeFinder = new FinishedTimeFinder(raceLog); - this.startTimeFinder = new StartTimeFinder(raceLog); + this.startTimeFinder = new StartTimeFinder(raceLogResolver, raceLog); this.raceLogListener = new RaceLogChangedVisitor(this); this.raceLog.addListener(raceLogListener); @@ -133,7 +131,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i break; case RUNNING: if (isIndividualRecallDisplayed()) { - rescheduleIndividualRecallTimeout(startTimeFinder.analyze()); + rescheduleIndividualRecallTimeout(); } break; default: @@ -141,6 +139,10 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i } } + private TimePoint getStartTime() { + return startTimeFinder.analyze().getStartTime(); + } + @Override public boolean isIndividualRecallDisplayed() { return cachedIsIndividualRecallDisplayed; @@ -148,10 +150,10 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i @Override public boolean isIndividualRecallDisplayed(TimePoint at) { - if (hasIndividualRecall()) { - return new IsIndividualRecallDisplayedAnalyzer(getRaceLog(), at).analyze(); - } - return false; + final TimePoint individualRecallDisplayedTime = getIndividualRecallDisplayedTime(); + final TimePoint individualRecallRemovalTime = getIndividualRecallRemovalTime(); + return (hasIndividualRecall() && individualRecallDisplayedTime != null && !individualRecallDisplayedTime.after(at) && + individualRecallRemovalTime != null && !individualRecallRemovalTime.after(at)); } @Override @@ -165,7 +167,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i @Override public TimePoint getIndividualRecallRemovalTime() { final TimePoint result; - final TimePoint raceStartTime = startTimeFinder.analyze(); + final TimePoint raceStartTime = getStartTime(); final TimePoint removedEvent; if (hasIndividualRecall() && (removedEvent = recallRemovedFinder.analyze()) != null && (raceStartTime == null || removedEvent.after(raceStartTime))) { result = removedEvent; @@ -212,18 +214,21 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i } protected void update() { - boolean isRecallDisplayed = isRecallDisplayedAnalyzer.analyze(); - + // TODO an X-ray up event with a time point in the future will not be recognized here because at the current time the flag is not displayed and no other race log event will trigger the update; we'd need to schedule another state event; as long as clocks are set correctly, additional transmission time will make this unlikely + boolean isRecallDisplayed = isIndividualRecallDisplayed(MillisecondsTimePoint.now()); if (cachedIsIndividualRecallDisplayed != isRecallDisplayed) { cachedIsIndividualRecallDisplayed = isRecallDisplayed; - if (cachedIsIndividualRecallDisplayed) { - changedListeners.onIndividualRecallDisplayed(this); - rescheduleIndividualRecallTimeout(startTimeFinder.analyze()); - } else { + if (!cachedIsIndividualRecallDisplayed) { + // individual recall was removed; no need to schedule an event for removal changedListeners.onIndividualRecallRemoved(this); unscheduleStateEvent(RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT); } - } + } + // (re-)schedule the individual recall removal in any case; the removal time may have changed + if (cachedIsIndividualRecallDisplayed) { + changedListeners.onIndividualRecallDisplayed(this); + rescheduleIndividualRecallTimeout(); + } // always call listeners for changed flag, as this does not only affect recall, but also // changes start procedure, for which some text elements need to be updated @@ -231,9 +236,9 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i changedListeners.onActiveFlagsChanged(this); } - private void rescheduleIndividualRecallTimeout(TimePoint raceStartTime) { + private void rescheduleIndividualRecallTimeout() { unscheduleStateEvent(RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT); - scheduleStateEvents(new RaceStateEventImpl(raceStartTime.plus(individualRecallRemovalTimeout), RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT)); + scheduleStateEvents(new RaceStateEventImpl(getIndividualRecallRemovalTime(), RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT)); } protected void scheduleStateEvents(RaceStateEvent stateEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java index 7f34843b014..06617dd1902 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureFactory; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure; import com.sap.sailing.domain.base.configuration.ConfigurationLoader; @@ -22,7 +23,7 @@ public class RacingProcedureFactoryImpl extends ReadonlyRacingProcedureFactory i } @Override - public ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog) { - return createProcedure(type, raceLog, author, factory); + public ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog, RaceLogResolver raceLogResolver) { + return createProcedure(type, raceLog, author, factory, raceLogResolver); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java index 4062f7a9893..971ac0caaa2 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java @@ -4,6 +4,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.NoAddingRaceLogWrapper; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureFactory; @@ -37,32 +38,32 @@ public class ReadonlyRacingProcedureFactory implements RacingProcedureFactory { } protected ReadonlyRacingProcedure createProcedure(RacingProcedureType type, RaceLog raceLog, - AbstractLogEventAuthor author, RaceLogEventFactory factory) { + AbstractLogEventAuthor author, RaceLogEventFactory factory, RaceLogResolver raceLogResolver) { RegattaConfiguration loadedConfiguration = configuration.load(); switch (type) { case ESS: - return new ESSRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getESSConfiguration()); + return new ESSRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getESSConfiguration(), raceLogResolver); case GateStart: return new GateStartRacingProcedureImpl(raceLog, author, factory, - loadedConfiguration.getGateStartConfiguration()); + loadedConfiguration.getGateStartConfiguration(), raceLogResolver); case RRS26: - return new RRS26RacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getRRS26Configuration()); + return new RRS26RacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getRRS26Configuration(), raceLogResolver); case BASIC: - return new BasicRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getBasicConfiguration()); + return new BasicRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getBasicConfiguration(), raceLogResolver); case LEAGUE: - return new LeagueRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getLeagueConfiguration()); + return new LeagueRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getLeagueConfiguration(), raceLogResolver); default: throw new UnsupportedOperationException("Unknown racing procedure " + type.toString()); } } @Override - public ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog) { + public ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog, RaceLogResolver raceLogResolver) { // Just a mock author since we will never add anything to the racelog AbstractLogEventAuthor author = new LogEventAuthorImpl("Illegal Author", 128); // Wrap the racelog to disable adding... RaceLog wrappedRaceLog = new NoAddingRaceLogWrapper(raceLog); - return createProcedure(type, wrappedRaceLog, author, RaceLogEventFactory.INSTANCE); + return createProcedure(type, wrappedRaceLog, author, RaceLogEventFactory.INSTANCE, raceLogResolver); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java index 2ba9189ad0a..f3e5f2508df 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java @@ -7,6 +7,7 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents; @@ -33,8 +34,8 @@ public class LeagueRacingProcedureImpl extends BaseRacingProcedure implements Le private final static Flags startmodeFlag = Flags.PAPA; public LeagueRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, LeagueConfiguration configuration) { - super(raceLog, author, factory, configuration); + RaceLogEventFactory factory, LeagueConfiguration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, factory, configuration, raceLogResolver); update(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java index 0ffd4522e5a..a89cc6b95d5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RRS26StartModeFlagFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RacingProcedureTypeAnalyzer; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; @@ -39,8 +40,8 @@ public class RRS26RacingProcedureImpl extends BaseRacingProcedure implements RRS private boolean startmodeFlagHasBeenSet; public RRS26RacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, RRS26Configuration configuration) { - super(raceLog, author, factory, configuration); + RaceLogEventFactory factory, RRS26Configuration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, factory, configuration, raceLogResolver); RacingProcedureTypeAnalyzer procedureAnalyzer = new RacingProcedureTypeAnalyzer(raceLog); if (configuration.getStartModeFlags() != null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java index c5e449a4da6..149d1bd388b 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java @@ -6,8 +6,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.regattalike.HasRegattaLike; public class ServerSideRaceLogResolver implements RaceLogResolver { - - private HasRegattaLike regattaLike; + private final HasRegattaLike regattaLike; public ServerSideRaceLogResolver(HasRegattaLike regattaLike) { this.regattaLike = regattaLike; 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 24c9af3ee5c..a4a3e4e7da6 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 @@ -730,7 +730,6 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl public TimePoint getStartOfRace() { if (startTime == null) { for (RaceLog raceLog : attachedRaceLogs.values()) { - //FIXME: how to get the HasRegattaLike? startTime = new StartTimeFinder(new ServerSideRaceLogResolver(null), raceLog).analyze().getStartTime(); if (startTime != null) { From 7cd0d554544e8f21706a4ae31b4d1a5ed432f51b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 19:04:26 +0200 Subject: [PATCH 19/27] solution proposal for bug2989: use getStartOfRace() instead of getStartTimeReceived() and default to "now" if no start time is known yet --- .../gwt/server/RibDashboardServiceImpl.java | 16 ++++++++-------- .../startanalysis/StartAnalysisDTOFactory.java | 11 ++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java index 1e92e506221..cc49eb907e9 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java @@ -245,14 +245,14 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib String leaderboardName) { List startAnalysisDTOs = new ArrayList(); if (leaderboardName != null) { - Competitor competitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorByIdAsString( - competitorIdAsString); + Competitor competitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString); List trackedRacesForLeaderBoardName = getTrackedRacesFromLeaderboard(leaderboardName); for (TrackedRace trackedRace : trackedRacesForLeaderBoardName) { StartAnalysisDTO startAnalysisDTO = startAnalysisCreationController .checkStartAnalysisForCompetitorInTrackedRace(competitor, trackedRace); - if (startAnalysisDTO != null) + if (startAnalysisDTO != null) { startAnalysisDTOs.add(startAnalysisDTO); + } } } return startAnalysisDTOs; @@ -261,11 +261,11 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib @Override public List getCompetitorsInLeaderboard(String leaderboardName) { logger.log(Level.INFO, "getCompetitorsInLeaderboard(...) Request."); - if(leaderboardName != null){ - Leaderboard lb = getRacingEventService().getLeaderboardByName(leaderboardName); - return baseDomainFactory.getCompetitorDTOList(lb.getCompetitorsFromBestToWorst(new MillisecondsTimePoint( - new Date()))); - }else{ + if (leaderboardName != null) { + Leaderboard lb = getRacingEventService().getLeaderboardByName(leaderboardName); + return baseDomainFactory.getCompetitorDTOList(lb.getCompetitorsFromBestToWorst(new MillisecondsTimePoint( + new Date()))); + } else { return null; } } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java index 8a395078acf..94968fade88 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java @@ -53,8 +53,7 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida boolean isCompetitorOneOfFirstThree = false; for (int i = 0; i < MINIMUM_NUMBER_COMPETITORS_FOR_STARTANALYSIS; i++) { - competitors.add(createStartAnalysisCompetitorDTO(trackedRace, i + 1, markPassingsInOrder.get(i) - .getCompetitor())); + competitors.add(createStartAnalysisCompetitorDTO(trackedRace, i + 1, markPassingsInOrder.get(i).getCompetitor())); if (markPassingsInOrder.get(i).getCompetitor().equals(competitor)) { isCompetitorOneOfFirstThree = true; } @@ -75,9 +74,9 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida startAnalysisDTO.racingProcedureType = RacingProcedureType.GateStart; long timePointOfGolfDownTime = trackedRace.getGateStartGolfDownTime(); startAnalysisDTO.timeOfStartInMilliSeconds = trackedRace.getStartOfRace().asMillis(); - if(timePointOfGolfDownTime < trackedRace.getStartOfRace().asMillis() || timePointOfGolfDownTime == 0){ + if (timePointOfGolfDownTime < trackedRace.getStartOfRace().asMillis() || timePointOfGolfDownTime == 0) { startAnalysisDTO.tailLenghtInMilliseconds = DEFAULT_GATE_START_INTERVALL_IN_MILLISECONDS; - }else{ + } else { startAnalysisDTO.tailLenghtInMilliseconds = timePointOfGolfDownTime-trackedRace.getStartOfRace().asMillis(); } } else { @@ -142,7 +141,9 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida private WindAndAdvantagesInfoForStartLineDTO createStartAnalysisWindAndLineData(TrackedRace trackedRace) { WindAndAdvantagesInfoForStartLineDTO startAnalysisWindLineInfoDTO = new WindAndAdvantagesInfoForStartLineDTO(); - LineDetails startline = trackedRace.getStartLine(trackedRace.getStartTimeReceived()); + final TimePoint startOfRace = trackedRace.getStartOfRace(); + final TimePoint timePoint = startOfRace == null ? MillisecondsTimePoint.now() : startOfRace; + LineDetails startline = trackedRace.getStartLine(timePoint); StartLineAdvantageDTO startLineAdvantageDTO = new StartLineAdvantageDTO(); startLineAdvantageDTO.startLineAdvatageType = getStartlineAdvantageType(trackedRace, new MillisecondsTimePoint( new Date())); From d8521346424d045b67c606cf91bafd7247ce0468 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 19:36:14 +0200 Subject: [PATCH 20/27] require X-ray to be up in order to automatically infer its down time based on the start time --- .../state/racingprocedure/impl/BaseRacingProcedure.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java index 8b7101c1cbe..fc04a76fedf 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java @@ -171,10 +171,13 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i final TimePoint removedEvent; if (hasIndividualRecall() && (removedEvent = recallRemovedFinder.analyze()) != null && (raceStartTime == null || removedEvent.after(raceStartTime))) { result = removedEvent; - } else if (raceStartTime != null) { - result = raceStartTime.plus(individualRecallRemovalTimeout); } else { - result = null; + final TimePoint individualRecallDisplayedTime = getIndividualRecallDisplayedTime(); + if (individualRecallDisplayedTime != null && raceStartTime != null) { + result = raceStartTime.plus(individualRecallRemovalTimeout); + } else { + result = null; + } } return result; } From d2113723a900ef4564da59d1aba19bfe015c16a7 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 21:07:46 +0200 Subject: [PATCH 21/27] RacingEventServiceImpl now implements RaceLogResolver --- .../sailing/domain/base/impl/RegattaImpl.java | 21 ++++++++- .../impl/FlexibleLeaderboardImpl.java | 9 +++- .../regattalike/BaseRegattaLikeImpl.java | 2 +- .../domain/regattalike/IsRegattaLike.java | 3 ++ .../server/impl/RacingEventServiceImpl.java | 46 ++++++++++++++++++- 5 files changed, 77 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index e8c17204a89..54f31616d04 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -196,7 +196,21 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene this.scoringScheme = scoringScheme; this.defaultCourseArea = courseArea; this.configuration = null; - this.regattaLikeHelper = new BaseRegattaLikeImpl(new RegattaAsRegattaLikeIdentifier(this), regattaLogStore); + this.regattaLikeHelper = new BaseRegattaLikeImpl(new RegattaAsRegattaLikeIdentifier(this), regattaLogStore) { + private static final long serialVersionUID = 8546222568682770206L; + + @Override + public RaceColumn getRaceColumnByName(String raceColumnName) { + for (final Series series : getSeries()) { + for (final RaceColumn raceColumn : series.getRaceColumns()) { + if (raceColumn.getName().equals(raceColumnName)) { + return raceColumn; + } + } + } + return null; + } + }; this.raceExecutionOrderCache = new RaceExecutionOrderCache(); } @@ -677,4 +691,9 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return result; } } + + @Override + public RaceColumn getRaceColumnByName(String raceColumnName) { + return regattaLikeHelper.getRaceColumnByName(raceColumnName); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index 3ebbe1e7727..fcf0fdabdca 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -84,7 +84,14 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements this.races = new ArrayList<>(); this.raceLogStore = raceLogStore; this.courseArea = courseArea; - this.regattaLikeHelper = new BaseRegattaLikeImpl(new FlexibleLeaderboardAsRegattaLikeIdentifier(this), regattaLogStore); + this.regattaLikeHelper = new BaseRegattaLikeImpl(new FlexibleLeaderboardAsRegattaLikeIdentifier(this), regattaLogStore) { + private static final long serialVersionUID = 4082392360832548953L; + + @Override + public RaceColumn getRaceColumnByName(String raceColumnName) { + return getRaceColumnByName(raceColumnName); + } + }; this.raceExecutionOrderProvider = new RaceExecutionOrderCache(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java index 7dbef9f0c15..e840bc76bfc 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java @@ -14,7 +14,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.regattalog.RegattaLogStore; import com.sap.sse.common.Duration; -public class BaseRegattaLikeImpl implements IsRegattaLike { +public abstract class BaseRegattaLikeImpl implements IsRegattaLike { private static final long serialVersionUID = -5629172342837950344L; private final RegattaLog regattaLog; private final RegattaLikeIdentifier identifier; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java index 32da1fa0c62..b7643151fd6 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java @@ -4,6 +4,7 @@ import java.io.Serializable; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; @@ -25,6 +26,8 @@ public interface IsRegattaLike extends Serializable { */ RegattaLog getRegattaLog(); + RaceColumn getRaceColumnByName(String raceColumnName); + RegattaLikeIdentifier getRegattaLikeIdentifier(); void addListener(RegattaLikeListener listener); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 8564f2e93f1..07e2281ff53 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -51,6 +51,8 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceState; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; @@ -226,7 +228,7 @@ import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; import com.sap.sse.util.ClearStateTestSupport; public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, - LeaderboardRegistry, Replicator, EventFetcher { + LeaderboardRegistry, Replicator, EventFetcher, RaceLogResolver { private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); /** @@ -3217,4 +3219,46 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes rankingInfo.getCompetitorRankingInfo().apply(c1).getWindwardDistanceSailed())); return result; } + + /** + * A {@link SimpleRaceLogIdentifier} in particular has a {@link SimpleRaceLogIdentifier#getRegattaLikeParentName()} + * which identifies either a regatta by name or a flexible leaderboard by name. Here is why this can luckily be + * resolved unanimously: A regatta leaderboard always uses as its name the regatta name (see + * {@link RegattaImpl#getName()}). Trying to {@link RegattaLeaderboardImpl#setName(String) set} the regatta leaderboard's + * name can only update its {@link Leaderboard#getDisplayName() display name}. Therefore, regatta leaderboards are always + * keyed in {@link #leaderboardsByName} by their regatta's name. Thus, no flexible leaderboard can have a regatta's name + * as its name, and therefore leaderboard names and regatta names are unitedly unique. + */ + @Override + public RaceLog resolve(SimpleRaceLogIdentifier identifier) { + final RaceLog result; + final IsRegattaLike regattaLike; + final Regatta regatta = regattasByName.get(identifier.getRegattaLikeParentName()); + if (regatta != null) { + regattaLike = regatta; + } else { + final Leaderboard leaderboard = leaderboardsByName.get(identifier.getRegattaLikeParentName()); + if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { + regattaLike = (FlexibleLeaderboard) leaderboard; + } else { + regattaLike = null; + } + } + if (regattaLike != null) { + final RaceColumn raceColumn = regattaLike.getRaceColumnByName(identifier.getRaceColumnName()); + if (raceColumn != null) { + final Fleet fleet = raceColumn.getFleetByName(identifier.getFleetName()); + if (fleet != null) { + result = raceColumn.getRaceLog(fleet); + } else { + result = null; + } + } else { + result = null; + } + } else { + result = null; + } + return result; + } } From 42dedcecfd9ca5c50036a03cdec7e7dfbadb1e04 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 20 Jun 2015 23:57:50 +0200 Subject: [PATCH 22/27] bug 2467 #19: passing through RacingEventService as RaceLogResolver; added as transient field to TrackedRace, restored after initial load in RacingEventServiceImpl --- .../test/impl/TrackedRaceLoadsFixesTest.java | 8 ++- .../impl/RaceLogConnectivityParams.java | 9 +-- .../impl/RaceLogRaceTracker.java | 15 +++-- .../META-INF/MANIFEST.MF | 3 +- .../SwissTimingFactory.java | 5 +- .../impl/SwissTimingFactoryImpl.java | 26 ++++---- .../impl/SwissTimingRaceTrackerImpl.java | 20 ++++-- ...sTimingTrackingConnectivityParameters.java | 9 +-- .../META-INF/MANIFEST.MF | 3 +- .../SwissTimingRaceConfigurationTest.java | 11 ++-- .../SwissTimingReplayAdapterServiceTest.java | 8 ++- .../META-INF/MANIFEST.MF | 3 +- .../SwissTimingReplayServiceFactory.java | 3 +- .../SwissTimingReplayServiceFactoryImpl.java | 5 +- .../impl/SwissTimingReplayServiceImpl.java | 11 +++- .../SwissTimingReplayToDomainAdapter.java | 8 ++- .../WaypointPositionAndDistanceCacheTest.java | 3 +- ...mpleTimeOnTimeRankingWithOneUpwindLeg.java | 4 +- .../sap/sailing/domain/test/CourseTest.java | 8 ++- ...pdateDuringNonAtomicSerializationTest.java | 4 +- .../sailing/domain/test/CourseUpdateTest.java | 5 +- .../test/LeaderboardCourseChangeTest.java | 4 +- .../test/MultipleClassesInRegattaTest.java | 11 ++-- .../domain/test/OnlineTracTracBasedTest.java | 6 +- .../sailing/domain/test/ReachingLegTest.java | 4 +- .../test/ReceiveMarkPassingDataTest.java | 8 ++- .../domain/test/ReceiveTrackingDataTest.java | 10 +-- ...tarbordSideOfStartLineRecognitionTest.java | 4 +- .../sailing/domain/test/TrackBasedTest.java | 5 +- ...nicodeCharactersInCompetitorNamesTest.java | 4 +- .../domain/test/UpdateMarkPassingTest.java | 3 +- .../com/sap/sailing/domain/test/WindTest.java | 5 +- .../AbstractMockedRaceMarkPassingTest.java | 7 +- .../domain/test/mock/MockedTrackedRace.java | 9 ++- .../META-INF/MANIFEST.MF | 3 +- .../domain/tractracadapter/DomainFactory.java | 23 ++++--- .../impl/DomainFactoryImpl.java | 64 ++++++++++--------- .../impl/RaceCourseReceiver.java | 10 ++- ...aceTrackingConnectivityParametersImpl.java | 9 +-- .../impl/TracTracRaceTrackerImpl.java | 22 ++++--- .../META-INF/MANIFEST.MF | 1 - .../analyzing/ServerSideRaceLogResolver.java | 25 -------- .../RaceTrackingConnectivityParameters.java | 7 +- .../sailing/domain/tracking/TrackedRace.java | 6 ++ .../domain/tracking/TrackedRegatta.java | 5 +- .../tracking/impl/DynamicTrackedRaceImpl.java | 9 +-- .../impl/DynamicTrackedRaceLogListener.java | 6 +- .../impl/DynamicTrackedRegattaImpl.java | 5 +- .../domain/tracking/impl/TrackedRaceImpl.java | 39 ++++++++--- .../tracking/impl/TrackedRegattaImpl.java | 5 +- .../gwt/ui/test/MockedTrackedRace.java | 3 +- .../gwt/ui/server/SailingServiceImpl.java | 16 ++--- .../ui/shared/dispatch/event/RaceContext.java | 7 +- .../dispatch/event/RacesActionUtil.java | 4 +- ...estStoringAndRetrievingWindTracksTest.java | 7 +- .../impl/EventRaceStatesJsonGetServlet.java | 2 +- .../jaxrs/api/EventRaceStatesSerializer.java | 34 +++++----- .../gateway/jaxrs/api/EventsResource.java | 2 +- .../jaxrs/api/RaceStateSerializer.java | 20 ++---- .../server/test/RaceTrackerStartStopTest.java | 8 ++- .../sailing/server/RacingEventService.java | 3 +- .../server/impl/RacingEventServiceImpl.java | 48 +++++++------- 62 files changed, 376 insertions(+), 268 deletions(-) delete mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java index 6194deacd23..75c6b0978f8 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceLoadsFixesTest.java @@ -4,6 +4,7 @@ import static junit.framework.Assert.assertEquals; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.mockito.Mockito.mock; import java.util.Arrays; import java.util.Collections; @@ -11,6 +12,7 @@ import java.util.Collections; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -80,7 +82,8 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, - Collections. emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + Collections. emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false, + OneDesignRankingMetric::new, mock(RaceLogResolver.class)); trackedRace.attachRaceLog(raceLog); trackedRace.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog); @@ -125,7 +128,8 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, - Collections. emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + Collections. emptyList(), EmptyWindStore.INSTANCE, store, 0, 0, 0, /*useMarkPassingCalculator*/ false, + OneDesignRankingMetric::new, mock(RaceLogResolver.class)); trackedRace.addListener(new AbstractRaceChangeListener() { @Override diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogConnectivityParams.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogConnectivityParams.java index 779a177f1d4..1c5c8928bab 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogConnectivityParams.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogConnectivityParams.java @@ -6,6 +6,7 @@ import java.util.UUID; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceInformationFinder; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; import com.sap.sailing.domain.base.BoatClass; @@ -51,13 +52,13 @@ public class RaceLogConnectivityParams implements RaceTrackingConnectivityParame @Override public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, - GPSFixStore gpsFixStore) { - return createRaceTracker(regatta, trackedRegattaRegistry, windStore, gpsFixStore); + GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) { + return createRaceTracker(regatta, trackedRegattaRegistry, windStore, gpsFixStore, raceLogResolver); } @Override public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, - WindStore windStore, GPSFixStore gpsFixStore) { + WindStore windStore, GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) { if (regatta == null) { BoatClass boatClass = new RaceInformationFinder(getRaceLog()).analyze().getBoatClass(); regatta = service.getOrCreateDefaultRegatta( @@ -68,7 +69,7 @@ public class RaceLogConnectivityParams implements RaceTrackingConnectivityParame throw new RaceNotCreatedException("No regatta for race-log tracked race"); } DynamicTrackedRegatta trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(regatta); - return new RaceLogRaceTracker(trackedRegatta, this, windStore, gpsFixStore); + return new RaceLogRaceTracker(trackedRegatta, this, windStore, gpsFixStore, raceLogResolver); } @Override 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 e4a91476b7f..55ed7d8088d 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 @@ -20,6 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; 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.RaceLogDenoteForTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; @@ -98,24 +99,26 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { private final WindStore windStore; private final GPSFixStore gpsFixStore; private final DynamicTrackedRegatta regatta; + private final RaceLogResolver raceLogResolver; private final Map, Object> visitors = new HashMap, Object>(); - private ConcurrentHashMap>> competitorMappings = new ConcurrentHashMap<>(); - private ConcurrentHashMap>> markMappings = new ConcurrentHashMap<>(); + private final ConcurrentHashMap>> competitorMappings = new ConcurrentHashMap<>(); + private final ConcurrentHashMap>> markMappings = new ConcurrentHashMap<>(); - private Map>> markMappingsByDevices = new HashMap<>(); - private Map>> competitorMappingsByDevices = new HashMap<>(); + private final Map>> markMappingsByDevices = new HashMap<>(); + private final Map>> competitorMappingsByDevices = new HashMap<>(); private DynamicTrackedRace trackedRace; private static final Logger logger = Logger.getLogger(RaceLogRaceTracker.class.getName()); public RaceLogRaceTracker(DynamicTrackedRegatta regatta, RaceLogConnectivityParams params, WindStore windStore, - GPSFixStore gpsFixStore) { + GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) { this.params = params; this.windStore = windStore; this.gpsFixStore = gpsFixStore; this.regatta = regatta; + this.raceLogResolver = raceLogResolver; // add log listeners for (AbstractLog log : params.getLogHierarchy()) { @@ -445,7 +448,7 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener { trackedRace = regatta.createTrackedRace(raceDef, sidelines, windStore, gpsFixStore, params.getDelayToLiveInMillis(), WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, - boatClass.getApproximateManeuverDurationInMilliseconds(), null, /*useMarkPassingCalculator*/ true); + boatClass.getApproximateManeuverDurationInMilliseconds(), null, /*useMarkPassingCalculator*/ true, raceLogResolver); trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 0)); 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 8f3cd37b203..ce94c7a2bf0 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingadapter/META-INF/MANIFEST.MF @@ -13,7 +13,8 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.xrr.resultimport, com.sap.sse.common, com.sap.sse, - com.sap.sailing.xrr.schema + com.sap.sailing.xrr.schema, + com.sap.sailing.domain.shared.android Export-Package: com.sap.sailing.domain.swisstimingadapter, com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test" Import-Package: com.sap.sailing.xrr.schema, diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java index ec4dfc7bb83..5c1740c625e 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/SwissTimingFactory.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.UnknownHostException; import java.text.ParseException; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -54,13 +55,13 @@ public interface SwissTimingFactory { BoatClass boatClass, String hostname, int port, StartList startList, long delayToLiveInMillis, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, boolean useInternalMarkPassingAlgorithm, DomainFactory domainFactory, - TrackedRegattaRegistry trackedRegattaRegistry) throws InterruptedException, UnknownHostException, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws InterruptedException, UnknownHostException, IOException, ParseException; RaceTracker createRaceTracker(Regatta regatta, String raceID, String raceName, String raceDescription, BoatClass boatClass, String hostname, int port, StartList startList, long delayToLiveInMillis, WindStore windStore, GPSFixStore gpsFixStore, boolean useInternalMarkPassingAlgorithm, - DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) throws UnknownHostException, + DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws UnknownHostException, InterruptedException, IOException, ParseException; Race createRace(String raceId, String raceName, String description, BoatClass boatClass); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingFactoryImpl.java index 3e54a269946..5782c0b7b11 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingFactoryImpl.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -89,23 +90,24 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory { @Override public SwissTimingRaceTracker createRaceTracker(String raceID, String raceName, String raceDescription, - BoatClass boatClass, String hostname, int port, - StartList startList, long delayToLiveInMillis, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, - WindStore windStore, GPSFixStore gpsFixStore, boolean useInternalMarkPassingAlgorithm, - DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) throws InterruptedException, - UnknownHostException, IOException, ParseException { + BoatClass boatClass, String hostname, int port, StartList startList, long delayToLiveInMillis, + RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, + boolean useInternalMarkPassingAlgorithm, DomainFactory domainFactory, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) + throws InterruptedException, UnknownHostException, IOException, ParseException { return new SwissTimingRaceTrackerImpl(raceID, raceName, raceDescription, boatClass, hostname, port, startList, raceLogStore, regattaLogStore, windStore, gpsFixStore, domainFactory, this, - trackedRegattaRegistry, delayToLiveInMillis, useInternalMarkPassingAlgorithm); + trackedRegattaRegistry, raceLogResolver, delayToLiveInMillis, useInternalMarkPassingAlgorithm); } @Override - public RaceTracker createRaceTracker(Regatta regatta, String raceID, String raceName, String raceDescription, BoatClass boatClass, String hostname, - int port, StartList startList, long delayToLiveInMillis, WindStore windStore, GPSFixStore gpsFixStore, boolean useInternalMarkPassingAlgorithm, - DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry) throws UnknownHostException, - InterruptedException, IOException, ParseException { - return new SwissTimingRaceTrackerImpl(regatta, raceID, raceName, raceDescription, boatClass, hostname, port, startList, windStore, gpsFixStore, domainFactory, - this, trackedRegattaRegistry, delayToLiveInMillis, useInternalMarkPassingAlgorithm); + public RaceTracker createRaceTracker(Regatta regatta, String raceID, String raceName, String raceDescription, + BoatClass boatClass, String hostname, int port, StartList startList, long delayToLiveInMillis, + WindStore windStore, GPSFixStore gpsFixStore, boolean useInternalMarkPassingAlgorithm, + DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) + throws UnknownHostException, InterruptedException, IOException, ParseException { + return new SwissTimingRaceTrackerImpl(regatta, raceID, raceName, raceDescription, boatClass, hostname, port, + startList, windStore, gpsFixStore, domainFactory, this, trackedRegattaRegistry, raceLogResolver, delayToLiveInMillis, useInternalMarkPassingAlgorithm); } @Override diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java index 33a1a85c5f1..d450b1651f8 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java @@ -15,6 +15,7 @@ import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; @@ -105,23 +106,28 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen * tracker by calling {@link #receivedTimingData(String, String, List)}. */ private final TMDMessageQueue tmdMessageQueue; + + private final RaceLogResolver raceLogResolver; protected SwissTimingRaceTrackerImpl(String raceID, String raceName, String raceDescription, BoatClass boatClass, String hostname, int port, StartList startList, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, DomainFactory domainFactory, SwissTimingFactory factory, - TrackedRegattaRegistry trackedRegattaRegistry, long delayToLiveInMillis, boolean useInternalMarkPassingAlgorithm) throws InterruptedException, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, long delayToLiveInMillis, boolean useInternalMarkPassingAlgorithm) throws InterruptedException, UnknownHostException, IOException, ParseException { this(domainFactory.getOrCreateDefaultRegatta(raceLogStore, regattaLogStore, raceID, boatClass, trackedRegattaRegistry), raceID, raceName, raceDescription, boatClass, hostname, port, startList, windStore, gpsFixStore, domainFactory, factory, trackedRegattaRegistry, - delayToLiveInMillis, useInternalMarkPassingAlgorithm); + raceLogResolver, delayToLiveInMillis, useInternalMarkPassingAlgorithm); } - protected SwissTimingRaceTrackerImpl(Regatta regatta, String raceID, String raceName, String raceDescription, BoatClass boatClass, String hostname, int port, StartList startList, - WindStore windStore, GPSFixStore gpsFixStore, DomainFactory domainFactory, SwissTimingFactory factory, - TrackedRegattaRegistry trackedRegattaRegistry, long delayToLiveInMillis, boolean useInternalMarkPassingAlgorithm) throws InterruptedException, - UnknownHostException, IOException, ParseException { + protected SwissTimingRaceTrackerImpl(Regatta regatta, String raceID, String raceName, String raceDescription, + BoatClass boatClass, String hostname, int port, StartList startList, WindStore windStore, + GPSFixStore gpsFixStore, DomainFactory domainFactory, SwissTimingFactory factory, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, + long delayToLiveInMillis, boolean useInternalMarkPassingAlgorithm) throws InterruptedException, UnknownHostException, IOException, + ParseException { super(); + this.raceLogResolver = raceLogResolver; this.tmdMessageQueue = new TMDMessageQueue(this); this.regatta = regatta; this.connector = factory.getOrCreateSailMasterConnector(hostname, port, raceID, raceName, raceDescription, boatClass); @@ -475,7 +481,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen // we already know our single RaceDefinition assert SwissTimingRaceTrackerImpl.this.race == race; } - }, useInternalMarkPassingAlgorithm); + }, useInternalMarkPassingAlgorithm, raceLogResolver); logger.info("Created SwissTiming RaceDefinition and TrackedRace for "+race.getName()); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingTrackingConnectivityParameters.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingTrackingConnectivityParameters.java index 7045b444af6..1a558463001 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingTrackingConnectivityParameters.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingTrackingConnectivityParameters.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.swisstimingadapter.impl; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -51,18 +52,18 @@ public class SwissTimingTrackingConnectivityParameters implements RaceTrackingCo @Override public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, - GPSFixStore gpsFixStore) throws Exception { + GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) throws Exception { return swissTimingFactory.createRaceTracker(raceID, raceName, raceDescription, boatClass, hostname, port, startList, delayToLiveInMillis, raceLogStore, regattaLogStore, windStore, gpsFixStore, useInternalMarkPassingAlgorithm, - domainFactory, trackedRegattaRegistry); + domainFactory, trackedRegattaRegistry, raceLogResolver); } @Override public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, - WindStore windStore, GPSFixStore gpsFixStore) throws Exception { + WindStore windStore, GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) throws Exception { return swissTimingFactory.createRaceTracker(regatta, raceID, raceName, raceDescription, boatClass, hostname, port, startList, delayToLiveInMillis, windStore, gpsFixStore, useInternalMarkPassingAlgorithm, - domainFactory, trackedRegattaRegistry); + domainFactory, trackedRegattaRegistry, raceLogResolver); } @Override diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/META-INF/MANIFEST.MF index b006bd01e0b..ead28dc4b0d 100644 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/META-INF/MANIFEST.MF @@ -10,4 +10,5 @@ Import-Package: org.json.simple, org.json.simple.parser Require-Bundle: com.sap.sailing.domain.test, org.junit4;bundle-version="4.8.2", - com.sap.sse.common + com.sap.sse.common, + org.mockito.mockito-core;bundle-version="1.10.14" diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingRaceConfigurationTest.java b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingRaceConfigurationTest.java index 2f261e29719..0de4deffcde 100644 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingRaceConfigurationTest.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingRaceConfigurationTest.java @@ -17,6 +17,9 @@ import java.util.Map; import org.junit.Ignore; import org.junit.Test; +import static org.mockito.Mockito.mock; + +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.swisstimingadapter.DomainFactory; import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayRace; import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingRaceConfig; @@ -30,13 +33,13 @@ public class SwissTimingRaceConfigurationTest { @Test public void testLoadConfigurations() throws IOException, ParseException, org.json.simple.parser.ParseException { InputStream inputStream = getClass().getResourceAsStream(JSON_URL); - List races = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).parseJSONObject(inputStream , JSON_URL); + List races = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE, mock(RaceLogResolver.class)).parseJSONObject(inputStream , JSON_URL); Map configsById = new HashMap(); for (SwissTimingReplayRace race : races) { URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, race.getRaceId())); URLConnection connection = configFileURL.openConnection(); InputStream configDataStream = connection.getInputStream(); - SwissTimingRaceConfig raceConfig = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream); + SwissTimingRaceConfig raceConfig = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE, mock(RaceLogResolver.class)).loadRaceConfig(configDataStream); configsById.put(race.getRaceId(), raceConfig); } } @@ -46,7 +49,7 @@ public class SwissTimingRaceConfigurationTest { URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, "446483")); URLConnection connection = configFileURL.openConnection(); InputStream configDataStream = connection.getInputStream(); - SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream); + SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE, mock(RaceLogResolver.class)).loadRaceConfig(configDataStream); assertNotNull(config_446483); assertEquals("GB", config_446483.country_code); assertNull(config_446483.event_name); @@ -63,7 +66,7 @@ public class SwissTimingRaceConfigurationTest { URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, "6260")); URLConnection connection = configFileURL.openConnection(); InputStream configDataStream = connection.getInputStream(); - SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream); + SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE, mock(RaceLogResolver.class)).loadRaceConfig(configDataStream); assertNotNull(config_446483); assertEquals("GB", config_446483.country_code); assertEquals("London 2012 Olympic Games", config_446483.event_name); diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java index e67c8f56bfd..461f6ed83de 100644 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter.test/src/com/sap/sailing/domain/swisstimingreplayadapter/test/SwissTimingReplayAdapterServiceTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.swisstimingreplayadapter.test; import static org.junit.Assert.assertArrayEquals; +import static org.mockito.Mockito.mock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; @@ -16,6 +17,7 @@ import java.util.List; import org.junit.Ignore; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.swisstimingadapter.DomainFactory; @@ -33,7 +35,7 @@ public class SwissTimingReplayAdapterServiceTest { public void testLoadRaceJson() throws Exception { String swissTimingUrlText = "/2012_OSG.json"; InputStream inputStream = getClass().getResourceAsStream(swissTimingUrlText); - final SwissTimingReplayServiceImpl swissTimingReplayService = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE); + final SwissTimingReplayServiceImpl swissTimingReplayService = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE, mock(RaceLogResolver.class)); List races = swissTimingReplayService.parseJSONObject(inputStream , swissTimingUrlText); assertEquals(201, races.size()); assertEquals("446483", races.get(0).getRaceId()); @@ -178,7 +180,7 @@ public class SwissTimingReplayAdapterServiceTest { @Test public void testRaceData_SAW010955_20120802_WithDomainAdapter() throws Exception { SwissTimingReplayToDomainAdapter replayListener = new SwissTimingReplayToDomainAdapter(null, DomainFactory.INSTANCE, - new DummyTrackedRegattaRegistry(), /* useInternalMarkPassingAlgorithm */ false); + new DummyTrackedRegattaRegistry(), /* useInternalMarkPassingAlgorithm */ false, mock(RaceLogResolver.class)); new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"), replayListener); Iterable trackedRaces = replayListener.getTrackedRaces(); assertFalse(Util.isEmpty(trackedRaces)); @@ -192,7 +194,7 @@ public class SwissTimingReplayAdapterServiceTest { @Test public void testStartPerformanceDetection() throws Exception { SwissTimingReplayToDomainAdapter replayListener = new SwissTimingReplayToDomainAdapter(null, DomainFactory.INSTANCE, - new DummyTrackedRegattaRegistry(), /* useInternalMarkPassingAlgorithm */ false); + new DummyTrackedRegattaRegistry(), /* useInternalMarkPassingAlgorithm */ false, mock(RaceLogResolver.class)); new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005906.20120805.replay"), replayListener); Iterable trackedRaces = replayListener.getTrackedRaces(); TrackedRace trackedRace = trackedRaces.iterator().next(); diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.swisstimingreplayadapter/META-INF/MANIFEST.MF index cd3c7b4a848..0507cad7850 100644 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/META-INF/MANIFEST.MF @@ -12,7 +12,8 @@ Require-Bundle: com.sap.sailing.domain.common, com.sap.sailing.domain.swisstimingadapter, com.googlecode.java-diff-utils;bundle-version="1.3.0", com.sap.sse, - com.sap.sse.common + com.sap.sse.common, + com.sap.sailing.domain.shared.android Export-Package: com.sap.sailing.domain.swisstimingreplayadapter Import-Package: org.osgi.framework;version="1.7.0" Bundle-Activator: com.sap.sailing.domain.swisstimingreplayadapter.impl.Activator diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayServiceFactory.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayServiceFactory.java index 12c40c4908b..34fb5c951e9 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayServiceFactory.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/SwissTimingReplayServiceFactory.java @@ -1,10 +1,11 @@ package com.sap.sailing.domain.swisstimingreplayadapter; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.swisstimingadapter.DomainFactory; import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayServiceFactoryImpl; public interface SwissTimingReplayServiceFactory { static SwissTimingReplayServiceFactory INSTANCE = new SwissTimingReplayServiceFactoryImpl(); - SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory); + SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory, RaceLogResolver raceLogResolver); } diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceFactoryImpl.java index 7adb8b89dbe..5334e7ea2f0 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceFactoryImpl.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.swisstimingreplayadapter.impl; import java.util.HashMap; import java.util.Map; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.swisstimingadapter.DomainFactory; import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayService; import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayServiceFactory; @@ -15,10 +16,10 @@ public class SwissTimingReplayServiceFactoryImpl implements SwissTimingReplaySer } @Override - public SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory) { + public SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory, RaceLogResolver raceLogResolver) { SwissTimingReplayService result = servicesForDomainFactories.get(domainFactory); if (result == null) { - result = new SwissTimingReplayServiceImpl(domainFactory); + result = new SwissTimingReplayServiceImpl(domainFactory, raceLogResolver); servicesForDomainFactories.put(domainFactory, result); } return result; diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java index 35215a778d8..3d5fe7ff094 100644 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayServiceImpl.java @@ -18,6 +18,7 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.swisstimingadapter.DomainFactory; import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayListener; @@ -34,9 +35,11 @@ public class SwissTimingReplayServiceImpl implements SwissTimingReplayService { private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("GMT"); private final DomainFactory domainFactory; + private final RaceLogResolver raceLogResolver; - public SwissTimingReplayServiceImpl(DomainFactory domainFactory) { + public SwissTimingReplayServiceImpl(DomainFactory domainFactory, RaceLogResolver raceLogResolver) { this.domainFactory = domainFactory; + this.raceLogResolver = raceLogResolver; } @Override @@ -143,8 +146,10 @@ public class SwissTimingReplayServiceImpl implements SwissTimingReplayService { } @Override - public void loadRaceData(String link, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, boolean useInternalMarkPassingAlgorithm) { - SwissTimingReplayListener listener = new SwissTimingReplayToDomainAdapter(regatta, domainFactory, trackedRegattaRegistry, useInternalMarkPassingAlgorithm); + public void loadRaceData(String link, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, + boolean useInternalMarkPassingAlgorithm) { + SwissTimingReplayListener listener = new SwissTimingReplayToDomainAdapter(regatta, domainFactory, + trackedRegattaRegistry, useInternalMarkPassingAlgorithm, raceLogResolver); loadRaceData(link, listener); } } diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java index fa87e202b21..096cbb03e87 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.TimeZone; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -136,6 +137,8 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter { private RaceStatus lastRaceStatus; private final boolean useInternalMarkPassingAlgorithm; + + private final RaceLogResolver raceLogResolver; /** * @param regatta @@ -144,7 +147,8 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter { * @param useInternalMarkPassingAlgorithm use our own instead of the SwissTiming-provided mark rounding / split times */ public SwissTimingReplayToDomainAdapter(Regatta regatta, DomainFactory domainFactory, - TrackedRegattaRegistry trackedRegattaRegistry, boolean useInternalMarkPassingAlgorithm) { + TrackedRegattaRegistry trackedRegattaRegistry, boolean useInternalMarkPassingAlgorithm, RaceLogResolver raceLogResolver) { + this.raceLogResolver = raceLogResolver; this.regatta = regatta; this.trackedRegattaRegistry = trackedRegattaRegistry; racePerRaceID = new HashMap<>(); @@ -317,7 +321,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter { createTrackedRace(race, Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS, WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), - /* raceDefinitionSetToUpdate */ null, useInternalMarkPassingAlgorithm); + /* raceDefinitionSetToUpdate */ null, useInternalMarkPassingAlgorithm, raceLogResolver); trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0)); TimePoint bestStartTimeKnownSoFar = bestStartTimePerRaceID.get(currentRaceID); if (bestStartTimeKnownSoFar != null) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java index 0b1dc175de5..a593a00f766 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java @@ -12,6 +12,7 @@ import java.util.function.Function; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -77,7 +78,7 @@ public class WaypointPositionAndDistanceCacheTest { trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections.emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 8000, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 15000, /* delayForCacheInvalidationOfWindEstimation */ 10000, - /* useInternalMarkPassingAlgorithm */ false, OneDesignRankingMetric::new); + /* useInternalMarkPassingAlgorithm */ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); timeRangeResolution = Duration.ONE_MINUTE; now = new MillisecondsTimePoint(MillisecondsTimePoint.now().asMillis() / timeRangeResolution.asMillis() * timeRangeResolution.asMillis()); trackedRace.getOrCreateTrack(pinEnd).addGPSFix(new GPSFixImpl(new DegreePosition(0, -0.0000001), now)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java index 87040eed61f..c4f9d04ccf2 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestSimpleTimeOnTimeRankingWithOneUpwindLeg.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.ranking; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; @@ -12,6 +13,7 @@ import java.util.function.Function; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -91,7 +93,7 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, tr->new TimeOnTimeAndDistanceRankingMetric(tr, timeOnTimeFactors, // time-on-time - c->new MillisecondsDurationImpl((long) (1000.*timeOnDistanceFactors.apply(c))))); + c->new MillisecondsDurationImpl((long) (1000.*timeOnDistanceFactors.apply(c)))), mock(RaceLogResolver.class)); // in this simplified artificial course, the top mark is exactly north of the right leeward gate DegreePosition topPosition = new DegreePosition(1, 0); trackedRace.getOrCreateTrack(left).addGPSFix(new GPSFixImpl(new DegreePosition(0, -0.000001), timePointForFixes)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java index c58772bfce8..1c09df563f9 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; @@ -15,6 +16,7 @@ import java.util.Set; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -304,7 +306,8 @@ public class CourseTest { new RaceDefinitionImpl("Test Race", course, new BoatClassImpl("49er", /* upwind start */true), hasso), Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE,/* delayToLiveInMillis */3000, /* millisecondsOverWhichToAverageWind */30000, - /* millisecondsOverWhichToAverageSpeed */8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + /* millisecondsOverWhichToAverageSpeed */8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); assertLegStructure(course, trackedRace); course.removeWaypoint(0); assertLegStructure(course, trackedRace); @@ -335,7 +338,8 @@ public class CourseTest { hasso), Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 30000, - /* millisecondsOverWhichToAverageSpeed */ 8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + /* millisecondsOverWhichToAverageSpeed */ 8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); assertLegStructure(course, trackedRace); final WaypointImpl wp1_5 = new WaypointImpl(new MarkImpl("Test Mark 1.5")); assertWaypointIndexes(course); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateDuringNonAtomicSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateDuringNonAtomicSerializationTest.java index 6d77db7ae2f..a4490ae9bb9 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateDuringNonAtomicSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateDuringNonAtomicSerializationTest.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -19,6 +20,7 @@ import java.util.UUID; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; @@ -81,7 +83,7 @@ public class CourseUpdateDuringNonAtomicSerializationTest implements Serializabl trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptySet(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */10000, /* millisecondsOverWhichToAverageWind */30000, /* millisecondsOverWhichToAverageSpeed */ - 7000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new) { + 7000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)) { private static final long serialVersionUID = 9114777576548711763L; @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index 07eb229db4a..c777e2d010c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -20,7 +20,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import static org.mockito.Mockito.mock; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -91,7 +93,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { } }, /* delayToLiveInMillis */0l, /* millisecondsOverWhichToAverageWind */30000, /* simulator */null, /* courseDesignUpdateURI */ - null, /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/false) { + null, /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), + /*ignoreTracTracMarkPassings*/false, mock(RaceLogResolver.class)) { @Override protected void handleEvent(Triple event) { super.handleEvent(event); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java index 391dbfba65e..62fceea3754 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardCourseChangeTest.java @@ -14,6 +14,7 @@ import java.util.concurrent.ExecutionException; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -138,7 +139,8 @@ public class LeaderboardCourseChangeTest { TrackedRegatta mockedTrackedRegatta = createMockedTrackedRegatta(regatta); RaceDefinition mockedRace = createMockedRace(course, boatClass); TrackedRace spyedTrackedRace = spy(new DynamicTrackedRaceImpl(mockedTrackedRegatta, mockedRace, - new HashSet(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, 5000, 20000, 20000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new)); + new HashSet(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, 5000, 20000, 20000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class))); return spyedTrackedRace; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java index f25fe97ef2c..7cbbad0ae5e 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInRegattaTest.java @@ -10,10 +10,13 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import static org.mockito.Mockito.mock; + import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; @@ -61,7 +64,7 @@ public class MultipleClassesInRegattaTest { false, EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, tracTracUsername, tracTracPassword, TracTracConnectionConstants.ONLINE_STATUS, TracTracConnectionConstants.ONLINE_VISIBILITY, - new DummyTrackedRegattaRegistry()); + new DummyTrackedRegattaRegistry(), mock(RaceLogResolver.class)); kiwotest2 = domainFactory .createRaceTracker( new URL( @@ -72,7 +75,7 @@ public class MultipleClassesInRegattaTest { false, EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, tracTracUsername, tracTracPassword, TracTracConnectionConstants.ONLINE_STATUS, TracTracConnectionConstants.ONLINE_VISIBILITY, - new DummyTrackedRegattaRegistry()); + new DummyTrackedRegattaRegistry(), mock(RaceLogResolver.class)); kiwotest3 = domainFactory .createRaceTracker( new URL( @@ -83,7 +86,7 @@ public class MultipleClassesInRegattaTest { false, EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, tracTracUsername, tracTracPassword, TracTracConnectionConstants.ONLINE_STATUS, TracTracConnectionConstants.ONLINE_VISIBILITY, - new DummyTrackedRegattaRegistry()); + new DummyTrackedRegattaRegistry(), mock(RaceLogResolver.class)); weym470may112014_2 = domainFactory .createRaceTracker( new URL( @@ -94,7 +97,7 @@ public class MultipleClassesInRegattaTest { false, EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, tracTracUsername, tracTracPassword, TracTracConnectionConstants.ONLINE_STATUS, TracTracConnectionConstants.ONLINE_VISIBILITY, - new DummyTrackedRegattaRegistry()); + new DummyTrackedRegattaRegistry(), mock(RaceLogResolver.class)); assertEquals("STG", kiwotest1.getRegatta().getBoatClass().getName()); assertEquals("5O5", kiwotest2.getRegatta().getBoatClass().getName()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java index e354501b1f3..28341dce76c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; import java.io.FileNotFoundException; import java.io.IOException; @@ -18,6 +19,7 @@ import java.util.regex.Pattern; import org.junit.Before; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceDefinition; @@ -113,8 +115,8 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest { ArrayList receivers = new ArrayList(); for (Receiver r : domainFactory.getUpdateReceivers(trackedRegatta, getTracTracRace(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */0l, /* simulator */null, createRaceDefinitionSet(), /* trackedRegattaRegistry */null, - /* courseDesignUpdateURI */null, /* tracTracUsername */null, null, /* tracTracPassword */ - getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, receiverTypes)) { + mock(RaceLogResolver.class), /* courseDesignUpdateURI */null, /* tracTracUsername */null, /* tracTracPassword */ + null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, receiverTypes)) { receivers.add(r); } getRaceSubscriber().subscribeConnectionStatus(new IConnectionStatusListener() { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java index 483614af2a2..d024ee59989 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReachingLegTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Collections; @@ -12,6 +13,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -109,7 +111,7 @@ public class ReachingLegTest extends TrackBasedTest { EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, - OneDesignRankingMetric::new); + OneDesignRankingMetric::new, mock(RaceLogResolver.class)); // in this simplified artificial course, the top mark is exactly north of the right leeward gate, the offset // mark is slightly west of the top mark; wind from the north makes the leg from top to offset a reaching leg Position leftPosition = new DegreePosition(0, -0.00001); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java index d86ae9384b8..cb7d6c5a6e0 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.net.MalformedURLException; import java.net.URISyntaxException; @@ -11,6 +12,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; @@ -106,9 +108,9 @@ public class ReceiveMarkPassingDataTest extends AbstractTracTracLiveTest { public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { } }, /* trackedRegattaRegistry */null, - /* courseDesignUpdateURI */null, /* tracTracUsername */null, null, /* tracTracPassword */ - getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, - ReceiverType.RAWPOSITIONS)) { + mock(RaceLogResolver.class), /* courseDesignUpdateURI */null, /* tracTracUsername */null, /* tracTracPassword */ + null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, + ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) { receivers.add(r); } addListenersForStoredDataAndStartController(receivers); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java index 649e9e59552..03f9b00753d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; import java.net.MalformedURLException; import java.net.URISyntaxException; @@ -8,6 +9,7 @@ import java.net.URISyntaxException; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; @@ -83,8 +85,8 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { } }, - /* trackedRegattaRegistry */null, getTracTracRace(), null, /* courseDesignUpdateURI */ - /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false)) { + /* trackedRegattaRegistry */null, mock(RaceLogResolver.class), getTracTracRace(), /* courseDesignUpdateURI */ + null, /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false)) { receiver.subscribe(); getRaceSubscriber().start(); } @@ -95,8 +97,8 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { @Override public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { } - }, /* trackedRegattaRegistry */null, getTracTracRace(), null, /* courseDesignUpdateURI */ - /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false)); + }, /* trackedRegattaRegistry */null, mock(RaceLogResolver.class), getTracTracRace(), /* courseDesignUpdateURI */ + null, /* tracTracUsername */null, /* tracTracPassword */null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false)); } @Test diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StarbordSideOfStartLineRecognitionTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StarbordSideOfStartLineRecognitionTest.java index 9e257f14e59..5502e58de45 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StarbordSideOfStartLineRecognitionTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StarbordSideOfStartLineRecognitionTest.java @@ -12,6 +12,7 @@ import java.util.Collections; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Mark; @@ -87,7 +88,8 @@ public class StarbordSideOfStartLineRecognitionTest { private static final long serialVersionUID = -8007932232555073829L; public MockedTrackedRaceImpl() { - super(null, null, Collections. emptyList(), null, null, 0, 0, 0, 0, false, OneDesignRankingMetric::new); + super(null, null, Collections. emptyList(), null, null, 0, 0, 0, 0, false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java index ac5a08d55fc..159809279a5 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java @@ -1,11 +1,14 @@ package com.sap.sailing.domain.test; +import static org.mockito.Mockito.mock; + import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.UUID; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -119,7 +122,7 @@ public abstract class TrackBasedTest { EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, /* delay for wind estimation cache invalidation */ 0, /*useMarkPassingCalculator*/ false, - OneDesignRankingMetric::new); + OneDesignRankingMetric::new, mock(RaceLogResolver.class)); // in this simplified artificial course, the top mark is exactly north of the right leeward gate DegreePosition topPosition = new DegreePosition(54.48, 10.24); TimePoint afterTheRace = new MillisecondsTimePoint(timePointForFixes.asMillis() + 36000000); // 10h after the fix timed diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java index de22a3fa28b..6d6652b7772 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test; import java.io.BufferedReader; +import static org.mockito.Mockito.mock; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; @@ -15,6 +16,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; @@ -68,7 +70,7 @@ public class UnicodeCharactersInCompetitorNamesTest { /* simulateWithStartTimeNow */ false, /* ignoreTracTracMarkPassings*/ false, EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, "tracTest", "tracTest", "", "", - new DummyTrackedRegattaRegistry()); + new DummyTrackedRegattaRegistry(), mock(RaceLogResolver.class)); Iterable competitors = fourtyninerYellow_2.getRacesHandle().getRace().getCompetitors(); for (Competitor competitor : competitors) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UpdateMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UpdateMarkPassingTest.java index d3a62ff752e..811da5b81ae 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UpdateMarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UpdateMarkPassingTest.java @@ -10,6 +10,7 @@ import java.util.HashSet; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; @@ -47,7 +48,7 @@ public class UpdateMarkPassingTest { /* trackedRegatta */new DynamicTrackedRegattaImpl(new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), race, Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */1000, /* millisecondsOverWhichToAverageWind */30000, - /* millisecondsOverWhichToAverageSpeed */30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + /* millisecondsOverWhichToAverageSpeed */30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); TimePoint now = MillisecondsTimePoint.now(); TimePoint later = now.plus(1000); trackedRace.updateMarkPassings(competitor, Arrays.asList(new MarkPassing[] { new MarkPassingImpl(now, waypoint, competitor) })); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java index 38ca32b9f38..cf6c06430f3 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -16,6 +17,7 @@ import java.util.Set; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -287,7 +289,8 @@ public class WindTest { boatClass, Collections.singleton(competitor)), Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 1000, /* millisecondsOverWhichToAverageWind */ 30000, - /* millisecondsOverWhichToAverageSpeed */ 30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + /* millisecondsOverWhichToAverageSpeed */ 30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); TimePoint start = MillisecondsTimePoint.now(); TimePoint topMarkRounding = start.plus(30000); TimePoint finish = topMarkRounding.plus(30000); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java index 469b23d8b39..06e7eedcc3b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/markpassing/AbstractMockedRaceMarkPassingTest.java @@ -5,6 +5,9 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; +import static org.mockito.Mockito.mock; + +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.Course; @@ -55,7 +58,6 @@ public class AbstractMockedRaceMarkPassingTest { public AbstractMockedRaceMarkPassingTest() { ControlPointWithTwoMarks cp = new ControlPointWithTwoMarksImpl(gate1, gate2, "cp"); - Waypoint w1 = new WaypointImpl(cp, PassingInstruction.Line); Waypoint w2 = new WaypointImpl(m, PassingInstruction.Port); Waypoint w3 = new WaypointImpl(cp, PassingInstruction.Gate); @@ -68,7 +70,8 @@ public class AbstractMockedRaceMarkPassingTest { new ArrayList(), null)), true, new HighPoint(), "ID", new CourseAreaImpl("area", new UUID(5, 5)), OneDesignRankingMetric::new); Course course = new CourseImpl("course", waypoints); RaceDefinition raceDef = new RaceDefinitionImpl("Performance Race", course, boatClass, Arrays.asList(ron, tom, ben)); - race = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(r), raceDef, new ArrayList(), new EmptyWindStore(), EmptyGPSFixStore.INSTANCE, 0, 10000, 10000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new); + race = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(r), raceDef, new ArrayList(), new EmptyWindStore(), EmptyGPSFixStore.INSTANCE, 0, 10000, 10000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, + mock(RaceLogResolver.class)); race.setStartTimeReceived(new MillisecondsTimePoint(10000)); TimePoint t = new MillisecondsTimePoint(30000); List> pos = Arrays.asList(new Util.Pair(m, new DegreePosition(0, 0)), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index 481323374f0..943e938d1d7 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -8,6 +8,7 @@ import java.util.Set; import java.util.TreeSet; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -16,6 +17,7 @@ import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.EventFetcher; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; @@ -462,6 +464,11 @@ public class MockedTrackedRace implements DynamicTrackedRace { public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { return null; } + + @Override + public RaceColumn getRaceColumnByName(String raceColumnName) { + return null; + } }; } @@ -510,7 +517,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingcalculator) { + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingcalculator, RaceLogResolver raceLogResolver) { return null; } diff --git a/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF index 9bee601cb0e..ae105762c5f 100644 --- a/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.tractracadapter/META-INF/MANIFEST.MF @@ -12,7 +12,8 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0", com.sap.sse, com.sap.sse.common, - com.sap.sailing.server.gateway.serialization.shared.android + com.sap.sailing.server.gateway.serialization.shared.android, + com.sap.sailing.domain.shared.android Export-Package: com.sap.sailing.domain.tractracadapter, com.sap.sailing.domain.tractracadapter.impl; x-friends:="com.sap.sailing.domain.test, diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index 502797d0123..24f100d306d 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -11,6 +11,7 @@ import java.text.ParseException; import java.util.List; import java.util.UUID; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Mark; @@ -133,23 +134,25 @@ public interface DomainFactory { * Provides the capability to obtain the {@link WindTrack}s for the different wind sources. A trivial * implementation is {@link EmptyWindStore} which simply provides new, empty tracks. This is always * available but loses track of the wind, e.g., during server restarts. + * @param raceLogResolver TODO */ TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, URI courseDesignUpdateURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, String tracTracPassword, - String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry) + String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException; /** * Same as {@link #createRaceTracker(URL, URI, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)}, only that * a predefined {@link Regatta} is used to hold the resulting races. + * @param raceLogResolver TODO */ RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI, URI courseDesignUpdateURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, String tracTracPassword, - String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry) + String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException; @@ -166,15 +169,16 @@ public interface DomainFactory { * must have been created before through * {@link #getOrCreateTrackedRegatta(com.sap.sailing.domain.base.Regatta)} because otherwise the link to * the {@link IEvent} can't be established + * @param raceLogResolver TODO * @param tokenToRetrieveAssociatedRace * used to update the set of{@link RaceDefinition}s received by the {@link RaceCourseReceiver} created by * this call */ Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, long delayToLiveInMillis, Simulator simulator, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, - IRace tractracRace, URI courseDesignUpdateURI, - String tracTracUsername, String tracTracPassword, IEventSubscriber eventSubscriber, - IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm); + RaceLogResolver raceLogResolver, IRace tractracRace, + URI courseDesignUpdateURI, String tracTracUsername, String tracTracPassword, + IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm); /** * Creates a {@link RaceDefinition} from a TracTrac {@link Race} and a domain {@link Course} definition. The @@ -188,17 +192,17 @@ public interface DomainFactory { * already immediately after the notification was sent, and that the {@link RaceDefinition} is already * {@link com.sap.sailing.domain.base.Regatta#getAllRaces() known} by its containing * {@link com.sap.sailing.domain.base.Regatta}. - * * @param raceDefinitionSetToUpdate * if not null, after creating the {@link TrackedRace}, the {@link RaceDefinition} is * {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that * object. + * @param raceLogResolver TODO */ DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, String raceName, Iterable competitors, BoatClass boatClass, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings); + URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver); /** * The record may be for a single mark or a gate. If for a gate, the @@ -213,11 +217,12 @@ public interface DomainFactory { /** * If the vm argument tractrac.usemarkpassings=false, the RecieverType MARKPASSINGS will not return anything + * @param raceLogResolver TODO */ Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, IRace tractracRace, WindStore windStore, long delayToLiveInMillis, Simulator simulator, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, - URI courseDesignUpdateURI, String tracTracUsername, - String tracTracPassword, IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean ignoreTracTracMarkPassings, ReceiverType... types); + RaceLogResolver raceLogResolver, URI courseDesignUpdateURI, + String tracTracUsername, String tracTracPassword, IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean ignoreTracTracMarkPassings, ReceiverType... types); JSONService parseJSONURLWithRaceRecords(URL jsonURL, boolean loadClientParams) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException; diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index c0e19ce6f7a..e514af5dcf9 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -19,6 +19,7 @@ import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; @@ -404,18 +405,19 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, IRace tractracRace, WindStore windStore, long delayToLiveInMillis, Simulator simulator, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - TrackedRegattaRegistry trackedRegattaRegistry, URI courseDesignUpdateURI, - String tracTracUsername, String tracTracPassword, IEventSubscriber eventSubscriber, - IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm, ReceiverType... types) { + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, + URI courseDesignUpdateURI, String tracTracUsername, String tracTracPassword, + IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm, ReceiverType... types) { IEvent tractracEvent = tractracRace.getEvent(); Collection result = new ArrayList(); for (ReceiverType type : types) { switch (type) { case RACECOURSE: - result.add(new RaceCourseReceiver(this, trackedRegatta, tractracEvent, tractracRace, - windStore, raceDefinitionSetToUpdate, - delayToLiveInMillis, WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, simulator, - courseDesignUpdateURI, tracTracUsername, tracTracPassword, eventSubscriber, raceSubscriber, useInternalMarkPassingAlgorithm)); + result.add(new RaceCourseReceiver(this, trackedRegatta, tractracEvent, tractracRace, windStore, + raceDefinitionSetToUpdate, delayToLiveInMillis, + WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, simulator, courseDesignUpdateURI, + tracTracUsername, tracTracPassword, eventSubscriber, raceSubscriber, + useInternalMarkPassingAlgorithm, raceLogResolver)); break; case MARKPOSITIONS: result.add(new MarkPositionReceiver( @@ -442,14 +444,14 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Iterable getUpdateReceivers(DynamicTrackedRegatta trackedRegatta, long delayToLiveInMillis, Simulator simulator, WindStore windStore, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, IRace tractracRace, - URI courseDesignUpdateURI, String tracTracUsername, - String tracTracPassword, IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm) { + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, + IRace tractracRace, URI courseDesignUpdateURI, + String tracTracUsername, String tracTracPassword, IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean useInternalMarkPassingAlgorithm) { return getUpdateReceivers(trackedRegatta, tractracRace, windStore, delayToLiveInMillis, simulator, - raceDefinitionSetToUpdate, trackedRegattaRegistry, courseDesignUpdateURI, tracTracUsername, - tracTracPassword, eventSubscriber, raceSubscriber, useInternalMarkPassingAlgorithm, - ReceiverType.RACECOURSE, ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, - ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); + raceDefinitionSetToUpdate, trackedRegattaRegistry, raceLogResolver, courseDesignUpdateURI, + tracTracUsername, tracTracPassword, eventSubscriber, raceSubscriber, + useInternalMarkPassingAlgorithm, ReceiverType.RACECOURSE, ReceiverType.MARKPASSINGS, + ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); } @Override @@ -518,7 +520,7 @@ public class DomainFactoryImpl implements DomainFactory { String raceName, Iterable competitors, BoatClass boatClass, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings) { + URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver) { synchronized (raceCache) { RaceDefinition raceDefinition = raceCache.get(raceId); if (raceDefinition == null) { @@ -533,7 +535,8 @@ public class DomainFactoryImpl implements DomainFactory { if (raceDefinition.getBoatClass() == trackedRegatta.getRegatta().getBoatClass()) { trackedRegatta.getRegatta().addRace(raceDefinition); trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, EmptyGPSFixStore.INSTANCE, - delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, ignoreTracTracMarkPassings); + delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, ignoreTracTracMarkPassings, + raceLogResolver); logger.info("Added race " + raceDefinition + " to regatta " + trackedRegatta.getRegatta()); addTracTracUpdateHandlers(tracTracUpdateURI, tracTracEventUuid, tracTracUsername, tracTracPassword, raceDefinition, trackedRace); @@ -568,12 +571,14 @@ public class DomainFactoryImpl implements DomainFactory { trackedRace.addRaceAbortedListener(raceAbortedHandler); } - private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, - long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator) { + private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, + Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, + long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, + boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { return trackedRegatta.createTrackedRace(race, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), - raceDefinitionSetToUpdate, useMarkPassingCalculator); + raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver); } @Override @@ -648,28 +653,29 @@ public class DomainFactoryImpl implements DomainFactory { @Override public TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, URI courseDesignUpdateURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, - boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, - WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, String tracTracPassword, - String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry) - throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, - SubscriberInitializationException { + boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, + RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, + String tracTracPassword, String raceStatus, String raceVisibility, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws MalformedURLException, FileNotFoundException, + URISyntaxException, CreateModelException, SubscriberInitializationException { return new TracTracRaceTrackerImpl(this, paramURL, liveURI, storedURI, courseDesignUpdateURI, startOfTracking, endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, useInternalMarkPassingAlgorithm, raceLogStore, regattaLogStore, windStore, - gpsFixStore, tracTracUsername, tracTracPassword, raceStatus, raceVisibility, trackedRegattaRegistry); + gpsFixStore, tracTracUsername, tracTracPassword, raceStatus, raceVisibility, trackedRegattaRegistry, raceLogResolver); } @Override public RaceTracker createRaceTracker(Regatta regatta, URL paramURL, URI liveURI, URI storedURI, URI courseDesignUpdateURI, TimePoint startOfTracking, TimePoint endOfTracking, long delayToLiveInMillis, - boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, - WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, String tracTracPassword, - String raceStatus, String raceVisibility, TrackedRegattaRegistry trackedRegattaRegistry) + boolean simulateWithStartTimeNow, boolean useInternalMarkPassingAlgorithm, RaceLogStore raceLogStore, + RegattaLogStore regattaLogStore, WindStore windStore, GPSFixStore gpsFixStore, String tracTracUsername, + String tracTracPassword, String raceStatus, String raceVisibility, + TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver) throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException, SubscriberInitializationException { return new TracTracRaceTrackerImpl(regatta, this, paramURL, liveURI, storedURI, courseDesignUpdateURI, startOfTracking, endOfTracking, delayToLiveInMillis, simulateWithStartTimeNow, useInternalMarkPassingAlgorithm, raceLogStore, regattaLogStore, windStore, gpsFixStore, tracTracUsername, tracTracPassword, raceStatus, - raceVisibility, trackedRegattaRegistry); + raceVisibility, trackedRegattaRegistry, raceLogResolver); } @Override diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java index a474744717d..9033ba85de2 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -61,14 +62,17 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue(); for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedRegatta(), delayToLiveInMillis, - simulator, windStore, this, trackedRegattaRegistry, tractracRace, tracTracUpdateURI, - tracTracUsername, tracTracPassword, eventSubscriber, raceSubscriber, useInternalMarkPassingAlgorithm)) { + simulator, windStore, this, trackedRegattaRegistry, raceLogResolver, tractracRace, + tracTracUpdateURI, tracTracUsername, tracTracPassword, eventSubscriber, raceSubscriber, useInternalMarkPassingAlgorithm)) { receivers.add(receiver); } addListenersForStoredDataAndStartController(receivers); diff --git a/java/com.sap.sailing.domain/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain/META-INF/MANIFEST.MF index 959694e5909..fbd86b1960a 100755 --- a/java/com.sap.sailing.domain/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain/META-INF/MANIFEST.MF @@ -19,7 +19,6 @@ Export-Package: com.sap.sailing.domain.base, com.sap.sailing.domain.masterdataimport, com.sap.sailing.domain.polars, com.sap.sailing.domain.racelog, - com.sap.sailing.domain.racelog.analyzing, com.sap.sailing.domain.racelog.impl, com.sap.sailing.domain.racelog.tracking, com.sap.sailing.domain.ranking, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java deleted file mode 100644 index 149d1bd388b..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/racelog/analyzing/ServerSideRaceLogResolver.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sap.sailing.domain.racelog.analyzing; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.regattalike.HasRegattaLike; - -public class ServerSideRaceLogResolver implements RaceLogResolver { - private final HasRegattaLike regattaLike; - - public ServerSideRaceLogResolver(HasRegattaLike regattaLike) { - this.regattaLike = regattaLike; - } - - @Override - public RaceLog resolve(SimpleRaceLogIdentifier identifier) { - final RaceLog result; - if (regattaLike == null) { - result = null; - } else { - result = regattaLike.getRacelog(identifier.getRaceColumnName(), identifier.getFleetName()); - } - return result; - } -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceTrackingConnectivityParameters.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceTrackingConnectivityParameters.java index 091a285fe9e..5e2592a956a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceTrackingConnectivityParameters.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/RaceTrackingConnectivityParameters.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.tracking; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; @@ -20,16 +21,18 @@ import com.sap.sailing.domain.racelog.tracking.GPSFixStore; public interface RaceTrackingConnectivityParameters { /** * Starts a {@link RaceTracker} using the connectivity parameters provided by this object. + * @param raceLogResolver TODO */ - RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore) throws Exception; + RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) throws Exception; /** * Starts a {@link RaceTracker}, associating the resulting races with the {@link Regatta} passed as argument * instead of using the tracker's domain factory to obtain a default {@link Regatta} object for the tracking * parameters. This is particularly useful if a predefined regatta with {@link Series} and {@link Fleet}s * is to be used. + * @param raceLogResolver TODO */ - RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore) throws Exception; + RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore, RaceLogResolver raceLogResolver) throws Exception; /** * Deliver an ID object equal to that of the {@link RaceTracker#getID()} delivered by the {@link RaceTracker} 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 2a8c9168b16..c560317f7f3 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 @@ -7,6 +7,7 @@ import java.util.Set; import java.util.SortedSet; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent; @@ -15,6 +16,7 @@ import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.base.Waypoint; @@ -42,6 +44,7 @@ import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.ranking.RankingMetric; import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -851,4 +854,7 @@ public interface TrackedRace extends Serializable { void setPolarDataService(PolarDataService polarDataService); + default RaceLogResolver getRaceLogResolver() { + return null; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java index e998afc4a5e..9fa20136bed 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRegatta.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking; import java.io.Serializable; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceDefinition; @@ -60,14 +61,14 @@ public interface TrackedRegatta extends Serializable { * Creates a {@link TrackedRace} based on the parameter specified and {@link #addTrackedRace(TrackedRace) adds} it * to this tracked regatta. Afterwards, calling {@link #getTrackedRace(RaceDefinition) getTrackedRace(raceDefinition)} * will return the result of this method call. - * * @param raceDefinitionSetToUpdate * if not null, after creating the {@link TrackedRace}, the raceDefinition is * {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that object. + * @param raceLogResolver TODO */ DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm); + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm, RaceLogResolver raceLogResolver); /** * Obtains the tracked race for race. Blocks until the tracked race has been created diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index e1463636149..a1d6796a12f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -16,6 +16,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; @@ -77,10 +78,10 @@ DynamicTrackedRace, GPSTrackListener { WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, long delayForCacheInvalidationOfWindEstimation, boolean useInternalMarkPassingAlgorithm, - RankingMetricConstructor rankingMetricConstructor) { + RankingMetricConstructor rankingMetricConstructor, RaceLogResolver raceLogResolver) { super(trackedRegatta, race, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - delayForCacheInvalidationOfWindEstimation, useInternalMarkPassingAlgorithm, rankingMetricConstructor); + delayForCacheInvalidationOfWindEstimation, useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver); this.logListener = new DynamicTrackedRaceLogListener(this); if (markPassingCalculator != null) { logListener.setMarkPassingUpdateListener(markPassingCalculator.getListener()); @@ -134,10 +135,10 @@ DynamicTrackedRace, GPSTrackListener { public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, - boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor) { + boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor, RaceLogResolver raceLogResolver) { this(trackedRegatta, race, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - millisecondsOverWhichToAverageWind / 2, useInternalMarkPassingAlgorithm, rankingMetricConstructor); + millisecondsOverWhichToAverageWind / 2, useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java index 7da497d2a61..e64d764f230 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java @@ -16,9 +16,9 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.SuppressedMarkPassingsEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.MarkPassingDataFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.WindFixesFinder; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; import com.sap.sailing.domain.base.Competitor; @@ -29,7 +29,6 @@ import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.markpassingcalculation.MarkPassingUpdateListener; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Triple; @@ -69,8 +68,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { trackedRace.invalidateStartTime(); trackedRace.invalidateEndTime(); courseDesignFinder = new LastPublishedCourseDesignFinder(raceLog); - //FIXME: how to get the HasRegattaLike? - startTimeFinder = new StartTimeFinder(new ServerSideRaceLogResolver(null), raceLog); + startTimeFinder = new StartTimeFinder(trackedRace.getRaceLogResolver(), raceLog); abortingFlagFinder = new AbortingFlagFinder(raceLog); initializeWindTrack(raceLog); analyze(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRegattaImpl.java index 1bf8d0ac359..a299a2b764e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRegattaImpl.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.tracking.impl; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Sideline; @@ -35,8 +36,8 @@ public class DynamicTrackedRegattaImpl extends TrackedRegattaImpl implements Dyn @Override public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator) { + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { return (DynamicTrackedRace) super.createTrackedRace(raceDefinition, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, - millisecondsOverWhichToAverageSpeed, raceDefinitionSetToUpdate, useMarkPassingCalculator); + millisecondsOverWhichToAverageSpeed, raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver); } } 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 a4a3e4e7da6..bb5ccfd6455 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 @@ -36,8 +36,11 @@ 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.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; @@ -103,7 +106,6 @@ import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuse import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; import com.sap.sailing.domain.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.racelogtracking.DeviceMapping; @@ -348,6 +350,14 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl * certificate. */ private final RankingMetric rankingMetric; + + /** + * Required in particular to resolve {@link SimpleRaceLogIdentifier}s that appear in + * {@link RaceLogDependentStartTimeEvent}s. The usual implementation on the server side is + * provided by RacingEventService which is not serializable. Therefore, the reference + * must be established again after de-serialization by invoking {@link #setRaceLogResolver}. + */ + private transient RaceLogResolver raceLogResolver; /** * Constructs the tracked race with one-design ranking. @@ -356,15 +366,14 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl final Iterable sidelines, final WindStore windStore, final GPSFixStore gpsFixStore, long delayToLiveInMillis, final long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation, - boolean useInternalMarkPassingAlgorithm) { + boolean useInternalMarkPassingAlgorithm, RaceLogResolver raceLogResolver) { this(trackedRegatta, race, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - delayForWindEstimationCacheInvalidation, useInternalMarkPassingAlgorithm, OneDesignRankingMetric::new); + delayForWindEstimationCacheInvalidation, useInternalMarkPassingAlgorithm, OneDesignRankingMetric::new, raceLogResolver); } /** * Constructs the tracked race with a configurable ranking metric. - * * @param rankingMetricConstructor * the function that creates the ranking metric, passing this tracked race as argument. Callers may use a * constructor method reference if the {@link RankingMetric} implementation to instantiate takes a single @@ -374,8 +383,10 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl final Iterable sidelines, final WindStore windStore, final GPSFixStore gpsFixStore, long delayToLiveInMillis, final long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation, - boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor) { + boolean useInternalMarkPassingAlgorithm, RankingMetricConstructor rankingMetricConstructor, + RaceLogResolver raceLogResolver) { super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind); + this.raceLogResolver = raceLogResolver; rankingMetric = rankingMetricConstructor.apply(this); raceStates = new WeakHashMap<>(); shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2); @@ -730,8 +741,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl public TimePoint getStartOfRace() { if (startTime == null) { for (RaceLog raceLog : attachedRaceLogs.values()) { - //FIXME: how to get the HasRegattaLike? - startTime = new StartTimeFinder(new ServerSideRaceLogResolver(null), raceLog).analyze().getStartTime(); + startTime = new StartTimeFinder(raceLogResolver, raceLog).analyze().getStartTime(); if (startTime != null) { break; } @@ -3139,8 +3149,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl synchronized (raceStates) { result = raceStates.get(raceLog); if (result == null) { - //FIXME: how to get the corresponding RegattaLike? - result = RaceStateImpl.create(new ServerSideRaceLogResolver(null), raceLog); + result = RaceStateImpl.create(raceLogResolver, raceLog); raceStates.put(raceLog, result); } } @@ -3672,4 +3681,16 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl public void setPolarDataService(PolarDataService polarDataService) { this.polarDataService = polarDataService; } + + /** + * Obtains the {@link #raceLogResolver}. + */ + @Override + public RaceLogResolver getRaceLogResolver() { + return raceLogResolver; + } + + public void setRaceLogResolver(RaceLogResolver raceLogResolver) { + this.raceLogResolver = raceLogResolver; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java index 442ca68ede2..361c2cbfa71 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRegattaImpl.java @@ -14,6 +14,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceDefinition; @@ -244,12 +245,12 @@ public class TrackedRegattaImpl implements TrackedRegatta { public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm) { + DynamicRaceDefinitionSet raceDefinitionSetToUpdate, boolean useInternalMarkPassingAlgorithm, RaceLogResolver raceLogResolver) { logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition " + raceDefinition.getName()); DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - /* useMarkPassingCalculator */useInternalMarkPassingAlgorithm, getRegatta().getRankingMetricConstructor()); + /* useMarkPassingCalculator */useInternalMarkPassingAlgorithm, getRegatta().getRankingMetricConstructor(), raceLogResolver); // adding the raceDefinition to the raceDefinitionSetToUpdate BEFORE calling addTrackedRace helps those who // are called back by RaceListener.raceAdded(TrackedRace) and who then expect the update to have happened if (raceDefinitionSetToUpdate != null) { diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index 9eca28dba48..6656cb1e4d7 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -9,6 +9,7 @@ import java.util.NavigableSet; import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -313,7 +314,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - boolean useMarkPassingCalculator) { + boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { return null; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 868b91e529e..8ebab6c5c0d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -232,7 +232,6 @@ import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.racelog.RaceLogStore; import com.sap.sailing.domain.racelog.RaceStateOfSameDayHelper; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.racelogtracking.DeviceIdentifierStringSerializationHandler; import com.sap.sailing.domain.racelogtracking.DeviceMapping; @@ -544,7 +543,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S // TODO what about passing on the mongo/domain object factory to obtain an according SwissTimingAdapterPersistence instance similar to how the tractracDomainObjectFactory etc. are created below? swissTimingAdapterPersistence = SwissTimingAdapterPersistence.INSTANCE; swissTimingReplayService = ServiceTrackerFactory.createAndOpen(context, SwissTimingReplayServiceFactory.class) - .getService().createSwissTimingReplayService(getSwissTimingAdapter().getSwissTimingDomainFactory()); + .getService().createSwissTimingReplayService(getSwissTimingAdapter().getSwissTimingDomainFactory(), + /* raceLogResolver */ getService()); scoreCorrectionProviderServiceTracker = ServiceTrackerFactory.createAndOpen(context, ScoreCorrectionProvider.class); tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE @@ -844,18 +844,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return raceColumnDTOs; } - private RaceInfoDTO createRaceInfoDTO(Leaderboard leaderboard, String seriesName, RaceColumn raceColumn, Fleet fleet) { + private RaceInfoDTO createRaceInfoDTO(String seriesName, RaceColumn raceColumn, Fleet fleet) { RaceInfoDTO raceInfoDTO = new RaceInfoDTO(); RaceLog raceLog = raceColumn.getRaceLog(fleet); if (raceLog != null) { raceInfoDTO.isTracked = raceColumn.getTrackedRace(fleet) != null ? true : false; - final HasRegattaLike regattaLike; - if (leaderboard instanceof HasRegattaLike) { - regattaLike = (HasRegattaLike) leaderboard; - } else { - regattaLike = null; - } - ReadonlyRaceState state = ReadonlyRaceStateImpl.create(new ServerSideRaceLogResolver(regattaLike), raceLog); + ReadonlyRaceState state = ReadonlyRaceStateImpl.create(getService(), raceLog); TimePoint startTime = state.getStartTime(); if (startTime != null) { raceInfoDTO.startTime = startTime.asDate(); @@ -4242,7 +4236,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S entry.boatClassName = boatClassName; entry.regattaDisplayName = regattaName; entry.regattaName = leaderboard.getName(); - entry.raceInfo = createRaceInfoDTO(leaderboard, seriesName, raceColumn, fleet); + entry.raceInfo = createRaceInfoDTO(seriesName, raceColumn, fleet); entry.currentServerTime = new Date(); if (showOnlyRacesOfSameDay) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java index a3212eee738..be2e6608279 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java @@ -6,6 +6,7 @@ import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.WindFixesFinder; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; @@ -31,8 +32,6 @@ import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; -import com.sap.sailing.domain.regattalike.HasRegattaLike; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.WindWithConfidence; @@ -59,7 +58,7 @@ public class RaceContext { private final Event event; private final long TIME_TO_SHOW_CANCELED_RACES_AS_LIVE = 5 * 60 * 1000; // 5 min - public RaceContext(Event event, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet) { + public RaceContext(Event event, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, RaceLogResolver raceLogResolver) { this.event = event; this.leaderboard = leaderboard; this.raceColumn = raceColumn; @@ -67,7 +66,7 @@ public class RaceContext { this.fleet = fleet; trackedRace = raceColumn.getTrackedRace(fleet); raceLog = raceColumn.getRaceLog(fleet); - state = ReadonlyRaceStateImpl.create(new ServerSideRaceLogResolver((HasRegattaLike) leaderboard), raceLog); + state = ReadonlyRaceStateImpl.create(raceLogResolver, raceLog); } private boolean isShowFleetData() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RacesActionUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RacesActionUtil.java index 8581ffe0e8f..e38c9c3b708 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RacesActionUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RacesActionUtil.java @@ -25,7 +25,7 @@ public final class RacesActionUtil { for (Leaderboard lb : lg.getLeaderboards()) { for(RaceColumn raceColumn : lb.getRaceColumns()) { for(Fleet fleet : raceColumn.getFleets()) { - callback.doForRace(new RaceContext(event, lb, raceColumn, fleet)); + callback.doForRace(new RaceContext(event, lb, raceColumn, fleet, context.getRacingEventService())); } } } @@ -38,7 +38,7 @@ public final class RacesActionUtil { Leaderboard lb = context.getRacingEventService().getLeaderboardByName(regattaName); for(RaceColumn raceColumn : lb.getRaceColumns()) { for(Fleet fleet : raceColumn.getFleets()) { - callback.doForRace(new RaceContext(event, lb, raceColumn, fleet)); + callback.doForRace(new RaceContext(event, lb, raceColumn, fleet, context.getRacingEventService())); } } } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java index 3485a2bedd1..770acae35f6 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java @@ -3,6 +3,7 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.net.MalformedURLException; import java.net.URISyntaxException; @@ -16,6 +17,7 @@ import com.mongodb.DB; import com.mongodb.Mongo; import com.mongodb.MongoClient; import com.mongodb.MongoException; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Sideline; @@ -87,7 +89,8 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive @Override public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { } - }, /* trackedRegattaRegistry */ null, /*courseDesignUpdateURI*/ null, /*tracTracUsername*/ null, /*tracTracPassword*/ null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE); + }, /* trackedRegattaRegistry */ null, mock(RaceLogResolver.class), + /*courseDesignUpdateURI*/ null, /*tracTracUsername*/ null, /*tracTracPassword*/ null, getEventSubscriber(), getRaceSubscriber(), /*ignoreTracTracMarkPassings*/ false, ReceiverType.RACECOURSE); addListenersForStoredDataAndStartController(typeControllers); RaceDefinition race = domainFactory.getAndWaitForRaceDefinition(getTracTracEvent().getRaces().iterator().next().getId()); DynamicTrackedRace trackedRace = trackedRegatta.createTrackedRace(race, Collections. emptyList(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, @@ -95,7 +98,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive @Override public void addRaceDefinition(RaceDefinition race, DynamicTrackedRace trackedRace) { } - }, /*useMarkPassingCalculator*/ false); + }, /*useMarkPassingCalculator*/ false, mock(RaceLogResolver.class)); WindSource windSource = new WindSourceImpl(WindSourceType.WEB); Mongo myFirstMongo = newMongo(); DB firstDatabase = myFirstMongo.getDB(dbConfiguration.getDatabaseName()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java index 1897a5ec74a..43ee3eb47f1 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java @@ -42,7 +42,7 @@ public class EventRaceStatesJsonGetServlet extends AbstractJsonHttpServlet { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event "+eventIdParam+" not found"); } else { EventRaceStatesSerializer eventRaceStatesSerializer = new EventRaceStatesSerializer(filterByCourseAreaParam, - filterByLeaderboardParam, filterByDayOffsetParam); + filterByLeaderboardParam, filterByDayOffsetParam, getService()); JSONObject result = eventRaceStatesSerializer.serialize(new Pair>(event, getService().getLeaderboards().values())); setJsonResponseHeader(response); result.writeJSONString(response.getWriter()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventRaceStatesSerializer.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventRaceStatesSerializer.java index aabe500d131..101f820c6db 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventRaceStatesSerializer.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventRaceStatesSerializer.java @@ -6,6 +6,7 @@ import java.util.Date; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Fleet; @@ -19,31 +20,30 @@ public class EventRaceStatesSerializer implements JsonSerializer>(event, getService().getLeaderboards().values())); String json = raceStatesJson.toJSONString(); response = Response.ok(json, MediaType.APPLICATION_JSON).build(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RaceStateSerializer.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RaceStateSerializer.java index 12154bf76ae..b48aae155d1 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RaceStateSerializer.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RaceStateSerializer.java @@ -7,9 +7,10 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastFlagsFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.ReadonlyGateStartRacingProcedure; @@ -17,23 +18,16 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.racelog.RaceStateOfSameDayHelper; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; -import com.sap.sailing.domain.regattalike.HasRegattaLike; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Pair; public class RaceStateSerializer implements JsonSerializer> { - private final HasRegattaLike regattaLike; + private final RaceLogResolver raceLogResolver; - public RaceStateSerializer(Leaderboard leaderboard) { - if (leaderboard instanceof HasRegattaLike) { - regattaLike = (HasRegattaLike) leaderboard; - } else { - regattaLike = null; - } + public RaceStateSerializer(RaceLogResolver raceLogResolver) { + this.raceLogResolver = raceLogResolver; } @Override @@ -49,7 +43,7 @@ public class RaceStateSerializer implements JsonSerializer()), boatClass, new ArrayList()); regatta.addRace(raceDef1); trackedRegatta1.createTrackedRace(raceDef1, Collections. emptyList(), /* windStore */ EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l, - /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false); + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogResolver.class)); regatta.addRace(raceDef2); trackedRegatta1.createTrackedRace(raceDef2, Collections. emptyList(), /* windStore */ EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l, - /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false); + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogResolver.class)); regatta.addRace(raceDef3); trackedRegatta1.createTrackedRace(raceDef3, Collections. emptyList(), /* windStore */ EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE, /* delayToLiveInMillis */ 0l, /* millisecondsOverWhichToAverageWind */ 0l, - /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false); + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null, /*useMarkPassingCalculator*/ false, mock(RaceLogResolver.class)); Set raceDefinitionSetRace1 = new HashSet(); raceDefinitionSetRace1.add(raceDef1); Set raceDefinitionSetRace2 = new HashSet(); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java index ccfc26062cd..635dd8e93f2 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java @@ -16,6 +16,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.CourseArea; @@ -110,7 +111,7 @@ import com.sap.sse.replication.impl.ReplicableWithObjectInputStream; */ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetcher, RegattaRegistry, RaceFetcher, LeaderboardRegistry, EventResolver, LeaderboardGroupResolver, TrackerManager, Searchable, - ReplicableWithObjectInputStream> { + ReplicableWithObjectInputStream>, RaceLogResolver { @Override Regatta getRegatta(RegattaName regattaName); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 07e2281ff53..6f8ea7c8fda 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -52,7 +52,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceState; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; @@ -132,7 +131,6 @@ import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFacto import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.racelog.analyzing.ServerSideRaceLogResolver; import com.sap.sailing.domain.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; @@ -159,6 +157,7 @@ import com.sap.sailing.domain.tracking.WindTrackerFactory; import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory; import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.Replicator; @@ -212,6 +211,7 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.TypeBasedServiceFinderFactory; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.media.ImageDescriptor; import com.sap.sse.common.media.VideoDescriptor; @@ -228,7 +228,7 @@ import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; import com.sap.sse.util.ClearStateTestSupport; public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, - LeaderboardRegistry, Replicator, EventFetcher, RaceLogResolver { + LeaderboardRegistry, Replicator, EventFetcher { private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); /** @@ -1336,10 +1336,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes Regatta regatta = regattaToAddTo == null ? null : getRegatta(regattaToAddTo); if (regatta == null) { // create tracker and use an existing or create a default regatta - tracker = params.createRaceTracker(this, windStore, gpsFixStore); + tracker = params.createRaceTracker(this, windStore, gpsFixStore, /* raceLogResolver */ this); } else { // use the regatta selected by the RaceIdentifier regattaToAddTo - tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore); + tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore, /* raceLogResolver */ this); assert tracker.getRegatta() == regatta; } LockUtil.lockForWrite(raceTrackersByRegattaLock); @@ -1482,7 +1482,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes RaceDefinition race = getRace(raceIdentifier); return trackedRegatta.createTrackedRace(race, Collections. emptyList(), windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - /* raceDefinitionSetToUpdate */null, useMarkPassingCalculator); + /* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this); } private void ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking( @@ -2531,6 +2531,17 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes regattaImpl.initializeSeriesAfterDeserialize(); regattaImpl.addRaceColumnListener(raceLogReplicator); } + // re-establish RaceLogResolver references to this RacingEventService in all TrackedRace instances + for (DynamicTrackedRegatta trackedRegatta : regattaTrackingCache.values()) { + trackedRegatta.lockTrackedRacesForRead(); + try { + for (TrackedRace trackedRace : trackedRegatta.getTrackedRaces()) { + ((TrackedRaceImpl) trackedRace).setRaceLogResolver(this); + } + } finally { + trackedRegatta.unlockTrackedRacesAfterRead(); + } + } logger.info(logoutput.toString()); } @@ -2919,8 +2930,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes Leaderboard leaderboard = getLeaderboardByName(leaderboardName); final TimePoint result; if (leaderboard instanceof HasRegattaLike && raceLog != null) { - RaceState state = RaceStateImpl.create(new ServerSideRaceLogResolver((HasRegattaLike) leaderboard), raceLog, - new LogEventAuthorImpl(authorName, authorPriority)); + RaceState state = RaceStateImpl.create(/* race log resolver */ this, raceLog, new LogEventAuthorImpl(authorName, authorPriority)); if (passId > raceLog.getCurrentPassId()) { state.setAdvancePass(logicalTimePoint); } @@ -2949,22 +2959,16 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( String leaderboardName, String raceColumnName, String fleetName) { RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - - if (!(leaderboard instanceof HasRegattaLike)){ - return null; - } - - if (raceLog == null) { - return null; - } - - ReadonlyRaceState state = ReadonlyRaceStateImpl.create(new ServerSideRaceLogResolver( - (HasRegattaLike) leaderboard), raceLog); - return new com.sap.sse.common.Util.Triple(state.getStartTime(), + final Triple result; + if (leaderboard instanceof HasRegattaLike && raceLog != null) { + ReadonlyRaceState state = ReadonlyRaceStateImpl.create(/* race log resolver */ this, raceLog); + result = new com.sap.sse.common.Util.Triple(state.getStartTime(), raceLog.getCurrentPassId(), state.getRacingProcedure().getType()); - + } else { + result = null; + } + return result; } private Iterable getWindTrackerFactories() { From a10e029c49d2fb936d74c8778aff1dca7f0920cb Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 21 Jun 2015 01:50:47 +0200 Subject: [PATCH 23/27] removed unused addDummyTrackedRace method from ImportMasterDataOperation; it was used before switching master data import to serialization --- .../ImportMasterDataOperation.java | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java index 4308830717e..6b1ad50bed0 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/ImportMasterDataOperation.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -54,7 +53,6 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.RacingEventServiceOperation; import com.sap.sailing.server.masterdata.DataImportLockWithProgress; @@ -308,31 +306,6 @@ public class ImportMasterDataOperation extends } } - /** - * Hack adding a dummy tracked race, so that the competitors will be added to the leaderboards - * - * @param leaderboard - * @return the race column and fleet the dummy was attached to - */ - public com.sap.sse.common.Util.Pair addDummyTrackedRace(Leaderboard leaderboard, - Regatta regatta) { - RaceColumn raceColumn = null; - Fleet fleet = null; - Iterable raceColumns = leaderboard.getRaceColumns(); - Iterator raceColumnIterator = raceColumns.iterator(); - if (raceColumnIterator.hasNext()) { - raceColumn = raceColumnIterator.next(); - Iterable fleets = raceColumn.getFleets(); - Iterator fleetIterator = fleets.iterator(); - if (fleetIterator.hasNext()) { - fleet = fleetIterator.next(); - DummyTrackedRace dummy = new DummyTrackedRace(UUID.randomUUID(), leaderboard.getAllCompetitors(), regatta, null, EmptyWindStore.INSTANCE); - raceColumn.setTrackedRace(fleet, dummy); - } - } - return new com.sap.sse.common.Util.Pair(raceColumn, fleet); - } - private void createWindTracks(RacingEventService toState) { int numOfWindTracks = masterData.getWindTrackMasterData().size(); int i = 0; From b4363fa79bf02218aa8a549fad0191e0872481f5 Mon Sep 17 00:00:00 2001 From: EC2 Server Date: Sun, 21 Jun 2015 12:31:25 +0000 Subject: [PATCH 24/27] Fixed NPE --- .../StartAnalysisDTOFactory.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java index 94968fade88..9e6c357a341 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/startanalysis/StartAnalysisDTOFactory.java @@ -149,13 +149,18 @@ public class StartAnalysisDTOFactory extends AbstractStartAnalysisCreationValida new Date())); startLineAdvantageDTO.startLineAdvantage = startline.getAdvantage().getMeters(); startAnalysisWindLineInfoDTO.startLineAdvantage = startLineAdvantageDTO; - Position portMarkPosition = trackedRace.getOrCreateTrack( - trackedRace.getStartLine(trackedRace.getStartTimeReceived()).getStarboardMarkWhileApproachingLine()) - .getEstimatedPosition(trackedRace.getStartTimeReceived(), /* extrapolate */ - false); - Wind windAtStart = trackedRace.getWind(portMarkPosition, trackedRace.getStartTimeReceived()); - startAnalysisWindLineInfoDTO.windDirectionInDegrees = windAtStart.getBearing().getDegrees(); - startAnalysisWindLineInfoDTO.windSpeedInKnots = windAtStart.getKnots(); + if (trackedRace.getStartTimeReceived() != null) { + Position portMarkPosition = trackedRace.getOrCreateTrack( + trackedRace.getStartLine(trackedRace.getStartTimeReceived()).getStarboardMarkWhileApproachingLine()) + .getEstimatedPosition(trackedRace.getStartTimeReceived(), /* extrapolate */ + false); + Wind windAtStart = trackedRace.getWind(portMarkPosition, trackedRace.getStartTimeReceived()); + startAnalysisWindLineInfoDTO.windDirectionInDegrees = windAtStart.getBearing().getDegrees(); + startAnalysisWindLineInfoDTO.windSpeedInKnots = windAtStart.getKnots(); + } else { + startAnalysisWindLineInfoDTO.windDirectionInDegrees = 0.0; + startAnalysisWindLineInfoDTO.windSpeedInKnots = 0.0; + } return startAnalysisWindLineInfoDTO; } From 229adaf03e1be0d64a27b38ff85ca918323c76ae Mon Sep 17 00:00:00 2001 From: Frederik Petersen Date: Sun, 21 Jun 2015 16:02:05 +0200 Subject: [PATCH 25/27] Added conditional time formatting for UpdatesBoxItems --- .../event/partials/updatesBox/UpdatesBox.gss | 3 ++ .../partials/updatesBox/UpdatesBoxItem.java | 16 +++++--- .../updatesBox/UpdatesBoxResources.java | 1 + .../sailing/gwt/ui/client/StringMessages.java | 3 ++ .../gwt/ui/client/StringMessages.properties | 3 ++ .../ui/client/StringMessages_de.properties | 3 ++ .../ui/client/StringMessages_ru.properties | 3 ++ .../event/GetEventOverviewNewsAction.java | 6 ++- .../news/AbstractRaceNewsEntryDTO.java | 4 +- .../dispatch/news/InfoNewsEntryDTO.java | 5 ++- .../news/LeaderboardNewsEntryDTO.java | 6 ++- .../ui/shared/dispatch/news/NewsEntryDTO.java | 19 +++++++--- .../news/RaceCompetitorNewsEntryDTO.java | 4 +- .../util/ConditionalDateTimeFormatter.java | 37 +++++++++++++++++++ 14 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBox.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBox.gss index 308dd6624eb..b919c914c20 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBox.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBox.gss @@ -104,6 +104,9 @@ overflow: hidden; text-overflow: ellipsis; } +.updatesbox_item_live { + color: red; +} .updatesbox_item_content_text_boatclass { display: none; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxItem.java index 37b0b613925..32a4c6c4e81 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxItem.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxItem.java @@ -8,8 +8,6 @@ import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.SpanElement; -import com.google.gwt.i18n.client.DateTimeFormat; -import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Event; @@ -19,9 +17,11 @@ import com.sap.sailing.gwt.common.client.BoatClassImageResolver; import com.sap.sailing.gwt.common.client.LinkUtil; import com.sap.sailing.gwt.home.client.app.PlaceNavigation; import com.sap.sailing.gwt.home.client.place.event.EventView; +import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.dispatch.news.AbstractRaceNewsEntryDTO; import com.sap.sailing.gwt.ui.shared.dispatch.news.LeaderboardNewsEntryDTO; import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; +import com.sap.sailing.gwt.ui.shared.util.ConditionalDateTimeFormatter; public class UpdatesBoxItem extends Widget { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @@ -37,6 +37,7 @@ public class UpdatesBoxItem extends Widget { @UiField DivElement timestampUi; public UpdatesBoxItem(NewsEntryDTO entry, EventView.Presenter presenter) { + UpdatesBoxResources.INSTANCE.css().ensureInjected(); setElement(uiBinder.createAndBindUi(this)); titleUi.setInnerText(entry.getTitle()); @@ -53,11 +54,15 @@ public class UpdatesBoxItem extends Widget { } - Date timestamp = entry.getTimestamp(); - if(timestamp == null) { + Date newsTimestamp = entry.getTimestamp(); + Date currentTimestamp = entry.getCurrentTimestamp(); + if(newsTimestamp == null || currentTimestamp == null) { timestampUi.removeFromParent(); } else { - timestampUi.setInnerText(DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM).format(timestamp)); + timestampUi.setInnerText(ConditionalDateTimeFormatter.format(newsTimestamp, currentTimestamp, StringMessages.INSTANCE)); + if (currentTimestamp.getTime() - 600000 < newsTimestamp.getTime()) { + timestampUi.addClassName(UpdatesBoxResources.INSTANCE.css().updatesbox_item_live()); + } } String directLink = entry.getExternalURL(); @@ -99,5 +104,4 @@ public class UpdatesBoxItem extends Widget { } } } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxResources.java index f0cf86a841c..f436e4ce213 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/partials/updatesBox/UpdatesBoxResources.java @@ -17,6 +17,7 @@ public interface UpdatesBoxResources extends ClientBundle { String box_content_item(); String updatesbox(); String updatesbox_item(); + String updatesbox_item_live(); String updatesbox_itemlink(); String updatesbox_item_icon(); String updatesbox_item_content(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 6a6eb4c65c2..e44c20db76d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -1313,4 +1313,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String sailorInfoLongText(); String resultsUpdate(); String competitorWonRace(String competitorName); + String now(); + String minutesAgo(String minutes); + String hoursAgo(String hours); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index fd4534d0798..cf07bc30979 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -1281,3 +1281,6 @@ raceCalculatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSeconds=Calc.Time raceCalculatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSecondsTooltip=Calculated time at estimated arrival at the competitor that is currently farthest ahead in the race;\nestimation based on average VMG in current leg and equal (calculated) performance to fastest boat in all subsequent legs sailorInfo=Sailor Info sailorInfoLongText=Official Results, Protests,\nNotice Board, Sailor weather: +now=Now +minutesAgo={0} min ago +hoursAgo={0} h ago \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 7eaac84e13c..89c846cffd4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -1271,3 +1271,6 @@ raceCalcluatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSeconds=Ber.Zeit@ raceCalculatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSecondsTooltip=Berechnete Zeit bei erwarteter Ankunft am derzeit absolut in Führung liegenden Teilnehmers;\nSchätzung basierend auf durchschnittlichem VMG im aktuellen Bahnschenkel und gleicher verrechneter Geschwindigket wie der absolut in Führung liegende Teilnehmer\nfür alle nachfolgenden Bahnschenkel sailorInfo=Segler Infos sailorInfoLongText=Offizielle Ergebnisse, Proteste,\nNotice Board, Segler-Wetter: +now=Jetzt +minutesAgo=vor {0} min +hoursAgo=vor {0} h \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index d72df5494e2..e66d5993e43 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -1219,3 +1219,6 @@ raceCalculatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSeconds=Calc.Time raceCalculatedTimeAtEstimatedArrivalAtCompetitorFarthestAheadInSecondsTooltip=Calculated time at estimated arrival at the competitor that is currently farthest ahead in the race;\nestimation based on average VMG in current leg and equal (calculated) performance to fastest boat in all subsequent legs sailorInfo=Моряки информация sailorInfoLongText=Official Results, Protests,\nNotice Board, Sailor weather: +now=в настоящее время +minutesAgo={0} минут назад +hoursAgo={0} h часов назад \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java index 61c5b6cb9f7..1e64ac9af69 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.ui.shared.dispatch.event; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.UUID; @@ -49,12 +50,13 @@ public class GetEventOverviewNewsAction implements Action news = new ArrayList<>(newsItems.size()); + Date currentTimestamp = new Date(); for(EventNewsItem newsItem: newsItems) { if(newsItem instanceof InfoEventNewsItem) { - news.add(new InfoNewsEntryDTO((InfoEventNewsItem) newsItem, dispatchContext.getClientLocale())); + news.add(new InfoNewsEntryDTO((InfoEventNewsItem) newsItem, dispatchContext.getClientLocale(), currentTimestamp)); } if(newsItem instanceof LeaderboardUpdateNewsItem) { - news.add(new LeaderboardNewsEntryDTO((LeaderboardUpdateNewsItem) newsItem)); + news.add(new LeaderboardNewsEntryDTO((LeaderboardUpdateNewsItem) newsItem, currentTimestamp)); } } return news; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java index 0c82cecc687..9128acbefa8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java @@ -14,8 +14,8 @@ public abstract class AbstractRaceNewsEntryDTO extends NewsEntryDTO { } @GwtIncompatible - public AbstractRaceNewsEntryDTO(String regattaName, String trackedRaceName, String raceTitle, String boatClass, Date timestamp) { - super(raceTitle, timestamp, null); + public AbstractRaceNewsEntryDTO(String regattaName, String trackedRaceName, String raceTitle, String boatClass, Date timestamp, Date currentTimestamp) { + super(raceTitle, timestamp, currentTimestamp, null); this.regattaName = regattaName; this.trackedRaceName = trackedRaceName; this.boatClass = boatClass; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/InfoNewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/InfoNewsEntryDTO.java index b11c8085268..67ff7e73676 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/InfoNewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/InfoNewsEntryDTO.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.shared.dispatch.news; +import java.util.Date; import java.util.Locale; import com.google.gwt.core.shared.GwtIncompatible; @@ -14,8 +15,8 @@ public class InfoNewsEntryDTO extends NewsEntryDTO { } @GwtIncompatible - public InfoNewsEntryDTO(InfoEventNewsItem item, Locale locale) { - super(item.getTitle(locale), item.getCreatedAtDate(), item.getRelatedItemLink()); + public InfoNewsEntryDTO(InfoEventNewsItem item, Locale locale, Date currentTimestamp) { + super(item.getTitle(locale), item.getCreatedAtDate(), currentTimestamp, item.getRelatedItemLink()); this.subtitle = item.getMessage(locale); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/LeaderboardNewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/LeaderboardNewsEntryDTO.java index 03ed23fafc1..462978d95ba 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/LeaderboardNewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/LeaderboardNewsEntryDTO.java @@ -1,5 +1,7 @@ package com.sap.sailing.gwt.ui.shared.dispatch.news; +import java.util.Date; + import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.news.impl.LeaderboardUpdateNewsItem; @@ -19,8 +21,8 @@ public class LeaderboardNewsEntryDTO extends NewsEntryDTO { } @GwtIncompatible - public LeaderboardNewsEntryDTO(LeaderboardUpdateNewsItem item) { - super(item.getTitle(), item.getCreatedAtDate(), null); + public LeaderboardNewsEntryDTO(LeaderboardUpdateNewsItem item, Date currentTimestamp) { + super(item.getTitle(), item.getCreatedAtDate(), currentTimestamp, null); this.boatClassName = item.getBoatClass(); this.type = Type.RESULTS_UPDATE; this.leaderboardName = item.getLeaderboardName(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/NewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/NewsEntryDTO.java index 314c07eb4fb..dfcec32b85d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/NewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/NewsEntryDTO.java @@ -8,7 +8,9 @@ import com.sap.sailing.gwt.ui.shared.dispatch.DTO; public abstract class NewsEntryDTO implements DTO { - private Date timestamp; + private Date newsTimestamp; + + private Date currentTimestamp; private String title; @@ -18,14 +20,15 @@ public abstract class NewsEntryDTO implements DTO { } @GwtIncompatible - public NewsEntryDTO(String title, Date timestamp, URL externalURL) { - this(title, timestamp, externalURL == null ? null : externalURL.toString()); + public NewsEntryDTO(String title, Date timestamp, Date currentTimestamp, URL externalURL) { + this(title, timestamp, currentTimestamp, externalURL == null ? null : externalURL.toString()); } @GwtIncompatible - private NewsEntryDTO(String title, Date timestamp, String externalURL) { + private NewsEntryDTO(String title, Date newsTimestamp, Date currentTimestamp, String externalURL) { this.title = title; - this.timestamp = timestamp; + this.newsTimestamp = newsTimestamp; + this.currentTimestamp = currentTimestamp; this.externalURL = externalURL; } @@ -38,10 +41,14 @@ public abstract class NewsEntryDTO implements DTO { public abstract String getBoatClass(); public Date getTimestamp() { - return timestamp; + return newsTimestamp; } public String getExternalURL() { return externalURL; } + + public Date getCurrentTimestamp() { + return currentTimestamp; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/RaceCompetitorNewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/RaceCompetitorNewsEntryDTO.java index 77d26641128..027233b6ae0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/RaceCompetitorNewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/RaceCompetitorNewsEntryDTO.java @@ -17,8 +17,8 @@ public class RaceCompetitorNewsEntryDTO extends AbstractRaceNewsEntryDTO { private RaceCompetitorNewsEntryDTO() { } - public RaceCompetitorNewsEntryDTO(String regattaName, String trackedRaceName, String raceTitle, String boatClass, Date timestamp, String competitorName, Type type) { - super(regattaName, trackedRaceName, raceTitle, boatClass, timestamp); + public RaceCompetitorNewsEntryDTO(String regattaName, String trackedRaceName, String raceTitle, String boatClass, Date timestamp, String competitorName, Type type, Date currentTimestamp) { + super(regattaName, trackedRaceName, raceTitle, boatClass, timestamp, currentTimestamp); this.competitorName = competitorName; this.type = type; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java new file mode 100644 index 00000000000..a85f9c24016 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.ui.shared.util; + +import java.util.Date; + +import com.google.gwt.i18n.shared.DateTimeFormat; +import com.google.gwt.i18n.shared.DateTimeFormat.PredefinedFormat; +import com.google.gwt.user.datepicker.client.CalendarUtil; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public class ConditionalDateTimeFormatter { + public static String format(Date newsTimestamp, Date currentTimestamp, StringMessages stringMessages) { + String result; + if (newsTimestamp.after(new Date(currentTimestamp.getTime() - 60000))) { + result = stringMessages.now(); + } else { + Date oneHourBeforeCurrent = new Date(currentTimestamp.getTime() - 3600000); + if (newsTimestamp.after(oneHourBeforeCurrent)) { + DateTimeFormat format = DateTimeFormat.getFormat("m"); + Date diffTime = new Date(currentTimestamp.getTime() - newsTimestamp.getTime()); + result = stringMessages.minutesAgo(format.format(diffTime)); + } else { + if (sameDay(newsTimestamp, currentTimestamp)) { + DateTimeFormat format = DateTimeFormat.getFormat("h:m"); + Date diffTime = new Date(currentTimestamp.getTime() - newsTimestamp.getTime()); + result = stringMessages.hoursAgo(format.format(diffTime)); + } else { + result = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_SHORT).format(newsTimestamp); + } + } + } + return result; + } + + private static boolean sameDay(Date timestamp1, Date timestamp2) { + return CalendarUtil.isSameDate(timestamp1, timestamp2); + } +} From 184cb693db09552015a256ab4cf9118aa5d803ba Mon Sep 17 00:00:00 2001 From: fmittag Date: Sun, 21 Jun 2015 20:12:50 +0200 Subject: [PATCH 26/27] little time format adjustings for the news box --- .../gwt/ui/shared/util/ConditionalDateTimeFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java index a85f9c24016..6f81f371dd8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/util/ConditionalDateTimeFormatter.java @@ -20,7 +20,7 @@ public class ConditionalDateTimeFormatter { result = stringMessages.minutesAgo(format.format(diffTime)); } else { if (sameDay(newsTimestamp, currentTimestamp)) { - DateTimeFormat format = DateTimeFormat.getFormat("h:m"); + DateTimeFormat format = DateTimeFormat.getFormat("hh:mm"); Date diffTime = new Date(currentTimestamp.getTime() - newsTimestamp.getTime()); result = stringMessages.hoursAgo(format.format(diffTime)); } else { From bb4daf0b8932814f4605207a9fd77f49c3dac270 Mon Sep 17 00:00:00 2001 From: fmittag Date: Sun, 21 Jun 2015 20:13:36 +0200 Subject: [PATCH 27/27] changed simulator refresh cache rate (for Christopher) --- .../com/sap/sailing/simulator/impl/PathGeneratorBase.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathGeneratorBase.java b/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathGeneratorBase.java index e6761c48730..fc2039b5b86 100644 --- a/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathGeneratorBase.java +++ b/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathGeneratorBase.java @@ -9,9 +9,11 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; public class PathGeneratorBase implements PathGenerator { - + // maximum duration of one path generation + private final static long MAX_DURATION_OF_PATH_GENERATION_MILLIS = 40 * 1000; // 40 seconds + protected SimulationParameters parameters; - protected final Duration algorithmMaxDuration = new MillisecondsDurationImpl(20000); // 20 seconds maximum duration of one path generation + protected final Duration algorithmMaxDuration = new MillisecondsDurationImpl(MAX_DURATION_OF_PATH_GENERATION_MILLIS); protected TimePoint algorithmStartTime; protected boolean algorithmTimedOut = false;