From 74f43331a28754543afe576017377e93ff0a3190 Mon Sep 17 00:00:00 2001 From: fmittag Date: Wed, 10 Aug 2016 12:41:52 +0200 Subject: [PATCH 001/271] implemented 'shortName' attribute for Competitor to prepare to remove the misuse of the sailId for team names --- .../domain/common/dto/CompetitorDTO.java | 4 +- .../domain/common/dto/CompetitorDTOImpl.java | 15 +++++- .../common/dto/PreviousCompetitorDTOImpl.java | 6 +++ .../impl/CompetitorJsonConstants.java | 1 + .../test/AbstractGPSFixStoreTest.java | 2 +- .../impl/CreateAndTrackWithRaceLogTest.java | 4 +- .../test/impl/TrackedRaceLoadsFixesTest.java | 4 +- .../TrackedRaceStartTimeInferenceTest.java | 10 ++-- .../test/CompetitorDeregistrationTest.java | 4 +- .../test/DeviceMappingFinderTest.java | 4 +- .../sap/sailing/domain/base/Competitor.java | 4 +- .../domain/base/CompetitorChangeListener.java | 4 +- .../domain/base/CompetitorFactory.java | 2 +- .../sailing/domain/base/CompetitorStore.java | 2 +- .../domain/base/impl/CompetitorImpl.java | 25 ++++++++-- .../domain/base/impl/DynamicCompetitor.java | 2 + .../base/impl/SharedDomainFactoryImpl.java | 4 +- .../impl/TransientCompetitorStoreImpl.java | 15 +++--- .../impl/DomainFactoryImpl.java | 4 +- .../test/LeaderboardDTODiffingTest.java | 8 +-- .../domain/test/AbstractLeaderboardTest.java | 6 +-- .../domain/test/CompetitorListenerTest.java | 23 ++++++++- .../test/LeaderboardCourseChangeTest.java | 2 +- .../domain/test/OfflineSerializationTest.java | 2 +- .../domain/test/StoredTrackBasedTest.java | 2 +- .../com/sap/sailing/domain/test/TackTest.java | 2 +- .../sailing/domain/test/TrackBasedTest.java | 2 +- .../com/sap/sailing/domain/test/WindTest.java | 2 +- .../AbstractMockedRaceMarkPassingTest.java | 6 +-- .../impl/DomainFactoryImpl.java | 2 +- .../base/impl/DynamicCompetitorStore.java | 2 +- .../leaderboard/LeaderboardCacheManager.java | 5 ++ .../domain/ranking/AbstractRankingMetric.java | 2 +- .../DummyMarkPassingWithTimePointOnly.java | 5 ++ .../ui/adminconsole/CompetitorEditDialog.java | 49 ++++++++++--------- .../adminconsole/CompetitorTableWrapper.java | 18 ++++++- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../ui/client/StringMessages_ja.properties | 1 + .../ui/client/StringMessages_ru.properties | 1 + .../ui/client/StringMessages_zh.properties | 1 + .../ui/client/StringMessages_zh_CN.properties | 1 + .../gwt/ui/server/SailingServiceImpl.java | 4 +- .../StoreAndLoadDeviceIdentifierTest.java | 2 +- .../test/StoreAndLoadRaceLogEventsTest.java | 2 +- .../mongodb/test/StoreGPSFixTrackTest.java | 2 +- ...estStoringAndLoadingEventsAndRegattas.java | 2 +- ...StoringAndRetrievingLeaderboardGroups.java | 12 ++--- .../TestStoringAndRetrievingLeaderboards.java | 6 +-- ...ingAndRetrievingRaceLogInLeaderboards.java | 6 +-- ...tStoringAndRetrievingRaceLogInRegatta.java | 4 +- .../impl/CompetitorJsonDeserializer.java | 3 +- .../impl/CompetitorJsonSerializer.java | 1 + .../racelog/RaceLogEventSerializerTest.java | 2 +- .../gateway/test/AbstractJsonExportTest.java | 2 +- .../test/jaxrs/AbstractJaxRsApiTest.java | 2 +- .../CompetitorsResourceTeamImageTest.java | 2 +- .../test/jaxrs/CompetitorsResourceTest.java | 4 +- ...LeaderboardsResourceCheckinAndOutTest.java | 2 +- .../jaxrs/api/CompetitorsResource.java | 3 +- .../test/CompetitorReplicationTest.java | 11 +++-- .../TrackedRaceContentsReplicationTest.java | 2 +- ...ithGPSFixStoreContentsReplicationTest.java | 2 +- .../test/ApplyScoresFromRaceLogTest.java | 2 +- .../server/test/CompetitorStoreTest.java | 14 +++--- .../server/test/LeaderboardStorageTest.java | 2 +- .../server/test/MasterDataImportTest.java | 40 +++++++-------- .../server/test/WindByRaceLogTest.java | 2 +- .../impl/PersistentCompetitorStore.java | 4 +- .../server/impl/RacingEventServiceImpl.java | 4 +- .../UpdateCompetitor.java | 6 ++- .../structureimport/StructureImporter.java | 3 +- .../app/data/OfflineDataManager.java | 10 ++-- 74 files changed, 271 insertions(+), 153 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 0769df08249..7d66e035aa2 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -25,7 +25,9 @@ public interface CompetitorDTO extends Serializable, MappableToDevice { BoatClassDTO getBoatClass(); String getName(); - + + String getShortName(); + Color getColor(); String getEmail(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index d10dea35696..f4022404e59 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -20,6 +20,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial private String twoLetterIsoCountryCode; private String threeLetterIocCountryCode; private Color color; + private String shortName; private String email; private String searchTag; private String idAsString; @@ -32,10 +33,11 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial public CompetitorDTOImpl() {} - public CompetitorDTOImpl(String name, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, + public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, String countryName, String idAsString, String imageURL, String flagImageURL, BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { super(name); + this.shortName = shortName; this.color = color; this.email = email; this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; @@ -60,6 +62,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); result = prime * result + ((color == null) ? 0 : color.hashCode()); result = prime * result + ((email == null) ? 0 : email.hashCode()); + result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode()); result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode()); @@ -108,6 +111,11 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial return false; } else if (!email.equals(other.email)) return false; + if (shortName == null) { + if (other.shortName != null) + return false; + } else if (!shortName.equals(other.shortName)) + return false; if (imageURL == null) { if (other.imageURL != null) return false; @@ -151,6 +159,11 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial return countryName; } + @Override + public String getShortName() { + return shortName; + } + @Override public String getSailID() { return boat==null?null:boat.getSailId(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java index de15b86d671..4259c5f7165 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java @@ -64,6 +64,12 @@ public class PreviousCompetitorDTOImpl implements CompetitorDTO { " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); } + @Override + public String getShortName() { + throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ + " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); + } + @Override public String getSailID() { throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java index 2d083a0ad1c..629c696393e 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/CompetitorJsonConstants.java @@ -8,6 +8,7 @@ package com.sap.sailing.domain.common.tracking.impl; public class CompetitorJsonConstants { public static final String FIELD_ID = "id"; public static final String FIELD_NAME = "name"; + public static final String FIELD_SHORT_NAME = "shortName"; public static final String FIELD_SAIL_ID = "sailID"; public static final String FIELD_NATIONALITY = "nationality"; public static final String FIELD_COUNTRY_CODE = "countryCode"; diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index ed21eaf7f14..2df64e4688b 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -46,7 +46,7 @@ public class AbstractGPSFixStoreTest { protected RaceLog raceLog; protected RegattaLog regattaLog; protected SensorFixStore store; - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index ac942992282..36f9fb03936 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -175,7 +175,7 @@ public class CreateAndTrackWithRaceLogTest { assertFalse(raceLog.isEmpty()); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null, + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10))); @@ -216,7 +216,7 @@ public class CreateAndTrackWithRaceLogTest { adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race"); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null, + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c1", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, 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 cec7a09e3c3..f659ae99a3f 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 @@ -50,7 +50,7 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { @Test public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2"); @@ -98,7 +98,7 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { @Test public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java index f38635a53df..933cff654a8 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java @@ -59,7 +59,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeInferencePrecedenceOrder() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); @@ -122,7 +122,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeChangeNotificationForFirstUpdateThroughRaceLog() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); @@ -160,7 +160,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeChangeNotificationForFirstUpdateThroughStartMarkPassing() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); @@ -201,7 +201,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartAndEndTrackingTimeInferencePrecedenceOrderTriggersListener() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); @@ -305,7 +305,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartAndEndOfTrackingTimeChangeNotificationForFirstUpdateThroughRaceLog() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java index 219ac0590cc..3546861f905 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java @@ -19,8 +19,8 @@ import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); @Test public void testCompetitorDeregistration() { diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java index 09e055b7734..1409f326ced 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java @@ -27,8 +27,8 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; import junit.framework.Assert; public class DeviceMappingFinderTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); private final DeviceIdentifier device = new SmartphoneImeiIdentifier("imei"); private int time = 0; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java index 7d8f5e5ea31..046c1830395 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java @@ -19,9 +19,11 @@ public interface Competitor extends NamedWithID, IsManagedByCache listeners; @@ -28,9 +29,10 @@ public class CompetitorImpl implements DynamicCompetitor { private Double timeOnTimeFactor; private Duration timeOnDistanceAllowancePerNauticalMile; - public CompetitorImpl(Serializable id, String name, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + public CompetitorImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { this.id = id; this.name = name; + this.shortName = shortName; this.team = team; this.boat = boat; this.color = color; @@ -51,7 +53,12 @@ public class CompetitorImpl implements DynamicCompetitor { public String getName() { return name; } - + + @Override + public String getShortName() { + return shortName; + } + @Override public String toString() { return getName(); @@ -67,7 +74,19 @@ public class CompetitorImpl implements DynamicCompetitor { } } } + + @Override + public void setShortName(String newShortName) { + final String oldShortName = this.shortName; + if (!Util.equalsWithNull(oldShortName, newShortName)) { + this.shortName = newShortName; + for (CompetitorChangeListener listener : getListeners()) { + listener.shortNameChanged(oldShortName, newShortName); + } + } + } + @Override public Serializable getId() { return id; @@ -86,7 +105,7 @@ public class CompetitorImpl implements DynamicCompetitor { @Override public Competitor resolve(SharedDomainFactory domainFactory) { Competitor result = domainFactory - .getOrCreateCompetitor(getId(), getName(), getColor(), getEmail(), getFlagImage(), getTeam(), + .getOrCreateCompetitor(getId(), getName(), getShortName(), getColor(), getEmail(), getFlagImage(), getTeam(), getBoat(), getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag); return result; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java index a0fd2afc28c..29405dfb0a5 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java @@ -16,6 +16,8 @@ public interface DynamicCompetitor extends Competitor, Renamable { void setEmail(String email); + void setShortName(String shortName); + void setSearchTag(String searchTag); void setFlagImage(URI flagImage); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index f35232cf6f6..7f2307cb27a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -337,13 +337,13 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { } @Override - public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, + public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortname, Color displayColor, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this); } - return getCompetitorStore().getOrCreateCompetitor(competitorId, name, displayColor, email, flagImage, team, + return getCompetitorStore().getOrCreateCompetitor(competitorId, name, shortname, displayColor, email, flagImage, team, boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 5a4d89e2f8b..64c5b83507b 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -70,9 +70,9 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab listeners.remove(listener); } - private Competitor createCompetitor(Serializable id, String name, Color displayColor, String email, URI flagImage, + private Competitor createCompetitor(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = new CompetitorImpl(id, name, displayColor, email, flagImage, team, boat, + Competitor result = new CompetitorImpl(id, name, shortName, displayColor, email, flagImage, team, boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); addNewCompetitor(id, result); if (logger.isLoggable(Level.FINEST)) { @@ -97,7 +97,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public Competitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, + public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access @@ -106,14 +106,14 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab try { result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock if (result == null) { - result = createCompetitor(competitorId, name, displayColor, email, flagImage, team, boat, + result = createCompetitor(competitorId, name, shortName, displayColor, email, flagImage, team, boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } } finally { LockUtil.unlockAfterWrite(lock); } } else if (isCompetitorToUpdateDuringGetOrCreate(result)) { - updateCompetitor(result.getId().toString(), name, displayColor, email, boat.getSailID(), team.getNationality(), + updateCompetitor(result.getId().toString(), name, shortName, displayColor, email, boat.getSailID(), team.getNationality(), team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); competitorNoLongerToUpdateDuringGetOrCreate(result); } @@ -198,7 +198,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public Competitor updateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, + public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString); @@ -206,6 +206,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab LockUtil.lockForWrite(lock); try { competitor.setName(newName); + competitor.setShortName(newShortName); competitor.setColor(newDisplayColor); competitor.setEmail(newEmail); competitor.setFlagImage(newFlagImageUri); @@ -242,7 +243,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab if (competitorDTO == null) { final Nationality nationality = c.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), c.getEmail(), countryCode == null ? "" + competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c.getId().toString(), diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index fd218645037..a3662bb57e1 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -125,7 +125,7 @@ public class DomainFactoryImpl implements DomainFactory { teamMembers.add(person); } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); - result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /*displayColor*/, null /*email*/, null, team, boat, + result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } return result; @@ -142,7 +142,7 @@ public class DomainFactoryImpl implements DomainFactory { } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(getCompetitorID(competitor.getBoatID(), raceId, boatClass), - competitor.getName(), null /*displayColor*/, null /*email*/, null, team, boat, + competitor.getName(), null /* short name */, null /*displayColor*/, null /*email*/, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); return result; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index feb5b68187a..fd4e8300ff1 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -233,7 +233,7 @@ public class LeaderboardDTODiffingTest { @Test public void testCompetitorListChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works @@ -254,7 +254,7 @@ public class LeaderboardDTODiffingTest { Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); newVersion.setSuppressedCompetitors(newSuppressedCompetitors); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only @@ -277,7 +277,7 @@ public class LeaderboardDTODiffingTest { @Test public void testDisplayNameChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); @@ -307,7 +307,7 @@ public class LeaderboardDTODiffingTest { List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index db4365de36d..4c9f57721dc 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -15,7 +15,7 @@ import com.sap.sse.common.Color; public abstract class AbstractLeaderboardTest { public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(competitorName, competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + return new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), @@ -24,7 +24,7 @@ public abstract class AbstractLeaderboardTest { } public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) { - return competitorFactory.getOrCreateCompetitor(competitorName, competitorName, Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( + return competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), @@ -34,7 +34,7 @@ public abstract class AbstractLeaderboardTest { } public static CompetitorImpl createCompetitor(String competitorName, Serializable id) { - return new CompetitorImpl(id, competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + return new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index ec519bdd7ac..8cffbc9a37c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -43,6 +43,9 @@ public class CompetitorListenerTest extends AbstractSerializationTest { private boolean nameChanged; private String oldName; private String newName; + private boolean shortNameChanged; + private String oldShortName; + private String newShortName; private boolean colorChanged; private Color oldColor; private Color newColor; @@ -78,6 +81,9 @@ public class CompetitorListenerTest extends AbstractSerializationTest { nameChanged = false; oldName = null; newName = null; + shortNameChanged = false; + oldShortName = null; + newShortName = null; colorChanged = false; oldColor = null; newColor = null; @@ -120,7 +126,14 @@ public class CompetitorListenerTest extends AbstractSerializationTest { CompetitorListenerTest.this.oldName = oldName; CompetitorListenerTest.this.newName = newName; } - + + @Override + public void shortNameChanged(String oldShortName, String newShortName) { + shortNameChanged = true; + CompetitorListenerTest.this.oldShortName = oldShortName; + CompetitorListenerTest.this.newShortName = newShortName; + } + @Override public void colorChanged(Color oldColor, Color newColor) { colorChanged = true; @@ -207,6 +220,14 @@ public class CompetitorListenerTest extends AbstractSerializationTest { assertFalse(nationalityChanged); } + @Test + public void testShortNameChange() throws URISyntaxException { + competitor.setShortName("Dr. HP"); + assertTrue(shortNameChanged); + assertEquals("HP", oldShortName); + assertEquals("Dr. HP", newShortName); + } + @Test public void testFlagChange() throws URISyntaxException { competitor.setFlagImage(new URI("http://www.something.de/pic.png")); 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 6600730bfd5..f8e65cfe68d 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 @@ -160,7 +160,7 @@ public class LeaderboardCourseChangeTest { Set competitors = new HashSet<>(); DynamicBoat mockedBoat = mock(DynamicBoat.class); when(mockedBoat.getBoatClass()).thenReturn(boatClass); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", Color.BLACK, null, null, + competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", "BYC", Color.BLACK, null, null, mock(DynamicTeam.class), mockedBoat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); return competitors; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index 378df1e5721..fb0a7bd4aae 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -188,7 +188,7 @@ public class OfflineSerializationTest extends AbstractSerializationTest { DomainFactory senderDomainFactory = new DomainFactoryImpl((srlid)->null); DomainFactory receiverDomainFactory = new DomainFactoryImpl((srlid)->null); String competitorName = "Tina Maximiliane Lutz"; - Competitor sendersCompetitor1 = new CompetitorImpl(123, competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor sendersCompetitor1 = new CompetitorImpl(123, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, senderDomainFactory.getOrCreateNationality("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 8c346df6cae..4545b7e6efa 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -117,7 +117,7 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) { DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null); DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null); - Competitor c = new CompetitorImpl(competitorName, competitorName, Color.RED, null, null, t, new BoatImpl(competitorName, + Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, new BoatImpl(competitorName, new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DynamicGPSFixTrack track = readTrack(c, KIELER_WOCHE); if (track != null) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 8c321f83ad5..3d767daf1aa 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -35,7 +35,7 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { @Override @Before public void setUp() { - competitor = new CompetitorImpl(123, "Wolfgang Hunger", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + competitor = new CompetitorImpl(123, "Wolfgang Hunger", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), 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 439524c9e5e..dcfcc4910c8 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 @@ -82,7 +82,7 @@ public abstract class TrackBasedTest { } public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + return new CompetitorImpl(UUID.randomUUID(), competitorName, "HP", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), 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 8d8e400480c..448b02160f3 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 @@ -272,7 +272,7 @@ public class WindTest { Waypoint w1 = domainFactory.createWaypoint(startFinish, /*passingInstruction*/ null); Waypoint w2 = domainFactory.createWaypoint(top, /*passingInstruction*/ null); Waypoint w3 = domainFactory.createWaypoint(startFinish, /*passingInstruction*/ null); - Competitor competitor = new CompetitorImpl(123, "Test Competitor", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor competitor = new CompetitorImpl(123, "Test Competitor", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Test Competitor", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), 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 1213134c486..edc1baa1758 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 @@ -45,9 +45,9 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class AbstractMockedRaceMarkPassingTest { final BoatClassImpl boatClass = new BoatClassImpl("boat", true, "boat", new MeterDistance(10), new MeterDistance(5), null); - protected Competitor ron = new CompetitorImpl("Ron", "Ron", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor tom = new CompetitorImpl("Tom", "Tom", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor ben = new CompetitorImpl("Ben", "Ben", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected Mark m = new MarkImpl("Mark"); protected Mark gate1 = new MarkImpl("Gate1"); 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 6d721a5e89b..d23ea7779cf 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 @@ -262,7 +262,7 @@ public class DomainFactoryImpl implements DomainFactory { } DynamicTeam team = createTeam(name, nationality, competitorId); DynamicBoat boat = new BoatImpl(shortName, boatClass, shortName); - result = competitorStore.getOrCreateCompetitor(competitorId, name, null /* displayColor */, + result = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, null /* email */, null /* flagImag */, team, boat, (double) timeOnTimeFactor, new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java index ba24fa23ff1..14f1acddcee 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java @@ -12,7 +12,7 @@ public interface DynamicCompetitorStore extends CompetitorStore { DynamicCompetitor getExistingCompetitorById(Serializable competitorId); @Override - DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, Color displayColor, String email, URI flagImage, + DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index a4ba3c0c0ec..4f70266338d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -99,6 +99,11 @@ public class LeaderboardCacheManager { removeFromCache(leaderboard); } + @Override + public void shortNameChanged(String oldShortName, String newShortName) { + removeFromCache(leaderboard); + } + public synchronized void updateCompetitorListeners() { Set competitorsToStopObserving = new HashSet<>(observedCompetitors); for (Competitor competitor : leaderboard.getCompetitors()) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java index 92d4e1494e4..0a7b1d872f9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java @@ -135,7 +135,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * Helper instance used to encode null values in {@link ConcurrentHashMap} instances which do not accept * null as key nor value. */ - private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null, null); + private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null, null, null); public abstract class AbstractRankingInfo implements RankingMetric.RankingInfo { private static final long serialVersionUID = 6845168655725234325L; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java index 8b3da218a62..98ccd4dc139 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java @@ -43,6 +43,11 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing { return "Dummy"; } + @Override + public String getShortName() { + return "Dummy"; + } + @Override public String getId() { return "Dummy"; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 2b996f96f4c..a74751a43f9 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -40,6 +40,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class CompetitorEditDialog extends DataEntryDialog { private final CompetitorDTO competitorToEdit; private final TextBox name; + private final TextBox shortName; private final SuggestBox boatClassName; private final TextBox displayColorTextBox; private final ListBox threeLetterIocCountryCode; @@ -102,6 +103,8 @@ public class CompetitorEditDialog extends DataEntryDialog { } this.name = createTextBox(competitorToEdit.getName()); name.ensureDebugId("NameTextBox"); + this.shortName = createTextBox(competitorToEdit.getShortName()); + shortName.ensureDebugId("ShortNameTextBox"); this.email = createTextBox(competitorToEdit.getEmail()); this.searchTag = createTextBox(competitorToEdit.getSearchTag()); this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); @@ -193,7 +196,7 @@ public class CompetitorEditDialog extends DataEntryDialog { } BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); BoatDTO boat = new BoatDTO(name.getText(), sailId.getText()); - CompetitorDTO result = new CompetitorDTOImpl(name.getText(), color, email.getText(), + CompetitorDTO result = new CompetitorDTOImpl(name.getText(), shortName.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), /* countryName */ null, competitorToEdit.getIdAsString(), @@ -206,29 +209,31 @@ public class CompetitorEditDialog extends DataEntryDialog { @Override protected Widget getAdditionalWidget() { - Grid result = new Grid(11, 2); + Grid result = new Grid(12, 2); result.setWidget(0, 0, new Label(stringMessages.name())); result.setWidget(0, 1, name); - result.setWidget(1, 0, new Label(stringMessages.sailNumber())); - result.setWidget(1, 1, sailId); - result.setWidget(2, 0, new Label(stringMessages.nationality())); - result.setWidget(2, 1, threeLetterIocCountryCode); - result.setWidget(3, 0, new Label(stringMessages.color())); - result.setWidget(3, 1, displayColorTextBox); - result.setWidget(4, 0, new Label(stringMessages.email())); - result.setWidget(4, 1, email); - result.setWidget(5, 0, new Label(stringMessages.searchTag())); - result.setWidget(5, 1, searchTag); - result.setWidget(6, 0, new Label(stringMessages.boatClass())); - result.setWidget(6, 1, boatClassName); - result.setWidget(7, 0, new Label(stringMessages.flagImageURL())); - result.setWidget(7, 1, flagImageURL); - result.setWidget(8, 0, new Label(stringMessages.imageURL())); - result.setWidget(8, 1, imageUrlAndUploadComposite); - result.setWidget(9, 0, new Label(stringMessages.timeOnTimeFactor())); - result.setWidget(9, 1, timeOnTimeFactor); - result.setWidget(10, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile())); - result.setWidget(10, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile); + result.setWidget(1, 0, new Label(stringMessages.shortName())); + result.setWidget(1, 1, shortName); + result.setWidget(2, 0, new Label(stringMessages.sailNumber())); + result.setWidget(2, 1, sailId); + result.setWidget(3, 0, new Label(stringMessages.nationality())); + result.setWidget(3, 1, threeLetterIocCountryCode); + result.setWidget(4, 0, new Label(stringMessages.color())); + result.setWidget(4, 1, displayColorTextBox); + result.setWidget(5, 0, new Label(stringMessages.email())); + result.setWidget(5, 1, email); + result.setWidget(6, 0, new Label(stringMessages.searchTag())); + result.setWidget(6, 1, searchTag); + result.setWidget(7, 0, new Label(stringMessages.boatClass())); + result.setWidget(7, 1, boatClassName); + result.setWidget(8, 0, new Label(stringMessages.flagImageURL())); + result.setWidget(8, 1, flagImageURL); + result.setWidget(9, 0, new Label(stringMessages.imageURL())); + result.setWidget(9, 1, imageUrlAndUploadComposite); + result.setWidget(10, 0, new Label(stringMessages.timeOnTimeFactor())); + result.setWidget(10, 1, timeOnTimeFactor); + result.setWidget(11, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile())); + result.setWidget(11, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index d10053c428a..baee59a7bdf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -65,6 +65,21 @@ public class CompetitorTableWrapper competitorShortNameColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + return competitor.getShortName(); + } + }; + competitorShortNameColumn.setSortable(true); + competitorColumnListHandler.setComparator(competitorShortNameColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false); + @Override + public int compare(CompetitorDTO o1, CompetitorDTO o2) { + return comparator.compare(o1.getShortName(), o2.getShortName()); + } + }); + TextColumn boatClassColumn = new TextColumn() { @Override public String getValue(CompetitorDTO competitor) { @@ -249,8 +264,9 @@ public class CompetitorTableWrapper competitors = new ArrayList(); - competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); Iterable waypoints = Collections.emptyList(); Course course = new CourseImpl("Course", waypoints); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index bfa1136c2a9..d8381131ddb 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -113,11 +113,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboardWithScoreCorrection() throws NoWindException { RacingEventService racingEventService = new RacingEventServiceImpl(); - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, null, + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), @@ -169,11 +169,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, null, + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), @@ -225,11 +225,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Test public void testStoringAndRetrievingLeaderboardGroupWithTwoSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null,null, + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index 768991ec3ce..d9541c18032 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -77,7 +77,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); Competitor wolfgang = createCompetitor(); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", Color.RED, null, null, + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), @@ -351,7 +351,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final DomainFactory domainFactory = new DomainFactoryImpl((srlid)->null); // create the competitor through the competitor store/factory here so that the DomainObjectFactory finds it and // resolves the score corrections appropriate - Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, "someone@nowhere.de", null, new TeamImpl("STG", Collections.singleton( + Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", "WH", Color.RED, "someone@nowhere.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), @@ -379,7 +379,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { } private Competitor createCompetitor() { - Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index 519b83672b6..83b8f675379 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -297,7 +297,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); @@ -321,7 +321,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEventWithContents() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); @@ -392,7 +392,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index 8d7d476a755..daebedb085f 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -200,7 +200,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); @@ -224,7 +224,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() { - Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.RED, + Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index 18cccebf0cb..09c8525535d 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -55,6 +55,7 @@ public class CompetitorJsonDeserializer implements JsonDeserializer competitorId = Helpers.tryUuidConversion(competitorId); } String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); + String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); @@ -88,7 +89,7 @@ public class CompetitorJsonDeserializer implements JsonDeserializer final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, displayColor, email, + Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, flagImageURI, team, boat, timeOnTimeFactor, timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index 60bb0ccff27..ac6c895b47a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -54,6 +54,7 @@ public class CompetitorJsonSerializer implements JsonSerializer { result.put(idKeyAndValue.getKey(), idKeyAndValue.getValue()); } result.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); + result.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); Color color = getColor(competitor); result.put(CompetitorJsonConstants.FIELD_DISPLAY_COLOR, color == null ? null : color.getAsHtml()); result.put(CompetitorJsonConstants.FIELD_EMAIL, competitor.getEmail()); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 6ba877577eb..ab422ad8343 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -241,7 +241,7 @@ public class RaceLogEventSerializerTest { // we use the real event type here because we do not want to re-implement the dispatching. RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0, DomainFactory.INSTANCE - .getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ + .getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); serializer.serialize(event); verify(registerCompetitorEventSerializer).serialize(event); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java index 2909a63f6e2..7c5eca83d11 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java @@ -89,7 +89,7 @@ public abstract class AbstractJsonExportTest { BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; - Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java index 4af70af38be..95390708f8e 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java @@ -79,7 +79,7 @@ public abstract class AbstractJaxRsApiTest { BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; - Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java index 8892eed8776..7f6b736a4d7 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java @@ -54,7 +54,7 @@ public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( nationality), null, null)), null); DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java index 9a80d9c972a..f0a94ce53ca 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java @@ -27,14 +27,14 @@ public class CompetitorsResourceTest extends AbstractJaxRsApiTest { private final String sailID = "GER 1"; private final String nationality = "GER"; private final String countryCode = "DE"; - + private final String shortName = "HK"; @Before public void setUp() { super.setUp(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, shortName, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } @Test diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index ee82a9d9858..c88e3076be0 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -46,7 +46,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest public void setUp() { super.setUp(); Competitor c = createCompetitors(1).get(0); - competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), + competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 17c7ca42125..6cd3a3e3bfa 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -164,7 +164,8 @@ public class CompetitorsResource extends AbstractSailingServerResource { .entity("Could not store competitor image").type(MediaType.TEXT_PLAIN).build()); } - getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), competitor.getEmail(), + getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getShortName(), + competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, competitor.getSearchTag()); logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index 808e5c9fde6..93ad9a24da1 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -79,8 +79,9 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); Iterable emptyWaypointList = Collections.emptyList(); final String competitorName = "Der mit dem Kiel zieht"; + final String competitorShortName = "DK"; Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor( - 123, competitorName, Color.RED, "someone@nowhere.de", flagImageURI, + 123, competitorName, competitorShortName, Color.RED, "someone@nowhere.de", flagImageURI, new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), @@ -104,6 +105,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { assertNotSame(replicatedCompetitor, competitor); assertEquals(competitor.getId(), replicatedCompetitor.getId()); assertEquals(competitor.getName(), replicatedCompetitor.getName()); + assertEquals(competitor.getShortName(), replicatedCompetitor.getShortName()); assertEquals(competitor.getColor(), replicatedCompetitor.getColor()); assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage()); assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID()); @@ -111,16 +113,18 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { // now update competitor on master using replicating operation final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht"; - master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + final String newCompetitorShortName = "VK"; + master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, newCompetitorShortName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); Thread.sleep(1000); assertEquals(newCompetitorName, replicatedCompetitor.getName()); // expect in-place update of existing competitor in replica + assertEquals(newCompetitorShortName, replicatedCompetitor.getShortName()); // now allow for resetting to default through some event, such as receiving a GPS position master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString()))); // modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally: - master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, Color.RED, competitor.getEmail(), + master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, competitorShortName, Color.RED, competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition); @@ -134,5 +138,6 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { assertNotNull(replicatedTrackedRace); assertNotNull(replicatedTrackedRace.getTrack(replicatedCompetitor).getFirstRawFix()); assertEquals(competitorName, replicatedCompetitor.getName()); + assertEquals(competitorShortName, replicatedCompetitor.getShortName()); } } \ No newline at end of file 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 b45c8255b85..436cf1dca49 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 @@ -71,7 +71,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio // FIXME use master DomainFactory; see bug 592 final DomainFactory masterDomainFactory = testSetUp.getMaster().getBaseDomainFactory(); 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", + competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", "TL", Color.RED, "someone@nowhere.de", null, new TeamImpl("Tina Lutz + Susann Beucke", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null), new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)), 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 index 3c656511430..571749c7332 100644 --- 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 @@ -74,7 +74,7 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS final String boatClassName = "49er"; final DomainFactory masterDomainFactory = testSetUp.getMaster().getBaseDomainFactory(); 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", + competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", "TL", 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)), diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java index 8267c1c0f3d..889498d5323 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java @@ -54,7 +54,7 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest for (int i=0; i<20; i++) { final String competitorName = "C"+i; competitors.add(service.getBaseDomainFactory().getCompetitorStore().getOrCreateCompetitor(UUID.randomUUID(), - competitorName, /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null, + competitorName, "c", /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index 489922fbb1c..bf565e1d9bf 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -23,10 +23,10 @@ public class CompetitorStoreTest { public void testAddingToTransientStore() { CompetitorStore transientStore = new TransientCompetitorStoreImpl(); DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), + Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); assertTrue(competitor != template); - Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), /* timeOnTimeFactor */ 1.345, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); @@ -34,7 +34,7 @@ public class CompetitorStoreTest { assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor, competitor3); // use existing competitor despite the different team @@ -42,7 +42,7 @@ public class CompetitorStoreTest { // now mark the competitor as to update from defaults transientStore.allowCompetitorResetToDefaults(competitor); - Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor, competitor4); // expecting an in-place update @@ -54,7 +54,7 @@ public class CompetitorStoreTest { CompetitorStore persistentStore1 = new PersistentCompetitorStore( PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); - Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); @@ -68,7 +68,7 @@ public class CompetitorStoreTest { assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor2, competitor3); // use existing competitor despite the different team @@ -77,7 +77,7 @@ public class CompetitorStoreTest { // expected to remain unchanged // now mark the competitor as to update from defaults persistentStore2.allowCompetitorResetToDefaults(competitor2); - Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), + Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor2, competitor4); // expecting an in-place update diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java index 8b9c6cdad4a..672318c3a85 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java @@ -60,7 +60,7 @@ public class LeaderboardStorageTest extends TestCase { DynamicTeam team = new TeamImpl("team", sailorList, null); DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); String competitorId = "testC"; - Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, + Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); double carriedPoints = 2.0; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 915604c2c40..23a9bbec36b 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -239,7 +239,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -250,7 +250,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -499,7 +499,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); @@ -508,7 +508,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); - CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, null, team2, + CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -657,7 +657,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -821,7 +821,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, + Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitors.add(competitor); @@ -832,7 +832,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, - "Froderik", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -981,7 +981,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -992,7 +992,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1183,7 +1183,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1194,7 +1194,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1285,7 +1285,7 @@ public class MasterDataImportTest { BoatClass boatClassToOverride = new BoatClassImpl("H16", true); DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; - Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, + Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitorsToOverride.add(competitorToOverride); @@ -1483,7 +1483,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1494,7 +1494,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1619,7 +1619,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1630,7 +1630,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1867,7 +1867,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1878,7 +1878,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -2097,7 +2097,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -2108,7 +2108,7 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index a066b9d3e15..833baa73cc9 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -105,7 +105,7 @@ public class WindByRaceLogTest { } private Competitor createCompetitor(final DomainFactory masterDomainFactory) { - return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", + return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 87020418d70..92d27d2369b 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -99,10 +99,10 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl } @Override - public Competitor updateCompetitor(String idAsString, String newName, Color newRgbDisplayColor, String newEmail, String newSailId, + public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newRgbDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = super.updateCompetitor(idAsString, newName, newRgbDisplayColor, newEmail, newSailId, newNationality, + Competitor result = super.updateCompetitor(idAsString, newName, newShortName, newRgbDisplayColor, newEmail, newSailId, newNationality, newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); storeTo.storeCompetitor(result); return result; 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 a1a22d5d16b..3ae02e3e22c 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 @@ -578,7 +578,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes this.competitorStore.addCompetitorUpdateListener(new CompetitorUpdateListener() { @Override public void competitorUpdated(Competitor competitor) { - replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor + replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor.getShortName(), competitor .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), @@ -2767,7 +2767,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes // the following should actually be redundant because during de-serialization the Competitor objects, // whose classes implement IsManagedByCache, should already have been got/created from/in the // competitor store - competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), + competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), dynamicCompetitor.getShortName(), dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(), dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), dynamicCompetitor.getSearchTag()); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java index 78f528c2e90..03324978e2f 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java @@ -13,6 +13,7 @@ public class UpdateCompetitor extends AbstractRacingEventServiceOperationnull, the competitor obtains the "NONE" nationality, usually represented by a white * flag */ - public UpdateCompetitor(String idAsString, String newName, Color newDisplayColor, String newEmail, + public UpdateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { super(); this.idAsString = idAsString; this.newName = newName; + this.newShortName = newShortName; this.newDisplayColor = newDisplayColor; this.newSailId = newSailId; this.newNationality = newNationality; @@ -58,7 +60,7 @@ public class UpdateCompetitor extends AbstractRacingEventServiceOperation competitors = new ArrayList(); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", "Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", "Red Bull", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", "Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); RaceLog log = new RaceLogImpl(UUID.randomUUID()); final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); From 5d7e3180e274d45320cbfdb1f0e823a3372aaac7 Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 12 Aug 2016 16:27:01 +0200 Subject: [PATCH 002/271] First implementation of CompetitorAndBoatStore (name is still CompetitorStore to minimize merge conflicts) including persistence for boats and the new 'id' field of each boat. Will add more tests now. --- .../persistence/DomainObjectFactory.java | 7 +- .../persistence/MongoObjectFactory.java | 13 + .../persistence/impl/CollectionNames.java | 15 +- .../impl/DomainObjectFactoryImpl.java | 21 ++ .../impl/MongoObjectFactoryImpl.java | 32 ++- .../src/com/sap/sailing/domain/base/Boat.java | 25 +- .../domain/base/BoatChangeListener.java | 16 +- .../sap/sailing/domain/base/BoatFactory.java | 31 +++ .../sailing/domain/base/CompetitorStore.java | 67 ++++- .../domain/base/SharedDomainFactory.java | 2 +- .../sailing/domain/base/impl/BoatImpl.java | 62 ++++- .../domain/base/impl/CompetitorImpl.java | 2 +- .../sailing/domain/base/impl/DynamicBoat.java | 25 +- .../base/impl/SharedDomainFactoryImpl.java | 37 ++- .../impl/TransientCompetitorStoreImpl.java | 245 +++++++++++++++++- .../impl/DomainFactoryImpl.java | 7 +- .../domain/test/AbstractLeaderboardTest.java | 12 +- .../domain/test/OfflineSerializationTest.java | 4 +- .../domain/test/StoredTrackBasedTest.java | 4 +- .../com/sap/sailing/domain/test/TackTest.java | 4 +- .../sailing/domain/test/TrackBasedTest.java | 4 +- .../sap/sailing/domain/test/TrackTest.java | 16 +- .../com/sap/sailing/domain/test/WindTest.java | 4 +- .../AbstractMockedRaceMarkPassingTest.java | 6 +- .../impl/DomainFactoryImpl.java | 6 +- .../domain/base/impl/DomainFactoryImpl.java | 2 +- .../gwt/ui/test/AbstractListFilterTest.java | 12 +- .../gwt/ui/server/SailingServiceImpl.java | 5 +- ...StoringAndRetrievingLeaderboardGroups.java | 14 +- .../TestStoringAndRetrievingLeaderboards.java | 8 +- .../impl/BoatJsonDeserializer.java | 48 +++- .../impl/CompetitorJsonDeserializer.java | 15 +- .../impl/BoatJsonSerializer.java | 29 ++- .../impl/CompetitorJsonSerializer.java | 8 +- .../gateway/test/AbstractJsonExportTest.java | 4 +- .../test/jaxrs/AbstractJaxRsApiTest.java | 4 +- .../CompetitorsResourceTeamImageTest.java | 2 +- .../test/jaxrs/CompetitorsResourceTest.java | 2 +- .../test/CompetitorReplicationTest.java | 2 +- .../TrackedRaceContentsReplicationTest.java | 2 +- ...ithGPSFixStoreContentsReplicationTest.java | 2 +- .../test/ApplyScoresFromRaceLogTest.java | 4 +- .../server/test/CompetitorStoreTest.java | 37 ++- .../server/test/LeaderboardStorageTest.java | 2 +- .../server/test/MasterDataImportTest.java | 40 +-- .../server/test/WindByRaceLogTest.java | 2 +- .../impl/PersistentCompetitorStore.java | 55 +++- .../server/impl/RacingEventServiceImpl.java | 8 +- .../structureimport/StructureImporter.java | 2 +- .../app/data/OnlineDataManager.java | 4 +- 50 files changed, 789 insertions(+), 191 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java index 2278bf700a4..1351b9cfa3a 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java @@ -9,6 +9,7 @@ import java.util.Set; import com.mongodb.DBObject; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; @@ -126,10 +127,14 @@ public interface DomainObjectFactory { /** * Loads all competitors, and resolves them via the domain factory. - * @return */ Collection loadAllCompetitors(); + /** + * Loads all boats, and resolves them via the domain factory. + */ + Collection loadAllBoats(); + DomainFactory getBaseDomainFactory(); Iterable> loadAllDeviceConfigurations(); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java index 71f6cd549e0..464458e6346 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java @@ -5,6 +5,7 @@ import java.net.URL; import com.mongodb.DB; import com.mongodb.DBObject; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; @@ -129,6 +130,18 @@ public interface MongoObjectFactory { void removeCompetitor(Competitor competitor); + /** + * Stores a boat. This should not be done for boats for which + * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, + * where this data is otherwise not recoverable. + * @param boat the boat to store/update in the database + */ + void storeBoat(Boat boat); + + void removeAllBoats(); + + void removeBoat(Boat boat); + DB getDatabase(); void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java index eeacdadee93..4700115ecd5 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java @@ -67,16 +67,21 @@ public enum CollectionNames { */ REGATTA_FOR_RACE_ID, - /** - * Stores the race log events for a tracked race. - */ /** - * Stores competitors for smartphone tracking. + * Stores competitors. */ COMPETITORS, - + + /** + * Stores boats. + */ + BOATS, + + /** + * Stores the race log events for a tracked race. + */ RACE_LOGS, REGATTA_LOGS, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 27b784d3456..3d864e96704 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -111,6 +111,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEv import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnTimeFactorEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -204,6 +205,7 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; @@ -231,6 +233,7 @@ import com.sap.sse.shared.media.impl.VideoDescriptorImpl; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); private final CompetitorJsonDeserializer competitorDeserializer; + private final BoatJsonDeserializer boatDeserializer; private final DB database; @@ -257,6 +260,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } this.baseDomainFactory = baseDomainFactory; this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); + this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } @@ -2025,6 +2029,23 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return result; } + @Override + public Collection loadAllBoats() { + ArrayList result = new ArrayList(); + DBCollection collection = database.getCollection(CollectionNames.BOATS.name()); + try { + for (DBObject o : collection.find()) { + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o))); + Boat b = boatDeserializer.deserialize(json); + result.add(b); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load boats."); + logger.log(Level.SEVERE, "loadBoats", e); + } + return result; + } + @Override public Iterable> loadAllDeviceConfigurations() { Map result = new HashMap<>(); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 8c10c04d2e4..66aa6548af1 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -60,6 +60,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; @@ -108,6 +109,7 @@ 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.server.gateway.serialization.JsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; @@ -126,6 +128,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); + private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; /** @@ -1233,6 +1236,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } return passing; } + @Override public void storeCompetitor(Competitor competitor) { DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); @@ -1244,7 +1248,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void removeAllCompetitors() { - logger.info("Removing all persistent competitor info"); + logger.info("Removing all persistent competitors"); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); collection.drop(); } @@ -1256,7 +1260,31 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); collection.remove(query, WriteConcern.SAFE); } - + + @Override + public void storeBoat(Boat boat) { + DBCollection collection = database.getCollection(CollectionNames.BOATS.name()); + JSONObject json = boatSerializer.serialize(boat); + DBObject query = (DBObject) JSON.parse(BoatJsonSerializer.getBoatIdQuery(boat).toString()); + DBObject entry = (DBObject) JSON.parse(json.toString()); + collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); + } + + @Override + public void removeAllBoats() { + logger.info("Removing all persistent boats"); + DBCollection collection = database.getCollection(CollectionNames.BOATS.name()); + collection.drop(); + } + + @Override + public void removeBoat(Boat boat) { + logger.info("Removing persistent boat "+boat.getName()+" with ID "+boat.getId()); + DBCollection collection = database.getCollection(CollectionNames.BOATS.name()); + DBObject query = (DBObject) JSON.parse(BoatJsonSerializer.getBoatIdQuery(boat).toString()); + collection.remove(query, WriteConcern.SAFE); + } + @Override public void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) { DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name()); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java index 0746e5e74da..33591a285a0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java @@ -1,14 +1,33 @@ package com.sap.sailing.domain.base; import com.sap.sse.common.Color; -import com.sap.sse.common.Named; +import com.sap.sse.common.IsManagedByCache; +import com.sap.sse.common.NamedWithID; import com.sap.sse.datamining.annotations.Dimension; -public interface Boat extends Named { - BoatClass getBoatClass(); +/** + * The boat being sailed by a competitor. + * + */ +public interface Boat extends NamedWithID, IsManagedByCache{ + BoatClass getBoatClass(); @Dimension(messageKey="SailID") String getSailID(); Color getColor(); + + /** + * Adds a listener to this boat. + * Adding a listener that is already part of this boat's listeners set remains without effect. + */ + void addBoatChangeListener(BoatChangeListener listener); + + /** + * Removes a listener from this boat. + * Trying to remove a listener that is not currently in the set of this boats's listener remains + * without effect. + */ + void removeBoatChangeListener(BoatChangeListener listener); + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java index cc86744e89b..93c7185c130 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java @@ -1,5 +1,11 @@ -package com.sap.sailing.domain.base; - -public interface BoatChangeListener { - void sailIdChanged(String oldSailId, String newSailId); -} +package com.sap.sailing.domain.base; + +import com.sap.sse.common.Color; + +public interface BoatChangeListener { + void nameChanged(String oldName, String newName); + + void colorChanged(Color oldColor, Color newColor); + + void sailIdChanged(String oldSailId, String newSailId); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java new file mode 100644 index 00000000000..2ad9809f175 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java @@ -0,0 +1,31 @@ +package com.sap.sailing.domain.base; + +import java.io.Serializable; + +import com.sap.sse.common.Color; + +/** + * Base interface for classes managing a set of {@link Boat} objects. + */ +public interface BoatFactory { + /** + * If a valid boat is returned and the caller has information available that could be used to update the boat, + * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Boat)}, and if true, + * must call {@link #getOrCreateBoat()} to cause an update of the boat's values. + */ + Boat getExistingBoatById(Serializable boatId); + + /** + * Checks if the boat shall be updated from the default provided by, e.g., a tracking infrastructure. + * Callers of {@link #getExistingBoatById(Serializable)} or {@link #getExistingBoatByIdAsString(String)} + * must call this method in case they retrieve a valid boat by ID and have data available that can be used to update + * the . + */ + boolean isBoatToUpdateDuringGetOrCreate(Boat result); + + Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color); + + Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color); + + Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 5e9c6009bb8..f152da4edb7 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -5,22 +5,27 @@ import java.net.URI; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; /** - * Manages a set of {@link Competitor} objects. There may be a transient implementation based on a simple cache, + * Manages a set of {@link Competitor} and {@link Boat} objects. There may be a transient implementation based on a simple cache, * and there may be persistent implementations. * * @author Axel Uhl (d043530) * */ -public interface CompetitorStore extends CompetitorFactory { +public interface CompetitorStore extends CompetitorFactory, BoatFactory { public interface CompetitorUpdateListener { void competitorUpdated(Competitor competitor); } - + + public interface BoatUpdateListener { + void boatUpdated(Boat boat); + } + /** * If a valid competitor is returned and the caller has information available that could be used to update the competitor, * the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if true, @@ -42,12 +47,12 @@ public interface CompetitorStore extends CompetitorFactory { */ void allowCompetitorResetToDefaults(Competitor competitor); - int size(); + int getCompetitorsCount(); /** * Removes all competitors from this store. Use with due care. */ - void clear(); + void clearCompetitors(); /** * Obtains a non-live snapshot of the list of competitors managed by this store. @@ -77,4 +82,56 @@ public interface CompetitorStore extends CompetitorFactory { void addCompetitorUpdateListener(CompetitorUpdateListener listener); void removeCompetitorUpdateListener(CompetitorUpdateListener listener); + + /** + * If a valid boat is returned and the caller has information available that could be used to update the boat, + * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, + * must call {@link #getOrCreateBoat(..)} to cause an update of the boat's values. + */ + Boat getExistingBoatByIdAsString(String idAsString); + + /** + * When a boat is queried using {@link #getOrCreateBoat(...)}, + * and the boat object for that ID already exists, it is generally returned unchanged, and the properties + * are not evaluated. This makes the data in this store generally "write-once." This + * method can be used to reset a boat object to what a tracking provider or an external system supplies to + * {@link #getOrCreateBoat(...)}. After calling this method, the + * next call to {@link #getOrCreateBoat(...)} with boat's {@link Boat#getId() ID} will + * {@link #updateBoat(...)} the boat in its updatable properties such as sail ID and the color. + */ + void allowBoatResetToDefaults(Boat boat); + + int getBoatsCount(); + + /** + * Removes all boats from this store. Use with due care. + */ + void clearBoats(); + + /** + * Obtains a non-live snapshot of the list of boats managed by this store. + */ + Iterable getBoats(); + + void removeBoat(Boat boat); + + /** + * Updates the boat with {@link Boat#getId() ID} id by setting the name, sail ID, etc. to + * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. + * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will + * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

+ * + * If no boat with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. + */ + Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId); + + BoatDTO convertToBoatDTO(Boat boat); + + /** + * Listeners added here are notified whenever {@link #updateBoat(...)} is called + * for any boat in this store. + */ + void addBoatUpdateListener(BoatUpdateListener listener); + + void removeBoatUpdateListener(BoatUpdateListener listener); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java index 1af85ef3f12..5e7d5476206 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java @@ -9,7 +9,7 @@ import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.PassingInstruction; -public interface SharedDomainFactory extends CompetitorFactory { +public interface SharedDomainFactory extends CompetitorFactory, BoatFactory { /** * Looks up or, if not found, creates a {@link Nationality} object and re-uses threeLetterIOCCode also as the diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java index 9a7f3a50b8a..3af956846cd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java @@ -2,39 +2,49 @@ package com.sap.sailing.domain.base.impl; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatChangeListener; import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sse.common.Color; import com.sap.sse.common.Util; -import com.sap.sse.common.impl.NamedImpl; -public class BoatImpl extends NamedImpl implements DynamicBoat { +public class BoatImpl implements DynamicBoat { private static final long serialVersionUID = 3489730487528955788L; private final BoatClass boatClass; + private final Serializable id; private String sailID; - private final Color color; + private Color color; + private String name; private transient Set listeners; - public BoatImpl(String name, BoatClass boatClass, String sailID) { - this(name, boatClass, sailID, null); + public BoatImpl(Serializable id, String name, BoatClass boatClass, String sailId) { + this(id, name, boatClass, sailId, null); } - public BoatImpl(String name, BoatClass boatClass, String sailID, Color color) { - super(name); + public BoatImpl(Serializable id, String name, BoatClass boatClass, String sailID, Color color) { + this.id = id; + this.name = name; this.boatClass = boatClass; this.sailID = sailID; this.color = color; this.listeners = new HashSet(); } - + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); listeners = new HashSet(); } + @Override + public Serializable getId() { + return id; + } + @Override public BoatClass getBoatClass() { return boatClass; @@ -49,7 +59,23 @@ public class BoatImpl extends NamedImpl implements DynamicBoat { public Color getColor() { return color; } - + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String newName) { + final String oldName = this.name; + if (!Util.equalsWithNull(oldName, newName)) { + this.name = newName; + for (BoatChangeListener listener : getListeners()) { + listener.nameChanged(oldName, newName); + } + } + } + @Override public void setSailId(String newSailId) { final String oldSailId = this.sailID; @@ -61,6 +87,22 @@ public class BoatImpl extends NamedImpl implements DynamicBoat { } } + @Override + public void setColor(Color newColor) { + final Color oldColor = this.color; + if (!Util.equalsWithNull(oldColor, newColor)) { + this.color = newColor; + for (BoatChangeListener listener : getListeners()) { + listener.colorChanged(oldColor, newColor); + } + } + } + + @Override + public Boat resolve(SharedDomainFactory domainFactory) { + return domainFactory.getOrCreateBoat(getId(), getName(), getBoatClass(), getSailID(), getColor()); + } + @Override public void addBoatChangeListener(BoatChangeListener listener) { synchronized (listeners) { @@ -69,7 +111,7 @@ public class BoatImpl extends NamedImpl implements DynamicBoat { } @Override - public void removeCompetitorChangeListener(BoatChangeListener listener) { + public void removeBoatChangeListener(BoatChangeListener listener) { synchronized (listeners) { listeners.remove(listener); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java index e046dd56e22..84ad336ad14 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java @@ -139,7 +139,7 @@ public class CompetitorImpl implements DynamicCompetitor { synchronized (listeners) { listeners.remove(listener); } - getBoat().removeCompetitorChangeListener(listener); + getBoat().removeBoatChangeListener(listener); getTeam().removeNationalityChangeListener(listener); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java index b3131fc9e4c..cadf8a6d2c0 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java @@ -1,13 +1,12 @@ -package com.sap.sailing.domain.base.impl; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.BoatChangeListener; - -public interface DynamicBoat extends Boat { - void setSailId(String newSailId); - - void addBoatChangeListener(BoatChangeListener listener); - - void removeCompetitorChangeListener(BoatChangeListener listener); - -} +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sse.common.Color; + +public interface DynamicBoat extends Boat { + void setSailId(String sailId); + + void setName(String name); + + void setColor(Color color); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 7f2307cb27a..3da0db78f0a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -16,12 +16,14 @@ 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.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.base.SharedDomainFactory; @@ -64,7 +66,7 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { private final Map boatClassCache; - protected final CompetitorStore competitorStore; + protected final CompetitorStore competitorAndBoatStore; private final Map courseAreaCache; @@ -126,7 +128,7 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { controlPointWithTwoMarksCache = new HashMap(); controlPointWithTwoMarksIdCache = new HashMap(); boatClassCache = new HashMap(); - this.competitorStore = competitorStore; + this.competitorAndBoatStore = competitorStore; waypointCache = new ConcurrentHashMap(); // FIXME ass also bug 3347: mapping to lower case should rather work through a common unification / canonicalization of boat class names mayStartWithNoUpwindLeg = Collections.singleton(BoatClassMasterdata.unifyBoatClassName(BoatClassMasterdata.EXTREME_40.getDisplayName())); @@ -323,7 +325,7 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { @Override public CompetitorStore getCompetitorStore() { - return competitorStore; + return competitorAndBoatStore; } @Override @@ -332,8 +334,8 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { } @Override - public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) { - return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(result); + public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { + return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(competitor); } @Override @@ -347,6 +349,31 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } + @Override + public Boat getExistingBoatById(Serializable boatId) { + return getCompetitorStore().getExistingBoatById(boatId); + } + + @Override + public boolean isBoatToUpdateDuringGetOrCreate(Boat boat) { + return getCompetitorStore().isBoatToUpdateDuringGetOrCreate(boat); + } + + @Override + public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { + return getCompetitorStore().getOrCreateBoat(id, name, boatClass, sailId, color); + } + + @Override + public Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color) { + return getCompetitorStore().getOrCreateBoat(competitor, name, boatClass, sailId, color); + } + + @Override + public Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color) { + return getCompetitorStore().getOrCreateBoat(leaderboardGroup, name, boatClass, sailId, color); + } + @Override public DeviceConfigurationMatcher getOrCreateDeviceConfigurationMatcher(List clientIdentifiers) { DeviceConfigurationMatcher probe = createMatcher(clientIdentifiers); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 64c5b83507b..6feac7974d5 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -14,8 +14,11 @@ import java.util.WeakHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; @@ -32,7 +35,10 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab private static final long serialVersionUID = -4198298775476586931L; private final Map competitorCache; private final Map competitorsByIdAsString; - private transient Set listeners; + private transient Set competitorUpdateListeners; + private final Map boatCache; + private final Map boatsByIdAsString; + private transient Set boatUpdateListeners; /** * The competitors contained in this map will have their changeable properties @@ -42,7 +48,11 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab private final Set competitorsToUpdateDuringGetOrCreate; private transient WeakHashMap weakCompetitorDTOCache; + + private final Set boatsToUpdateDuringGetOrCreate; + private transient WeakHashMap weakBoatDTOCache; + private final NamedReentrantReadWriteLock lock; public TransientCompetitorStoreImpl() { @@ -51,23 +61,30 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitorsByIdAsString = new HashMap(); competitorsToUpdateDuringGetOrCreate = new HashSet(); weakCompetitorDTOCache = new WeakHashMap(); - listeners = Collections.synchronizedSet(new HashSet()); + competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + boatCache = new HashMap(); + boatsByIdAsString = new HashMap(); + boatsToUpdateDuringGetOrCreate = new HashSet(); + weakBoatDTOCache = new WeakHashMap(); + boatUpdateListeners = Collections.synchronizedSet(new HashSet()); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); weakCompetitorDTOCache = new WeakHashMap(); - listeners = Collections.synchronizedSet(new HashSet()); + competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + weakBoatDTOCache = new WeakHashMap(); + boatUpdateListeners = Collections.synchronizedSet(new HashSet()); } @Override public void addCompetitorUpdateListener(CompetitorUpdateListener listener) { - listeners.add(listener); + competitorUpdateListeners.add(listener); } @Override public void removeCompetitorUpdateListener(CompetitorUpdateListener listener) { - listeners.remove(listener); + competitorUpdateListeners.remove(listener); } private Competitor createCompetitor(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, @@ -120,13 +137,13 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab return result; } - private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor result) { - competitorsToUpdateDuringGetOrCreate.remove(result); + private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor competitor) { + competitorsToUpdateDuringGetOrCreate.remove(competitor); } @Override - public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result) { - return competitorsToUpdateDuringGetOrCreate.contains(result); + public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { + return competitorsToUpdateDuringGetOrCreate.contains(competitor); } @Override @@ -150,7 +167,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public int size() { + public int getCompetitorsCount() { LockUtil.lockForRead(lock); try { return competitorCache.size(); @@ -160,7 +177,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public void clear() { + public void clearCompetitors() { LockUtil.lockForWrite(lock); try { competitorCache.clear(); @@ -221,8 +238,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab LockUtil.unlockAfterWrite(lock); } } - synchronized (listeners) { - for (CompetitorUpdateListener listener : listeners) { + synchronized (competitorUpdateListeners) { + for (CompetitorUpdateListener listener : competitorUpdateListeners) { listener.competitorUpdated(competitor); } } @@ -275,4 +292,206 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab LockUtil.unlockAfterWrite(lock); } } + + /** Boat stuff starts here */ + + @Override + public void addBoatUpdateListener(BoatUpdateListener listener) { + boatUpdateListeners.add(listener); + } + + @Override + public void removeBoatUpdateListener(BoatUpdateListener listener) { + boatUpdateListeners.remove(listener); + } + + private Boat createBoat(Serializable id, String name, BoatClass boatClass, String sailID, Color color) { + Boat result = new BoatImpl(id, name, boatClass, sailID, color); + addNewBoat(result.getId(), result); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Created boat "+name+" with ID "+id, new Exception("Here is where it happened")); + } + return result; + } + + /** + * Adds the boat to this transient boat collection so that it is available in + * {@link #getExistingBoatById(Serializable)}. Subclasses may override in case they need to take additional + * measures such as durably storing the boat. Overriding implementations must call this implementation. + */ + protected void addNewBoat(Serializable id, Boat boat) { + LockUtil.lockForWrite(lock); + try { + boatCache.put(id, boat); + boatsByIdAsString.put(id.toString(), boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { + // create compound boat ID here? + Boat result = getExistingBoatById(id); // avoid synchronization for successful read access + if (result == null) { + LockUtil.lockForWrite(lock); + try { + result = getExistingBoatById(id); // try again, now while holding the write lock + if (result == null) { + result = createBoat(id, name, boatClass, sailId, color); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } else if (isBoatToUpdateDuringGetOrCreate(result)) { + updateBoat(result.getId().toString(), name, color, sailId); + boatNoLongerToUpdateDuringGetOrCreate(result); + } + return result; + } + + @Override + public Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color) { + return getOrCreateBoat(leaderboardGroup.getId(), name, boatClass, sailId, color); + } + + @Override + public Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color) { + return getOrCreateBoat(competitor.getId(), name, boatClass, sailId, color); + } + + private void boatNoLongerToUpdateDuringGetOrCreate(Boat boat) { + boatsToUpdateDuringGetOrCreate.remove(boat); + } + + @Override + public boolean isBoatToUpdateDuringGetOrCreate(Boat boat) { + return boatsToUpdateDuringGetOrCreate.contains(boat); + } + + @Override + public Boat getExistingBoatById(Serializable boatId) { + LockUtil.lockForRead(lock); + try { + return boatCache.get(boatId); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public Boat getExistingBoatByIdAsString(String boatIdAsString) { + LockUtil.lockForRead(lock); + try { + return boatsByIdAsString.get(boatIdAsString); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public int getBoatsCount() { + LockUtil.lockForRead(lock); + try { + return boatCache.size(); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void clearBoats() { + LockUtil.lockForWrite(lock); + try { + boatCache.clear(); + boatsByIdAsString.clear(); + boatsToUpdateDuringGetOrCreate.clear(); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Clearing boat store "+this, new Exception("here is where it happened")); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Iterable getBoats() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(boatCache.values()); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void removeBoat(Boat boat) { + LockUtil.lockForWrite(lock); + try { + logger.fine("Removing boat "+boat+" from boat store "+this); + boatCache.remove(boat.getId()); + boatsByIdAsString.remove(boat.getId().toString()); + weakBoatDTOCache.remove(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId) { + DynamicBoat boat = (DynamicBoat) getExistingBoatByIdAsString(idAsString); + if (boat != null) { + LockUtil.lockForWrite(lock); + try { + boat.setName(newName); + boat.setSailId(newSailId); + boat.setColor(newColor); + weakBoatDTOCache.remove(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + synchronized (boatUpdateListeners) { + for (BoatUpdateListener listener : boatUpdateListeners) { + listener.boatUpdated(boat); + } + } + return boat; + } + + @Override + public BoatDTO convertToBoatDTO(Boat b) { + LockUtil.lockForRead(lock); + boolean needToUnlockReadLock = true; + try { + BoatDTO boatDTO = weakBoatDTOCache.get(b); + if (boatDTO == null) { + LockUtil.unlockAfterRead(lock); + needToUnlockReadLock = false; + LockUtil.lockForWrite(lock); + boatDTO = weakBoatDTOCache.get(b); + if (boatDTO == null) { + boatDTO = new BoatDTO(b.getName(), b.getSailID(), b.getColor()); + weakBoatDTOCache.put(b, boatDTO); + } + } + return boatDTO; + } finally { + if (needToUnlockReadLock) { + LockUtil.unlockAfterRead(lock); + } else { + LockUtil.unlockAfterWrite(lock); + } + } + } + + @Override + public void allowBoatResetToDefaults(Boat boat) { + LockUtil.lockForWrite(lock); + try { + boatsToUpdateDuringGetOrCreate.add(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index a3662bb57e1..2e8dfbcdc0a 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -117,7 +117,7 @@ public class DomainFactoryImpl implements DomainFactory { CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); Competitor result = competitorStore.getExistingCompetitorByIdAsString(competitor.getID()); if (result == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)) { - DynamicBoat boat = new BoatImpl(competitor.getName(), boatClass, competitor.getBoatID()); + DynamicBoat boat = new BoatImpl(result.getId(), competitor.getName(), boatClass, competitor.getBoatID()); List teamMembers = new ArrayList(); for (CrewMember crewMember: competitor.getCrew()) { DynamicPerson person = new PersonImpl(crewMember.getName().trim(), getOrCreateNationality(crewMember.getNationality()), @@ -134,14 +134,15 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Competitor createCompetitorWithoutID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, String raceId, BoatClass boatClass) { Competitor result = null; - DynamicBoat boat = new BoatImpl(competitor.getName(), boatClass, competitor.getBoatID()); List teamMembers = new ArrayList(); for (String teamMemberName : competitor.getName().split("[-+&]")) { teamMembers.add(new PersonImpl(teamMemberName.trim(), getOrCreateNationality(competitor.getThreeLetterIOCCode()), /* dateOfBirth */ null, teamMemberName.trim())); } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); - result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(getCompetitorID(competitor.getBoatID(), raceId, boatClass), + String competitorID = getCompetitorID(competitor.getBoatID(), raceId, boatClass); + DynamicBoat boat = new BoatImpl(competitorID, competitor.getName(), boatClass, competitor.getBoatID()); + result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitorID, competitor.getName(), null /* short name */, null /*displayColor*/, null /*email*/, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); return result; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 4c9f57721dc..333e06d6ffe 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -19,8 +19,8 @@ public abstract class AbstractLeaderboardTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", + competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) { @@ -28,8 +28,8 @@ public abstract class AbstractLeaderboardTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", + competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); } @@ -38,7 +38,7 @@ public abstract class AbstractLeaderboardTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(id, + competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index fb0a7bd4aae..b337738fc62 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -192,8 +192,8 @@ public class OfflineSerializationTest extends AbstractSerializationTest { new PersonImpl(competitorName, senderDomainFactory.getOrCreateNationality("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + competitorName + "'s boat", senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Competitor receiversCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); Competitor receiversSecondCopyOfCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); assertSame(receiversCompetitor1, receiversSecondCopyOfCompetitor1); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 4545b7e6efa..f7e7a4fa285 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -117,8 +117,8 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) { DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null); DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null); - Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, new BoatImpl(competitorName, - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, new BoatImpl("123", + competitorName, new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DynamicGPSFixTrack track = readTrack(c, KIELER_WOCHE); if (track != null) { tracks.put(c, track); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 3d767daf1aa..a577752799b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -39,8 +39,8 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Wolfgang Hunger's boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + "Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", Collections.singleton(competitor), new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()), /* useMarkPassingCalculator */ false)); } 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 dcfcc4910c8..f067d3468ae 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 @@ -86,8 +86,8 @@ public abstract class TrackBasedTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } /** diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index faedaf6d37e..53300c21e5f 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -72,7 +72,7 @@ public class TrackTest { @Before public void setUp() throws InterruptedException { - track = new DynamicGPSFixMovingTrackImpl(new BoatImpl("MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + track = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 3); @@ -112,7 +112,7 @@ public class TrackTest { @Test public void positionEstimationTest() { track = new DynamicGPSFixMovingTrackImpl( - new BoatImpl("MyFirstBoat", new BoatClassImpl("505", true), null), 5000, null); + new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", true), null), 5000, null); DegreePosition p1 = new DegreePosition(0, 0); DegreePosition p2 = new DegreePosition(90, 0); TimePoint t1 = MillisecondsTimePoint.now(); @@ -1039,8 +1039,8 @@ public class TrackTest { @Test public void testValidCheckForFixThatSaysItsAsFastAsItWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s AbstractBearing bearing = new DegreeBearingImpl(90); @@ -1060,8 +1060,8 @@ public class TrackTest { @Test public void testValidCheckForFixThatSaysItsFasterThanItActuallyWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s AbstractBearing bearing = new DegreeBearingImpl(90); @@ -1081,8 +1081,8 @@ public class TrackTest { @Test public void testValidCheckForFixThatSaysItsSlowerThanItActuallyWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s AbstractBearing bearing = new DegreeBearingImpl(90); 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 448b02160f3..2cbf522906a 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 @@ -276,8 +276,8 @@ public class WindTest { new PersonImpl("Test Competitor", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Test Competitor" + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + "Test Competitor" + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final BoatClass boatClass = domainFactory.getOrCreateBoatClass("ESS40"); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl( new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, 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 edc1baa1758..4684ef7b19e 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 @@ -45,9 +45,9 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class AbstractMockedRaceMarkPassingTest { final BoatClassImpl boatClass = new BoatClassImpl("boat", true, "boat", new MeterDistance(10), new MeterDistance(5), null); - protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, new BoatImpl("boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected Mark m = new MarkImpl("Mark"); protected Mark gate1 = new MarkImpl("Gate1"); 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 d23ea7779cf..6cb61474ebc 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 @@ -261,7 +261,7 @@ public class DomainFactoryImpl implements DomainFactory { logger.log(Level.SEVERE, "Unknown nationality "+nationalityAsString+" for competitor "+name+"; leaving null", iae); } DynamicTeam team = createTeam(name, nationality, competitorId); - DynamicBoat boat = new BoatImpl(shortName, boatClass, shortName); + DynamicBoat boat = new BoatImpl(competitorId, shortName, boatClass, shortName); result = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, null /* email */, null /* flagImag */, team, boat, (double) timeOnTimeFactor, new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); @@ -576,8 +576,8 @@ public class DomainFactoryImpl implements DomainFactory { Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); if (existingCompetitor != null && competitorBoatInfo != null) { - Boat boatOfCompetitor = new BoatImpl(competitorBoatInfo.getA(), defaultBoatClass, - competitorBoatInfo.getB(), AbstractColor.getCssColor(competitorBoatInfo.getC())); + Boat boatOfCompetitor = new BoatImpl(existingCompetitor.getId(), competitorBoatInfo.getA(), + defaultBoatClass, competitorBoatInfo.getB(), AbstractColor.getCssColor(competitorBoatInfo.getC())); competitorBoatInfos.put(existingCompetitor, boatOfCompetitor); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 0e51ef84538..2ca67433ab8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -136,7 +136,7 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain @Override public CompetitorDTO convertToCompetitorDTO(Competitor c) { - return competitorStore.convertToCompetitorDTO(c); + return competitorAndBoatStore.convertToCompetitorDTO(c); } @Override diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java index 10f0f64f74e..f29df643b6e 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java @@ -25,12 +25,12 @@ public class AbstractListFilterTest { @Before public void setUp() { - all.add(new BoatImpl("Race 1", null, "Kiel")); - all.add(new BoatImpl("Race 2", null, "Kiel")); - all.add(new BoatImpl("Race 3", null, "Kiel")); - all.add(new BoatImpl("Race 1", null, "Wannsee")); - all.add(new BoatImpl("Race 2", null, "Wannsee")); - all.add(new BoatImpl("Final", null, "Wannsee")); + all.add(new BoatImpl("1", "Race 1", null, "Kiel")); + all.add(new BoatImpl("2", "Race 2", null, "Kiel")); + all.add(new BoatImpl("3", "Race 3", null, "Kiel")); + all.add(new BoatImpl("4", "Race 1", null, "Wannsee")); + all.add(new BoatImpl("5", "Race 2", null, "Wannsee")); + all.add(new BoatImpl("6", "Final", null, "Wannsee")); } @Test 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 60f47e7b7ee..33f2f497262 100644 --- 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 @@ -4744,12 +4744,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final CompetitorDTO result; // new competitor if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { + UUID competitorUUID = UUID.randomUUID(); BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(competitor.getBoatClass().getName()); DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - DynamicBoat boat = new BoatImpl(competitor.getName() + " boat", boatClass, competitor.getSailID()); + DynamicBoat boat = new BoatImpl(competitorUUID, competitor.getName() + " boat", boatClass, competitor.getSailID()); result = getBaseDomainFactory().convertToCompetitorDTO( - getBaseDomainFactory().getOrCreateCompetitor(UUID.randomUUID(), competitor.getName(), competitor.getShortName(), + getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, boat, competitor.getTimeOnTimeFactor(), diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index d8381131ddb..4d66d7af6ed 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -69,7 +69,7 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe @Before public void setUp() { - DomainFactory.INSTANCE.getCompetitorStore().clear(); + DomainFactory.INSTANCE.getCompetitorStore().clearCompetitors(); mongoObjectFactory = new MongoObjectFactoryImpl(db); domainObjectFactory = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE); } @@ -116,12 +116,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -172,12 +172,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -228,12 +228,12 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index d9541c18032..cbc0b2fa1a3 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -49,7 +49,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { @Before public void clearCompetitorStore() { - DomainFactory.INSTANCE.getCompetitorStore().clear(); + DomainFactory.INSTANCE.getCompetitorStore().clearCompetitors(); } @Test @@ -81,7 +81,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitor(hasso); @@ -354,7 +354,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", "WH", Color.RED, "someone@nowhere.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -382,7 +382,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); return competitor; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java index 22759b45efc..17330618b77 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java @@ -1,31 +1,61 @@ package com.sap.sailing.server.gateway.deserialization.impl; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.util.UUID; + import org.json.simple.JSONObject; import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.BoatFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; +import com.sap.sse.common.Color; +import com.sap.sse.common.impl.RGBColor; public class BoatJsonDeserializer implements JsonDeserializer { private final BoatClassJsonDeserializer boatClassDeserializer; + private final BoatFactory boatFactory; + + public static BoatJsonDeserializer create(SharedDomainFactory baseDomainFactory) { + return new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory)); + } - public BoatJsonDeserializer(BoatClassJsonDeserializer boatClassDeserializer) { + public BoatJsonDeserializer(BoatFactory boatFactory, BoatClassJsonDeserializer boatClassDeserializer) { super(); + this.boatFactory = boatFactory; this.boatClassDeserializer = boatClassDeserializer; } public DynamicBoat deserialize(JSONObject object) throws JsonDeserializationException { - String name = (String) object.get(BoatJsonSerializer.FIELD_NAME); - final Object sailID = object.get(BoatJsonSerializer.FIELD_SAIL_ID); - String sailId = sailID == null ? null : sailID.toString(); - BoatClass boatClass = null; - if (boatClassDeserializer != null) { - boatClass = boatClassDeserializer.deserialize(Helpers.getNestedObjectSafe(object, BoatJsonSerializer.FIELD_BOAT_CLASS)); + Serializable boatId = (Serializable) object.get(BoatJsonSerializer.FIELD_ID); + try { + Class idClass = Class.forName((String) object.get(BoatJsonSerializer.FIELD_ID_TYPE)); + if (Number.class.isAssignableFrom(idClass)) { + Constructor constructorFromString = idClass.getConstructor(String.class); + boatId = (Serializable) constructorFromString.newInstance(boatId.toString()); + } else if (UUID.class.isAssignableFrom(idClass)) { + boatId = Helpers.tryUuidConversion(boatId); + } + + String name = (String) object.get(BoatJsonSerializer.FIELD_NAME); + final Object sailID = object.get(BoatJsonSerializer.FIELD_SAIL_ID); + String sailId = sailID == null ? null : sailID.toString(); + BoatClass boatClass = null; + if (boatClassDeserializer != null) { + boatClass = boatClassDeserializer.deserialize(Helpers.getNestedObjectSafe(object, BoatJsonSerializer.FIELD_BOAT_CLASS)); + } + String colorAsString = (String) object.get(BoatJsonSerializer.FIELD_COLOR); + final Color color = colorAsString == null || colorAsString.isEmpty() ? null : new RGBColor(colorAsString); + DynamicBoat boat = (DynamicBoat) boatFactory.getOrCreateBoat(boatId, name, boatClass, sailId, color); + + return boat; + } catch (Exception e) { + throw new JsonDeserializationException(e); } - return new BoatImpl(name, boatClass, sailId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index 09c8525535d..08182b017cc 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -10,7 +10,6 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorFactory; -import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; @@ -23,22 +22,22 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.RGBColor; public class CompetitorJsonDeserializer implements JsonDeserializer { - protected final CompetitorFactory competitorStore; + protected final CompetitorFactory competitorFactory; protected final JsonDeserializer teamJsonDeserializer; protected final JsonDeserializer boatJsonDeserializer; private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName()); public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) { return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( - new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(new BoatClassJsonDeserializer(baseDomainFactory))); + new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); } - public CompetitorJsonDeserializer(CompetitorStore store) { - this(store, null, /* boatDeserializer */ null); + public CompetitorJsonDeserializer(CompetitorFactory competitorFactory) { + this(competitorFactory, null, /* boatDeserializer */ null); } - public CompetitorJsonDeserializer(CompetitorFactory competitorStore, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorStore = competitorStore; + public CompetitorJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorFactory = competitorFactory; this.teamJsonDeserializer = teamJsonDeserializer; this.boatJsonDeserializer = boatDeserializer; } @@ -89,7 +88,7 @@ public class CompetitorJsonDeserializer implements JsonDeserializer final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - Competitor competitor = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, + Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, flagImageURI, team, boat, timeOnTimeFactor, timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/BoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/BoatJsonSerializer.java index 39a866a2419..4cc0c63591e 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/BoatJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/BoatJsonSerializer.java @@ -1,15 +1,25 @@ package com.sap.sailing.server.gateway.serialization.impl; +import java.io.Serializable; +import java.util.Set; +import java.util.UUID; +import java.util.Map.Entry; + import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sse.common.Color; public class BoatJsonSerializer implements JsonSerializer { + public static final String FIELD_ID = "id"; + public static final String FIELD_ID_TYPE = "idtype"; public static final String FIELD_NAME = "name"; public static final String FIELD_SAIL_ID = "sailId"; public static final String FIELD_BOAT_CLASS = "boatClass"; + public static final String FIELD_COLOR = "color"; private final JsonSerializer boatClassJsonSerializer; @@ -21,15 +31,32 @@ public class BoatJsonSerializer implements JsonSerializer { this.boatClassJsonSerializer = boatClassJsonSerializer; } + public static JSONObject getBoatIdQuery(Boat boat) { + JSONObject result = new JSONObject(); + Serializable competitorId = boat.getId() instanceof UUID ? boat.getId().toString() : boat.getId(); + result.put(FIELD_ID, competitorId); + return result; + } + @Override public JSONObject serialize(Boat boat) { JSONObject result = new JSONObject(); + // Special treatment for UUIDs. They are represented as String because JSON doesn't have a way to represent them otherwise. + // However, other, e.g., numeric, types used to encode a serializable ID must be preserved according to JSON semantics. + // Also see the corresponding case distinction in the deserialized which first tries to parse a string as a UUID before + // returning the ID as is. + result.put(CompetitorJsonConstants.FIELD_ID_TYPE, boat.getId().getClass().getName()); + Set> entries = getBoatIdQuery(boat).entrySet(); + for (Entry idKeyAndValue : entries) { + result.put(idKeyAndValue.getKey(), idKeyAndValue.getValue()); + } result.put(FIELD_NAME, boat.getName()); result.put(FIELD_SAIL_ID, boat.getSailID()); + Color color = boat.getColor(); + result.put(FIELD_COLOR, color != null ? color.getAsHtml() : null); if (boatClassJsonSerializer != null) { result.put(FIELD_BOAT_CLASS, boatClassJsonSerializer.serialize(boat.getBoatClass())); } - return result; } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index ac6c895b47a..4bbca31c60c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -37,7 +37,8 @@ public class CompetitorJsonSerializer implements JsonSerializer { public static JSONObject getCompetitorIdQuery(Competitor competitor) { JSONObject result = new JSONObject(); - result.put(FIELD_ID, getPersistentCompetitorId(competitor)); + Serializable competitorId = competitor.getId() instanceof UUID ? competitor.getId().toString() : competitor.getId(); + result.put(FIELD_ID, competitorId); return result; } @@ -81,11 +82,6 @@ public class CompetitorJsonSerializer implements JsonSerializer { return result; } - private static Serializable getPersistentCompetitorId(Competitor competitor) { - Serializable competitorId = competitor.getId() instanceof UUID ? competitor.getId().toString() : competitor.getId(); - return competitorId; - } - protected Color getColor(Competitor competitor ) { return competitor.getColor(); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java index 7c5eca83d11..9dfec145385 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java @@ -93,8 +93,8 @@ public abstract class AbstractJsonExportTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); result.add(competitor); } return result; diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java index 95390708f8e..85bbc94e2bc 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java @@ -83,8 +83,8 @@ public abstract class AbstractJaxRsApiTest { new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); result.add(competitor); } return result; diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java index 7f6b736a4d7..14ce55b2cbe 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java @@ -53,7 +53,7 @@ public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { doReturn(storageService).when(fsmsMock).getActiveFileStorageService(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( nationality), null, null)), null); - DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); + DynamicBoat boat = new BoatImpl("123", "My boat", new BoatClassImpl(boatClassName, false), sailID); racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java index f0a94ce53ca..fe7184ec23c 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java @@ -33,7 +33,7 @@ public class CompetitorsResourceTest extends AbstractJaxRsApiTest { public void setUp() { super.setUp(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); - DynamicBoat boat = new BoatImpl(null, new BoatClassImpl(boatClassName, false), sailID); + DynamicBoat boat = new BoatImpl("123", "My boat", new BoatClassImpl(boatClassName, false), sailID); racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, shortName, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index 93ad9a24da1..2884c18cce3 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -86,7 +86,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - new BoatImpl(competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + new BoatImpl("123", competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Iterable competitors = Collections.singleton(competitor); final String raceName = "Test Race"; RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList), 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 436cf1dca49..ef02e278bb0 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 @@ -75,7 +75,7 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null), new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)), - new BoatImpl("GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), + new BoatImpl("123", "GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); final String baseEventName = "Test Event"; AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, 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 index 571749c7332..e12dc824186 100644 --- 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 @@ -78,7 +78,7 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS (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"), + new BoatImpl("123", "GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); final String baseEventName = "Test Event"; AddDefaultRegatta addEventOperation = new AddDefaultRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java index 889498d5323..5e411f4766b 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java @@ -59,8 +59,8 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", - new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", + competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); } final Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1, diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index bf565e1d9bf..2e2a77d07bf 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -7,9 +7,13 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicCompetitor; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; @@ -17,10 +21,11 @@ import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.test.AbstractLeaderboardTest; import com.sap.sailing.server.impl.PersistentCompetitorStore; import com.sap.sse.common.Duration; +import com.sap.sse.common.impl.RGBColor; public class CompetitorStoreTest { @Test - public void testAddingToTransientStore() { + public void testAddingCompetitorsToTransientStore() { CompetitorStore transientStore = new TransientCompetitorStoreImpl(); DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), @@ -66,6 +71,7 @@ public class CompetitorStoreTest { assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); + DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), @@ -83,4 +89,33 @@ public class CompetitorStoreTest { assertSame(competitor2, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); } + + @Test + public void testPersistentBoatStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicBoat template = new BoatImpl("id-12345", "Morning Glory", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), + "GER 1234", new RGBColor(255, 0, 0)); + DynamicBoat boat = (DynamicBoat) persistentStore1.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + template.getSailID(), template.getColor()); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + Boat boat2 = persistentStore2.getExistingBoatById(template.getId()); + assertNotSame(boat2, template); // the new store loads new instances from the database + assertEquals(template.getId(), boat2.getId()); + + String differentSailId = "USA 1234"; + Boat boat3 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + differentSailId, template.getColor()); + assertSame(boat2, boat3); // use existing boat despite the different sailID + assertNotSame(differentSailId, boat2.getSailID()); // sailID expected to remain unchanged + + // now mark the boat as to update from defaults + persistentStore2.allowBoatResetToDefaults(boat2); + Boat boat4 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + differentSailId, template.getColor()); + assertSame(boat2, boat4); // expecting an in-place update + assertEquals(differentSailId, boat4.getSailID()); + } } diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java index 672318c3a85..c6fee5c1e9a 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java @@ -58,7 +58,7 @@ public class LeaderboardStorageTest extends TestCase { List sailorList = new ArrayList(); sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, "")); DynamicTeam team = new TeamImpl("team", sailorList, null); - DynamicBoat boat = new BoatImpl("woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); + DynamicBoat boat = new BoatImpl("123", "woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); String competitorId = "testC"; Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 23a9bbec36b..20775d11342 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -238,7 +238,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -249,7 +249,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -498,7 +498,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -507,7 +507,7 @@ public class MasterDataImportTest { sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); + DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor2); @@ -656,7 +656,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -820,7 +820,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); @@ -830,7 +830,7 @@ public class MasterDataImportTest { sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); + DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); @@ -980,7 +980,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -991,7 +991,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1182,7 +1182,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1193,7 +1193,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1283,7 +1283,7 @@ public class MasterDataImportTest { 645487200000L), "Der Lennart halt"); DynamicTeam teamToOverride = new TeamImpl("Pros", sailorsToOverride, coachToOverride); BoatClass boatClassToOverride = new BoatClassImpl("H16", true); - DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); + DynamicBoat boatToOverride = new BoatImpl(null, "Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ @@ -1482,7 +1482,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1493,7 +1493,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1618,7 +1618,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1629,7 +1629,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1866,7 +1866,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1877,7 +1877,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -2096,7 +2096,7 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); + DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -2107,7 +2107,7 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); + DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index 833baa73cc9..ec841261f12 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -108,7 +108,7 @@ public class WindByRaceLogTest { return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), - new BoatImpl("GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + new BoatImpl("123", "GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); } private void attachTrackedRaceToRaceColumn() { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 92d27d2369b..f7071c0934f 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -6,6 +6,7 @@ import java.io.Serializable; import java.net.URI; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.DomainFactory; @@ -21,12 +22,13 @@ import com.sap.sse.common.TypeBasedServiceFinderFactory; import com.sap.sse.mongodb.MongoDBService; /** - * Manages a persistent set of {@link Competitor}s using a {@link MongoObjectFactory} to update the persistent store, + * Manages a persistent set of {@link Competitor}s and {@link Boat}s using a {@link MongoObjectFactory} to update the persistent store, * and a {@link DomainObjectFactory} for initially filling this store's in-memory representation from the persistent * store.

* - * Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} are not stored - * persistently and therefore will be reset when re-initializing a competitor store from the database. + * Note that the results of calling {@link CompetitorStore#allowCompetitorResetToDefaults(Competitor)} and + * {@link CompetitorStore#allowBoatResetToDefaults(Boat)} are not stored + * persistently and therefore will be reset when re-initializing a competitor/boat store from the database. * * @author Axel Uhl (d043530) * @@ -37,21 +39,25 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl private transient DomainObjectFactory loadFrom; /** - * @param clear - * if true, the persistent competitor store is initially cleared, with all persistent - * competitor data removed; use with caution! + * @param clearCompetitorsAndBaots + * if true, the persistent competitor and boats store is initially cleared, with all persistent + * competitor and boat data removed; use with caution! */ - public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clear, + public PersistentCompetitorStore(MongoObjectFactory storeTo, boolean clearCompetitorsAndBaots, TypeBasedServiceFinderFactory serviceFinderFactory, RaceLogResolver raceLogResolver) { DomainFactoryImpl baseDomainFactory = new DomainFactoryImpl(this, raceLogResolver); this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory); this.storeTo = storeTo; - if (clear) { + if (clearCompetitorsAndBaots) { storeTo.removeAllCompetitors(); + storeTo.removeAllBoats(); } else { for (Competitor competitor : loadFrom.loadAllCompetitors()) { addCompetitorToTransientStore(competitor.getId(), competitor); } + for (Boat boat: loadFrom.loadAllBoats()) { + addBoatToTransientStore(boat.getId(), boat); + } } } @@ -87,9 +93,9 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl } @Override - public void clear() { + public void clearCompetitors() { storeTo.removeAllCompetitors(); - super.clear(); + super.clearCompetitors(); } @Override @@ -107,4 +113,33 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo.storeCompetitor(result); return result; } + + private void addBoatToTransientStore(Serializable id, Boat boat) { + super.addNewBoat(id, boat); + } + + @Override + protected void addNewBoat(Serializable id, Boat boat) { + storeTo.storeBoat(boat); + super.addNewBoat(id, boat); + } + + @Override + public void clearBoats() { + storeTo.removeAllBoats(); + super.clearBoats(); + } + + @Override + public void removeBoat(Boat boat) { + storeTo.removeBoat(boat); + super.removeBoat(boat); + } + + @Override + public Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId) { + Boat result = super.updateBoat(idAsString, newName, newColor, newSailId); + storeTo.storeBoat(result); + return result; + } } 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 3ae02e3e22c..f381bc715eb 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 @@ -693,7 +693,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes mediaTrackDeleted(mediaTrack); } // TODO clear user store? See bug 2430. - this.competitorStore.clear(); + this.competitorStore.clearCompetitors(); } @Override @@ -2672,7 +2672,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } logger.info("Serializing persisted competitors..."); oos.writeObject(competitorStore); - logoutput.append("Serialized " + competitorStore.size() + " persisted competitors\n"); + logoutput.append("Serialized " + competitorStore.getCompetitorsCount() + " persisted competitors\n"); logger.info("Serializing configuration map..."); oos.writeObject(configurationMap); @@ -2772,7 +2772,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), dynamicCompetitor.getSearchTag()); } - logoutput.append("Received " + competitorStore.size() + " NEW competitors\n"); + logoutput.append("Received " + competitorStore.getCompetitorsCount() + " NEW competitors\n"); logger.info("Reading device configurations..."); configurationMap.putAll((DeviceConfigurationMapImpl) ois.readObject()); @@ -2857,7 +2857,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } eventsById.clear(); mediaLibrary.clear(); - competitorStore.clear(); + competitorStore.clearCompetitors(); remoteSailingServerSet.clear(); if (notificationService != null) { notificationService.stop(); diff --git a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java index 4b8d2bfc2bd..8c395a0ee1d 100755 --- a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java +++ b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java @@ -272,7 +272,7 @@ public class StructureImporter { } private DynamicBoat createBoat(String name, Boat boat, BoatClass boatClass) { - DynamicBoat boat1 = new BoatImpl(name + " boat", boatClass, boat.getSailNumber()); + DynamicBoat boat1 = new BoatImpl(name + " boat", name + " boat", boatClass, boat.getSailNumber()); return boat1; } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java index 1730e0178d8..392689013b0 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java @@ -248,7 +248,9 @@ public class OnlineDataManager extends DataManager { @Override public Loader>> create(int id, Bundle args) throws Exception { ExLog.i(context, TAG, "Creating Competitor-OnlineDataLoader " + id); - JsonDeserializer competitorDeserializer = new CompetitorJsonDeserializer(domainFactory.getCompetitorStore(), new TeamJsonDeserializer(new PersonJsonDeserializer(new NationalityJsonDeserializer(domainFactory))), new BoatJsonDeserializer(new BoatClassJsonDeserializer(domainFactory))); + JsonDeserializer competitorDeserializer = new CompetitorJsonDeserializer(domainFactory.getCompetitorStore(), + new TeamJsonDeserializer(new PersonJsonDeserializer(new NationalityJsonDeserializer(domainFactory))), + new BoatJsonDeserializer(domainFactory, new BoatClassJsonDeserializer(domainFactory))); DataParser> parser = new CompetitorsDataParser(competitorDeserializer); DataHandler> handler = new CompetitorsDataHandler(OnlineDataManager.this, managedRace); From 07f4f27a40f2785790f9fb6070c074ee0d896cb6 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 16 Aug 2016 12:53:14 +0200 Subject: [PATCH 003/271] fixed broken test --- .../src/com/sap/sailing/server/test/MasterDataImportTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 20775d11342..2fdae15a0f4 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -1283,7 +1283,7 @@ public class MasterDataImportTest { 645487200000L), "Der Lennart halt"); DynamicTeam teamToOverride = new TeamImpl("Pros", sailorsToOverride, coachToOverride); BoatClass boatClassToOverride = new BoatClassImpl("H16", true); - DynamicBoat boatToOverride = new BoatImpl(null, "Wingy", boatClassToOverride, "GER70133"); + DynamicBoat boatToOverride = new BoatImpl("123", "Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ From c41346d21cb245d7dca58a3c39403d877bd2b615 Mon Sep 17 00:00:00 2001 From: fmittag Date: Wed, 17 Aug 2016 17:01:48 +0200 Subject: [PATCH 004/271] - Implemented the new RaceDefinition constructor which only works with a Map instead Iterable - Adapted the creation of competitors and boats for all tracking providers - Adapted all tests --- .../META-INF/MANIFEST.MF | 1 + .../test/AbstractGPSFixStoreTest.java | 6 +- .../test/impl/TrackedRaceLoadsFixesTest.java | 17 +- .../TrackedRaceStartTimeInferenceTest.java | 33 +++- .../impl/RaceLogRaceTracker.java | 12 +- .../domain/base/CompetitorChangeListener.java | 2 +- .../swisstimingadapter/DomainFactory.java | 11 +- .../impl/DomainFactoryImpl.java | 50 ++--- .../SwissTimingReplayToDomainAdapter.java | 25 ++- .../impl/CandidateFinderImplWhiteBoxTest.java | 9 +- ...stFarthestAheadWithSkippedMarkPassing.java | 15 +- ...mpleTimeOnTimeRankingWithOneUpwindLeg.java | 15 +- .../domain/test/CompetitorListenerTest.java | 2 +- .../sap/sailing/domain/test/CourseTest.java | 25 ++- ...pdateDuringNonAtomicSerializationTest.java | 3 +- ...eInvalidationAfterLoadingFinishedTest.java | 9 +- .../sailing/domain/test/LineAnalysisTest.java | 5 +- ...ecutionOrderProvdiderAttachDetachTest.java | 25 +-- .../sailing/domain/test/ReachingLegTest.java | 34 ++-- ...ttaLogEventNotificationForwardingTest.java | 2 +- .../test/SerializeRankingMetricTest.java | 3 +- .../domain/test/StoredTrackBasedTest.java | 6 +- .../StoredTrackBasedTestWithTrackedRace.java | 15 +- .../com/sap/sailing/domain/test/TackTest.java | 12 +- .../sailing/domain/test/TrackBasedTest.java | 32 +++- ...rtTimeUpdateForDependentStartTimeTest.java | 9 +- .../domain/test/UpdateMarkPassingTest.java | 5 +- ...WindEstimationOnConstructedTracksTest.java | 17 +- .../com/sap/sailing/domain/test/WindTest.java | 13 +- .../AbstractMockedRaceMarkPassingTest.java | 14 +- ...ockedTrackedRaceWithStartTimeAndRanks.java | 18 +- .../impl/BravoFixTrackSerializationTest.java | 6 +- .../domain/tractracadapter/DomainFactory.java | 6 +- .../impl/DomainFactoryImpl.java | 59 +++--- .../impl/RaceCourseReceiver.java | 7 +- .../domain/base/impl/RaceDefinitionImpl.java | 60 +++--- ...estStoringAndLoadingEventsAndRegattas.java | 12 +- .../test/CompetitorReplicationTest.java | 13 +- ...tialLoadReplicationObjectIdentityTest.java | 11 +- .../test/RegattaLogReplicationTest.java | 6 +- .../test/ServerReplicationTest.java | 5 +- .../TrackedRaceContentsReplicationTest.java | 10 +- ...ithGPSFixStoreContentsReplicationTest.java | 13 +- .../server/test/MasterDataImportTest.java | 180 ++++++++++-------- .../server/test/RaceTrackerStartStopTest.java | 7 +- .../server/test/SearchServiceTest.java | 40 ++-- .../server/test/WindByRaceLogTest.java | 19 +- .../server/masterdata/DummyTrackedRace.java | 15 +- 48 files changed, 565 insertions(+), 349 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF index 3f9cbc1525d..d183a6a537a 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/META-INF/MANIFEST.MF @@ -14,6 +14,7 @@ Require-Bundle: org.junit4;bundle-version="4.8.2", org.mongodb.mongo-java-driver;bundle-version="2.13.0", com.sap.sse.common Import-Package: com.sap.sailing.domain.abstractlog.regatta.events, + com.sap.sailing.domain.base, com.sap.sailing.domain.persistence.impl, com.sap.sailing.domain.persistence.racelog.tracking.impl, com.sap.sailing.domain.tractracadapter, diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index 2df64e4688b..ae296715e5f 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -16,6 +16,8 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; +import com.sap.sailing.domain.base.Boat; +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.Mark; @@ -46,7 +48,9 @@ public class AbstractGPSFixStoreTest { protected RaceLog raceLog; protected RegattaLog regattaLog; protected SensorFixStore store; - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Boat boat = DomainFactory.INSTANCE.getOrCreateBoat(comp, "boat", boatClass, "GER 234", null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); 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 f659ae99a3f..97eaca2cb0c 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 @@ -5,6 +5,8 @@ import static org.mockito.Mockito.mock; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.Rule; import org.junit.Test; @@ -12,7 +14,7 @@ import org.junit.rules.Timeout; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; -import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -42,7 +44,6 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.TimeRangeImpl; public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { - private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); @Rule public Timeout TrackedRaceLoadsFixesTestTimeout = new Timeout(3 * 60 * 1000); @@ -52,13 +53,17 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); map(comp, device, 0, 10000); map(mark, markDevice, 0, 10000); @@ -100,6 +105,10 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); @@ -107,7 +116,7 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3"); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp, comp2)); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); map(comp, device, 0, 20000); map(comp2, device2, 0, 600); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java index 933cff654a8..62825354254 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java @@ -8,6 +8,8 @@ import static org.mockito.Mockito.mock; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import org.junit.Test; @@ -18,6 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -61,12 +64,16 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ @@ -124,12 +131,16 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); @@ -162,12 +173,16 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); @@ -203,12 +218,16 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); @@ -307,12 +326,16 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { NoCorrespondingServiceRegisteredException, InterruptedException { Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author, new MillisecondsTimePoint(1), 0, mark)); regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author, new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(new Competitor[] { comp, comp2 })); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); 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 0e52b232aac..0af5d6e0214 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 @@ -35,6 +35,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -46,6 +47,7 @@ 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.Waypoint; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; @@ -290,7 +292,15 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } Iterable competitors = raceColumn.getAllCompetitors(params.getFleet()); Serializable raceId = denoteEvent.getRaceId(); - final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitors, raceId); + // TODO: How do we retrieve the boats for the competitors of this raceColumn + // For now we create the boats here which MUST be corrected later on + Map competitorsAndBoats = new HashMap<>(); + for (Competitor c: competitors) { + Boat theWrongBoat = c.getBoat(); + Boat b = new BoatImpl(c.getId(), theWrongBoat.getName(), boatClass, theWrongBoat.getSailID(), theWrongBoat.getColor()); + competitorsAndBoats.put(c, b); + } + final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats, raceId); Iterable sidelines = Collections. emptyList(); // set race definition, so race is linked to leaderboard automatically regatta.getRegatta().addRace(raceDef); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorChangeListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorChangeListener.java index e0800fbf86e..ac50212e7f4 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorChangeListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorChangeListener.java @@ -5,7 +5,7 @@ import java.net.URI; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; -public interface CompetitorChangeListener extends BoatChangeListener, NationalityChangeListener { +public interface CompetitorChangeListener extends /** MUST BE REMOVED AFTER AFTER bug 2822 IS SOLVED */BoatChangeListener, NationalityChangeListener { void colorChanged(Color oldColor, Color newColor); void nameChanged(String oldName, String newName); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java index 929614077f3..7469c12c440 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/DomainFactory.java @@ -1,7 +1,9 @@ package com.sap.sailing.domain.swisstimingadapter; import java.util.List; +import java.util.Map; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -18,6 +20,7 @@ import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import difflib.PatchFailedException; @@ -35,11 +38,11 @@ public interface DomainFactory { Nationality getOrCreateNationality(String threeLetterIOCCode); - Competitor createCompetitorWithoutID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, String raceId, BoatClass boatClass); + Pair createCompetitorWithoutID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, String raceId, BoatClass boatClass); - Competitor createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass); + Pair createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass); - Competitor createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass); + Pair createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass); String getCompetitorID(String boatID, RaceType raceType); @@ -66,7 +69,7 @@ public interface DomainFactory { ControlPoint getOrCreateControlPoint(Iterable devices); - RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Iterable competitors, + RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Map competitorsAndBoats, List courseDefinition); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 2e8dfbcdc0a..ee4d2e2f4a1 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -2,15 +2,16 @@ package com.sap.sailing.domain.swisstimingadapter.impl; import java.util.ArrayList; import java.util.Calendar; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; @@ -51,6 +52,7 @@ import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sse.common.Named; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.WithID; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -113,11 +115,11 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public Competitor createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass) { - CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); - Competitor result = competitorStore.getExistingCompetitorByIdAsString(competitor.getID()); - if (result == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)) { - DynamicBoat boat = new BoatImpl(result.getId(), competitor.getName(), boatClass, competitor.getBoatID()); + public Pair createCompetitorWithID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, BoatClass boatClass) { + CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); + Competitor domainCompetitor = competitorAndBoatStore.getExistingCompetitorByIdAsString(competitor.getID()); + if (domainCompetitor == null || competitorAndBoatStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) { + DynamicBoat boat = new BoatImpl(domainCompetitor.getId(), competitor.getName(), boatClass, competitor.getBoatID()); List teamMembers = new ArrayList(); for (CrewMember crewMember: competitor.getCrew()) { DynamicPerson person = new PersonImpl(crewMember.getName().trim(), getOrCreateNationality(crewMember.getNationality()), @@ -125,15 +127,16 @@ public class DomainFactoryImpl implements DomainFactory { teamMembers.add(person); } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); - result = competitorStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team, boat, + domainCompetitor = competitorAndBoatStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } - return result; + Boat domainBoat = competitorAndBoatStore.getOrCreateBoat(domainCompetitor, competitor.getName(), boatClass, competitor.getBoatID(), null); + return new Pair(domainCompetitor, domainBoat); } @Override - public Competitor createCompetitorWithoutID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, String raceId, BoatClass boatClass) { - Competitor result = null; + public Pair createCompetitorWithoutID(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, String raceId, BoatClass boatClass) { + CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); List teamMembers = new ArrayList(); for (String teamMemberName : competitor.getName().split("[-+&]")) { teamMembers.add(new PersonImpl(teamMemberName.trim(), getOrCreateNationality(competitor.getThreeLetterIOCCode()), @@ -142,14 +145,15 @@ public class DomainFactoryImpl implements DomainFactory { DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); String competitorID = getCompetitorID(competitor.getBoatID(), raceId, boatClass); DynamicBoat boat = new BoatImpl(competitorID, competitor.getName(), boatClass, competitor.getBoatID()); - result = baseDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitorID, + Competitor domainCompetitor = competitorAndBoatStore.getOrCreateCompetitor(competitorID, competitor.getName(), null /* short name */, null /*displayColor*/, null /*email*/, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - return result; + Boat domainBoat = competitorAndBoatStore.getOrCreateBoat(domainCompetitor, competitor.getName(), boatClass, competitor.getBoatID(), null); + return new Pair(domainCompetitor, domainBoat); } @Override - public Competitor createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass) { + public Pair createCompetitorWithoutID(String boatID, String threeLetterIOCCode, String name, String raceId, BoatClass boatClass) { return createCompetitorWithoutID(new CompetitorWithoutID(boatID, threeLetterIOCCode, name), raceId, boatClass); } @@ -177,7 +181,7 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Iterable competitors, + public RaceDefinition createRaceDefinition(Regatta regatta, String raceID, Map competitorsAndBoats, List courseDefinition) { List waypoints = new ArrayList<>(); for (ControlPoint controlPoint : courseDefinition) { @@ -187,7 +191,7 @@ public class DomainFactoryImpl implements DomainFactory { com.sap.sailing.domain.base.Course domainCourse = new CourseImpl("Course", waypoints); BoatClass boatClass = getRaceTypeFromRaceID(raceID).getBoatClass(); logger.info("Creating RaceDefinitionImpl for race "+raceID); - RaceDefinition result = new RaceDefinitionImpl(regatta.getId().toString()+"/"+raceID, domainCourse, boatClass, competitors); + RaceDefinition result = new RaceDefinitionImpl(regatta.getId().toString()+"/"+raceID, domainCourse, boatClass, competitorsAndBoats); regatta.addRace(result); return result; } @@ -195,10 +199,10 @@ public class DomainFactoryImpl implements DomainFactory { @Override public RaceDefinition createRaceDefinition(Regatta regatta, Race race, StartList startList, Course course) { com.sap.sailing.domain.base.Course domainCourse = createCourse(race.getDescription(), course); - Iterable competitors = createCompetitorList(startList, race.getRaceID(), race.getBoatClass()); + Map competitorsAndBoats = createCompetitorsAndBoats(startList, race.getRaceID(), race.getBoatClass()); logger.info("Creating RaceDefinitionImpl for race "+race.getRaceID()); BoatClass boatClass = race.getBoatClass() != null ? race.getBoatClass() : getRaceTypeFromRaceID(race.getRaceID()).getBoatClass(); - RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitors, /* competitorsAndTheirBoats */ Collections.emptyMap(), race.getRaceID()); + RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitorsAndBoats, race.getRaceID()); regatta.addRace(result); return result; } @@ -248,16 +252,16 @@ public class DomainFactoryImpl implements DomainFactory { return result; } - private Iterable createCompetitorList(StartList startList, String raceId, BoatClass boatClass) { - List result = new ArrayList(); + private Map createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass) { + Map result = new LinkedHashMap<>(); for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) { - Competitor domainCompetitor; + Pair domainCompetitorAndBoat; if (swissTimingCompetitor.getID() != null) { - domainCompetitor = createCompetitorWithID(swissTimingCompetitor, boatClass); + domainCompetitorAndBoat = createCompetitorWithID(swissTimingCompetitor, boatClass); } else { - domainCompetitor = createCompetitorWithoutID(swissTimingCompetitor, raceId, boatClass); + domainCompetitorAndBoat = createCompetitorWithoutID(swissTimingCompetitor, raceId, boatClass); } - result.add(domainCompetitor); + result.put(domainCompetitorAndBoat.getA(), domainCompetitorAndBoat.getB()); } return result; } 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 da048fee42f..39ad963d5f1 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 @@ -5,17 +5,16 @@ import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableSet; -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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -92,11 +91,11 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i private TimePoint referenceTimePoint; /** - * feference location for location / lat/lng specifications + * reference location for location / lat/lng specifications */ private Position referenceLocation; - private final Map> competitorsPerRaceID; + private final Map> competitorsAndBoatsPerRaceID; private final Map> marksPerRaceIDPerMarkID; @@ -155,7 +154,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i trackedRacePerRaceID = new HashMap<>(); bestStartTimePerRaceID = new HashMap<>(); raceTimePerRaceID = new HashMap<>(); - competitorsPerRaceID = new HashMap<>(); + competitorsAndBoatsPerRaceID = new HashMap<>(); marksPerRaceIDPerMarkID = new HashMap<>(); markByHashValue = new HashMap<>(); competitorByHashValue = new HashMap<>(); @@ -242,15 +241,15 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i CompetitorStatus competitorStatus, BoatType boatType, short cRank_Bracket, short cnPoints_x10_Bracket, short ctPoints_x10_Winner) { if (boatType == BoatType.Competitor) { - Competitor competitor = domainFactory.createCompetitorWithoutID(sailNumberOrTrackerID, threeLetterIOCCode.trim(), name.trim(), + Pair competitorAndBoat = domainFactory.createCompetitorWithoutID(sailNumberOrTrackerID, threeLetterIOCCode.trim(), name.trim(), currentRaceID, domainFactory.getRaceTypeFromRaceID(currentRaceID).getBoatClass()); - Set competitorsOfCurrentRace = competitorsPerRaceID.get(currentRaceID); - if (competitorsOfCurrentRace == null) { - competitorsOfCurrentRace = new HashSet<>(); - competitorsPerRaceID.put(currentRaceID, competitorsOfCurrentRace); + Map competitorAndBoatsOfCurrentRace = competitorsAndBoatsPerRaceID.get(currentRaceID); + if (competitorAndBoatsOfCurrentRace == null) { + competitorAndBoatsOfCurrentRace = new HashMap<>(); + competitorsAndBoatsPerRaceID.put(currentRaceID, competitorAndBoatsOfCurrentRace); } - competitorsOfCurrentRace.add(competitor); - competitorByHashValue.put(hashValue, competitor); + competitorAndBoatsOfCurrentRace.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + competitorByHashValue.put(hashValue, competitorAndBoat.getA()); } else { // consider it a mark Mark mark = domainFactory.getOrCreateMark(sailNumberOrTrackerID.trim()); @@ -315,7 +314,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, currentRaceID, domainFactory.getRaceTypeFromRaceID(currentRaceID).getBoatClass(), trackedRegattaRegistry); RaceDefinition race = domainFactory.createRaceDefinition(myRegatta, - currentRaceID, competitorsPerRaceID.get(currentRaceID), currentCourseDefinition); + currentRaceID, competitorsAndBoatsPerRaceID.get(currentRaceID), currentCourseDefinition); racePerRaceID.put(currentRaceID, race); DynamicTrackedRace trackedRace = trackedRegattaRegistry.getOrCreateTrackedRegatta(myRegatta). createTrackedRace(race, Collections. emptyList(), EmptyWindStore.INSTANCE, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java index 267a6dc571b..5d212665a90 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java @@ -7,8 +7,8 @@ import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.StreamSupport; import org.junit.Before; @@ -18,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.ReadonlyRacingProcedureFactory; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; @@ -61,8 +62,10 @@ public class CandidateFinderImplWhiteBoxTest { @Before public void setUp() { now = MillisecondsTimePoint.now(); - competitor = TrackBasedTest.createCompetitor("Competitor"); - trackedRace = TrackBasedTest.createTestTrackedRace("Test Regatta", "Test Race", "505", Collections.singleton(competitor), now, /* useMarkPassingCalculator */ true); + Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Competitor"); + competitor = competitorAndBoat.getA(); + Map competitorAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); + trackedRace = TrackBasedTest.createTestTrackedRace("Test Regatta", "Test Race", "505", competitorAndBoats, now, /* useMarkPassingCalculator */ true); finder = new CandidateFinderWithPublicGetProbabilityOfStartBasedOnOtherCompetitorsStartLineDistances(trackedRace); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java index a8ad94bdd98..ea454eea66a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java @@ -9,11 +9,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; 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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -53,6 +55,7 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; /** @@ -79,15 +82,17 @@ public class TestFarthestAheadWithSkippedMarkPassing { private Waypoint finish; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - c1 = TrackBasedTest.createCompetitor("SlowBoat"); - c2 = TrackBasedTest.createCompetitor("FastBoat"); - trackedRace = createTrackedRace(Arrays.asList(c1, c2)); + Pair fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + c1 = fastCompetitorAndBoat.getA(); + Pair slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + c2 = slowCompetitorAndBoat.getA(); + trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat)); rankingMetric = trackedRace.getRankingMetric(); assertEquals(120, trackedRace.getCourseLength().getNauticalMiles(), 0.02); assertSame(RankingMetrics.ONE_DESIGN, trackedRace.getTrackedRegatta().getRegatta().getRankingMetricType()); } - private DynamicTrackedRace createTrackedRace(Iterable competitors) { + private DynamicTrackedRace createTrackedRace(Map competitorsAndBoats) { final TimePoint timePointForFixes = MillisecondsTimePoint.now(); BoatClassImpl boatClass = new BoatClassImpl("Some Handicap Boat Class", /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, @@ -107,7 +112,7 @@ public class TestFarthestAheadWithSkippedMarkPassing { finish = new WaypointImpl(leeGate); waypoints.add(finish); Course course = new CourseImpl("Test Course", waypoints); - RaceDefinition race = new RaceDefinitionImpl("Test Race", course, boatClass, competitors); + RaceDefinition race = new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, 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 05704e29fcf..157f49cc655 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 @@ -9,11 +9,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; 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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -52,6 +54,7 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -61,15 +64,17 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { private Competitor c1, c2; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - c1 = TrackBasedTest.createCompetitor("FastBoat"); - c2 = TrackBasedTest.createCompetitor("SlowBoat"); - trackedRace = createTrackedRace(Arrays.asList(c1, c2), timeOnTimeFactors, timeOnDistanceFactors); + Pair fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + c1 = fastCompetitorAndBoat.getA(); + Pair slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + c2 = slowCompetitorAndBoat.getA(); + trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat), timeOnTimeFactors, timeOnDistanceFactors); tot = trackedRace.getRankingMetric(); assertEquals(60, trackedRace.getCourseLength().getNauticalMiles(), 0.01); assertSame(RankingMetrics.TIME_ON_TIME_AND_DISTANCE, trackedRace.getTrackedRegatta().getRegatta().getRankingMetricType()); } - private DynamicTrackedRace createTrackedRace(Iterable competitors, TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { + private DynamicTrackedRace createTrackedRace(Map competitorsAndBoats, TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { final TimePoint timePointForFixes = MillisecondsTimePoint.now(); BoatClassImpl boatClass = new BoatClassImpl("Some Handicap Boat Class", /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, @@ -85,7 +90,7 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { waypoints.add(new WaypointImpl(leeGate)); waypoints.add(new WaypointImpl(windwardMark)); Course course = new CourseImpl("Test Course", waypoints); - RaceDefinition race = new RaceDefinitionImpl("Test Race", course, boatClass, competitors); + RaceDefinition race = new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index 8cffbc9a37c..d15204a2f34 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -70,7 +70,7 @@ public class CompetitorListenerTest extends AbstractSerializationTest { @Before public void setUp() { baseDomainFactory = new DomainFactoryImpl((srlid)->null); - competitor = TrackBasedTest.createCompetitor("Hasso"); + competitor = (DynamicCompetitor) TrackBasedTest.createCompetitorAndBoat("Hasso").getA(); nationalityChanged = false; whatChangedNationality = null; oldNationality = null; 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 aaacc4afa9f..2f458541f76 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 @@ -9,14 +9,18 @@ import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; +import java.util.Map; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -25,7 +29,7 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.MarkImpl; @@ -299,10 +303,14 @@ public class CourseTest { waypoints.add(wp3); Course course = new CourseImpl("Test Course", waypoints); assertWaypointIndexes(course); - final Set hasso = Collections.singleton(AbstractLeaderboardTest.createCompetitor("Hasso")); + final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); + final Competitor hasso = AbstractLeaderboardTest.createCompetitor("Hasso"); + final Boat hassosBoat = new BoatImpl("id12345", "Hasso's boat", boatClass, /* sailID */ null); + final Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(hasso, hassosBoat); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */new DynamicTrackedRegattaImpl( new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), - new RaceDefinitionImpl("Test Race", course, new BoatClassImpl("49er", /* upwind start */true), hasso), + new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */3000, /* millisecondsOverWhichToAverageWind */30000, /* millisecondsOverWhichToAverageSpeed */8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, @@ -330,11 +338,14 @@ public class CourseTest { final WaypointImpl wp2 = new WaypointImpl(new MarkImpl("Test Mark 2")); waypoints.add(wp2); Course course = new CourseImpl("Test Course", waypoints); - final Set hasso = Collections.singleton(AbstractLeaderboardTest.createCompetitor("Hasso")); + final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); + final Competitor hasso = AbstractLeaderboardTest.createCompetitor("Hasso"); + final Boat hassosBoat = new BoatImpl("id12345", "Hasso's boat", boatClass, /* sailID */ null); + final Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(hasso, hassosBoat); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ new DynamicTrackedRegattaImpl( new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), - new RaceDefinitionImpl("Test Race", course, new BoatClassImpl("49er", /* upwind start */ true), - hasso), Collections. emptyList(), + new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 8000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, 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 c7d1deee589..203e1a98b98 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 @@ -21,6 +21,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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; @@ -78,7 +79,7 @@ public class CourseUpdateDuringNonAtomicSerializationTest implements Serializabl new BoatClassImpl("505", BoatClassMasterdata._5O5), /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, new LowPoint(), UUID.randomUUID(), new CourseAreaImpl("Alpha", UUID.randomUUID())); TrackedRegatta trackedRegatta = new TrackedRegattaImpl(regatta); - RaceDefinition race = new RaceDefinitionImpl("Test Race", course, regatta.getBoatClass(), Collections.emptySet()); + RaceDefinition race = new RaceDefinitionImpl("Test Race", course, regatta.getBoatClass(), Collections.emptyMap()); trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptySet(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */10000, /* millisecondsOverWhichToAverageWind */30000, /* millisecondsOverWhichToAverageSpeed */ diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java index 290a02d13cc..cdcd0272671 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java @@ -3,10 +3,12 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import java.util.Collections; +import java.util.Map; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Position; @@ -21,6 +23,7 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; /** @@ -37,8 +40,10 @@ public class DistanceCacheInvalidationAfterLoadingFinishedTest extends TrackBase @Before public void setUp() { - competitor = createCompetitor("Test Competitor"); - trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", Collections.singleton(competitor), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); + Pair competitorAndBoat = createCompetitorAndBoat("Test Competitor"); + Map competitorsAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); + competitor = competitorAndBoat.getA(); + trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", competitorsAndBoats, MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); } @Test diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java index 35e19bcd554..b7e57b74262 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java @@ -3,11 +3,11 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import java.util.Collections; -import java.util.List; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.common.NauticalSide; @@ -28,9 +28,8 @@ public class LineAnalysisTest extends TrackBasedTest { @Before public void setUp() { - final List emptyCompetitorList = Collections.emptyList(); now = MillisecondsTimePoint.now(); - trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", emptyCompetitorList, now, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", Collections.emptyMap(), now, /* useMarkPassingCalculator */ false); } @Test diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java index 4f4bc51fb91..8b5657bd0da 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java @@ -13,6 +13,7 @@ import java.util.UUID; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; @@ -75,7 +76,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest @Test public void testRaceExecutionOrderProviderAttachDetachWithRaceColumn() { - trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), + trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); @@ -89,9 +90,9 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest public void testWindInRegularIntervalWithPreviousRaceStillTracking() { final TimePoint startOfFirstRace = MillisecondsTimePoint.now(); final TimePoint startOfSecondRace = startOfFirstRace.plus(Duration.ONE_MINUTE.times(5)); - DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), startOfFirstRace, /* useMarkPassingCalculator */ false); + DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), startOfFirstRace, /* useMarkPassingCalculator */ false); previousTrackedRace.setStartOfTrackingReceived(startOfFirstRace); - trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyList(), startOfSecondRace, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyMap(), startOfSecondRace, /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); flexibleLeaderboard.addRace(previousTrackedRace, RACECOLUMN_FLEXIBLELEADERBOARD+"1", false); @@ -107,10 +108,10 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest final TimePoint startOfFirstRace = MillisecondsTimePoint.now(); final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_SECOND); final TimePoint startOfSecondRace = startOfFirstRace.plus(Duration.ONE_HOUR); - DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), startOfFirstRace, /* useMarkPassingCalculator */ false); + DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), startOfFirstRace, /* useMarkPassingCalculator */ false); previousTrackedRace.setStartOfTrackingReceived(startOfFirstRace); previousTrackedRace.setEndOfTrackingReceived(endOfFirstRace); // a very short race... - trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyList(), startOfSecondRace, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyMap(), startOfSecondRace, /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); flexibleLeaderboard.addRace(previousTrackedRace, RACECOLUMN_FLEXIBLELEADERBOARD+"1", false); @@ -129,7 +130,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest final TimePoint startOfFirstRace = MillisecondsTimePoint.now(); final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_SECOND); final TimePoint startOfSecondRace = startOfFirstRace.plus(Duration.ONE_HOUR); - trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyList(), startOfSecondRace, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyMap(), startOfSecondRace, /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); flexibleLeaderboard.addRace(trackedRace, RACECOLUMN_FLEXIBLELEADERBOARD, false); @@ -145,10 +146,10 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest final TimePoint startOfFirstRace = MillisecondsTimePoint.now(); final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_SECOND); final TimePoint startOfSecondRace = startOfFirstRace.plus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.times(2)); - DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), startOfFirstRace, /* useMarkPassingCalculator */ false); + DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), startOfFirstRace, /* useMarkPassingCalculator */ false); previousTrackedRace.setStartOfTrackingReceived(startOfFirstRace); previousTrackedRace.setEndOfTrackingReceived(endOfFirstRace); // a very short race... - trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyList(), startOfSecondRace, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyMap(), startOfSecondRace, /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); flexibleLeaderboard.addRace(previousTrackedRace, RACECOLUMN_FLEXIBLELEADERBOARD+"1", false); @@ -166,10 +167,10 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest final TimePoint startOfFirstRace = MillisecondsTimePoint.now(); final TimePoint endOfFirstRace = startOfFirstRace.plus(Duration.ONE_SECOND); final TimePoint startOfSecondRace = startOfFirstRace.plus(TrackedRaceImpl.EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS.divide(2)); - DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), startOfFirstRace, /* useMarkPassingCalculator */ false); + DynamicTrackedRaceImpl previousTrackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), startOfFirstRace, /* useMarkPassingCalculator */ false); previousTrackedRace.setStartOfTrackingReceived(startOfFirstRace); previousTrackedRace.setEndOfTrackingReceived(endOfFirstRace); // a very short race... - trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyList(), startOfSecondRace, /* useMarkPassingCalculator */ false); + trackedRace = createTestTrackedRace(REGATTA, "TestRace2", BOATCLASS, Collections. emptyMap(), startOfSecondRace, /* useMarkPassingCalculator */ false); flexibleLeaderboard = new FlexibleLeaderboardImpl(FLEXIBLELEADERBOARD, new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); flexibleLeaderboard.addRace(previousTrackedRace, RACECOLUMN_FLEXIBLELEADERBOARD+"1", false); @@ -214,7 +215,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest } private void createTestSetupWithRegattaAndSeries(boolean linkSeriesToRegatta) { - trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), + trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyMap(), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); fleet = new FleetImpl(FLEET); Set fleets = new HashSet<>(); @@ -285,7 +286,7 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest } private DynamicTrackedRace createTrackedRace(final String name, final TimePoint startOfRace, final TimePoint endOfRace) { - DynamicTrackedRace trackedRace = createTestTrackedRace(REGATTA, name, BOATCLASS, Collections. emptyList(), startOfRace, /* useMarkPassingCalculator */ false); + DynamicTrackedRace trackedRace = createTestTrackedRace(REGATTA, name, BOATCLASS, Collections. emptyMap(), startOfRace, /* useMarkPassingCalculator */ false); trackedRace.setStartOfTrackingReceived(startOfRace); trackedRace.setEndOfTrackingReceived(endOfRace); return trackedRace; 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 d77f4c76acb..3bab891639c 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 @@ -8,12 +8,15 @@ import java.util.ArrayList; import java.util.Collections; import java.util.GregorianCalendar; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -24,7 +27,6 @@ import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.MarkImpl; @@ -56,12 +58,13 @@ import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class ReachingLegTest extends TrackBasedTest { - private List competitors; - private CompetitorImpl plattner; - private CompetitorImpl hunger; + private Map competitorsAndBoats; + private Competitor plattner; + private Competitor hunger; private MillisecondsTimePoint start; private Competitor schomaeker; @@ -71,15 +74,18 @@ public class ReachingLegTest extends TrackBasedTest { */ @Before public void setUp() { - competitors = new ArrayList(); - hunger = createCompetitor("Wolfgang Hunger"); - competitors.add(hunger); - plattner = createCompetitor("Dr. Hasso Plattner"); - competitors.add(plattner); - schomaeker = createCompetitor("Meike Schom�ker"); - competitors.add(schomaeker); + competitorsAndBoats = new LinkedHashMap<>(); + Pair hungerWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); + hunger = hungerWithBoat.getA(); + competitorsAndBoats.put(hungerWithBoat.getA(), hungerWithBoat.getB()); + Pair plattnerWithBoat = createCompetitorAndBoat("Dr. Hasso Plattner"); + plattner = plattnerWithBoat.getA(); + competitorsAndBoats.put(plattnerWithBoat.getA(), plattnerWithBoat.getB()); + Pair schomaekerWithBoat = createCompetitorAndBoat("Meike Schom�ker"); + schomaeker = schomaekerWithBoat.getA(); + competitorsAndBoats.put(schomaekerWithBoat.getA(), schomaekerWithBoat.getB()); start = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()); - setTrackedRace(createTrackedRace("Kieler Woche", "505 Race 2", "505", competitors, start)); + setTrackedRace(createTrackedRace("Kieler Woche", "505 Race 2", "505", competitorsAndBoats, start)); List hungersMarkPassings = createMarkPassings(hunger, start); getTrackedRace().updateMarkPassings(hunger, hungersMarkPassings); List plattnersMarkPassings = createMarkPassings(plattner, start); @@ -87,7 +93,7 @@ public class ReachingLegTest extends TrackBasedTest { } protected DynamicTrackedRaceImpl createTrackedRace(String regattaName, String raceName, String boatClassName, - Iterable competitors, TimePoint timePointForFixes) { + Map competitorsAndBoats, TimePoint timePointForFixes) { BoatClassImpl boatClass = new BoatClassImpl(boatClassName, /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, @@ -105,7 +111,7 @@ public class ReachingLegTest extends TrackBasedTest { waypoints.add(new WaypointImpl(offsetMark)); waypoints.add(new WaypointImpl(leeGate)); Course course = new CourseImpl(raceName, waypoints); - RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitors); + RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index 7c536831842..e6e482204b7 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -103,7 +103,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa private RegattaLogRegisterCompetitorEventImpl createRegattaLogEvent() { final RegattaLogRegisterCompetitorEventImpl event = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), /* author */ null, - AbstractTracTracLiveTest.createCompetitor("Someone")); + AbstractTracTracLiveTest.createCompetitorAndBoat("Someone").getA()); return event; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java index 83c3ef1f356..ca0af2d4cfc 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java @@ -9,6 +9,7 @@ import java.util.UUID; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -36,7 +37,7 @@ public class SerializeRankingMetricTest extends AbstractSerializationTest { /* startDate */ null, /* endDate */ null, /* trackedRegattaRegistry */ null, new LowPoint(), UUID.randomUUID(), /* courseArea */ null)), new RaceDefinitionImpl("Race", new CourseImpl("Course", Collections.emptyList()) , - /* boatClass */ _49er, Collections.emptySet()), + /* boatClass */ _49er, Collections.emptyMap()), Collections. emptyList(), EmptyWindStore.INSTANCE, 0l, 0l, 0l, false, TimeOnTimeAndDistanceRankingMetric::new, null); RankingMetric clone = cloneBySerialization(trackedRace.getRankingMetric(), DomainFactory.INSTANCE); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index f7e7a4fa285..7c120543834 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -16,6 +16,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; @@ -114,11 +115,12 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { protected Map> loadTracks() throws FileNotFoundException, IOException { Map> tracks = new HashMap>(); final String KIELER_WOCHE = "Kieler Woche"; + final BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) { DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null); DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null); - Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, new BoatImpl("123", - competitorName, new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, + new BoatImpl("123", competitorName, boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DynamicGPSFixTrack track = readTrack(c, KIELER_WOCHE); if (track != null) { tracks.put(c, track); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTestWithTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTestWithTrackedRace.java index 8912ec0893d..03eca2939b8 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTestWithTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTestWithTrackedRace.java @@ -4,12 +4,17 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Before; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; import com.sap.sailing.domain.tracking.MarkPassing; @@ -20,7 +25,15 @@ public class StoredTrackBasedTestWithTrackedRace extends StoredTrackBasedTest { @Before public void setUp() throws FileNotFoundException, IOException { Map> tracks = loadTracks(); - setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", tracks.keySet(), + + final BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + Map competitorsAndBoats = new HashMap<>(); + int i = 1; + for(Competitor c: tracks.keySet()) { + Boat b = new BoatImpl("Boat" + i++, c.getName(), boatClass, null); + competitorsAndBoats.put(c, b); + } + setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", competitorsAndBoats, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()), /* useMarkPassingCalculator */ false)); copyTracks(tracks); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index a577752799b..454a5b3239b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -4,10 +4,14 @@ import static org.junit.Assert.assertEquals; import java.util.Collections; import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; @@ -35,13 +39,17 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { @Override @Before public void setUp() { + BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); competitor = new CompetitorImpl(123, "Wolfgang Hunger", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - "Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", Collections.singleton(competitor), + "Wolfgang Hunger's boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat boat = new BoatImpl(competitor.getId(), "Wolfgang Hunger's boat", boatClass, "123", null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); + setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", competitorsAndBoats, new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()), /* useMarkPassingCalculator */ false)); } 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 f067d3468ae..57fdee964c4 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 @@ -7,10 +7,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -65,6 +68,7 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -72,6 +76,7 @@ public abstract class TrackBasedTest { private DynamicTrackedRaceImpl trackedRace; final static Fleet regattaFleet = new FleetImpl("fleet name"); + final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */true); protected DynamicTrackedRaceImpl getTrackedRace() { return trackedRace; @@ -81,15 +86,26 @@ public abstract class TrackBasedTest { this.trackedRace = trackedRace; } - public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(UUID.randomUUID(), competitorName, "HP", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + @SafeVarargs + public static Map createCompetitorAndBoatsMap(Pair... competitorsAndBoats) { + Map result = new LinkedHashMap<>(); + for (Pair competitorAndBoat: competitorsAndBoats) { + result.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + } + return result; + } + + public static Pair createCompetitorAndBoat(String competitorName) { + Competitor c = new CompetitorImpl(UUID.randomUUID(), competitorName, "HP", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat b = new BoatImpl(c.getId(), competitorName + "'s boat", boatClass, null, null); + return new Pair<>(c, b); } - + /** * For {@link #trackedRace}'s race course, creates a list of mark passings using the time points specified, in order * for the waypoints. @@ -119,8 +135,8 @@ public abstract class TrackBasedTest { * @param useMarkPassingCalculator whether or not to use the internal mark passing calculator */ public static DynamicTrackedRaceImpl createTestTrackedRace(String regattaName, String raceName, String boatClassName, - Iterable competitors, TimePoint timePointForFixes, boolean useMarkPassingCalculator) { - return createTestTrackedRace(regattaName, raceName, boatClassName, competitors, timePointForFixes, useMarkPassingCalculator, + Map competitorsAndBoats, TimePoint timePointForFixes, boolean useMarkPassingCalculator) { + return createTestTrackedRace(regattaName, raceName, boatClassName, competitorsAndBoats, timePointForFixes, useMarkPassingCalculator, mock(RaceLogResolver.class)); } /** @@ -139,7 +155,7 @@ public abstract class TrackBasedTest { * @param useMarkPassingCalculator whether or not to use the internal mark passing calculator */ public static DynamicTrackedRaceImpl createTestTrackedRace(String regattaName, String raceName, String boatClassName, - Iterable competitors, TimePoint timePointForFixes, boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { + Map competitorsAndBoats, TimePoint timePointForFixes, boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { BoatClassImpl boatClass = new BoatClassImpl(boatClassName, /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, @@ -157,7 +173,7 @@ public abstract class TrackBasedTest { waypoints.add(new WaypointImpl(windwardMark)); waypoints.add(new WaypointImpl(leeGate)); Course course = new CourseImpl(raceName, waypoints); - RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitors); + RaceDefinition race = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(trackedRegatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java index af8f1c0cee5..0d6f71eb99a 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java @@ -6,7 +6,6 @@ import static org.junit.Assert.assertNull; import java.io.IOException; import java.net.MalformedURLException; -import java.util.Collections; import org.junit.Test; @@ -19,17 +18,19 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEve import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.tracking.StartTimeChangedListener; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class TrackedRaceStartTimeUpdateForDependentStartTimeTest extends TrackBasedTest { @Test public void testStartTimeUpdateForRaceWithDependentStartTime() { - final Competitor hasso = createCompetitor("Hasso"); + final Pair hasso = createCompetitorAndBoat("Hasso"); final RaceLog r1RaceLog = new RaceLogImpl("r1RaceLog"); final RaceLog r2RaceLog = new RaceLogImpl("r2RaceLog"); final RaceLogResolver raceLogResolver = new RaceLogResolver() { @@ -43,9 +44,9 @@ public class TrackedRaceStartTimeUpdateForDependentStartTimeTest extends TrackBa return null; } }; - final TrackedRace r1 = createTestTrackedRace("Regatta", "R1", "J/70", Collections.singleton(hasso), + final TrackedRace r1 = createTestTrackedRace("Regatta", "R1", "J/70", createCompetitorAndBoatsMap(hasso), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false, raceLogResolver); - final TrackedRace r2 = createTestTrackedRace("Regatta", "R2", "J/70", Collections.singleton(hasso), + final TrackedRace r2 = createTestTrackedRace("Regatta", "R2", "J/70", createCompetitorAndBoatsMap(hasso), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false, raceLogResolver); r1.attachRaceLog(r1RaceLog); r2.attachRaceLog(r2RaceLog); 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 4179b4b4f3c..9d4a7a8321b 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 @@ -11,6 +11,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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; @@ -30,6 +31,7 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class UpdateMarkPassingTest { @@ -40,7 +42,8 @@ public class UpdateMarkPassingTest { when(race.getName()).thenReturn("Test Race"); Course c = new CourseImpl("Test Course", Collections.singleton(waypoint)); when(race.getCourse()).thenReturn(c); - Competitor competitor = TrackBasedTest.createCompetitor("Test Competitor"); + Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + Competitor competitor = competitorAndBoat.getA(); when(race.getBoatClass()).thenReturn(new BoatClassImpl("49er", /* typicallyStartsUpwind */ true)); when(race.getCompetitors()).thenReturn(Collections.singleton(competitor)); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl( diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java index 38799401bfc..5526c189438 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java @@ -18,6 +18,7 @@ import java.util.Set; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; @@ -44,23 +45,33 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TrackBasedEstimationWindTrackImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest { private List competitors; + private List> competitorsWithBoats; private static final String[] competitorNames = new String[] { "Wolfgang Hunger", "Dr. Hasso Plattner", "Robert Stanjek", "Simon Grotelueschen" }; @Before public void setUp() { - competitors = new ArrayList(); + competitorsWithBoats = new ArrayList<>(); + competitors = new ArrayList<>(); for (String name : competitorNames) { - competitors.add(createCompetitor(name)); + Pair competitorAndBoat = createCompetitorAndBoat(name); + competitorsWithBoats.add(competitorAndBoat); + competitors.add(competitorAndBoat.getA()); } } private void initRace(int numberOfCompetitorsToUse, int[] numberOfMarksPassed, TimePoint timePointForFixes) { + List> subList = competitorsWithBoats.subList(0, numberOfCompetitorsToUse); + Map competitorsAndBoats = new HashMap<>(); + for (Pair competitorAndBoat: subList) { + competitorsAndBoats.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + } setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", - competitors.subList(0, numberOfCompetitorsToUse), timePointForFixes, /* useMarkPassingCalculator */ false)); + competitorsAndBoats, timePointForFixes, /* useMarkPassingCalculator */ false)); for (int i=0; i competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl( new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, domainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null)), new RaceDefinitionImpl("Test Race", new CourseImpl("Test Course", Arrays.asList(new Waypoint[] { w1, w2, w3 })), - boatClass, Collections.singleton(competitor)), Collections. emptyList(), + boatClass, competitorsAndBoats), Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 1000, /* millisecondsOverWhichToAverageWind */ 30000, /* millisecondsOverWhichToAverageSpeed */ 30000, /*useMarkPassingCalculator*/ false, OneDesignRankingMetric::new, 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 4684ef7b19e..cf0a56d3050 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 @@ -4,10 +4,13 @@ import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.Course; @@ -48,7 +51,10 @@ public class AbstractMockedRaceMarkPassingTest { protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - + protected Boat boatRon = new BoatImpl("123", "boat1", boatClass, "GER 123"); + protected Boat boatTom = new BoatImpl("456", "boat2", boatClass, "GER 456"); + protected Boat boatBen = new BoatImpl("789", "boat3", boatClass, "GER 789"); + protected Mark m = new MarkImpl("Mark"); protected Mark gate1 = new MarkImpl("Gate1"); protected Mark gate2 = new MarkImpl("Gate2"); @@ -70,7 +76,11 @@ public class AbstractMockedRaceMarkPassingTest { /*startDate*/ null, /*endDate*/ null, Arrays.asList(new SeriesImpl("Series", true, /* isFleetsCanRunInParallel */ true, Arrays.asList(new FleetImpl("fleet")), 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)); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(ron, boatRon); + competitorsAndBoats.put(tom, boatTom); + competitorsAndBoats.put(ben, boatBen); + RaceDefinition raceDef = new RaceDefinitionImpl("Performance Race", course, boatClass, competitorsAndBoats); race = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(r), raceDef, new ArrayList(), new EmptyWindStore(), 0, 10000, 10000, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java index dec1dc6c246..03ade4713cc 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java @@ -3,12 +3,16 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.NavigableSet; import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; @@ -18,6 +22,8 @@ import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; import com.sap.sailing.domain.common.Distance; @@ -92,9 +98,15 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { this.startTime = startTime; // copies the list to make sure that later modifications to the list passed to this constructor don't affect the ranking produced by this race this.competitorsFromBestToWorst = new ArrayList(competitorsFromBestToWorst); - final List waypoints = Collections.emptyList(); - this.race = new RaceDefinitionImpl("Mocked Race", new CourseImpl("Mock Course", waypoints), /* boat class */ null, - competitorsFromBestToWorst); + BoatClass boatClass = new BoatClassImpl("49er", /* upwind start */ true); + final Map competitorsAndBoats = new HashMap<>(); + int i = 1; + for (Competitor c: competitorsFromBestToWorst) { + Boat b = new BoatImpl("Boat" + i++, c.getName(), boatClass, c.getName(), null); + competitorsAndBoats.put(c, b); + } + this.race = new RaceDefinitionImpl("Mocked Race", new CourseImpl("Mock Course", Collections.emptyList()), boatClass, + competitorsAndBoats); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java index 546eb8e0925..256e5185b27 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java @@ -14,6 +14,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.impl.BravoFixImpl; @@ -23,6 +24,7 @@ import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicBravoFixTrack; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; public class BravoFixTrackSerializationTest { @@ -30,8 +32,8 @@ public class BravoFixTrackSerializationTest { @Before public void setUp() { - Competitor competitor = TrackBasedTest.createCompetitor("SAP Extreme Sailing Team"); - track = new BravoFixTrackImpl(competitor, BravoFixTrack.TRACK_NAME); + Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SAP Extreme Sailing Team"); + track = new BravoFixTrackImpl(competitorAndBoat.getA(), BravoFixTrack.TRACK_NAME); } @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 863458c7fc9..fc44f01b0d5 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 @@ -202,7 +202,7 @@ public interface DomainFactory { * @param raceLogResolver TODO */ DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitors, BoatClass boatClass, Map competitorBoats, + String raceName, BoatClass boatClass, Map competitorsAndBoats, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver); @@ -257,9 +257,7 @@ public interface DomainFactory { */ RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds); - Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass); - - Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race); + Util.Pair, BoatClass> getCompetitorsAndTheirBoatsAndDominantBoatClass(IRace race); /** * @param offsetToStartTimeOfSimulatedRace 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 6cb61474ebc..31b37d77920 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 @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -73,6 +74,7 @@ import com.sap.sailing.domain.tractracadapter.ReceiverType; import com.sap.sailing.domain.tractracadapter.TracTracConfiguration; import com.sap.sailing.domain.tractracadapter.TracTracControlPoint; import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker; +import com.sap.sse.common.Color; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -505,7 +507,7 @@ public class DomainFactoryImpl implements DomainFactory { @Override public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitors, BoatClass boatClass, Map competitorBoats, Course course, + String raceName, BoatClass boatClass, Map competitorsAndBoats, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver) { @@ -513,7 +515,7 @@ public class DomainFactoryImpl implements DomainFactory { RaceDefinition raceDefinition = raceCache.get(raceId); if (raceDefinition == null) { logger.info("Creating RaceDefinitionImpl for race "+raceName); - raceDefinition = new RaceDefinitionImpl(raceName, course, boatClass, competitors, competitorBoats, raceId); + raceDefinition = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats, raceId); } else { logger.info("Already found RaceDefinitionImpl for race "+raceName); } @@ -570,37 +572,40 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass) { - final Map competitorBoatInfos = new HashMap<>(); + public Util.Pair, BoatClass> getCompetitorsAndTheirBoatsAndDominantBoatClass(IRace race) { + final Map competitorsAndBoats = new LinkedHashMap(); + final List competitorClasses = new ArrayList(); for (IRaceCompetitor rc : race.getRaceCompetitors()) { - Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); - Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); - if (existingCompetitor != null && competitorBoatInfo != null) { - Boat boatOfCompetitor = new BoatImpl(existingCompetitor.getId(), competitorBoatInfo.getA(), - defaultBoatClass, competitorBoatInfo.getB(), AbstractColor.getCssColor(competitorBoatInfo.getC())); - competitorBoatInfos.put(existingCompetitor, boatOfCompetitor); - } - } - return competitorBoatInfos; - } - - - @Override - public Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race) { - List competitorClasses = new ArrayList(); - final List competitors = new ArrayList(); - for (IRaceCompetitor rc : race.getRaceCompetitors()) { - // also add those whose race class doesn't match the dominant one (such as camera boats) - // because they may still send data that we would like to record in some tracks - competitors.add(getOrCreateCompetitor(rc.getCompetitor())); competitorClasses.add(rc.getCompetitor().getCompetitorClass()); } BoatClass dominantBoatClass = getDominantBoatClass(competitorClasses); - Util.Pair, BoatClass> competitorsAndDominantBoatClass = new com.sap.sse.common.Util.Pair, BoatClass>( - competitors, dominantBoatClass); - return competitorsAndDominantBoatClass; + for (IRaceCompetitor rc : race.getRaceCompetitors()) { + // also add those whose race class doesn't match the dominant one (such as camera boats) + // because they may still send data that we would like to record in some tracks + Competitor competitor = getOrCreateCompetitor(rc.getCompetitor()); + Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); + Boat boatOfCompetitor; + if (competitorBoatInfo != null) { + boatOfCompetitor = getOrCreateBoat(competitor, competitorBoatInfo.getA(), + dominantBoatClass, competitorBoatInfo.getB(), AbstractColor.getCssColor(competitorBoatInfo.getC())); + } else { + boatOfCompetitor = getOrCreateBoat(competitor, competitor.getShortName(), dominantBoatClass, competitor.getShortName(), null); + } + + competitorsAndBoats.put(competitor, boatOfCompetitor); + } + return new Util.Pair, BoatClass>(competitorsAndBoats, dominantBoatClass); } + private Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color) { + CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); + Boat boat = competitorAndBoatStore.getExistingBoatById(competitor.getId()); + if (boat == null) { + boat = competitorAndBoatStore.getOrCreateBoat(competitor, name, boatClass, sailId, color); + } + return boat; + } + private BoatClass getDominantBoatClass(Collection competitorClasses) { List competitorClassNames = new ArrayList<>(); for (ICompetitorClass competitorClass : competitorClasses) { 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 c547175725d..90700a06d4c 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 @@ -155,11 +155,10 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue, BoatClass> competitorsAndDominantBoatClass = getDomainFactory().getCompetitorsAndDominantBoatClass(tractracRace); - Map competitorBoats = getDomainFactory().getBoatsInfoForCompetitors(tractracRace, competitorsAndDominantBoatClass.getB()); + com.sap.sse.common.Util.Pair, BoatClass> competitorsAndBoatsAndDominantBoatClass = getDomainFactory().getCompetitorsAndTheirBoatsAndDominantBoatClass(tractracRace); trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace( - getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getA(), - competitorsAndDominantBoatClass.getB(), competitorBoats, course, sidelines, windStore, delayToLiveInMillis, + getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), + competitorsAndBoatsAndDominantBoatClass.getB(), competitorsAndBoatsAndDominantBoatClass.getA(), course, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, tracTracUpdateURI, getTracTracEvent().getId(), tracTracUsername, tracTracPassword, useInternalMarkPassingAlgorithm, raceLogResolver); needToUpdateRaceTimes = true; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java index 9545afb6742..a790417a8b3 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java @@ -6,11 +6,9 @@ import java.security.NoSuchAlgorithmException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.logging.Logger; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; @@ -21,63 +19,49 @@ import com.sap.sailing.domain.common.RaceCompetitorIdsAsStringWithMD5Hash; import com.sap.sse.common.impl.NamedImpl; public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { - private static final Logger logger = Logger.getLogger(RaceDefinitionImpl.class.getName()); - private static final long serialVersionUID = -1900955198751393727L; private final Course course; - private final LinkedHashMap competitorsById; - private final Set competitors; - private final Map competitorBoats; + private final HashMap competitorsByCompetitorId; + private final HashMap boatsByCompetitorId; private final BoatClass boatClass; private final Serializable id; private final RaceCompetitorIdsAsStringWithMD5Hash raceCompetitorsMD5Hash; + private final Map competitorsAndTheirBoats; - public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors) { - this(name, course, boatClass, competitors, Collections.emptyMap()); + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass) { + this(name, course, boatClass, Collections.emptyMap()); } - public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, - Map competitorsAndTheirBoats) { - this(name, course, boatClass, competitors, competitorsAndTheirBoats, /* use name as default ID */ name); + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Map competitorsAndTheirBoats) { + this(name, course, boatClass, competitorsAndTheirBoats, /* use name as default ID */ name); } - public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, Serializable id) { - this(name, course, boatClass, competitors, /* per-race boats for competitors */ Collections.emptyMap(), id); - } - - public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, - Map competitorsAndTheirBoats, Serializable id) { + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Map competitorsAndTheirBoats, Serializable id) { super(name); assert name != null; + this.boatClass = boatClass; this.course = course; - this.competitors = new HashSet<>(); - this.competitorsById = new LinkedHashMap<>(); - this.competitorBoats = new HashMap<>(); + this.competitorsAndTheirBoats = new HashMap<>(competitorsAndTheirBoats); + this.id = id; + final Set idsOfCompetitorsAsString = new HashSet<>(); - for (Competitor competitor : competitors) { - Competitor competitorWithEqualID = competitorsById.put(competitor.getId(), competitor); - this.competitors.add(competitor); + this.competitorsByCompetitorId = new HashMap<>(); + this.boatsByCompetitorId = new HashMap<>(); + + for (Entry competitorAndBoat : competitorsAndTheirBoats.entrySet()) { + Competitor competitor = competitorAndBoat.getKey(); + Competitor competitorWithEqualID = competitorsByCompetitorId.put(competitor.getId(), competitor); + boatsByCompetitorId.put(competitor.getId(), competitorAndBoat.getValue()); idsOfCompetitorsAsString.add(competitor.getId().toString()); if (competitorWithEqualID != null && competitorWithEqualID != competitor) { throw new IllegalArgumentException("Two distinct competitors with equal ID "+competitor.getId()+" are not allowed within the single race "+name); } } - for (Entry competitorAndBoat : competitorsAndTheirBoats.entrySet()) { - Competitor competitor = competitorsById.get(competitorAndBoat.getKey().getId()); // only assign boat if competitor is part of race - if (competitor != null && competitorAndBoat.getValue() != null) { - competitorBoats.put(competitor.getId(), competitorAndBoat.getValue()); - } else { - logger.warning("Trying to set boat "+competitorAndBoat.getValue()+" for competitor "+competitorAndBoat.getKey()+ - " which is not part of race "+getName()+"'s set of competitors"); - } - } try { raceCompetitorsMD5Hash = new RaceCompetitorIdsAsStringWithMD5Hash(idsOfCompetitorsAsString); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { throw new RuntimeException("Internal error: issue with UTF8 or MD5 for encoding competitor IDs as MD5 hash", e); } - this.boatClass = boatClass; - this.id = id; } @Override @@ -92,7 +76,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { @Override public Iterable getCompetitors() { - return Collections.unmodifiableSet(competitors); + return Collections.unmodifiableSet(competitorsAndTheirBoats.keySet()); } @Override @@ -102,7 +86,7 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { @Override public Competitor getCompetitorById(Serializable competitorID) { - return competitorsById.get(competitorID); + return competitorsByCompetitorId.get(competitorID); } @Override @@ -112,6 +96,6 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { @Override public Boat getBoatOfCompetitorById(Serializable competitorID) { - return competitorBoats.get(competitorID); + return boatsByCompetitorId.get(competitorID); } } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index dbf69fbf6aa..164170244ab 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -17,14 +17,17 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.UUID; import java.util.logging.Logger; import org.junit.Test; import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -40,6 +43,7 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Venue; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.EventImpl; @@ -844,12 +848,14 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest Regatta regatta = createRegatta(RegattaImpl.getDefaultName("Cologne Masters", boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - List competitors = new ArrayList(); - competitors.add(new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + Map competitorsAndBoats = new LinkedHashMap<>(); + Competitor c = new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat b = new BoatImpl("123", "boat", boatClass, "GER 124"); + competitorsAndBoats.put(c, b); Iterable waypoints = Collections.emptyList(); Course course = new CourseImpl("Course", waypoints); - RaceDefinition racedef = new RaceDefinitionImpl("M1", course, boatClass, competitors); + RaceDefinition racedef = new RaceDefinitionImpl("M1", course, boatClass, competitorsAndBoats); regatta.addRace(racedef); RacingEventServiceImpl evs = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index 2884c18cce3..b22c61e35bc 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -9,9 +9,13 @@ import static org.junit.Assert.assertTrue; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.DomainFactory; @@ -80,17 +84,20 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { Iterable emptyWaypointList = Collections.emptyList(); final String competitorName = "Der mit dem Kiel zieht"; final String competitorShortName = "DK"; + final BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */true); Competitor competitor = master.getBaseDomainFactory().getOrCreateCompetitor( 123, competitorName, competitorShortName, Color.RED, "someone@nowhere.de", flagImageURI, new TeamImpl("STG", Collections.singleton(new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - new BoatImpl("123", competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); - Iterable competitors = Collections.singleton(competitor); + new BoatImpl("123", competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Boat boat = new BoatImpl(competitor.getId(), competitorName + "'s boat", boatClass, /* sailID */ null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); final String raceName = "Test Race"; RaceDefinition raceDefinition = new RaceDefinitionImpl(raceName, new CourseImpl("Empty Course", emptyWaypointList), - masterRegatta.getBoatClass(), competitors); + masterRegatta.getBoatClass(), competitorsAndBoats); master.apply(new AddRaceDefinition(masterRegatta.getRegattaIdentifier(), raceDefinition)); Thread.sleep(1000); Regatta replicatedRegatta = replica.getRegatta(new RegattaName(masterRegatta.getName())); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index 6a3c718686c..71eb11a89ab 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -11,9 +11,11 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -25,6 +27,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -131,7 +134,7 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl /* RaceDefinition and DynamicTrackedRace */ RaceDefinition masterRace = new RaceDefinitionImpl("Test Race", new CourseImpl("Test Course", Collections.emptyList()), - masterRegatta.getBoatClass(), Collections.emptyList()); + masterRegatta.getBoatClass(), Collections.emptyMap()); masterRegatta.addRace(masterRace); DynamicTrackedRace masterTrackedRace = master.createTrackedRace(new RegattaNameAndRaceName(masterRegatta.getName(), masterRace.getName()), master.getWindStore(), /* delayToLiveInMillis */ 3000, @@ -252,10 +255,10 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl Regatta regatta = master.apply(addEventOperation); final String raceName1 = "Test Race 1"; final String raceName2 = "Test Race 2"; - Competitor competitor = TrackBasedTest.createCompetitor("The Same Competitor"); + Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("The Same Competitor"); final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); - final ArrayList competitors = new ArrayList(); - competitors.add(competitor); + final Map competitors = new HashMap<>(); + competitors.put(competitorAndBoat.getA(), competitorAndBoat.getB()); RaceDefinition race1 = new RaceDefinitionImpl(raceName1, masterCourse, boatClass, competitors); AddRaceDefinition addRaceOperation1 = new AddRaceDefinition(new RegattaName(regatta.getName()), race1); master.apply(addRaceOperation1); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java index 8b8972d5c97..c243280292b 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.RegattaImpl; @@ -18,6 +19,7 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.test.TrackBasedTest; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaLogReplicationTest extends @@ -33,8 +35,8 @@ public class RegattaLogReplicationTest extends @Before public void createEvent() throws Exception { - final Competitor competitor = TrackBasedTest.createCompetitor("Test Competitor"); - regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), t(0), author, 0, competitor); + final Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), t(0), author, 0, competitorAndBoat.getA()); // anotherRegattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(1), author, t(1), 1, null); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ServerReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ServerReplicationTest.java index b591b792c11..254babf8182 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ServerReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/ServerReplicationTest.java @@ -8,10 +8,12 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.UUID; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -92,8 +94,7 @@ public class ServerReplicationTest extends AbstractServerReplicationTest { Regatta regatta = master.apply(addRegattaOperation); final String raceName = "Test Race"; final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); - RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, - new ArrayList()); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.emptyMap()); AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); master.apply(addRaceOperation); masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); 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 ef02e278bb0..9c7667713c3 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 @@ -7,14 +7,16 @@ 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.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.Before; import org.junit.Test; import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -77,13 +79,17 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)), new BoatImpl("123", "GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Boat boat = masterDomainFactory.getCompetitorStore().getOrCreateBoat(competitor, "boat123", + masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61", null); + Map competitorAndBoats = new HashMap<>(); + competitorAndBoats.put(competitor, boat); 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)); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, competitorAndBoats); AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); master.apply(addRaceOperation); masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); 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 index e12dc824186..4f23ed4bd38 100644 --- 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 @@ -7,13 +7,15 @@ 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.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -37,6 +39,7 @@ 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.racelog.tracking.GPSFixStore; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.GPSFixTrack; @@ -74,19 +77,23 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS final String boatClassName = "49er"; final DomainFactory masterDomainFactory = testSetUp.getMaster().getBaseDomainFactory(); BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); + BoatClass boatClass470 = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true); competitor = masterDomainFactory.getCompetitorStore().getOrCreateCompetitor("GER 61", "Tina Lutz", "TL", 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("123", "GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), + new BoatImpl("123", "GER 61", boatClass470, "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Boat boat = masterDomainFactory.getCompetitorStore().getOrCreateBoat(competitor, "GER 61", boatClass470, "GER 61", 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)); + final Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, competitorsAndBoats); AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); master.apply(addRaceOperation); masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 2fdae15a0f4..ccc2e183b3e 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -17,9 +17,12 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -50,6 +53,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompeti import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -112,7 +116,7 @@ import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServi import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.test.TrackBasedTest; +import com.sap.sailing.domain.test.TrackBasedTest; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindTrack; @@ -123,7 +127,7 @@ import com.sap.sailing.server.gateway.jaxrs.spi.MasterDataResource; import com.sap.sailing.server.impl.RacingEventServiceImpl; import com.sap.sailing.server.masterdata.DummyTrackedRace; import com.sap.sailing.server.masterdata.MasterDataImporter; -import com.sap.sailing.server.testsupport.RacingEventServiceImplMock; +import com.sap.sailing.server.testsupport.RacingEventServiceImplMock; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -135,8 +139,8 @@ import com.sap.sse.mongodb.MongoDBService; import com.sap.sse.shared.media.ImageDescriptor; import com.sap.sse.shared.media.VideoDescriptor; -import junit.framework.Assert; - +import junit.framework.Assert; + public class MasterDataImportTest { private static final String TEST_GROUP_NAME = "testGroup"; @@ -182,6 +186,16 @@ public class MasterDataImportTest { service.getDB().dropDatabase(); } + private Map createCompetitorsAndBoatsMap(BoatClass boatClass, Iterable competitors) { + Map result = new LinkedHashMap<>(); + int i = 1; + for(Competitor c: competitors) { + Boat b = new BoatImpl(c.getId(), "Boat of " + c.getName(), boatClass, "GER " + i++, null); + result.put(c, b); + } + return result; + } + @Test public void testMasterDataImportWithoutHttpStack() throws MalformedURLException, IOException, InterruptedException, ClassNotFoundException { @@ -206,7 +220,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl(testFleet1Name); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -240,7 +254,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -251,10 +265,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -326,7 +340,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID), serviceFinderFactory){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID), serviceFinderFactory){}; domainFactory = destService.getBaseDomainFactory(); DB db = destService.getMongoObjectFactory().getDatabase(); db.setWriteConcern(WriteConcern.SAFE); @@ -361,7 +375,7 @@ public class MasterDataImportTest { Assert.assertNull(raceColumnOnTarget.getTrackedRace(raceColumnOnTarget.getFleetByName(testFleet1Name))); raceColumnOnTarget.setTrackedRace(raceColumnOnTarget.getFleets().iterator().next(), new DummyTrackedRace( - raceId, competitors, regattaOnTarget, null, sourceService.getWindStore())); + raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regattaOnTarget, null, sourceService.getWindStore())); Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); @@ -369,7 +383,7 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsCreatedOnTarget), regattaOnTarget, null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -430,7 +444,7 @@ public class MasterDataImportTest { Assert.assertTrue(destService.getSensorFixStore().getNumberOfFixes(deviceIdentifier) == 1); // Check for persisting of race log events: - RacingEventService dest2 = new RacingEventServiceImplMock(){}; + RacingEventService dest2 = new RacingEventServiceImplMock(){}; Leaderboard lb2 = dest2.getLeaderboardByName(TEST_LEADERBOARD_NAME); RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleetByName(fleet1OnTarget.getName())); @@ -469,7 +483,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -500,7 +514,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -509,10 +523,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", "KYC", Color.RED, null, null, team2, - boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -547,7 +561,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -583,7 +597,7 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsCreatedOnTarget), regattaOnTarget, null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -628,7 +642,7 @@ public class MasterDataImportTest { List fleets = new ArrayList(); FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ @@ -647,7 +661,6 @@ public class MasterDataImportTest { /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors - Set competitors = new HashSet(); UUID competitorUUID = UUID.randomUUID(); Set sailors = new HashSet(); sailors.add(new PersonImpl("Froderik Poterson", new NationalityImpl("GER"), new Date(645487200000L), @@ -658,12 +671,13 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); - competitors.add(competitor); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); DynamicTrackedRegatta trackedRegatta = sourceService.getOrCreateTrackedRegatta(regatta); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, trackedRegatta, + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitorsAndBoats, regatta, trackedRegatta, sourceService.getWindStore()); regatta.addRace(trackedRace.getRace()); // make sure the competitor is serialized together with the regatta raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -694,7 +708,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -724,12 +738,12 @@ public class MasterDataImportTest { Assert.assertNotNull(raceColumnOnTarget); Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); - Set competitorsCreatedOnTarget = new HashSet(); - competitorsCreatedOnTarget.add(competitorOnTarget); - + Boat boatOnTarget = domainFactory.getExistingBoatById(competitorUUID); + Map competitorsAndBoatsOnTarget = new HashMap<>(); + competitorsAndBoatsOnTarget.put(competitorOnTarget, boatOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); DynamicTrackedRegatta trackedRegattaForTarget = destService.getOrCreateTrackedRegatta(regattaOnTarget); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsAndBoatsOnTarget, regattaOnTarget, trackedRegattaForTarget, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -791,7 +805,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -823,7 +837,7 @@ public class MasterDataImportTest { DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null, null); + null, null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -833,10 +847,10 @@ public class MasterDataImportTest { DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null, null); + null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -877,7 +891,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -912,7 +926,7 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsCreatedOnTarget), regattaOnTarget, null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -951,7 +965,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -982,7 +996,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -993,10 +1007,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -1047,7 +1061,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); // Create existing data on target venueNameNotToOverride = "doNotOverride"; @@ -1065,7 +1079,7 @@ public class MasterDataImportTest { List fleetsNotToOverride = new ArrayList(); FleetImpl testFleet1NotToOverride = new FleetImpl("testFleet1"); fleetsNotToOverride.add(testFleet1NotToOverride); - seriesNotToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsNotToOverride, emptyRaceColumnNamesList, + seriesNotToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsNotToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaNotToOverride = destService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ @@ -1153,7 +1167,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -1184,7 +1198,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1195,10 +1209,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -1245,7 +1259,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); // Create existing data on target String venueNameToOverride = "Override"; @@ -1263,7 +1277,7 @@ public class MasterDataImportTest { List fleetsToOverride = new ArrayList(); FleetImpl testFleet1ToOverride = new FleetImpl("testFleet1"); fleetsToOverride.add(testFleet1ToOverride); - seriesToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsToOverride, emptyRaceColumnNamesList, + seriesToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaToOverride = destService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ @@ -1287,13 +1301,13 @@ public class MasterDataImportTest { String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ - null, null); + null, null); competitorsToOverride.add(competitorToOverride); Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( regattaToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); - TrackedRace trackedRace2 = new DummyTrackedRace(raceId, competitorsToOverride, regattaToOverride, null, - sourceService.getWindStore()); + TrackedRace trackedRace2 = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsToOverride), + regattaToOverride, null, sourceService.getWindStore()); RaceColumn columnToOverride = leaderboardToOverride.getRaceColumns().iterator().next(); columnToOverride.setTrackedRace(testFleet1ToOverride, trackedRace2); identifierOfRegattaTrackedRace = regattaToOverride.getRaceIdentifier(columnToOverride @@ -1410,7 +1424,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1454,7 +1468,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( @@ -1484,7 +1498,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1495,10 +1509,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -1544,7 +1558,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1589,7 +1603,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -1620,7 +1634,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1631,10 +1645,10 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); sourceService.setRegattaForRace(regatta, "dummy"); @@ -1682,7 +1696,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1711,7 +1725,7 @@ public class MasterDataImportTest { Assert.assertEquals(regattaOnTarget, map.get("dummy2")); // Check if persistent regatta for race id has been persisted - RacingEventServiceImplMock destService2 = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + RacingEventServiceImplMock destService2 = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; ConcurrentHashMap map2 = destService2.getPersistentRegattasForRaceIDs(); Regatta regattaOnTarget2 = destService2.getRegattaByName(TEST_LEADERBOARD_NAME); Assert.assertEquals(regattaOnTarget2, map2.get("dummy")); @@ -1744,7 +1758,7 @@ public class MasterDataImportTest { sourceService.mediaTrackAdded(trackOnSource); Collection raceColumnNames = Arrays.asList(raceName1, raceName2, raceName3, raceName4, raceName5); - Regatta regatta = TrackBasedTest.createTestRegatta(regattaName1, raceColumnNames); + Regatta regatta = TrackBasedTest.createTestRegatta(regattaName1, raceColumnNames); sourceService.addRegattaWithoutReplication(regatta); int[] discardThresholds = new int[0]; RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), @@ -1754,7 +1768,7 @@ public class MasterDataImportTest { new RegattaNameAndRaceName(regattaName1, raceName3), new RegattaNameAndRaceName(regattaName2, raceName4), new RegattaNameAndRaceName(regattaName2, raceName5)); - TrackBasedTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); + TrackBasedTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); boolean displayGroupsInReverseOrder = false; int[] overallLeaderboardDiscardThresholds = new int[0]; UUID leaderboardGropuUuid = UUID.randomUUID(); @@ -1781,7 +1795,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1791,15 +1805,15 @@ public class MasterDataImportTest { os.close(); inputStream.close(); } - MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID).getResult(); + MasterDataImportObjectCreationCount creationCount = destService.getDataImportLock().getProgress(randomUUID).getResult(); // ---Asserts--- Assert.assertNotNull(creationCount); - Iterable targetTracks = destService.getAllMediaTracks(); + Iterable targetTracks = destService.getAllMediaTracks(); - Assert.assertEquals(1, Util.size(targetTracks)); + Assert.assertEquals(1, Util.size(targetTracks)); MediaTrack trackOnTarget = targetTracks.iterator().next(); @@ -1833,7 +1847,7 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl("testFleet1"); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, @@ -1868,7 +1882,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1879,11 +1893,11 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); raceColumn.setTrackedRace(testFleet1, trackedRace); @@ -1907,7 +1921,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1979,7 +1993,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -2020,7 +2034,7 @@ public class MasterDataImportTest { Assert.assertEquals(factor, metaColumn.getFactor()); // Verify that overall leaderboard data has been persisted - RacingEventService persistenceVerifier = new RacingEventServiceImplMock(){}; + RacingEventService persistenceVerifier = new RacingEventServiceImplMock(){}; LeaderboardGroup lg = persistenceVerifier.getLeaderboardGroupByName(TEST_GROUP_NAME); Assert.assertNotNull(lg); overallLeaderboard = (LeaderboardGroupMetaLeaderboard) lg.getOverallLeaderboard(); @@ -2063,8 +2077,8 @@ public class MasterDataImportTest { FleetImpl testFleet1 = new FleetImpl(testFleet1Name); fleets.add(testFleet1); fleets.add(new FleetImpl("testFleet2")); - seriesOnSource.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); - seriesOnTarget.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + seriesOnSource.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); + seriesOnTarget.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ @@ -2098,7 +2112,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -2109,9 +2123,9 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); leaderboard.addRace(trackedRace, raceColumnName, false); RaceColumn raceColumnOnLeaderboard = leaderboard.getRaceColumnByName(raceColumnName); @@ -2166,7 +2180,7 @@ public class MasterDataImportTest { // Delete all data above from the database, to allow recreating all of it on target server deleteAllDataFromDatabase(); // Import in new service - destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; + destService = new RacingEventServiceImplMock(new DataImportProgressImpl(randomUUID)){}; domainFactory = destService.getBaseDomainFactory(); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -2199,7 +2213,7 @@ public class MasterDataImportTest { /* startDate */null, /* endDate */null, regattaUUID, seriesOnTarget, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); - raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, competitors, + raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regattaOnTarget, null, sourceService.getWindStore())); Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); @@ -2208,7 +2222,7 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Assert.assertEquals(defaultFleetOnTarget, leaderboardOnTarget.getFleet(null)); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsCreatedOnTarget), regattaOnTarget, null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, trackedRaceForTarget); @@ -2247,7 +2261,7 @@ public class MasterDataImportTest { .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); // Check for persisting of race log events: - RacingEventService dest2 = new RacingEventServiceImplMock(){}; + RacingEventService dest2 = new RacingEventServiceImplMock(){}; Leaderboard lb2 = dest2.getLeaderboardByName(flexLeaderboardName); RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleets().iterator().next()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java index 25ec563ca13..b04779260ea 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java @@ -22,6 +22,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -75,9 +76,9 @@ public class RaceTrackerStartStopTest { TrackedRegatta trackedRegatta1 = racingEventService.getOrCreateTrackedRegatta(regatta); racingEventService.getRegattasByName().put(EVENTNAME, regatta); raceTrackerSet = Collections.newSetFromMap(new ConcurrentHashMap()); - raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList()), boatClass, new ArrayList()); - raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList()), boatClass, new ArrayList()); - raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList()), boatClass, new ArrayList()); + raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList()), boatClass, Collections.emptyMap()); + raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList()), boatClass, Collections.emptyMap()); + raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList()), boatClass, Collections.emptyMap()); regatta.addRace(raceDef1); trackedRegatta1.createTrackedRace(raceDef1, Collections. emptyList(), /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java index 8344d056a99..deddc193571 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; @@ -73,6 +74,7 @@ import com.sap.sailing.server.operationaltransformation.RemoveRegatta; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.common.search.Result; @@ -85,12 +87,12 @@ public class SearchServiceTest { private Venue flensburg; private Event pfingstbusch; private Regatta pfingstbusch29er; - private Competitor hassoPlattner; - private Competitor alexanderRies; - private Competitor antonKoch; - private Competitor tobiasSchadewaldt; - private Competitor philippBuhl; - private Competitor dennisGehrlein; + private Pair hassoPlattner; + private Pair alexanderRies; + private Pair antonKoch; + private Pair tobiasSchadewaldt; + private Pair philippBuhl; + private Pair dennisGehrlein; private Regatta pfingstbusch470; private Regatta aalRegatta; private DynamicTrackedRace pfingstbusch29erTrackedR1; @@ -181,18 +183,18 @@ public class SearchServiceTest { /* displayGroupsInReverseOrder */ false, Collections.singletonList(RegattaImpl.getDefaultName("Aalregatta", "ORC")), new int[0], /* overallLeaderboardScoringSchemeType */ null)); server.apply(new AddLeaderboardGroupToEvent(aalEvent.getId(), aalLeaderboardGroup.getId())); - hassoPlattner = AbstractTracTracLiveTest.createCompetitor("Hasso Plattner"); - alexanderRies = AbstractTracTracLiveTest.createCompetitor("Alexander Ries"); - antonKoch = AbstractTracTracLiveTest.createCompetitor("Anton Koch"); - tobiasSchadewaldt = AbstractTracTracLiveTest.createCompetitor("Tobias Schadewaldt"); - philippBuhl = AbstractTracTracLiveTest.createCompetitor("Philipp Buhl"); - dennisGehrlein = AbstractTracTracLiveTest.createCompetitor("Dennis Gehrlein"); + hassoPlattner = AbstractTracTracLiveTest.createCompetitorAndBoat("Hasso Plattner"); + alexanderRies = AbstractTracTracLiveTest.createCompetitorAndBoat("Alexander Ries"); + antonKoch = AbstractTracTracLiveTest.createCompetitorAndBoat("Anton Koch"); + tobiasSchadewaldt = AbstractTracTracLiveTest.createCompetitorAndBoat("Tobias Schadewaldt"); + philippBuhl = AbstractTracTracLiveTest.createCompetitorAndBoat("Philipp Buhl"); + dennisGehrlein = AbstractTracTracLiveTest.createCompetitorAndBoat("Dennis Gehrlein"); final RaceDefinitionImpl pfingstbusch29erR1 = new RaceDefinitionImpl("R1", new CourseImpl("up/down", Collections.emptyList()), pfingstbusch29er.getBoatClass(), - Arrays.asList(new Competitor[] { alexanderRies, tobiasSchadewaldt })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(alexanderRies, tobiasSchadewaldt)); final RaceDefinitionImpl pfingstbusch29erR2 = new RaceDefinitionImpl("R2", new CourseImpl("up/down", Collections.emptyList()), pfingstbusch29er.getBoatClass(), - Arrays.asList(new Competitor[] { alexanderRies, tobiasSchadewaldt })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(alexanderRies, tobiasSchadewaldt)); final RaceDefinitionImpl pfingstbusch29erR3 = new RaceDefinitionImpl("R3", new CourseImpl("up/down", Collections.emptyList()), pfingstbusch29er.getBoatClass(), - Arrays.asList(new Competitor[] { alexanderRies, tobiasSchadewaldt })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(alexanderRies, tobiasSchadewaldt)); server.apply(new AddRaceDefinition(pfingstbusch29er.getRegattaIdentifier(), pfingstbusch29erR1)); server.apply(new AddRaceDefinition(pfingstbusch29er.getRegattaIdentifier(), pfingstbusch29erR2)); server.apply(new AddRaceDefinition(pfingstbusch29er.getRegattaIdentifier(), pfingstbusch29erR3)); @@ -206,9 +208,9 @@ public class SearchServiceTest { pfingstbusch29erLeaderboard.getRaceColumnByName("R3").setTrackedRace(pfingstbusch29erLeaderboard.getRaceColumnByName("R3").getFleetByName("Default"), pfingstbusch29erTrackedR3); final RaceDefinitionImpl pfingstbush470R1 = new RaceDefinitionImpl("R1", new CourseImpl("up/down", Collections.emptyList()), pfingstbusch470.getBoatClass(), - Arrays.asList(new Competitor[] { philippBuhl, antonKoch })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(philippBuhl, antonKoch)); final RaceDefinitionImpl pfingstbush470R2 = new RaceDefinitionImpl("R2", new CourseImpl("up/down", Collections.emptyList()), pfingstbusch470.getBoatClass(), - Arrays.asList(new Competitor[] { philippBuhl, antonKoch })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(philippBuhl, antonKoch)); server.apply(new AddRaceDefinition(pfingstbusch470.getRegattaIdentifier(), pfingstbush470R1)); server.apply(new AddRaceDefinition(pfingstbusch470.getRegattaIdentifier(), pfingstbush470R2)); // track only R1 and R2 @@ -221,9 +223,9 @@ public class SearchServiceTest { pfingstbusch470Leaderboard.getRaceColumnByName("R2").setTrackedRace(pfingstbusch470Leaderboard.getRaceColumnByName("R2").getFleetByName("Default"), pfingstbusch470TrackedR2); final RaceDefinitionImpl aalOrcR1 = new RaceDefinitionImpl("R1", new CourseImpl("up/down", Collections.emptyList()), aalRegatta.getBoatClass(), - Arrays.asList(new Competitor[] { hassoPlattner, dennisGehrlein, philippBuhl })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(hassoPlattner, dennisGehrlein, philippBuhl)); final RaceDefinitionImpl aalOrcR2 = new RaceDefinitionImpl("R2", new CourseImpl("up/down", Collections.emptyList()), aalRegatta.getBoatClass(), - Arrays.asList(new Competitor[] { hassoPlattner, dennisGehrlein, philippBuhl })); + AbstractTracTracLiveTest.createCompetitorAndBoatsMap(hassoPlattner, dennisGehrlein, philippBuhl)); server.apply(new AddRaceDefinition(aalRegatta.getRegattaIdentifier(), aalOrcR1)); server.apply(new AddRaceDefinition(aalRegatta.getRegattaIdentifier(), aalOrcR2)); // track only R1 and R2 diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index ec841261f12..3fcdf878007 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -5,8 +5,9 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.Before; @@ -17,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -58,6 +60,7 @@ import com.sap.sailing.server.operationaltransformation.TrackRegatta; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class WindByRaceLogTest { @@ -79,7 +82,7 @@ public class WindByRaceLogTest { // FIXME use master DomainFactory; see bug 592 final DomainFactory masterDomainFactory = service.getBaseDomainFactory(); BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); - Competitor competitor = createCompetitor(masterDomainFactory); + Pair competitorAndBoat = createCompetitorAndBoat(masterDomainFactory, boatClass); int[] discardThreshold = {1, 2}; CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null); service.apply(createLeaderboardOperation); @@ -92,7 +95,9 @@ public class WindByRaceLogTest { Regatta regatta = service.apply(addRegattaOperation); final String raceName = "Test Race"; final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); - RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, Collections.singletonList(competitor)); + final Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, competitorsAndBoats); AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); service.apply(addRaceOperation); masterCourse.addWaypoint(0, masterDomainFactory.createWaypoint(masterDomainFactory.getOrCreateMark("Mark1"), /*passingInstruction*/ null)); @@ -104,11 +109,13 @@ public class WindByRaceLogTest { defaultFleet = Util.get(raceColumn.getFleets(), 0); } - private Competitor createCompetitor(final DomainFactory masterDomainFactory) { - return masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", + private Pair createCompetitorAndBoat(final DomainFactory masterDomainFactory, final BoatClass boatClass) { + Competitor competitor = masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), - new BoatImpl("123", "GER 61", DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + new BoatImpl("123", "GER 61", boatClass, "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Boat boat = masterDomainFactory.getOrCreateBoat(competitor, "GER 61", boatClass, "GER 61", null); + return new Pair(competitor, boat); } private void attachTrackedRaceToRaceColumn() { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java index c2f41836b14..c0cb60abea3 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java @@ -2,13 +2,14 @@ package com.sap.sailing.server.masterdata; import java.io.Serializable; import java.util.Collections; -import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.NavigableSet; import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; @@ -66,17 +67,17 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { private static final long serialVersionUID = -11522605089325440L; private Regatta regatta; - public DummyTrackedRace(final Serializable raceId, final Iterable competitors, final Regatta regatta, final TrackedRegatta trackedRegatta, final WindStore windStore) { - this(competitors, regatta, trackedRegatta, new RaceDefinitionImpl("DummyRace", new CourseImpl("Dummy Course", Collections.emptyList()), - regatta.getBoatClass(), competitors, raceId), windStore); + public DummyTrackedRace(final Serializable raceId, final Map competitorsAndBoats, final Regatta regatta, final TrackedRegatta trackedRegatta, final WindStore windStore) { + this(competitorsAndBoats, regatta, trackedRegatta, new RaceDefinitionImpl("DummyRace", new CourseImpl("Dummy Course", Collections.emptyList()), + regatta.getBoatClass(), competitorsAndBoats, raceId), windStore); } - public DummyTrackedRace(final Iterable competitors, final Regatta regatta, final TrackedRegatta trackedRegatta, + public DummyTrackedRace(final Map competitors, final Regatta regatta, final TrackedRegatta trackedRegatta, RaceDefinition race, WindStore windStore) { super(race, trackedRegatta, windStore, -1); this.regatta = regatta; } - public DummyTrackedRace(final Iterable competitors, final Regatta regatta, final TrackedRegatta trackedRegatta, + public DummyTrackedRace(final Map competitors, final Regatta regatta, final TrackedRegatta trackedRegatta, RaceDefinition race) { this(competitors, regatta, trackedRegatta, race, EmptyWindStore.INSTANCE); @@ -84,7 +85,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { public DummyTrackedRace(final String raceName, final Serializable raceId) { super(new RaceDefinitionImpl(raceName, new CourseImpl("Dummy Course", Collections. emptyList()), - /* boatClass */ null, new HashSet(), raceId), null, EmptyWindStore.INSTANCE, -1); + /* boatClass */ null, Collections.emptyMap(), raceId), null, EmptyWindStore.INSTANCE, -1); } @Override From 7e632a16d3630d16de5dddd6750bf60c62b90342 Mon Sep 17 00:00:00 2001 From: fmittag Date: Thu, 18 Aug 2016 12:17:45 +0200 Subject: [PATCH 005/271] fix for some broken tests (this code will be removed anyway in the futher progress of the bug implementation) --- .../domain/racelogtracking/impl/RaceLogRaceTracker.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 0af5d6e0214..6e4f8738cf3 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 @@ -296,8 +296,12 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { // For now we create the boats here which MUST be corrected later on Map competitorsAndBoats = new HashMap<>(); for (Competitor c: competitors) { - Boat theWrongBoat = c.getBoat(); - Boat b = new BoatImpl(c.getId(), theWrongBoat.getName(), boatClass, theWrongBoat.getSailID(), theWrongBoat.getColor()); + Boat b; + if (c.getBoat() != null) { + b = new BoatImpl(c.getId(), c.getBoat().getName(), boatClass, c.getBoat().getSailID(), c.getBoat().getColor()); + } else { + b = new BoatImpl(c.getId(), c.getShortName(), boatClass, c.getShortName(), null); + } competitorsAndBoats.put(c, b); } final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats, raceId); From bad74219357a3b46c69e7acd8aa828aab61ca161 Mon Sep 17 00:00:00 2001 From: fmittag Date: Thu, 18 Aug 2016 17:29:15 +0200 Subject: [PATCH 006/271] Added draft implementation of regatta.getAllBoats() Added CompetitorWithBoat utility class Adapted all tests --- .../domain/base/CompetitorWithBoat.java | 8 ++ .../base/impl/CompetitorWithBoatImpl.java | 26 ++++ .../impl/CandidateFinderImplWhiteBoxTest.java | 5 +- ...stFarthestAheadWithSkippedMarkPassing.java | 10 +- ...mpleTimeOnTimeRankingWithOneUpwindLeg.java | 10 +- .../domain/test/AbstractLeaderboardTest.java | 30 ++-- .../domain/test/CompetitorListenerTest.java | 2 +- ...mpetitorProviderCacheInvalidationTest.java | 2 +- .../sap/sailing/domain/test/CourseTest.java | 12 +- ...eInvalidationAfterLoadingFinishedTest.java | 6 +- .../domain/test/LeaderboardOfflineTest.java | 129 +++++++++--------- .../LeaderboardScoringAndRankingTestBase.java | 2 +- .../sailing/domain/test/ReachingLegTest.java | 20 +-- ...ttaLogEventNotificationForwardingTest.java | 2 +- .../sailing/domain/test/TrackBasedTest.java | 13 +- ...rtTimeUpdateForDependentStartTimeTest.java | 6 +- .../domain/test/UpdateMarkPassingTest.java | 7 +- ...WindEstimationOnConstructedTracksTest.java | 14 +- .../domain/test/mock/MockedTrackedRace.java | 6 + .../mock/MockedTrackedRaceWithFixedRank.java | 30 ++-- ...edRaceWithFixedRankAndManyCompetitors.java | 23 ++-- .../impl/BravoFixTrackSerializationTest.java | 7 +- .../sailing/domain/base/RaceDefinition.java | 2 + .../com/sap/sailing/domain/base/Regatta.java | 2 + .../domain/base/impl/RaceDefinitionImpl.java | 7 +- .../sailing/domain/base/impl/RegattaImpl.java | 16 +++ .../mongodb/test/StoreCompetitorTest.java | 8 +- ...estStoringAndLoadingEventsAndRegattas.java | 7 +- ...StoringAndRetrievingLeaderboardGroups.java | 23 +++- .../TestStoringAndRetrievingLeaderboards.java | 117 ++++++++-------- ...LeaderboardCorrectionsReplicationTest.java | 18 +-- ...tialLoadReplicationObjectIdentityTest.java | 5 +- .../test/RegattaLogReplicationTest.java | 8 +- .../server/test/CompetitorStoreTest.java | 8 +- .../test/LeaderboardDiscardingRulesTest.java | 56 ++++---- .../server/test/SearchServiceTest.java | 16 +-- .../server/test/WindByRaceLogTest.java | 11 +- 37 files changed, 387 insertions(+), 287 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java new file mode 100644 index 00000000000..c11fe0b3200 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java @@ -0,0 +1,8 @@ +package com.sap.sailing.domain.base; + +import java.io.Serializable; + +public interface CompetitorWithBoat extends Serializable { + Competitor getCompetitor(); + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java new file mode 100644 index 00000000000..b7d050b8d37 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java @@ -0,0 +1,26 @@ +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; + +public class CompetitorWithBoatImpl implements CompetitorWithBoat { + private static final long serialVersionUID = 6057339511208358777L; + private final Competitor competitor; + private final Boat boat; + + public CompetitorWithBoatImpl(Competitor competitor, Boat boat) { + this.competitor = competitor; + this.boat = boat; + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + @Override + public Boat getBoat() { + return boat; + } + +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java index 5d212665a90..752c4f89c56 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.ReadonlyRacingProcedureFactory; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; import com.sap.sailing.domain.common.Position; @@ -62,8 +63,8 @@ public class CandidateFinderImplWhiteBoxTest { @Before public void setUp() { now = MillisecondsTimePoint.now(); - Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Competitor"); - competitor = competitorAndBoat.getA(); + CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Competitor"); + competitor = competitorAndBoat.getCompetitor(); Map competitorAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); trackedRace = TrackBasedTest.createTestTrackedRace("Test Regatta", "Test Race", "505", competitorAndBoats, now, /* useMarkPassingCalculator */ true); finder = new CandidateFinderWithPublicGetProbabilityOfStartBasedOnOtherCompetitorsStartLineDistances(trackedRace); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java index ea454eea66a..b2f4cbdecd3 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java @@ -17,6 +17,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -55,7 +56,6 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; /** @@ -82,10 +82,10 @@ public class TestFarthestAheadWithSkippedMarkPassing { private Waypoint finish; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - Pair fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); - c1 = fastCompetitorAndBoat.getA(); - Pair slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); - c2 = slowCompetitorAndBoat.getA(); + CompetitorWithBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + c1 = fastCompetitorAndBoat.getCompetitor(); + CompetitorWithBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + c2 = slowCompetitorAndBoat.getCompetitor(); trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat)); rankingMetric = trackedRace.getRankingMetric(); assertEquals(120, trackedRace.getCourseLength().getNauticalMiles(), 0.02); 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 157f49cc655..1e8bf04f673 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 @@ -17,6 +17,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -54,7 +55,6 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -64,10 +64,10 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { private Competitor c1, c2; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - Pair fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); - c1 = fastCompetitorAndBoat.getA(); - Pair slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); - c2 = slowCompetitorAndBoat.getA(); + CompetitorWithBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + c1 = fastCompetitorAndBoat.getCompetitor(); + CompetitorWithBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + c2 = slowCompetitorAndBoat.getCompetitor(); trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat), timeOnTimeFactors, timeOnDistanceFactors); tot = trackedRace.getRankingMetric(); assertEquals(60, trackedRace.getCourseLength().getNauticalMiles(), 0.01); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 333e06d6ffe..772a387fa88 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -3,42 +3,54 @@ package com.sap.sailing.domain.test; import java.io.Serializable; import java.util.Collections; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorFactory; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sse.common.Color; public abstract class AbstractLeaderboardTest { - public static CompetitorImpl createCompetitor(String competitorName) { - return new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + + public static CompetitorWithBoat createCompetitorAndBoat(String competitorName) { + Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", - competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); + return new CompetitorWithBoatImpl(c, b); } - public static Competitor createCompetitor(String competitorName, CompetitorFactory competitorFactory) { - return competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( + public static CompetitorWithBoat createCompetitorAndBoat(String competitorName, CompetitorFactory competitorFactory) { + Competitor c = competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", - competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), + competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); + return new CompetitorWithBoatImpl(c, b); } - public static CompetitorImpl createCompetitor(String competitorName, Serializable id) { - return new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + public static CompetitorWithBoat createCompetitorAndBoat(String competitorName, Serializable id) { + Competitor c = new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(id, - competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); + return new CompetitorWithBoatImpl(c, b); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index d15204a2f34..98f8aed2e45 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -70,7 +70,7 @@ public class CompetitorListenerTest extends AbstractSerializationTest { @Before public void setUp() { baseDomainFactory = new DomainFactoryImpl((srlid)->null); - competitor = (DynamicCompetitor) TrackBasedTest.createCompetitorAndBoat("Hasso").getA(); + competitor = (DynamicCompetitor) TrackBasedTest.createCompetitorAndBoat("Hasso").getCompetitor(); nationalityChanged = false; whatChangedNationality = null; oldNationality = null; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index b47d2282365..1b2a504e273 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -83,7 +83,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard for (int l = 0; l < NUMBER_OF_COMP_LISTS; l++) { compLists[l] = new ArrayList(); for (int i = 0; i < 10; i++) { - compLists[l].add(createCompetitor("" + l + "/" + i)); + compLists[l].add(createCompetitorAndBoat("" + l + "/" + i).getCompetitor()); } } competitorProviderRegattaLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard); 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 2f458541f76..4842e8bc283 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 @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -29,7 +30,6 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.MarkImpl; @@ -304,10 +304,9 @@ public class CourseTest { Course course = new CourseImpl("Test Course", waypoints); assertWaypointIndexes(course); final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); - final Competitor hasso = AbstractLeaderboardTest.createCompetitor("Hasso"); - final Boat hassosBoat = new BoatImpl("id12345", "Hasso's boat", boatClass, /* sailID */ null); + final CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); final Map competitorsAndBoats = new HashMap<>(); - competitorsAndBoats.put(hasso, hassosBoat); + competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */new DynamicTrackedRegattaImpl( new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), @@ -339,10 +338,9 @@ public class CourseTest { waypoints.add(wp2); Course course = new CourseImpl("Test Course", waypoints); final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); - final Competitor hasso = AbstractLeaderboardTest.createCompetitor("Hasso"); - final Boat hassosBoat = new BoatImpl("id12345", "Hasso's boat", boatClass, /* sailID */ null); + final CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); final Map competitorsAndBoats = new HashMap<>(); - competitorsAndBoats.put(hasso, hassosBoat); + competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ new DynamicTrackedRegattaImpl( new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), Collections. emptyList(), diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java index cdcd0272671..a622aa69dfc 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java @@ -10,6 +10,7 @@ import org.junit.Test; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.TrackedRaceStatusEnum; @@ -23,7 +24,6 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; /** @@ -40,9 +40,9 @@ public class DistanceCacheInvalidationAfterLoadingFinishedTest extends TrackBase @Before public void setUp() { - Pair competitorAndBoat = createCompetitorAndBoat("Test Competitor"); + CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat("Test Competitor"); Map competitorsAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); - competitor = competitorAndBoat.getA(); + competitor = competitorAndBoat.getCompetitor(); trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", competitorsAndBoats, MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 0721b20c5ce..1cdaecee5cd 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -48,22 +49,22 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class LeaderboardOfflineTest extends AbstractLeaderboardTest { private Set testRaces; private Map raceColumnsInLeaderboard; - private Competitor competitor; + private CompetitorWithBoat competitorWithBoat; @Before public void setUp() { - competitor = createCompetitor("Wolfgang Hunger"); + competitorWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); } public void setupRaces(int numberOfStartedRaces, int numberOfNotStartedRaces) { testRaces = new HashSet(); raceColumnsInLeaderboard = new HashMap(); for (int i=0; i(); raceColumnsInLeaderboard = new HashMap(); - Competitor c2 = createCompetitor("Marcus Baur"); - Competitor c3 = createCompetitor("Robert Stanjek"); + CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); for (int i=0; i<3; i++) { - MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitor, i+1, /* started */ true); - r.addCompetitor(c2); - r.addCompetitor(c3); // this makes maxPoints==4 + MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitorWithBoat, i+1, /* started */ true); + r.addCompetitorAndBoat(c2); + r.addCompetitorAndBoat(c3); // this makes maxPoints==4 testRaces.add(r); // hash set should take care of more or less randomly permuting the races } FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( @@ -181,80 +182,80 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { i++; RaceColumn raceColumn = leaderboard.addRace(race, "Test Race " + i, /* medalRace */false); raceColumnsInLeaderboard.put(race, raceColumn); - if (race.getRank(competitor) < bestScore) { - bestScore = race.getRank(competitor); + if (race.getRank(competitorWithBoat.getCompetitor()) < bestScore) { + bestScore = race.getRank(competitorWithBoat.getCompetitor()); bestScoringRaceColumn = raceColumn; } } - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DSQ); + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MaxPointsReason.DSQ); // assert that best scoring but now disqualified race gets max total points because of disqualification: assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1, - leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); + leaderboard.getEntry(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); // now assert that it gets discarded because due to disqualification it scores worse than all others: - assertEquals(0, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); + assertEquals(0, leaderboard.getEntry(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); } @Test public void testCarriedPointsCountInSorting() throws NoWindException { raceColumnsInLeaderboard = new HashMap(); - Competitor c2 = createCompetitor("Marcus Baur"); - Competitor c3 = createCompetitor("Robert Stanjek"); + CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); TimePoint now = MillisecondsTimePoint.now(); MockedTrackedRaceWithFixedRankAndManyCompetitors testRace = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - competitor, /* rank */ 1, /* started */true); - testRace.addCompetitor(c2); - testRace.addCompetitor(c3); // this makes maxPoints==4 + competitorWithBoat, /* rank */ 1, /* started */true); + testRace.addCompetitorAndBoat(c2); + testRace.addCompetitorAndBoat(c3); // this makes maxPoints==4 FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); leaderboard.addRace(testRace, "R1", /* medalRace */false); - assertEquals(1., leaderboard.getNetPoints(competitor, now), 0.00000001); - assertEquals(1., leaderboard.getNetPoints(c2, now), 0.00000001); - assertEquals(1., leaderboard.getNetPoints(c3, now), 0.00000001); - leaderboard.setCarriedPoints(competitor, 100); - leaderboard.setCarriedPoints(c2, 50); - leaderboard.setCarriedPoints(c3, 25); - assertEquals(101., leaderboard.getNetPoints(competitor, now), 0.00000001); - assertEquals(51., leaderboard.getNetPoints(c2, now), 0.00000001); - assertEquals(26., leaderboard.getNetPoints(c3, now), 0.00000001); + assertEquals(1., leaderboard.getNetPoints(competitorWithBoat.getCompetitor(), now), 0.00000001); + assertEquals(1., leaderboard.getNetPoints(c2.getCompetitor(), now), 0.00000001); + assertEquals(1., leaderboard.getNetPoints(c3.getCompetitor(), now), 0.00000001); + leaderboard.setCarriedPoints(competitorWithBoat.getCompetitor(), 100); + leaderboard.setCarriedPoints(c2.getCompetitor(), 50); + leaderboard.setCarriedPoints(c3.getCompetitor(), 25); + assertEquals(101., leaderboard.getNetPoints(competitorWithBoat.getCompetitor(), now), 0.00000001); + assertEquals(51., leaderboard.getNetPoints(c2.getCompetitor(), now), 0.00000001); + assertEquals(26., leaderboard.getNetPoints(c3.getCompetitor(), now), 0.00000001); List sortedCompetitors = leaderboard.getCompetitorsFromBestToWorst(now); assertSame(c3, sortedCompetitors.get(0)); assertSame(c2, sortedCompetitors.get(1)); - assertSame(competitor, sortedCompetitors.get(2)); + assertSame(competitorWithBoat, sortedCompetitors.get(2)); } @Test public void testDNDNotDiscardedInUntrackedRace() throws NoWindException { raceColumnsInLeaderboard = new HashMap(); - Competitor c2 = createCompetitor("Marcus Baur"); - Competitor c3 = createCompetitor("Robert Stanjek"); + CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); MockedTrackedRaceWithFixedRankAndManyCompetitors testRace = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - competitor, /* rank */ 1, /* started */true); - testRace.addCompetitor(c2); - testRace.addCompetitor(c3); // this makes maxPoints==4 + competitorWithBoat, /* rank */ 1, /* started */true); + testRace.addCompetitorAndBoat(c2); + testRace.addCompetitorAndBoat(c3); // this makes maxPoints==4 FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); RaceColumn r1 = leaderboard.addRace(testRace, "R1", /* medalRace */false); raceColumnsInLeaderboard.put(testRace, r1); RaceColumn r2 = leaderboard.addRaceColumn("R2", /* medalRace */false); - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, r2, MaxPointsReason.DND); // non-discardable disqualification + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), r2, MaxPointsReason.DND); // non-discardable disqualification // assert that max points were given before discarding... - assertEquals(4.0, leaderboard.getEntry(competitor, r2, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); + assertEquals(4.0, leaderboard.getEntry(competitorWithBoat.getCompetitor(), r2, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); // ...and after... - assertEquals(4.0, leaderboard.getEntry(competitor, r2, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); + assertEquals(4.0, leaderboard.getEntry(competitorWithBoat.getCompetitor(), r2, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); // ...because it's not discarded - assertFalse(leaderboard.getEntry(competitor, r2, MillisecondsTimePoint.now()).isDiscarded()); + assertFalse(leaderboard.getEntry(competitorWithBoat.getCompetitor(), r2, MillisecondsTimePoint.now()).isDiscarded()); } @Test public void testNoDNDDiscard() throws NoWindException { testRaces = new HashSet(); raceColumnsInLeaderboard = new HashMap(); - Competitor c2 = createCompetitor("Marcus Baur"); - Competitor c3 = createCompetitor("Robert Stanjek"); + CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); for (int i=0; i<3; i++) { - MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitor, i+1, /* started */ true); - r.addCompetitor(c2); - r.addCompetitor(c3); // this makes maxPoints==4 + MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitorWithBoat, i+1, /* started */ true); + r.addCompetitorAndBoat(c2); + r.addCompetitorAndBoat(c3); // this makes maxPoints==4 testRaces.add(r); // hash set should take care of more or less randomly permuting the races } FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl( @@ -267,18 +268,18 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { i++; RaceColumn raceColumn = leaderboard.addRace(race, "Test Race " + i, /* medalRace */false); raceColumnsInLeaderboard.put(race, raceColumn); - if (race.getRank(competitor) < bestScore) { - bestScore = race.getRank(competitor); + if (race.getRank(competitorWithBoat.getCompetitor()) < bestScore) { + bestScore = race.getRank(competitorWithBoat.getCompetitor()); bestScoringRaceColumn = raceColumn; } } - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DND); + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MaxPointsReason.DND); // assert that best scoring but now disqualified race gets max total points because of disqualification: assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1, - leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); + leaderboard.getEntry(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints(), 0.000000001); // now assert that it does not get discarded because it's a DND assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1, - leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); + leaderboard.getEntry(competitorWithBoat.getCompetitor(), bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints(), 0.000000001); } protected void testLeaderboard(int numberOfStartedRaces, int numberOfNotStartedRaces, int firstDiscardingThreshold, @@ -299,7 +300,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { leaderboard.addRaceColumn("Test Race "+i, /* medalRace */ addOneMedalRace && j == numberOfUntrackedRaces-1); } if (carry != null) { - leaderboard.setCarriedPoints(competitor, carry); + leaderboard.setCarriedPoints(competitorWithBoat.getCompetitor(), carry); } List ranksOfNonMedalStartedRaces = new ArrayList(); TimePoint now = MillisecondsTimePoint.now(); @@ -308,25 +309,25 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { if (column.getTrackedRace(defaultFleet) != null && column.getTrackedRace(defaultFleet).hasStarted(now)) { numberOfRacesToCompareToDiscardThresholds++; if (!column.isMedalRace()) { - ranksOfNonMedalStartedRaces.add(column.getTrackedRace(defaultFleet).getRank(competitor, now)); + ranksOfNonMedalStartedRaces.add(column.getTrackedRace(defaultFleet).getRank(competitorWithBoat.getCompetitor(), now)); } } } Collections.sort(ranksOfNonMedalStartedRaces); int carryInt = (carry == null ? 0 : carry); int netPoints = carryInt; - int medalRacePoints = getMedalRacePoints(competitor, now, defaultFleet); + int medalRacePoints = getMedalRacePoints(competitorWithBoat.getCompetitor(), now, defaultFleet); for (TrackedRace race : testRaces) { RaceColumn raceColumn = raceColumnsInLeaderboard.get(race); - com.sap.sse.common.Util.Pair key = new com.sap.sse.common.Util.Pair(competitor, raceColumn); + com.sap.sse.common.Util.Pair key = new com.sap.sse.common.Util.Pair(competitorWithBoat.getCompetitor(), raceColumn); if (race.hasStarted(now)) { - int rank = race.getRank(competitor, now); - assertEquals(rank, leaderboard.getTrackedRank(competitor, raceColumn, now)); + int rank = race.getRank(competitorWithBoat.getCompetitor(), now); + assertEquals(rank, leaderboard.getTrackedRank(competitorWithBoat.getCompetitor(), raceColumn, now)); assertEquals(rank, leaderboard.getContent(now).get(key).getTrackedRank()); - assertEquals(rank, leaderboard.getEntry(competitor, raceColumn, now).getTrackedRank()); - assertEquals(rank, leaderboard.getTotalPoints(competitor, raceColumn, now), 0.000000001); + assertEquals(rank, leaderboard.getEntry(competitorWithBoat.getCompetitor(), raceColumn, now).getTrackedRank()); + assertEquals(rank, leaderboard.getTotalPoints(competitorWithBoat.getCompetitor(), raceColumn, now), 0.000000001); assertEquals(rank, leaderboard.getContent(now).get(key).getTotalPoints(), 0.000000001); - assertEquals(rank, leaderboard.getEntry(competitor, raceColumn, now).getTotalPoints(), 0.000000001); + assertEquals(rank, leaderboard.getEntry(competitorWithBoat.getCompetitor(), raceColumn, now).getTotalPoints(), 0.000000001); // One race is discarded because four races were started, and for [3-6) one race can be discarded. // The discarded race is the worst of those started, so the one with rank 4. int expectedNumberOfDiscardedRaces = @@ -334,21 +335,21 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { numberOfRacesToCompareToDiscardThresholds < secondDiscardingThreshold ? 1 : 2; boolean discarded = ranksOfNonMedalStartedRaces.indexOf(rank) >= ranksOfNonMedalStartedRaces.size()-expectedNumberOfDiscardedRaces; int expected = discarded ? 0 : rank==medalRacePoints?2*rank:rank; - assertEquals(expected, leaderboard.getNetPoints(competitor, raceColumn, now), 0.000000001); + assertEquals(expected, leaderboard.getNetPoints(competitorWithBoat.getCompetitor(), raceColumn, now), 0.000000001); assertEquals(expected, leaderboard.getContent(now).get(key).getNetPoints(), 0.000000001); - assertEquals(expected, leaderboard.getEntry(competitor, raceColumn, now).getNetPoints(), 0.000000001); + assertEquals(expected, leaderboard.getEntry(competitorWithBoat.getCompetitor(), raceColumn, now).getNetPoints(), 0.000000001); netPoints += leaderboard.getContent(now).get(key).getNetPoints(); } else { - assertEquals(0, leaderboard.getTrackedRank(competitor, raceColumn, now)); - assertNull(leaderboard.getTotalPoints(competitor, raceColumn, now)); + assertEquals(0, leaderboard.getTrackedRank(competitorWithBoat.getCompetitor(), raceColumn, now)); + assertNull(leaderboard.getTotalPoints(competitorWithBoat.getCompetitor(), raceColumn, now)); assertEquals(0, leaderboard.getContent(now).get(key).getTrackedRank()); assertNull(leaderboard.getContent(now).get(key).getTotalPoints()); - assertEquals(0, leaderboard.getEntry(competitor, raceColumn, now).getTrackedRank()); - assertNull(leaderboard.getEntry(competitor, raceColumn, now).getTotalPoints()); + assertEquals(0, leaderboard.getEntry(competitorWithBoat.getCompetitor(), raceColumn, now).getTrackedRank()); + assertNull(leaderboard.getEntry(competitorWithBoat.getCompetitor(), raceColumn, now).getTotalPoints()); // no increment on netPoints } } - assertEquals(netPoints, leaderboard.getNetPoints(competitor, now), 0.000000001); + assertEquals(netPoints, leaderboard.getNetPoints(competitorWithBoat.getCompetitor(), now), 0.000000001); } private int getMedalRacePoints(Competitor competitor, TimePoint at, Fleet fleet) throws NoWindException { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java index 5d8c94e37d2..230fb300874 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java @@ -106,7 +106,7 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes public static List createCompetitors(int numberOfCompetitorsToCreate) { List result = new ArrayList(); for (int i=1; i<=numberOfCompetitorsToCreate; i++) { - result.add(createCompetitor("C"+i)); + result.add(createCompetitorAndBoat("C"+i).getCompetitor()); } return result; } 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 3bab891639c..00632f9bf2f 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 @@ -18,6 +18,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -58,7 +59,6 @@ import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class ReachingLegTest extends TrackBasedTest { @@ -75,15 +75,15 @@ public class ReachingLegTest extends TrackBasedTest { @Before public void setUp() { competitorsAndBoats = new LinkedHashMap<>(); - Pair hungerWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); - hunger = hungerWithBoat.getA(); - competitorsAndBoats.put(hungerWithBoat.getA(), hungerWithBoat.getB()); - Pair plattnerWithBoat = createCompetitorAndBoat("Dr. Hasso Plattner"); - plattner = plattnerWithBoat.getA(); - competitorsAndBoats.put(plattnerWithBoat.getA(), plattnerWithBoat.getB()); - Pair schomaekerWithBoat = createCompetitorAndBoat("Meike Schom�ker"); - schomaeker = schomaekerWithBoat.getA(); - competitorsAndBoats.put(schomaekerWithBoat.getA(), schomaekerWithBoat.getB()); + CompetitorWithBoat hungerWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); + hunger = hungerWithBoat.getCompetitor(); + competitorsAndBoats.put(hungerWithBoat.getCompetitor(), hungerWithBoat.getBoat()); + CompetitorWithBoat plattnerWithBoat = createCompetitorAndBoat("Dr. Hasso Plattner"); + plattner = plattnerWithBoat.getCompetitor(); + competitorsAndBoats.put(plattnerWithBoat.getCompetitor(), plattnerWithBoat.getBoat()); + CompetitorWithBoat schomaekerWithBoat = createCompetitorAndBoat("Meike Schom�ker"); + schomaeker = schomaekerWithBoat.getCompetitor(); + competitorsAndBoats.put(schomaekerWithBoat.getCompetitor(), schomaekerWithBoat.getBoat()); start = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()); setTrackedRace(createTrackedRace("Kieler Woche", "505 Race 2", "505", competitorsAndBoats, start)); List hungersMarkPassings = createMarkPassings(hunger, start); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index e6e482204b7..4ce14ad671b 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -103,7 +103,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa private RegattaLogRegisterCompetitorEventImpl createRegattaLogEvent() { final RegattaLogRegisterCompetitorEventImpl event = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), /* author */ null, - AbstractTracTracLiveTest.createCompetitorAndBoat("Someone").getA()); + AbstractTracTracLiveTest.createCompetitorAndBoat("Someone").getCompetitor()); return event; } 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 57fdee964c4..1daaa3f2724 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 @@ -16,6 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.CourseArea; @@ -31,6 +32,7 @@ import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseImpl; @@ -68,7 +70,6 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -87,15 +88,15 @@ public abstract class TrackBasedTest { } @SafeVarargs - public static Map createCompetitorAndBoatsMap(Pair... competitorsAndBoats) { + public static Map createCompetitorAndBoatsMap(CompetitorWithBoat... competitorsAndBoats) { Map result = new LinkedHashMap<>(); - for (Pair competitorAndBoat: competitorsAndBoats) { - result.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + for (CompetitorWithBoat competitorAndBoat: competitorsAndBoats) { + result.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); } return result; } - public static Pair createCompetitorAndBoat(String competitorName) { + public static CompetitorWithBoat createCompetitorAndBoat(String competitorName) { Competitor c = new CompetitorImpl(UUID.randomUUID(), competitorName, "HP", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", @@ -103,7 +104,7 @@ public abstract class TrackBasedTest { /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat b = new BoatImpl(c.getId(), competitorName + "'s boat", boatClass, null, null); - return new Pair<>(c, b); + return new CompetitorWithBoatImpl(c, b); } /** diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java index 0d6f71eb99a..2fadd5ffb20 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java @@ -18,19 +18,17 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEve import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.tracking.StartTimeChangedListener; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class TrackedRaceStartTimeUpdateForDependentStartTimeTest extends TrackBasedTest { @Test public void testStartTimeUpdateForRaceWithDependentStartTime() { - final Pair hasso = createCompetitorAndBoat("Hasso"); + final CompetitorWithBoat hasso = createCompetitorAndBoat("Hasso"); final RaceLog r1RaceLog = new RaceLogImpl("r1RaceLog"); final RaceLog r2RaceLog = new RaceLogImpl("r2RaceLog"); final RaceLogResolver raceLogResolver = new RaceLogResolver() { 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 9d4a7a8321b..9b2c3427171 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 @@ -11,8 +11,8 @@ import java.util.HashSet; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Series; @@ -31,7 +31,6 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class UpdateMarkPassingTest { @@ -42,8 +41,8 @@ public class UpdateMarkPassingTest { when(race.getName()).thenReturn("Test Race"); Course c = new CourseImpl("Test Course", Collections.singleton(waypoint)); when(race.getCourse()).thenReturn(c); - Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); - Competitor competitor = competitorAndBoat.getA(); + CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + Competitor competitor = competitorAndBoat.getCompetitor(); when(race.getBoatClass()).thenReturn(new BoatClassImpl("49er", /* typicallyStartsUpwind */ true)); when(race.getCompetitors()).thenReturn(Collections.singleton(competitor)); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl( diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java index 5526c189438..bc55603d04c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.LegType; @@ -45,12 +46,11 @@ import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TrackBasedEstimationWindTrackImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest { private List competitors; - private List> competitorsWithBoats; + private List competitorsWithBoats; private static final String[] competitorNames = new String[] { "Wolfgang Hunger", "Dr. Hasso Plattner", "Robert Stanjek", "Simon Grotelueschen" }; @Before @@ -58,17 +58,17 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest competitorsWithBoats = new ArrayList<>(); competitors = new ArrayList<>(); for (String name : competitorNames) { - Pair competitorAndBoat = createCompetitorAndBoat(name); + CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat(name); competitorsWithBoats.add(competitorAndBoat); - competitors.add(competitorAndBoat.getA()); + competitors.add(competitorAndBoat.getCompetitor()); } } private void initRace(int numberOfCompetitorsToUse, int[] numberOfMarksPassed, TimePoint timePointForFixes) { - List> subList = competitorsWithBoats.subList(0, numberOfCompetitorsToUse); + List subList = competitorsWithBoats.subList(0, numberOfCompetitorsToUse); Map competitorsAndBoats = new HashMap<>(); - for (Pair competitorAndBoat: subList) { - competitorsAndBoats.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + for (CompetitorWithBoat competitorAndBoat: subList) { + competitorsAndBoats.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); } setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", competitorsAndBoats, timePointForFixes, /* useMarkPassingCalculator */ false)); 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 8e0d08e10b9..aa8b33a3d93 100644 --- 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 @@ -10,6 +10,7 @@ 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.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -322,6 +323,11 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } + @Override + public Iterable getAllBoats() { + return null; + } + @Override public void addRace(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java index dadc21866c5..b3fbb339f7c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java @@ -3,11 +3,14 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; @@ -19,20 +22,21 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { private static final long serialVersionUID = -8587203762630194172L; private final int rank; private final boolean started; - private final RaceDefinition raceDefinition; - private final Competitor competitor; + protected final Map competitorsAndBoats; private final BoatClass boatClass; + protected RaceDefinition raceDefinition; - public MockedTrackedRaceWithFixedRank(Competitor competitor, int rank, boolean started, BoatClass boatClass) { + public MockedTrackedRaceWithFixedRank(CompetitorWithBoat competitorWithBoat, int rank, boolean started, BoatClass boatClass) { this.rank = rank; this.started = started; - this.competitor = competitor; + this.competitorsAndBoats = new HashMap<>(); this.raceDefinition = new MockedRaceDefinition(); this.boatClass = boatClass; + this.competitorsAndBoats.put(competitorWithBoat.getCompetitor(), competitorWithBoat.getBoat()); } - public MockedTrackedRaceWithFixedRank(Competitor competitor, int rank, boolean started) { - this(competitor, rank, started, /* boatClass */ null); + public MockedTrackedRaceWithFixedRank(CompetitorWithBoat competitorWithBoat,int rank, boolean started) { + this(competitorWithBoat, rank, started, /* boatClass */ null); } private class MockedRaceDefinition implements RaceDefinition { @@ -55,7 +59,12 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { @Override public Iterable getCompetitors() { - return Collections.singleton(MockedTrackedRaceWithFixedRank.this.competitor); + return MockedTrackedRaceWithFixedRank.this.competitorsAndBoats.keySet(); + } + + @Override + public Iterable getBoats() { + return MockedTrackedRaceWithFixedRank.this.competitorsAndBoats.values(); } @Override @@ -70,8 +79,9 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { @Override public Competitor getCompetitorById(Serializable competitorID) { - if (competitorID.equals(MockedTrackedRaceWithFixedRank.this.competitor.getId())) { - return MockedTrackedRaceWithFixedRank.this.competitor; + Competitor c = competitorsAndBoats.keySet().iterator().next(); + if (competitorID.equals(c.getId())) { + return competitorsAndBoats.keySet().iterator().next(); } else { return null; } @@ -90,7 +100,7 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { @Override public List getCompetitorsFromBestToWorst(TimePoint timePoint) { - return Collections.singletonList(competitor); + return Collections.singletonList(competitorsAndBoats.keySet().iterator().next()); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java index 02ac83a163d..54b0cedbf42 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java @@ -1,24 +1,19 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrackedRaceWithFixedRank { private static final long serialVersionUID = -6189437610363552577L; - private final Set competitors; - private final RaceDefinition raceDefinition; - public MockedTrackedRaceWithFixedRankAndManyCompetitors(Competitor competitor, int rank, boolean started) { - super(competitor, rank, started); - competitors = new HashSet(); - competitors.add(competitor); + public MockedTrackedRaceWithFixedRankAndManyCompetitors(CompetitorWithBoat competitorWithBoat, int rank, boolean started) { + super(competitorWithBoat, rank, started); this.raceDefinition = new RaceDefinition() { private static final long serialVersionUID = 8878878939443845646L; @Override @@ -31,11 +26,15 @@ public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrac } @Override public Iterable getCompetitors() { - return competitors; + return competitorsAndBoats.keySet(); + } + @Override + public Iterable getBoats() { + return competitorsAndBoats.values(); } @Override public Competitor getCompetitorById(Serializable competitorID) { - for (Competitor competitor : competitors) { + for (Competitor competitor : competitorsAndBoats.keySet()) { if (competitorID.equals(competitor.getId())) { return competitor; } @@ -62,8 +61,8 @@ public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrac }; } - public void addCompetitor(Competitor competitor) { - competitors.add(competitor); + public void addCompetitorAndBoat(CompetitorWithBoat competitorWithBoat) { + competitorsAndBoats.put(competitorWithBoat.getCompetitor(), competitorWithBoat.getBoat()); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java index 256e5185b27..c418211ac45 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java @@ -14,8 +14,8 @@ import java.util.List; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.impl.BravoFixImpl; import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; @@ -24,7 +24,6 @@ import com.sap.sailing.domain.tracking.BravoFixTrack; import com.sap.sailing.domain.tracking.DynamicBravoFixTrack; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; public class BravoFixTrackSerializationTest { @@ -32,8 +31,8 @@ public class BravoFixTrackSerializationTest { @Before public void setUp() { - Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SAP Extreme Sailing Team"); - track = new BravoFixTrackImpl(competitorAndBoat.getA(), BravoFixTrack.TRACK_NAME); + CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SAP Extreme Sailing Team"); + track = new BravoFixTrackImpl(competitorAndBoat.getCompetitor(), BravoFixTrack.TRACK_NAME); } @Test diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java index aebf2c94a27..b40d9056934 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java @@ -24,6 +24,8 @@ public interface RaceDefinition extends NamedWithID { Iterable getCompetitors(); + Iterable getBoats(); + Competitor getCompetitorById(Serializable competitorID); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index a1c15e95ff5..5875a6d1997 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -109,6 +109,8 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe Iterable getAllCompetitors(); + Iterable getAllBoats(); + /** * Will remove the series from this regatta. Will also call {@link RaceColumn#removeRaceIdentifier(Fleet)} to make * sure that all raceLogs and race associations get removed for all race columns in this series. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java index a790417a8b3..d41a14d80fa 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java @@ -78,7 +78,12 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { public Iterable getCompetitors() { return Collections.unmodifiableSet(competitorsAndTheirBoats.keySet()); } - + + @Override + public Iterable getBoats() { + return Collections.unmodifiableCollection(competitorsAndTheirBoats.values()); + } + @Override public byte[] getCompetitorMD5() { return raceCompetitorsMD5Hash.getMd5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID(); 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 e6e7344e907..bea09f3bf38 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 @@ -28,6 +28,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -409,6 +410,21 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return result; } + @Override + public Iterable getAllBoats() { + Set result = new HashSet(); +// if (boatsProvider == null) { +// boatsProvider = new BoatsProviderFromRaceColumnsAndRegattaLike(this); +// } +// Util.addAll(boatsProvider.getAllBoats(), result); + for (RaceDefinition race : getAllRaces()) { + for (Boat b: race.getBoats()) { + result.add(b); + } + } + return result; + } + @Override public void addRegattaListener(RegattaListener listener) { synchronized (regattaListeners) { diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java index 58a0b750a91..13ab47ba314 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java @@ -57,7 +57,7 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor(competitorName1); + DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat(competitorName1).getCompetitor(); c.setFlagImage(flagImageURI1); mongoObjectFactory.storeCompetitor(c); @@ -84,7 +84,7 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID()); + DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); c.setName("Hasso Plattner"); @@ -98,7 +98,7 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso"); + DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso").getCompetitor(); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); @@ -112,7 +112,7 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = AbstractLeaderboardTest.createCompetitor("Hasso", UUID.randomUUID()); + DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 164170244ab..f0f35946169 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -30,6 +30,7 @@ import com.mongodb.MongoException; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.DomainFactory; @@ -430,7 +431,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest // for some reason the dropping of collections doesn't work reliably on Linux... explicitly drop those collections that we depend on getMongoService().getDB().getCollection(CollectionNames.LEADERBOARDS.name()).drop(); getMongoService().getDB().getCollection(CollectionNames.REGATTAS.name()).drop(); - Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); + CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); final DynamicTrackedRegatta[] trackedRegatta = new DynamicTrackedRegatta[1]; final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { @@ -464,7 +465,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest assertNotNull(regattaLeaderboard.getRaceColumnByName(q2.getName())); res.apply(new ConnectTrackedRaceToLeaderboardColumn(regattaLeaderboard.getName(), q2.getName(), yellow .getName(), q2YellowTrackedRace.getRaceIdentifier())); - res.apply(new UpdateLeaderboardMaxPointsReason(regattaLeaderboard.getName(), q2.getName(), hasso.getId().toString(), + res.apply(new UpdateLeaderboardMaxPointsReason(regattaLeaderboard.getName(), q2.getName(), hasso.getCompetitor().getId().toString(), MaxPointsReason.DNF, MillisecondsTimePoint.now())); // load new RacingEventService including regatta and leaderboard @@ -489,7 +490,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest trackedRegatta[0] = new DynamicTrackedRegattaImpl(loadedRegatta); resForLoading.apply(new ConnectTrackedRaceToLeaderboardColumn(loadedLeaderboard.getName(), loadedQ2.getName(), loadedYellow .getName(), q2YellowTrackedRace.getRaceIdentifier())); - MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso, loadedQ2, MillisecondsTimePoint.now()); + MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso.getCompetitor(), loadedQ2, MillisecondsTimePoint.now()); assertEquals(MaxPointsReason.DNF, hassosLoadedMaxPointsReason); } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 4d66d7af6ed..32b8de27a18 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -18,6 +18,7 @@ import org.junit.Before; import org.junit.Test; import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; @@ -25,6 +26,7 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -117,14 +119,17 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitor(hasso); + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; @@ -173,14 +178,17 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitor(hasso); + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; @@ -229,14 +237,17 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitor(hasso); + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index cbc0b2fa1a3..d3a01276738 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -13,12 +13,15 @@ import org.junit.Before; import org.junit.Test; import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -76,23 +79,25 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor wolfgang = createCompetitor(); + CompetitorWithBoat wolfgang = createCompetitorAndBoat(); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + CompetitorWithBoat hassoWithBoat = new CompetitorWithBoatImpl(hasso, hassosBoat); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitor(hasso); + raceWithTwoCompetitors.addCompetitorAndBoat(hassoWithBoat); leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */ false); - leaderboard.setSuppressed(wolfgang, true); + leaderboard.setSuppressed(wolfgang.getCompetitor(), true); assertTrue(Util.contains(leaderboard.getSuppressedCompetitors(), wolfgang)); assertFalse(Util.contains(leaderboard.getSuppressedCompetitors(), hasso)); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors2 = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); - raceWithTwoCompetitors2.addCompetitor(hasso); + raceWithTwoCompetitors2.addCompetitorAndBoat(hassoWithBoat); loadedLeaderboard.getRaceColumnByName(raceColumnName1).setTrackedRace(loadedLeaderboard.getFleet(null), raceWithTwoCompetitors2); assertTrue(Util.contains(loadedLeaderboard.getSuppressedCompetitors(), wolfgang)); assertFalse(Util.contains(loadedLeaderboard.getSuppressedCompetitors(), hasso)); @@ -119,18 +124,18 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); final String raceColumnName1 = "My First Race 1"; leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); final String displayName = "$$$ ... The Renamed Competitor ... $$$"; - leaderboard.setDisplayName(competitor, displayName); + leaderboard.setDisplayName(competitorWithBoat.getCompetitor(), displayName); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard( leaderboardName, /* regattaRegistry */null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); - Competitor loadedCompetitor = loadedLeaderboard.getCompetitorByName(competitor.getName()); + Competitor loadedCompetitor = loadedLeaderboard.getCompetitorByName(competitorWithBoat.getCompetitor().getName()); assertEquals(displayName, loadedLeaderboard.getDisplayName(loadedCompetitor)); } @@ -167,10 +172,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false); - leaderboard.setCarriedPoints(competitor, carriedPointsForWolfgangHunger); + leaderboard.setCarriedPoints(competitorWithBoat.getCompetitor(), carriedPointsForWolfgangHunger); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly @@ -179,8 +184,8 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { assertTrue(Arrays.equals(discardIndexResultsStartingWithHowManyRaces, ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces())); assertEquals(1, Util.size(loadedLeaderboard.getCompetitors())); - assertEquals(competitor, loadedLeaderboard.getCompetitors().iterator().next()); - assertEquals(carriedPointsForWolfgangHunger, loadedLeaderboard.getCarriedPoints(competitor), 0.000000001); + assertEquals(competitorWithBoat, loadedLeaderboard.getCompetitors().iterator().next()); + assertEquals(carriedPointsForWolfgangHunger, loadedLeaderboard.getCarriedPoints(competitorWithBoat.getCompetitor()), 0.000000001); } @Test @@ -192,21 +197,21 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); - TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); + TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); - leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); + leaderboard.getScoreCorrection().correctScore(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); - assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.00000001); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn1, MillisecondsTimePoint.now())); + assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitorWithBoat.getCompetitor(), loadedColumn1), 0.00000001); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -218,21 +223,21 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); + CompetitorWithBoat competitor = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); - leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); + leaderboard.getScoreCorrection().correctScore(competitor.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); - assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.00000001); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor.getCompetitor(), loadedColumn1, MillisecondsTimePoint.now())); + assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor.getCompetitor(), loadedColumn1), 0.00000001); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -244,21 +249,21 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); - TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); + TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); - assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn1, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); + assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); } @Test @@ -271,23 +276,23 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); - TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); + TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); - leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); + leaderboard.getScoreCorrection().correctScore(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); // attach tracked race to leaderboard to ensure that competitor object is assigned properly RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); - assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.000000001); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); - assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn1, MillisecondsTimePoint.now())); + assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitorWithBoat.getCompetitor(), loadedColumn1), 0.000000001); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); + assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); } /** @@ -309,13 +314,13 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - Competitor competitor = createCompetitor(); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); - TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); + CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); + TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); RaceColumn r1 = leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); RaceColumn r2 = leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); - leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); - leaderboard.getScoreCorrection().setMaxPointsReason(competitor, leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); + leaderboard.getScoreCorrection().correctScore(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); + leaderboard.getScoreCorrection().setMaxPointsReason(competitorWithBoat.getCompetitor(), leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason); // now release the tracked races; leaving no competitors in leaderboard.getCompetitors() r1.releaseTrackedRace(leaderboard.getFleet(null)); r2.releaseTrackedRace(leaderboard.getFleet(null)); @@ -325,10 +330,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false); RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false); assertEquals(leaderboardName, loadedLeaderboard.getName()); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1, MillisecondsTimePoint.now())); - assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1), 0.000000001); - assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2, MillisecondsTimePoint.now())); - assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn1, MillisecondsTimePoint.now())); + assertEquals(correctedPoints, (double) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitorWithBoat.getCompetitor(), loadedColumn1), 0.000000001); + assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); + assertEquals(maxPointsReason, loadedLeaderboard.getScoreCorrection().getMaxPointsReason(competitorWithBoat.getCompetitor(), loadedColumn2, MillisecondsTimePoint.now())); } /** @@ -356,8 +361,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); - TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); + Boat boat = domainFactory.getOrCreateBoat(competitor, "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null, null); + CompetitorWithBoat competitorWithBoat = new CompetitorWithBoatImpl(competitor, boat); + TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); + TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true); leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints); @@ -378,12 +385,12 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { assertEquals(maxPointsReason, loadedLeaderboard2.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); } - private Competitor createCompetitor() { + private CompetitorWithBoat createCompetitorAndBoat() { Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - return competitor; + Boat boat = new BoatImpl(competitor.getId(), "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + return new CompetitorWithBoatImpl(competitor, boat); } - } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java index ed07795b3fb..a1fe58e208f 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java @@ -14,11 +14,11 @@ import org.junit.Test; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; -import com.sap.sailing.domain.base.impl.DynamicCompetitor; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaNameAndRaceName; @@ -79,7 +79,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer // resolved properly on the replica. final DomainFactory domainFactory = new DomainFactoryImpl((srlid)->null); BoatClass boatClass = domainFactory.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - DynamicCompetitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore + CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { private static final long serialVersionUID = 1234L; @Override @@ -98,9 +98,9 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer master.apply(new AddColumnToLeaderboard(Q2, leaderboardName, /* medalRace */ false)); // uses leaderboard's default fleet master.apply(new ConnectTrackedRaceToLeaderboardColumn(masterLeaderboard.getName(), Q2, /* default fleet */ masterLeaderboard.getFleet(null).getName(), q2YellowTrackedRace.getRaceIdentifier())); - master.apply(new UpdateLeaderboardMaxPointsReason(masterLeaderboard.getName(), Q2, hasso.getId().toString(), + master.apply(new UpdateLeaderboardMaxPointsReason(masterLeaderboard.getName(), Q2, hasso.getCompetitor().getId().toString(), MaxPointsReason.DNF, MillisecondsTimePoint.now())); - assertEquals(MaxPointsReason.DNF, masterLeaderboard.getMaxPointsReason(hasso, + assertEquals(MaxPointsReason.DNF, masterLeaderboard.getMaxPointsReason(hasso.getCompetitor(), masterLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); // re-load new master from persistence @@ -112,7 +112,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer // expecting the correction to not be in the leaderboard because the competitor was not found in the // domain factory's competitor store while loading and therefore the score correction could not immediately // be applied to the leaderboard's real score correction - assertEquals(MaxPointsReason.NONE, masterLeaderboardReloaded.getMaxPointsReason(hasso, + assertEquals(MaxPointsReason.NONE, masterLeaderboardReloaded.getMaxPointsReason(hasso.getCompetitor(), masterLeaderboardReloaded.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); // replicate the re-loaded environment @@ -130,7 +130,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2)); // so far, the replica should also only have the delayed corrections since during deserializing them the // replicatedHasso competitor was not yet known to the replica's competitor store: - assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hasso, + assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hasso.getCompetitor(), replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); logger.info("hasso object ID hash: "+System.identityHashCode(hasso)); @@ -153,11 +153,11 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer logger.info("got score correction for competitor "+System.identityHashCode(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2).iterator().next())); assertTrue(Util.contains(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2), hasso)); // now score corrections must have been applied from Delayed... // now the delayed corrections are expected to have been resolved: - assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hasso, + assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hasso.getCompetitor(), master.getLeaderboardByName(leaderboardName).getRaceColumnByName(Q2), MillisecondsTimePoint.now())); Thread.sleep(1000); // wait for the tracked race to column connection to be replicated - assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2).getTrackedRace(hasso)); - assertEquals(MaxPointsReason.DNF, replicaLeaderboard.getMaxPointsReason(hasso, + assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2).getTrackedRace(hasso.getCompetitor())); + assertEquals(MaxPointsReason.DNF, replicaLeaderboard.getMaxPointsReason(hasso.getCompetitor(), replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index 71eb11a89ab..8529432b637 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -30,6 +30,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceColumn; @@ -255,10 +256,10 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl Regatta regatta = master.apply(addEventOperation); final String raceName1 = "Test Race 1"; final String raceName2 = "Test Race 2"; - Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("The Same Competitor"); + CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("The Same Competitor"); final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); final Map competitors = new HashMap<>(); - competitors.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + competitors.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); RaceDefinition race1 = new RaceDefinitionImpl(raceName1, masterCourse, boatClass, competitors); AddRaceDefinition addRaceOperation1 = new AddRaceDefinition(new RegattaName(regatta.getName()), race1); master.apply(addRaceOperation1); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java index c243280292b..2e9c5df82eb 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java @@ -11,15 +11,13 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.test.TrackBasedTest; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaLogReplicationTest extends @@ -35,8 +33,8 @@ public class RegattaLogReplicationTest extends @Before public void createEvent() throws Exception { - final Pair competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); - regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), t(0), author, 0, competitorAndBoat.getA()); + final CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), t(0), author, 0, competitorAndBoat.getCompetitor()); // anotherRegattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(1), author, t(1), 1, null); } diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index 2e2a77d07bf..9382e0988ef 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -27,7 +27,7 @@ public class CompetitorStoreTest { @Test public void testAddingCompetitorsToTransientStore() { CompetitorStore transientStore = new TransientCompetitorStoreImpl(); - DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); assertTrue(competitor != template); @@ -37,7 +37,7 @@ public class CompetitorStoreTest { /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); assertSame(competitor, competitor2); assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); - DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ @@ -58,7 +58,7 @@ public class CompetitorStoreTest { public void testPersistentCompetitorStore() { CompetitorStore persistentStore1 = new PersistentCompetitorStore( PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); - DynamicCompetitor template = AbstractLeaderboardTest.createCompetitor("Test Competitor"); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); @@ -72,7 +72,7 @@ public class CompetitorStoreTest { assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); - DynamicTeam differentTeam = AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java index a26a4200d04..49880c43074 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java @@ -8,7 +8,7 @@ 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.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; @@ -66,28 +66,28 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); + CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race2, "R2", /* medalRace */false); - Competitor wolfgang = AbstractLeaderboardTest.createCompetitor("Wolfgang Hunger"); + CompetitorWithBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 124, /* started */ true, boatClass); leaderboard.addRace(race4, "R4", /* medalRace */false); - leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R3"), 123.); - leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R4"), 123.); - leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R1"), 122.); - leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R2"), 122.); + leaderboard.getScoreCorrection().correctScore(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R3"), 123.); + leaderboard.getScoreCorrection().correctScore(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R4"), 123.); + leaderboard.getScoreCorrection().correctScore(wolfgang.getCompetitor(), leaderboard.getRaceColumnByName("R1"), 122.); + leaderboard.getScoreCorrection().correctScore(wolfgang.getCompetitor(), leaderboard.getRaceColumnByName("R2"), 122.); TimePoint now = MillisecondsTimePoint.now(); // Hunger scores better than Plattner in this case because Hunger's two discards are 123/124, keeping 122/122 // whereas Plattner is to discard two of the four 123 results, keeping 123/123, being two points worse than Hunger: - double netPointsHasso = leaderboard.getNetPoints(hasso, now); - double netPointsWolfgang = leaderboard.getNetPoints(wolfgang, now); + double netPointsHasso = leaderboard.getNetPoints(hasso.getCompetitor(), now); + double netPointsWolfgang = leaderboard.getNetPoints(wolfgang.getCompetitor(), now); assertEquals(122.+122., netPointsWolfgang, 0.0000000001); assertEquals(123.+123., netPointsHasso, 0.000000001); } @@ -105,32 +105,32 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", /* typicallyStartsUpwind */ true); - Competitor rasmus = AbstractLeaderboardTest.createCompetitor("Rasmus"); + CompetitorWithBoat rasmus = AbstractLeaderboardTest.createCompetitorAndBoat("Rasmus"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(rasmus, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(rasmus, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race2, "R2", /* medalRace */false); - Competitor jes = AbstractLeaderboardTest.createCompetitor("Jes"); + CompetitorWithBoat jes = AbstractLeaderboardTest.createCompetitorAndBoat("Jes"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(jes, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(jes, /* rank */ 3, /* started */ true, boatClass); // score 1.0 leaderboard.addRace(race4, "R4", /* medalRace */false); - Competitor nobody = AbstractLeaderboardTest.createCompetitor("Nobody"); + CompetitorWithBoat nobody = AbstractLeaderboardTest.createCompetitorAndBoat("Nobody"); final TrackedRace race5 = new MockedTrackedRaceWithFixedRank(nobody, /* rank */ 3, /* started */ true, boatClass); // score 1.0 leaderboard.addRace(race5, "R5", /* medalRace */false); - leaderboard.getScoreCorrection().correctScore(rasmus, leaderboard.getRaceColumnByName("R3"), 2.0); - leaderboard.getScoreCorrection().correctScore(rasmus, leaderboard.getRaceColumnByName("R4"), 2.0); - leaderboard.getScoreCorrection().correctScore(jes, leaderboard.getRaceColumnByName("R1"), 3.0); - leaderboard.getScoreCorrection().correctScore(jes, leaderboard.getRaceColumnByName("R2"), 3.0); + leaderboard.getScoreCorrection().correctScore(rasmus.getCompetitor(), leaderboard.getRaceColumnByName("R3"), 2.0); + leaderboard.getScoreCorrection().correctScore(rasmus.getCompetitor(), leaderboard.getRaceColumnByName("R4"), 2.0); + leaderboard.getScoreCorrection().correctScore(jes.getCompetitor(), leaderboard.getRaceColumnByName("R1"), 3.0); + leaderboard.getScoreCorrection().correctScore(jes.getCompetitor(), leaderboard.getRaceColumnByName("R2"), 3.0); TimePoint now = MillisecondsTimePoint.now(); // Jes scores better than Rasmus in this case because Jes's two discards are 1.0/2.0, keeping 3.0/3.0 // whereas Rasmus is to discard two of the four 2.0 results, keeping 2.0/2.0, being two points worse than Hunger: - double netPointsRasmus = leaderboard.getNetPoints(rasmus, now); - double netPointsJes = leaderboard.getNetPoints(jes, now); + double netPointsRasmus = leaderboard.getNetPoints(rasmus.getCompetitor(), now); + double netPointsJes = leaderboard.getNetPoints(jes.getCompetitor(), now); assertEquals(3, Util.size(leaderboard.getCompetitors())); assertEquals(3.+3., netPointsJes, 0.0000000001); assertEquals(2.+2., netPointsRasmus, 0.000000001); @@ -149,30 +149,30 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); + CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race2, "R2", /* medalRace */false); - Competitor wolfgang = AbstractLeaderboardTest.createCompetitor("Wolfgang Hunger"); + CompetitorWithBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 124, /* started */ true, boatClass); leaderboard.addRace(race4, "R4", /* medalRace */false); - leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R3"), 123.); - leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R4"), 123.); - leaderboard.getScoreCorrection().setMaxPointsReason(hasso, leaderboard.getRaceColumnByName("R1"), MaxPointsReason.DNE); - leaderboard.getScoreCorrection().correctScore(hasso, leaderboard.getRaceColumnByName("R1"), 123.); - leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R1"), 122.); - leaderboard.getScoreCorrection().correctScore(wolfgang, leaderboard.getRaceColumnByName("R2"), 122.); + leaderboard.getScoreCorrection().correctScore(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R3"), 123.); + leaderboard.getScoreCorrection().correctScore(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R4"), 123.); + leaderboard.getScoreCorrection().setMaxPointsReason(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R1"), MaxPointsReason.DNE); + leaderboard.getScoreCorrection().correctScore(hasso.getCompetitor(), leaderboard.getRaceColumnByName("R1"), 123.); + leaderboard.getScoreCorrection().correctScore(wolfgang.getCompetitor(), leaderboard.getRaceColumnByName("R1"), 122.); + leaderboard.getScoreCorrection().correctScore(wolfgang.getCompetitor(), leaderboard.getRaceColumnByName("R2"), 122.); TimePoint now = MillisecondsTimePoint.now(); // Hunger scores better than Plattner in this case because Hunger's two discards are 123/124, keeping 122/122 // whereas Plattner is to discard two of the four 123 results, keeping 123/123, being two points worse than Hunger: - double netPointsHasso = leaderboard.getNetPoints(hasso, now); - double netPointsWolfgang = leaderboard.getNetPoints(wolfgang, now); + double netPointsHasso = leaderboard.getNetPoints(hasso.getCompetitor(), now); + double netPointsWolfgang = leaderboard.getNetPoints(wolfgang.getCompetitor(), now); assertEquals(122.+122., netPointsWolfgang, 0.0000000001); assertEquals(123.+123., netPointsHasso, 0.000000001); } diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java index deddc193571..318730f4f6f 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java @@ -20,8 +20,7 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.LeaderboardGroupBase; @@ -74,7 +73,6 @@ import com.sap.sailing.server.operationaltransformation.RemoveRegatta; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.common.search.Result; @@ -87,12 +85,12 @@ public class SearchServiceTest { private Venue flensburg; private Event pfingstbusch; private Regatta pfingstbusch29er; - private Pair hassoPlattner; - private Pair alexanderRies; - private Pair antonKoch; - private Pair tobiasSchadewaldt; - private Pair philippBuhl; - private Pair dennisGehrlein; + private CompetitorWithBoat hassoPlattner; + private CompetitorWithBoat alexanderRies; + private CompetitorWithBoat antonKoch; + private CompetitorWithBoat tobiasSchadewaldt; + private CompetitorWithBoat philippBuhl; + private CompetitorWithBoat dennisGehrlein; private Regatta pfingstbusch470; private Regatta aalRegatta; private DynamicTrackedRace pfingstbusch29erTrackedR1; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index 3fcdf878007..d24eecfe6a5 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -28,6 +29,7 @@ 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.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; @@ -60,7 +62,6 @@ import com.sap.sailing.server.operationaltransformation.TrackRegatta; import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class WindByRaceLogTest { @@ -82,7 +83,7 @@ public class WindByRaceLogTest { // FIXME use master DomainFactory; see bug 592 final DomainFactory masterDomainFactory = service.getBaseDomainFactory(); BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); - Pair competitorAndBoat = createCompetitorAndBoat(masterDomainFactory, boatClass); + CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat(masterDomainFactory, boatClass); int[] discardThreshold = {1, 2}; CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null); service.apply(createLeaderboardOperation); @@ -96,7 +97,7 @@ public class WindByRaceLogTest { final String raceName = "Test Race"; final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); final Map competitorsAndBoats = new HashMap<>(); - competitorsAndBoats.put(competitorAndBoat.getA(), competitorAndBoat.getB()); + competitorsAndBoats.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); RaceDefinition race = new RaceDefinitionImpl(raceName, masterCourse, boatClass, competitorsAndBoats); AddRaceDefinition addRaceOperation = new AddRaceDefinition(new RegattaName(regatta.getName()), race); service.apply(addRaceOperation); @@ -109,13 +110,13 @@ public class WindByRaceLogTest { defaultFleet = Util.get(raceColumn.getFleets(), 0); } - private Pair createCompetitorAndBoat(final DomainFactory masterDomainFactory, final BoatClass boatClass) { + private CompetitorWithBoat createCompetitorAndBoat(final DomainFactory masterDomainFactory, final BoatClass boatClass) { Competitor competitor = masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), new BoatImpl("123", "GER 61", boatClass, "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat boat = masterDomainFactory.getOrCreateBoat(competitor, "GER 61", boatClass, "GER 61", null); - return new Pair(competitor, boat); + return new CompetitorWithBoatImpl(competitor, boat); } private void attachTrackedRaceToRaceColumn() { From 2034a0119343c0fd27fe4cdce91f68ffc973ec86 Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 29 Aug 2016 15:32:47 +0200 Subject: [PATCH 007/271] Added new boat attributes to BoatDTO --- .../sailing/domain/common/dto/BoatDTO.java | 30 +++++++++++++++++-- .../impl/TransientCompetitorStoreImpl.java | 11 ++++--- .../test/LeaderboardDTODiffingTest.java | 8 ++--- .../ui/adminconsole/CompetitorEditDialog.java | 2 +- .../gwt/ui/server/SailingServiceImpl.java | 6 ++-- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java index 09a4e29ebf2..cf936a2c98e 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java @@ -7,18 +7,22 @@ import com.sap.sse.common.Color; public class BoatDTO extends NamedDTO implements Serializable { private static final long serialVersionUID = -4076992788294272162L; + private String idAsString; + private BoatClassDTO boatClass; private String sailId; private Color color; // for GWT BoatDTO() {} - public BoatDTO(String name, String sailId) { - this(name, sailId, null); + public BoatDTO(String idAsString, String name, BoatClassDTO boatClass, String sailId) { + this(idAsString, name, boatClass, sailId, null); } - public BoatDTO(String name, String sailId, Color color) { + public BoatDTO(String idAsString, String name, BoatClassDTO boatClass, String sailId, Color color) { super(name); + this.idAsString = idAsString; + this.boatClass = boatClass; this.sailId = sailId; this.color = color; } @@ -31,10 +35,20 @@ public class BoatDTO extends NamedDTO implements Serializable { return sailId; } + public String getIdAsString() { + return idAsString; + } + + public BoatClassDTO getBoatClass() { + return boatClass; + } + @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); + result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); + result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); result = prime * result + ((color == null) ? 0 : color.hashCode()); result = prime * result + ((sailId == null) ? 0 : sailId.hashCode()); return result; @@ -49,6 +63,16 @@ public class BoatDTO extends NamedDTO implements Serializable { if (getClass() != obj.getClass()) return false; BoatDTO other = (BoatDTO) obj; + if (boatClass == null) { + if (other.boatClass != null) + return false; + } else if (!boatClass.equals(other.boatClass)) + return false; + if (idAsString == null) { + if (other.idAsString != null) + return false; + } else if (!idAsString.equals(other.idAsString)) + return false; if (color == null) { if (other.color != null) return false; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 6feac7974d5..ff557929bff 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -260,15 +260,16 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab if (competitorDTO == null) { final Nationality nationality = c.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); + BoatClassDTO boatClassDTO = new BoatClassDTO(c.getBoat().getBoatClass() + .getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()); competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c.getId().toString(), c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), c.getFlagImage() == null ? null : c.getFlagImage().toString(), - new BoatDTO(c.getBoat().getName(), c.getBoat().getSailID(), c.getBoat().getColor()), - new BoatClassDTO(c.getBoat().getBoatClass() - .getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()), + new BoatDTO(c.getBoat().getId().toString(), c.getBoat().getName(), boatClassDTO, c.getBoat().getSailID(), c.getBoat().getColor()), + boatClassDTO, c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); weakCompetitorDTOCache.put(c, competitorDTO); } @@ -471,7 +472,9 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab LockUtil.lockForWrite(lock); boatDTO = weakBoatDTOCache.get(b); if (boatDTO == null) { - boatDTO = new BoatDTO(b.getName(), b.getSailID(), b.getColor()); + BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), + b.getBoatClass().getDisplayName(), b.getBoatClass().getHullLength().getMeters()); + boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); weakBoatDTOCache.put(b, boatDTO); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index fd4e8300ff1..42ab3c5ab0f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -234,7 +234,7 @@ public class LeaderboardDTODiffingTest { public void testCompetitorListChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", 5.05), "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS"); @@ -255,7 +255,7 @@ public class LeaderboardDTODiffingTest { newVersion.setSuppressedCompetitors(newSuppressedCompetitors); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", 5.05), "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well @@ -278,7 +278,7 @@ public class LeaderboardDTODiffingTest { public void testDisplayNameChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", 5.05), "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); newVersion.competitorDisplayNames = new HashMap(newVersion.competitorDisplayNames); @@ -308,7 +308,7 @@ public class LeaderboardDTODiffingTest { newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", 5.05), "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); newOrdering.add(somebodyNew); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 2d9c3dcb1a7..3514e05674a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -191,7 +191,7 @@ public class CompetitorEditDialog extends DataEntryDialog { } } BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); - BoatDTO boat = new BoatDTO(name.getText(), sailId.getText()); + BoatDTO boat = new BoatDTO(competitorToEdit.getBoat().getIdAsString(), name.getText(), boatClass, sailId.getText()); CompetitorDTO result = new CompetitorDTOImpl(name.getText(), shortName.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 33f2f497262..c6e6500364d 100644 --- 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 @@ -1696,8 +1696,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Competitor competitor : race.getCompetitors()) { Boat boatOfCompetitor = race.getBoatOfCompetitorById(competitor.getId()); if (boatOfCompetitor != null) { - BoatDTO boatDTO = new BoatDTO(boatOfCompetitor.getName(), boatOfCompetitor.getSailID(), - boatOfCompetitor.getColor()); + BoatClassDTO boatClassDTO = new BoatClassDTO(boatOfCompetitor.getBoatClass().getName(), + boatOfCompetitor.getBoatClass().getDisplayName(), boatOfCompetitor.getBoatClass().getHullLength().getMeters()); + BoatDTO boatDTO = new BoatDTO(boatOfCompetitor.getId().toString(), boatOfCompetitor.getName(), boatClassDTO, + boatOfCompetitor.getSailID(), boatOfCompetitor.getColor()); competitorBoats.put(competitorDTOsMap.get(competitor.getId().toString()), boatDTO); } } From ca9c8c96da0f80fdf986ca04d03c6e4ddd880b2d Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 29 Aug 2016 17:05:33 +0200 Subject: [PATCH 008/271] first draft version of a BoatPanel for managing boats in the admin console --- .../domain/common/security/Permission.java | 1 + .../SailingPermissionsForRoleProvider.java | 1 + .../sailing/domain/base/DomainFactory.java | 3 + .../domain/base/impl/DomainFactoryImpl.java | 7 + .../adminconsole/AdminConsoleEntryPoint.java | 9 + .../adminconsole/BoatConfigImagesBarCell.java | 33 +++ .../gwt/ui/adminconsole/BoatPanel.java | 110 +++++++ .../gwt/ui/adminconsole/BoatTableWrapper.java | 277 ++++++++++++++++++ .../sailing/gwt/ui/client/SailingService.java | 8 + .../gwt/ui/client/SailingServiceAsync.java | 8 + .../gwt/ui/server/SailingServiceImpl.java | 50 +++- .../operationaltransformation/UpdateBoat.java | 53 ++++ 12 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatConfigImagesBarCell.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/Permission.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/Permission.java index d03bfa17191..f1d923445eb 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/Permission.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/Permission.java @@ -11,6 +11,7 @@ public enum Permission implements com.sap.sse.security.shared.Permission { SHOW_TRACKED_RACES, MANAGE_RACELOG_TRACKING, MANAGE_ALL_COMPETITORS, + MANAGE_ALL_BOATS, MANAGE_COURSE_LAYOUT, MANAGE_WIND, MANAGE_IGTIMI_ACCOUNTS, diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SailingPermissionsForRoleProvider.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SailingPermissionsForRoleProvider.java index 7c386a881d2..bcce8d546bd 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SailingPermissionsForRoleProvider.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/security/SailingPermissionsForRoleProvider.java @@ -23,6 +23,7 @@ public class SailingPermissionsForRoleProvider implements PermissionsForRoleProv // AdminConsole: Permission.MANAGE_ALL_COMPETITORS, + Permission.MANAGE_ALL_BOATS, Permission.MANAGE_COURSE_LAYOUT, Permission.MANAGE_DEVICE_CONFIGURATION, Permission.MANAGE_EVENTS, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java index ebf6a86281b..32f11876ccc 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.common.Placemark; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; @@ -57,6 +58,8 @@ public interface DomainFactory extends SharedDomainFactory { CompetitorDTO convertToCompetitorDTO(Competitor c); + BoatDTO convertToBoatDTO(Boat boat); + FleetDTO convertToFleetDTO(Fleet fleet); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 2ca67433ab8..98e8ddd7d4d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.DomainFactory; @@ -23,6 +24,7 @@ import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; @@ -139,6 +141,11 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return competitorAndBoatStore.convertToCompetitorDTO(c); } + @Override + public BoatDTO convertToBoatDTO(Boat boat) { + return competitorAndBoatStore.convertToBoatDTO(boat); + } + @Override public FleetDTO convertToFleetDTO(Fleet fleet) { return new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index b02792ba839..29f2fd8c677 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -162,6 +162,15 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements } }, getStringMessages().competitors(), Permission.MANAGE_ALL_COMPETITORS); + final BoatPanel boatPanel = new BoatPanel(sailingService, getStringMessages(), this); + boatPanel.ensureDebugId("BoatPanel"); + panel.addToTabPanel(racesTabPanel, new DefaultRefreshableAdminConsolePanel(boatPanel) { + @Override + public void refreshAfterBecomingVisible() { + getWidget().refreshBoatList(); + } + }, "BOATS", Permission.MANAGE_ALL_BOATS); + RaceCourseManagementPanel raceCourseManagementPanel = new RaceCourseManagementPanel(sailingService, this, this, getStringMessages()); panel.addToTabPanel(racesTabPanel, new DefaultRefreshableAdminConsolePanel(raceCourseManagementPanel), getStringMessages().courseLayout(), Permission.MANAGE_COURSE_LAYOUT); regattasDisplayers.add(raceCourseManagementPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatConfigImagesBarCell.java new file mode 100644 index 00000000000..94c88a4431f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatConfigImagesBarCell.java @@ -0,0 +1,33 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.Arrays; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.text.shared.SafeHtmlRenderer; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; + +public class BoatConfigImagesBarCell extends ImagesBarCell { + static final String ACTION_EDIT = "ACTION_EDIT"; + static final String ACTION_REFRESH = "ACTION_REFRESH"; + private final StringMessages stringMessages; + private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); + + public BoatConfigImagesBarCell(StringMessages stringMessages) { + super(); + this.stringMessages = stringMessages; + } + + public BoatConfigImagesBarCell(SafeHtmlRenderer renderer, StringMessages stringMessages) { + super(); + this.stringMessages = stringMessages; + } + + @Override + protected Iterable getImageSpecs() { + return Arrays.asList( + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), + new ImageSpec(ACTION_REFRESH, stringMessages.reload(), makeImagePrototype(resources.reloadIcon())) + ); + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java new file mode 100644 index 00000000000..beba2bbc60f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java @@ -0,0 +1,110 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.google.gwt.view.client.SelectionChangeEvent.Handler; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; + +/** + * Allows an administrator to view and edit the set of boats currently maintained by the server. + * + * @author Frank Mittag (c5163874) + * + */ +public class BoatPanel extends SimplePanel { + private final BoatTableWrapper> boatTable; + private final RefreshableMultiSelectionModel refreshableBoatSelectionModel; + private final String leaderboardName; + + public BoatPanel(final SailingServiceAsync sailingService, final StringMessages stringMessages, + final ErrorReporter errorReporter) { + this(sailingService, null, stringMessages, errorReporter); + } + + public BoatPanel(final SailingServiceAsync sailingService, final String leaderboardName, + final StringMessages stringMessages, final ErrorReporter errorReporter) { + super(); + this.leaderboardName = leaderboardName; + this.boatTable = new BoatTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ false); + this.refreshableBoatSelectionModel = (RefreshableMultiSelectionModel) boatTable.getSelectionModel(); + VerticalPanel mainPanel = new VerticalPanel(); + this.setWidget(mainPanel); + mainPanel.setWidth("100%"); + HorizontalPanel boatsPanel = new HorizontalPanel(); + boatsPanel.setSpacing(5); + mainPanel.add(boatsPanel); + HorizontalPanel buttonPanel = new HorizontalPanel(); + buttonPanel.setSpacing(5); + Button refreshButton = new Button(stringMessages.refresh()); + refreshButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + refreshBoatList(); + } + }); + refreshButton.ensureDebugId("RefreshButton"); + buttonPanel.add(refreshButton); + final Button allowReloadButton = new Button(stringMessages.allowReload()); + allowReloadButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + boatTable.allowUpdate(refreshableBoatSelectionModel.getSelectedSet()); + } + }); + buttonPanel.add(allowReloadButton); + Button addBoatButton = new Button(stringMessages.add()); + addBoatButton.ensureDebugId("AddBoatButton"); + addBoatButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + openAddBoatDialog(); + } + }); + buttonPanel.add(addBoatButton); + + Button selectAllButton = new Button(stringMessages.selectAll()); + selectAllButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + for (BoatDTO b : boatTable.getDataProvider().getList()) { + refreshableBoatSelectionModel.setSelected(b, true); + } + } + }); + buttonPanel.add(selectAllButton); + + boatsPanel.add(buttonPanel); + mainPanel.add(boatTable); + + refreshableBoatSelectionModel.addSelectionChangeHandler(new Handler() { + @Override + public void onSelectionChange(SelectionChangeEvent event) { + allowReloadButton.setEnabled(!refreshableBoatSelectionModel.getSelectedSet().isEmpty()); + } + }); + allowReloadButton.setEnabled(!refreshableBoatSelectionModel.getSelectedSet().isEmpty()); + + if (leaderboardName != null) { + refreshBoatList(); + } + } + + private void openAddBoatDialog() { + // boatTable.openEditBoatDialog(new CompetitorDTOImpl(), /* boat class to be used from CompetitorDTO */ null); + } + + public void refreshBoatList() { + boatTable.refreshBoatList(leaderboardName); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java new file mode 100644 index 00000000000..816f4383600 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -0,0 +1,277 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.cell.client.SafeHtmlCell; +import com.google.gwt.core.client.Callback; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.ImageResourceRenderer; +import com.google.gwt.user.client.ui.Label; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; +import com.sap.sailing.gwt.ui.client.FlagImageResolver; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Color; +import com.sap.sse.common.Util; +import com.sap.sse.common.util.NaturalComparator; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; +import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; + +public class BoatTableWrapper> extends TableWrapper { + private final LabeledAbstractFilterablePanel filterField; + + public BoatTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages,ErrorReporter errorReporter, + boolean multiSelection, boolean enablePager) { + super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + new EntityIdentityComparator() { + @Override + public boolean representSameEntity(BoatDTO dto1, BoatDTO dto2) { + return dto1.getIdAsString().equals(dto2.getIdAsString()); + } + @Override + public int hashCode(BoatDTO t) { + return t.getIdAsString().hashCode(); + } + }); + ListHandler boatColumnListHandler = getColumnSortHandler(); + + // boats table + TextColumn boatNameColumn = new TextColumn() { + @Override + public String getValue(BoatDTO boat) { + return boat.getName(); + } + }; + boatNameColumn.setSortable(true); + boatColumnListHandler.setComparator(boatNameColumn, new Comparator() { + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + TextColumn boatClassColumn = new TextColumn() { + @Override + public String getValue(BoatDTO competitor) { + return competitor.getBoatClass() != null ? competitor.getBoatClass().getName() : ""; + } + }; + boatClassColumn.setSortable(true); + boatColumnListHandler.setComparator(boatClassColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* caseSensitive */ false); + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return comparator.compare(o1.getBoatClass().getName(), o2.getBoatClass().getName()); + } + }); + + Column sailIdColumn = new Column(new SafeHtmlCell()) { + @Override + public SafeHtml getValue(BoatDTO competitor) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + sb.appendEscaped(competitor.getSailId()); + return sb.toSafeHtml(); + } + }; + sailIdColumn.setSortable(true); + boatColumnListHandler.setComparator(sailIdColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false); + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return comparator.compare(o1.getSailId(), o2.getSailId()); + } + }); + + Column boatColorColumn = new ColorColumn<>(new ColorRetriever() { + @Override + public Color getColor(BoatDTO t) { + return t.getColor(); + } + }); + + TextColumn competitorIdColumn = new TextColumn() { + @Override + public String getValue(BoatDTO competitor) { + return competitor.getIdAsString(); + } + }; + competitorIdColumn.setSortable(true); + boatColumnListHandler.setComparator(competitorIdColumn, new Comparator() { + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return new NaturalComparator(false).compare(o1.getIdAsString(), o2.getIdAsString()); + } + }); + + filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterCompetitors()), + new ArrayList(), table, dataProvider) { + @Override + public Iterable getSearchableStrings(BoatDTO t) { + List string = new ArrayList(); + string.add(t.getName()); + string.add(t.getSailId()); + string.add(t.getBoatClass().getName()); + string.add(t.getIdAsString()); + return string; + } + }; + registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider()); + + // BoatTable edit features + ImagesBarColumn boatActionColumn = new ImagesBarColumn( + new BoatConfigImagesBarCell(stringMessages)); + boatActionColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, final BoatDTO boat, String value) { + if (BoatConfigImagesBarCell.ACTION_EDIT.equals(value)) { + openEditBoatDialog(boat, boat.getBoatClass().getName()); + } else if (BoatConfigImagesBarCell.ACTION_REFRESH.equals(value)) { + allowUpdate(Collections.singleton(boat)); + } + } + + }); + + mainPanel.insert(filterField, 0); + table.addColumnSortHandler(boatColumnListHandler); + table.addColumn(boatNameColumn, stringMessages.name()); + table.addColumn(sailIdColumn, stringMessages.sailNumber()); + table.addColumn(boatClassColumn, stringMessages.boatClass()); + table.addColumn(boatColorColumn, stringMessages.color()); + table.addColumn(competitorIdColumn, stringMessages.id()); + table.addColumn(boatActionColumn, stringMessages.actions()); + table.ensureDebugId("BoatsTable"); + } + + public Iterable getAllBoats() { + return filterField.getAll(); + } + + public LabeledAbstractFilterablePanel getFilterField() { + return filterField; + } + + public void refreshBoatList(Iterable boats) { + getFilteredBoats(boats); + } + + public void refreshBoatList(String leaderboardName) { + refreshBoatList(leaderboardName, null); + } + + /** + * @param leaderboardName If null, all existing boats are loaded + */ + public void refreshBoatList(String leaderboardName, final Callback, + Throwable> callback) { + if (leaderboardName != null) { + sailingService.getBoatsOfLeaderboard(leaderboardName, new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Remote Procedure Call getCompetitors() - Failure: " + caught.getMessage()); + if (callback != null) { + callback.onFailure(caught); + } + } + + @Override + public void onSuccess(Iterable result) { + refreshBoatList(result); + if (callback != null) { + callback.onSuccess(result); + } + } + }); + } else { + sailingService.getBoats(new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Remote Procedure Call getCompetitors() - Failure: " + caught.getMessage()); + if (callback != null) { + callback.onFailure(caught); + } + } + + @Override + public void onSuccess(Iterable result) { + getFilteredBoats(result); + refreshBoatList(result); + if (callback != null) { + callback.onSuccess(result); + } + } + }); + } + } + + private void getFilteredBoats(Iterable result) { + filterField.updateAll(result); + } + + void openEditBoatDialog(final BoatDTO originalBoat, String boatClass) { +// final CompetitorEditDialog dialog = new CompetitorEditDialog(stringMessages, originalCompetitor, new DialogCallback() { +// @Override +// public void ok(final BoatDTO competitor) { +// sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { +// @Override +// public void onFailure(Throwable caught) { +// errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); +// } +// +// @Override +// public void onSuccess(BoatDTO updatedCompetitor) { +// //only reload selected competitors reloading with refreshCompetitorList(leaderboardName) +// //would not work in case the list is not based on a leaderboard e.g. AbstractCompetitorRegistrationDialog +// int editedCompetitorIndex = getFilterField().indexOf(originalCompetitor); +// getFilterField().remove(originalCompetitor); +// if (editedCompetitorIndex >= 0){ +// getFilterField().add(editedCompetitorIndex, updatedCompetitor); +// } else { +// //in case competitor was not present --> not edit, but create +// getFilterField().add(updatedCompetitor); +// } +// getDataProvider().refresh(); +// } +// }); +// } +// +// @Override +// public void cancel() { +// } +// }, boatClass); +// dialog.ensureDebugId("BoatEditDialog"); +// dialog.show(); + } + + protected void allowUpdate(final Iterable boats) { + List serializableSingletonList = new ArrayList(); + Util.addAll(boats, serializableSingletonList); + sailingService.allowBoatResetToDefaults(serializableSingletonList, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to allow resetting boats " + boats + + " to defaults: " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + Window.alert(stringMessages.successfullyAllowedCompetitorReset(boats.toString())); + } + }); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 8d6a798b56c..cfb6ca82ed7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -436,7 +436,15 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS CompetitorDTO addOrUpdateCompetitor(CompetitorDTO competitor) throws Exception; void allowCompetitorResetToDefaults(Iterable competitors); + + Iterable getBoats(); + Iterable getBoatsOfLeaderboard(String leaderboardName); + + BoatDTO addOrUpdateBoat(BoatDTO boat) throws Exception; + + void allowBoatResetToDefaults(Iterable boats); + List getDeviceConfigurationMatchers(); DeviceConfigurationDTO getDeviceConfiguration(DeviceConfigurationMatcherDTO matcher); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 9330f490e54..a1a87976bb2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -588,6 +588,14 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void allowCompetitorResetToDefaults(Iterable competitors, AsyncCallback asyncCallback); + void getBoats(AsyncCallback> asyncCallback); + + void getBoatsOfLeaderboard(String leaderboardName, AsyncCallback> asyncCallback); + + void addOrUpdateBoat(BoatDTO boat, AsyncCallback asyncCallback); + + void allowBoatResetToDefaults(Iterable boats, AsyncCallback asyncCallback); + void getDeviceConfigurationMatchers(AsyncCallback> asyncCallback); void getDeviceConfiguration(DeviceConfigurationMatcherDTO matcher, AsyncCallback callback); 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 c6e6500364d..24e7326d5b4 100644 --- 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 @@ -420,6 +420,7 @@ import com.sap.sailing.server.operationaltransformation.SetSuppressedFlagForComp import com.sap.sailing.server.operationaltransformation.SetWindSourcesToExclude; import com.sap.sailing.server.operationaltransformation.StopTrackingRace; import com.sap.sailing.server.operationaltransformation.StopTrackingRegatta; +import com.sap.sailing.server.operationaltransformation.UpdateBoat; import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; import com.sap.sailing.server.operationaltransformation.UpdateCompetitorDisplayNameInLeaderboard; import com.sap.sailing.server.operationaltransformation.UpdateEvent; @@ -1020,6 +1021,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } + private List convertToBoatDTOs(Iterable iterable) { + List result = new ArrayList(); + for (Boat b : iterable) { + BoatDTO boatDTO = baseDomainFactory.convertToBoatDTO(b); + result.add(boatDTO); + } + return result; + } + @Override public com.sap.sse.common.Util.Pair> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces) throws MalformedURLException, IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException { com.sap.sse.common.Util.Pair> raceRecords; @@ -4779,7 +4789,45 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } getService().apply(new AllowCompetitorResetToDefaults(competitorIdsAsStrings)); } - + + @Override + public Iterable getBoats() { + return convertToBoatDTOs(getService().getBaseDomainFactory().getCompetitorStore().getBoats()); + } + + @Override + public Iterable getBoatsOfLeaderboard(String leaderboardName) { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + return Collections.emptyList(); //convertToBoatDTOs(leaderboard.getAllBoats()); + } + + @Override + public BoatDTO addOrUpdateBoat(BoatDTO boat) { + Boat existingBoat = getService().getCompetitorStore().getExistingBoatByIdAsString(boat.getIdAsString()); + final BoatDTO result; + // new boat + if (boat.getIdAsString() == null || boat.getIdAsString().isEmpty() || existingBoat == null) { + UUID boatUUID = UUID.randomUUID(); + BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName()); + result = getBaseDomainFactory().convertToBoatDTO( + getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor())); + } else { + result = getBaseDomainFactory().convertToBoatDTO( + getService().apply( + new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId()))); + } + return result; + } + + @Override + public void allowBoatResetToDefaults(Iterable boats) { + List boatIdsAsStrings = new ArrayList(); + for (BoatDTO boat : boats) { + boatIdsAsStrings.add(boat.getIdAsString()); + } +// getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); + } + @Override public List getDeviceConfigurationMatchers() { List configs = new ArrayList(); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java new file mode 100644 index 00000000000..bbcde670d36 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java @@ -0,0 +1,53 @@ +package com.sap.sailing.server.operationaltransformation; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.Color; + +public class UpdateBoat extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = 1341635844670894476L; + private final String idAsString; + private final String newName; + private final Color newColor; + private final String newSailId; + + /** + * @param idAsString + * Identifies the boat to update + */ + public UpdateBoat(String idAsString, String newName, Color newColor, String newSailId) { + super(); + this.idAsString = idAsString; + this.newName = newName; + this.newColor = newColor; + this.newSailId = newSailId; + } + + /** + * {@link #internalApplyTo(RacingEventService)} already replicates the effects + */ + @Override + public boolean isRequiresExplicitTransitiveReplication() { + return false; + } + + @Override + public Boat internalApplyTo(RacingEventService toState) throws Exception { + Boat result = toState.getBaseDomainFactory().getCompetitorStore().updateBoat(idAsString, newName, newColor, newSailId); + return result; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + +} From 0aa188cf5fa3b318adc7a13e94d6bee15cc9fac7 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 30 Aug 2016 11:58:01 +0200 Subject: [PATCH 009/271] fixed broken tests --- .../domain/base/impl/TransientCompetitorStoreImpl.java | 8 +++++--- .../sailing/domain/test/LeaderboardCourseChangeTest.java | 8 ++++---- .../sap/sailing/domain/test/LeaderboardOfflineTest.java | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index ff557929bff..f2d86931731 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -260,15 +260,17 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab if (competitorDTO == null) { final Nationality nationality = c.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - BoatClassDTO boatClassDTO = new BoatClassDTO(c.getBoat().getBoatClass() - .getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()); + Boat b = c.getBoat(); + BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), b.getBoatClass().getDisplayName(), + b.getBoatClass().getHullLength().getMeters()); + BoatDTO boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c.getId().toString(), c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), c.getFlagImage() == null ? null : c.getFlagImage().toString(), - new BoatDTO(c.getBoat().getId().toString(), c.getBoat().getName(), boatClassDTO, c.getBoat().getSailID(), c.getBoat().getColor()), + boatDTO, boatClassDTO, c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); weakCompetitorDTOCache.put(c, competitorDTO); 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 f8e65cfe68d..289cedf6e1f 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 @@ -29,10 +29,10 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.MarkImpl; @@ -158,10 +158,10 @@ public class LeaderboardCourseChangeTest { private Iterable createCompetitorSet(BoatClass boatClass) { Set competitors = new HashSet<>(); - DynamicBoat mockedBoat = mock(DynamicBoat.class); - when(mockedBoat.getBoatClass()).thenReturn(boatClass); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", "BYC", Color.BLACK, null, null, - mock(DynamicTeam.class), mockedBoat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + mock(DynamicTeam.class), new BoatImpl("123", "boat", boatClass, "GER 124"), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); return competitors; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 1cdaecee5cd..34073d2fd15 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -218,9 +218,9 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { assertEquals(51., leaderboard.getNetPoints(c2.getCompetitor(), now), 0.00000001); assertEquals(26., leaderboard.getNetPoints(c3.getCompetitor(), now), 0.00000001); List sortedCompetitors = leaderboard.getCompetitorsFromBestToWorst(now); - assertSame(c3, sortedCompetitors.get(0)); - assertSame(c2, sortedCompetitors.get(1)); - assertSame(competitorWithBoat, sortedCompetitors.get(2)); + assertSame(c3.getCompetitor(), sortedCompetitors.get(0)); + assertSame(c2.getCompetitor(), sortedCompetitors.get(1)); + assertSame(competitorWithBoat.getCompetitor(), sortedCompetitors.get(2)); } @Test From ede3d5707e3e50755165b5900045bba6d3938914 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 30 Aug 2016 14:29:57 +0200 Subject: [PATCH 010/271] fixed two more tests --- .../TestStoringAndRetrievingLeaderboards.java | 14 ++++++------ ...LeaderboardCorrectionsReplicationTest.java | 22 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index d3a01276738..504684a1a4b 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -79,7 +79,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat wolfgang = createCompetitorAndBoat(); + CompetitorWithBoat wolfgangWithBoat = createCompetitorAndBoat(); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), @@ -88,18 +88,18 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { Boat hassosBoat = new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); CompetitorWithBoat hassoWithBoat = new CompetitorWithBoatImpl(hasso, hassosBoat); final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgangWithBoat, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitorAndBoat(hassoWithBoat); leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */ false); - leaderboard.setSuppressed(wolfgang.getCompetitor(), true); - assertTrue(Util.contains(leaderboard.getSuppressedCompetitors(), wolfgang)); + leaderboard.setSuppressed(wolfgangWithBoat.getCompetitor(), true); + assertTrue(Util.contains(leaderboard.getSuppressedCompetitors(), wolfgangWithBoat.getCompetitor())); assertFalse(Util.contains(leaderboard.getSuppressedCompetitors(), hasso)); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE).loadLeaderboard(leaderboardName, /* regattaRegistry */ null); - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors2 = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgang, /* rank */ 1, /* started */ true); + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors2 = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgangWithBoat, /* rank */ 1, /* started */ true); raceWithTwoCompetitors2.addCompetitorAndBoat(hassoWithBoat); loadedLeaderboard.getRaceColumnByName(raceColumnName1).setTrackedRace(loadedLeaderboard.getFleet(null), raceWithTwoCompetitors2); - assertTrue(Util.contains(loadedLeaderboard.getSuppressedCompetitors(), wolfgang)); + assertTrue(Util.contains(loadedLeaderboard.getSuppressedCompetitors(), wolfgangWithBoat.getCompetitor())); assertFalse(Util.contains(loadedLeaderboard.getSuppressedCompetitors(), hasso)); } @@ -184,7 +184,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { assertTrue(Arrays.equals(discardIndexResultsStartingWithHowManyRaces, ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces())); assertEquals(1, Util.size(loadedLeaderboard.getCompetitors())); - assertEquals(competitorWithBoat, loadedLeaderboard.getCompetitors().iterator().next()); + assertEquals(competitorWithBoat.getCompetitor(), loadedLeaderboard.getCompetitors().iterator().next()); assertEquals(carriedPointsForWolfgangHunger, loadedLeaderboard.getCarriedPoints(competitorWithBoat.getCompetitor()), 0.000000001); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java index a1fe58e208f..afe18ad265a 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java @@ -79,8 +79,8 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer // resolved properly on the replica. final DomainFactory domainFactory = new DomainFactoryImpl((srlid)->null); BoatClass boatClass = domainFactory.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore - final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { + CompetitorWithBoat hassoWithBoat = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore + final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hassoWithBoat, /* rank */ 1, /* started */ false, boatClass) { private static final long serialVersionUID = 1234L; @Override public RegattaAndRaceIdentifier getRaceIdentifier() { @@ -98,9 +98,9 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer master.apply(new AddColumnToLeaderboard(Q2, leaderboardName, /* medalRace */ false)); // uses leaderboard's default fleet master.apply(new ConnectTrackedRaceToLeaderboardColumn(masterLeaderboard.getName(), Q2, /* default fleet */ masterLeaderboard.getFleet(null).getName(), q2YellowTrackedRace.getRaceIdentifier())); - master.apply(new UpdateLeaderboardMaxPointsReason(masterLeaderboard.getName(), Q2, hasso.getCompetitor().getId().toString(), + master.apply(new UpdateLeaderboardMaxPointsReason(masterLeaderboard.getName(), Q2, hassoWithBoat.getCompetitor().getId().toString(), MaxPointsReason.DNF, MillisecondsTimePoint.now())); - assertEquals(MaxPointsReason.DNF, masterLeaderboard.getMaxPointsReason(hasso.getCompetitor(), + assertEquals(MaxPointsReason.DNF, masterLeaderboard.getMaxPointsReason(hassoWithBoat.getCompetitor(), masterLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); // re-load new master from persistence @@ -112,7 +112,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer // expecting the correction to not be in the leaderboard because the competitor was not found in the // domain factory's competitor store while loading and therefore the score correction could not immediately // be applied to the leaderboard's real score correction - assertEquals(MaxPointsReason.NONE, masterLeaderboardReloaded.getMaxPointsReason(hasso.getCompetitor(), + assertEquals(MaxPointsReason.NONE, masterLeaderboardReloaded.getMaxPointsReason(hassoWithBoat.getCompetitor(), masterLeaderboardReloaded.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); // replicate the re-loaded environment @@ -130,10 +130,10 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2)); // so far, the replica should also only have the delayed corrections since during deserializing them the // replicatedHasso competitor was not yet known to the replica's competitor store: - assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hasso.getCompetitor(), + assertEquals(MaxPointsReason.NONE, replicaLeaderboard.getMaxPointsReason(hassoWithBoat.getCompetitor(), replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); - logger.info("hasso object ID hash: "+System.identityHashCode(hasso)); + logger.info("hasso object ID hash: "+System.identityHashCode(hassoWithBoat)); Leaderboard newMasterLeaderboard = master.getLeaderboardByName(masterLeaderboard.getName()); SettableScoreCorrection newMasterScoreCorrections = newMasterLeaderboard.getScoreCorrection(); RaceColumn newMasterQ2 = newMasterLeaderboard.getRaceColumnByName(Q2); @@ -151,13 +151,13 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer master.apply(new ConnectTrackedRaceToLeaderboardColumn(masterLeaderboard.getName(), Q2, /* default fleet */ masterLeaderboard.getFleet(null).getName(), q2YellowTrackedRace.getRaceIdentifier())); logger.info("got score correction for competitor "+System.identityHashCode(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2).iterator().next())); - assertTrue(Util.contains(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2), hasso)); // now score corrections must have been applied from Delayed... + assertTrue(Util.contains(newMasterScoreCorrections.getCompetitorsThatHaveCorrectionsIn(newMasterQ2), hassoWithBoat.getCompetitor())); // now score corrections must have been applied from Delayed... // now the delayed corrections are expected to have been resolved: - assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hasso.getCompetitor(), + assertEquals(MaxPointsReason.DNF, master.getLeaderboardByName(leaderboardName).getMaxPointsReason(hassoWithBoat.getCompetitor(), master.getLeaderboardByName(leaderboardName).getRaceColumnByName(Q2), MillisecondsTimePoint.now())); Thread.sleep(1000); // wait for the tracked race to column connection to be replicated - assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2).getTrackedRace(hasso.getCompetitor())); - assertEquals(MaxPointsReason.DNF, replicaLeaderboard.getMaxPointsReason(hasso.getCompetitor(), + assertNotNull(replicaLeaderboard.getRaceColumnByName(Q2).getTrackedRace(hassoWithBoat.getCompetitor())); + assertEquals(MaxPointsReason.DNF, replicaLeaderboard.getMaxPointsReason(hassoWithBoat.getCompetitor(), replicaLeaderboard.getRaceColumnByName(Q2), MillisecondsTimePoint.now())); } From b3f5c31dc18438c6d05e7a90e717d227fc8d7b5a Mon Sep 17 00:00:00 2001 From: fmittag Date: Thu, 1 Sep 2016 13:32:22 +0200 Subject: [PATCH 011/271] some preparation work for Selenium tests for the BoatPanel --- .../adminconsole/AdminConsoleEntryPoint.java | 2 +- .../gwt/ui/adminconsole/BoatEditDialog.java | 145 ++++++++++++++++++ .../gwt/ui/adminconsole/BoatPanel.java | 2 - .../gwt/ui/adminconsole/BoatTableWrapper.java | 4 - .../sailing/gwt/ui/client/StringMessages.java | 2 + .../gwt/ui/client/StringMessages.properties | 2 + .../ui/client/StringMessages_de.properties | 2 + .../ui/client/StringMessages_ja.properties | 2 + .../ui/client/StringMessages_ru.properties | 2 + .../ui/client/StringMessages_zh.properties | 2 + .../ui/client/StringMessages_zh_CN.properties | 2 + .../pages/adminconsole/AdminConsolePage.java | 14 +- .../tracking/TrackedRacesBoatsPanelPO.java | 20 +++ 13 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java create mode 100644 java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index 29f2fd8c677..64a08733438 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -169,7 +169,7 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements public void refreshAfterBecomingVisible() { getWidget().refreshBoatList(); } - }, "BOATS", Permission.MANAGE_ALL_BOATS); + }, getStringMessages().boats(), Permission.MANAGE_ALL_BOATS); RaceCourseManagementPanel raceCourseManagementPanel = new RaceCourseManagementPanel(sailingService, this, this, getStringMessages()); panel.addToTabPanel(racesTabPanel, new DefaultRefreshableAdminConsolePanel(raceCourseManagementPanel), getStringMessages().courseLayout(), Permission.MANAGE_COURSE_LAYOUT); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java new file mode 100644 index 00000000000..2a304a9adac --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java @@ -0,0 +1,145 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import com.google.gwt.user.client.ui.FocusWidget; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Color; +import com.sap.sse.common.impl.RGBColor; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; + +/** + * @author Frank Mittag (c516374) + * + */ +public class BoatEditDialog extends DataEntryDialog { + private final BoatDTO boatToEdit; + private final TextBox name; + private final SuggestBox boatClassName; + private final TextBox displayColorTextBox; + private final TextBox sailId; + private final StringMessages stringMessages; + + /** + * The class creates the UI-dialog to type in the Data about a competitor. + * + * @param competitorToEdit + * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. + * @param boatClass + * The boat class is the default shown boat class for new competitors. Set null if your competitor is + * already initialized or you don�t want a default boat class. + */ + public BoatEditDialog(final StringMessages stringMessages, BoatDTO competitorToEdit, + DialogCallback callback, String boatClass) { + super(stringMessages.editCompetitor(), null, stringMessages.ok(), stringMessages + .cancel(), new Validator() { + @Override + public String getErrorMessage(BoatDTO valueToValidate) { + String result = null; + if (valueToValidate.getName() == null || valueToValidate.getName().isEmpty()) { + result = stringMessages.pleaseEnterAName(); + } else if (valueToValidate.getSailId() == null || valueToValidate.getSailId().isEmpty()) { + result = stringMessages.pleaseEnterASailNumber(); + } else if (valueToValidate.getColor() != null) { + Color displayColor = valueToValidate.getColor(); + if (displayColor instanceof InvalidColor) { + result = displayColor.getAsHtml(); + } + } else if (valueToValidate.getBoatClass().getName() == null || valueToValidate.getBoatClass().getName().isEmpty()) { + result = stringMessages.pleaseEnterABoatClass(); + } + return result; + } + }, /* animationEnabled */true, callback); + this.ensureDebugId("BoatEditDialog"); + this.stringMessages = stringMessages; + this.boatToEdit = competitorToEdit; + + this.boatClassName = createSuggestBox(new BoatClassMasterdataSuggestOracle()); + boatClassName.ensureDebugId("BoatClassNameSuggestBox"); + if (competitorToEdit.getBoatClass() != null) { + boatClassName.setValue(competitorToEdit.getBoatClass().getName()); + boatClassName.setEnabled(false); + } else { + boatClassName.setValue(boatClass); // widgets have to accept null values here + } + this.name = createTextBox(competitorToEdit.getName()); + name.ensureDebugId("NameTextBox"); + this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); + this.sailId = createTextBox(competitorToEdit.getSailId()); + sailId.ensureDebugId("SailIdTextBox"); + } + + @Override + protected FocusWidget getInitialFocusWidget() { + return name; + } + + /** + * Encodes an invalid color; can be used + * @author Axel Uhl (D043530) + * + */ + private class InvalidColor implements Color { + private static final long serialVersionUID = 4012986110898149543L; + private final Exception exception; + + protected InvalidColor(Exception exception) { + this.exception = exception; + } + + @Override + public com.sap.sse.common.Util.Triple getAsRGB() { + return null; + } + + @Override + public com.sap.sse.common.Util.Triple getAsHSV() { + return null; + } + + @Override + public String getAsHtml() { + return stringMessages.invalidColor(exception.getMessage()); + } + + } + + @Override + protected BoatDTO getResult() { + Color color; + if (displayColorTextBox.getText() == null || displayColorTextBox.getText().isEmpty()) { + color = null; + } else { + try { + color = new RGBColor(displayColorTextBox.getText()); + } catch (IllegalArgumentException iae) { + color = new InvalidColor(iae); + } + } + BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); + BoatDTO boat = new BoatDTO(boatToEdit.getIdAsString(), name.getText(), boatClass, sailId.getText(), color); + return boat; + } + + @Override + protected Widget getAdditionalWidget() { + Grid result = new Grid(4, 2); + result.setWidget(0, 0, new Label(stringMessages.name())); + result.setWidget(0, 1, name); + result.setWidget(1, 0, new Label(stringMessages.sailNumber())); + result.setWidget(1, 1, sailId); + result.setWidget(2, 0, new Label(stringMessages.color())); + result.setWidget(2, 1, displayColorTextBox); + result.setWidget(3, 0, new Label(stringMessages.boatClass())); + result.setWidget(3, 1, boatClassName); + return result; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java index beba2bbc60f..e6529b5d5ee 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java @@ -9,8 +9,6 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java index 816f4383600..d55c7936f67 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -8,7 +8,6 @@ import java.util.List; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.cell.client.SafeHtmlCell; import com.google.gwt.core.client.Callback; -import com.google.gwt.resources.client.ImageResource; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.cellview.client.Column; @@ -16,11 +15,9 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.ImageResourceRenderer; import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; -import com.sap.sailing.gwt.ui.client.FlagImageResolver; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Color; @@ -29,7 +26,6 @@ import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; -import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; public class BoatTableWrapper> extends TableWrapper { 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 d3ff13224eb..0ba3417ebd8 100644 --- 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 @@ -47,6 +47,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String competitor(); String competitors(); String competitorsSelected(int selectedCompetitorsCount, int competitorsCount); + String boat(); + String boats(); String noSuchLeaderboard(); String leaderboardConfiguration(); String newDotDotDot(); 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 899bdb93107..283ae88a49b 100644 --- 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 @@ -37,6 +37,8 @@ carry=Accumulated competitor=Competitor competitors=Competitors competitorsSelected={0}/{1} competitors selected. +boat=Boat +boats=Boats noSuchLeaderboard=No such leaderboard leaderboardConfiguration=Leaderboard Configuration newDotDotDot=New... 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 db5cfb0af20..939a528a73b 100644 --- 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 @@ -37,6 +37,8 @@ carry=übertr. competitor=Team competitors=Teams competitorsSelected={0}/{1} Teams ausgewählt. +boat=Boot +boats=Boote noSuchLeaderboard=Rangliste nicht gefunden leaderboardConfiguration=Ranglisten-Konfiguration newDotDotDot=Neu... diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties index 3a53194a29d..2ec00c93b2e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties @@ -37,6 +37,8 @@ carry=累積 competitor=競技者 competitors=競技者 competitorsSelected={0}/{1} の競技者が選択されました。 +boat=Boat +boats=Boats noSuchLeaderboard=そのようなリーダーボードはありません leaderboardConfiguration=リーダーボード設定 newDotDotDot=新規... 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 6d21244e64b..5e645ee783b 100644 --- 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 @@ -37,6 +37,8 @@ carry=Накоплено competitor=Участник competitors=Участники competitorsSelected=Выбрано участников: {0}/{1}. +boat=Boat +boats=Boats noSuchLeaderboard=Нет такой таблицы лидеров leaderboardConfiguration=Конфигурация таблицы лидеров newDotDotDot=Создать... diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index af7a81996a3..d6d4cafe57c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -37,6 +37,8 @@ carry=累积 competitor=参赛队 competitors=参赛队 competitorsSelected=已选择{0}/{1}支参赛队。 +boat=Boat +boats=Boats noSuchLeaderboard=没有积分榜 leaderboardConfiguration=积分榜配置 newDotDotDot=新建... diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties index af7a81996a3..d6d4cafe57c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties @@ -37,6 +37,8 @@ carry=累积 competitor=参赛队 competitors=参赛队 competitorsSelected=已选择{0}/{1}支参赛队。 +boat=Boat +boats=Boats noSuchLeaderboard=没有积分榜 leaderboardConfiguration=积分榜配置 newDotDotDot=新建... diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java index 6fa00594bdc..1454860dea3 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java @@ -15,6 +15,7 @@ import com.sap.sailing.selenium.pages.adminconsole.event.EventConfigurationPanel import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO; import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardGroupConfigurationPanelPO; import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesBoatsPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorsPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesManagementPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; @@ -59,7 +60,10 @@ public class AdminConsolePage extends HostPageWithAuthentication { private static final String COMPETITOR_PANEL_TAB_LABEL = "Competitors"; //$NON-NLS-1$ private static final String COMPETITOR_PANEL_TAB_IDENTIFIER = "CompetitorPanel"; //$NON-NLS-1$ - + + private static final String BOAT_PANEL_TAB_LABEL = "Boats"; //$NON-NLS-1$ + private static final String BOAT_PANEL_TAB_IDENTIFIER = "BoatPanel"; //$NON-NLS-1$ + private static final String SMARTPHONETRACKINGPANEL_PANEL_TAB_LABEL = "Smartphone Tracking"; //$NON-NLS-1$ private static final String SMARTPHONETRACKINGPANEL_PANEL_TAB_IDENTIFIER = "SmartphoneTrackingPanel"; //$NON-NLS-1$ /** @@ -128,7 +132,13 @@ public class AdminConsolePage extends HostPageWithAuthentication { return new TrackedRacesCompetitorsPanelPO(this.driver, goToTab(COMPETITOR_PANEL_TAB_LABEL, COMPETITOR_PANEL_TAB_IDENTIFIER, false)); } - + + public TrackedRacesBoatsPanelPO goToTrackedRacesBoats() { + goToTab(TRACKED_RACES_TAB_PARENT_LABEL, TRACKED_RACES_TAB_PARENT_IDENTIFIER, true); + return new TrackedRacesBoatsPanelPO(this.driver, goToTab(BOAT_PANEL_TAB_LABEL, + BOAT_PANEL_TAB_IDENTIFIER, false)); + } + public SmartphoneTrackingEventManagementPanelPO goToSmartphoneTrackingPanel() { goToTab(TRACTRAC_EVENTS_TAB_PARENT_LABEL, TRACTRAC_EVENTS_TAB_PARENT_IDENTIFIER, true); return new SmartphoneTrackingEventManagementPanelPO(this.driver, goToTab(SMARTPHONETRACKINGPANEL_PANEL_TAB_LABEL, diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java new file mode 100644 index 00000000000..4aa31add0d1 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java @@ -0,0 +1,20 @@ +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.PageArea; + +public class TrackedRacesBoatsPanelPO extends PageArea { + @FindBy(how = BySeleniumId.class, using = "BoatsTable") + private WebElement boatsTable; + + public final WebDriver driver; + + public TrackedRacesBoatsPanelPO(WebDriver driver, WebElement element) { + super(driver, element); + this.driver = driver; + } +} From 310d7693bb6e4d3134d2b6282e0dbc0ae55f4a62 Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 2 Sep 2016 17:01:09 +0200 Subject: [PATCH 012/271] fix for loading legacy boats having no ID field --- .../impl/BoatJsonDeserializer.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java index 17330618b77..70b7bfe1d18 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/BoatJsonDeserializer.java @@ -33,14 +33,18 @@ public class BoatJsonDeserializer implements JsonDeserializer { public DynamicBoat deserialize(JSONObject object) throws JsonDeserializationException { Serializable boatId = (Serializable) object.get(BoatJsonSerializer.FIELD_ID); try { - Class idClass = Class.forName((String) object.get(BoatJsonSerializer.FIELD_ID_TYPE)); - if (Number.class.isAssignableFrom(idClass)) { - Constructor constructorFromString = idClass.getConstructor(String.class); - boatId = (Serializable) constructorFromString.newInstance(boatId.toString()); - } else if (UUID.class.isAssignableFrom(idClass)) { - boatId = Helpers.tryUuidConversion(boatId); + if (boatId == null) { + // no boatId - probably a legacy boat -> create an UUID + boatId = UUID.randomUUID(); + } else { + Class idClass = Class.forName((String) object.get(BoatJsonSerializer.FIELD_ID_TYPE)); + if (Number.class.isAssignableFrom(idClass)) { + Constructor constructorFromString = idClass.getConstructor(String.class); + boatId = (Serializable) constructorFromString.newInstance(boatId.toString()); + } else if (UUID.class.isAssignableFrom(idClass)) { + boatId = Helpers.tryUuidConversion(boatId); + } } - String name = (String) object.get(BoatJsonSerializer.FIELD_NAME); final Object sailID = object.get(BoatJsonSerializer.FIELD_SAIL_ID); String sailId = sailID == null ? null : sailID.toString(); From 7f6eb01efc1c5525159a8c99f788927c67d3096b Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 5 Sep 2016 13:55:37 +0200 Subject: [PATCH 013/271] fix for broken CompetitorEditDialog --- .../sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 3514e05674a..d676426e69e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -191,7 +191,8 @@ public class CompetitorEditDialog extends DataEntryDialog { } } BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); - BoatDTO boat = new BoatDTO(competitorToEdit.getBoat().getIdAsString(), name.getText(), boatClass, sailId.getText()); + // Use temporary competitorID as boat Id -> boat will be removed from competitor later on anyway + BoatDTO boat = new BoatDTO(competitorToEdit.getIdAsString(), name.getText(), boatClass, sailId.getText()); CompetitorDTO result = new CompetitorDTOImpl(name.getText(), shortName.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), From ea76424e351664f95a29f35d7f00c463ec3ad27f Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 5 Sep 2016 13:56:01 +0200 Subject: [PATCH 014/271] further implementation of BoatPanel methods --- .../sailing/domain/common/dto/BoatDTO.java | 2 +- .../gwt/ui/adminconsole/BoatEditDialog.java | 27 +++--- .../gwt/ui/adminconsole/BoatPanel.java | 2 +- .../gwt/ui/adminconsole/BoatTableWrapper.java | 93 ++++++++++--------- .../AllowBoatResetToDefaults.java | 46 +++++++++ 5 files changed, 107 insertions(+), 63 deletions(-) create mode 100644 java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java index cf936a2c98e..7c2faae518e 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java @@ -13,7 +13,7 @@ public class BoatDTO extends NamedDTO implements Serializable { private Color color; // for GWT - BoatDTO() {} + public BoatDTO() {} public BoatDTO(String idAsString, String name, BoatClassDTO boatClass, String sailId) { this(idAsString, name, boatClass, sailId, null); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java index 2a304a9adac..50187fd3ca6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java @@ -29,15 +29,12 @@ public class BoatEditDialog extends DataEntryDialog { /** * The class creates the UI-dialog to type in the Data about a competitor. * - * @param competitorToEdit - * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. - * @param boatClass - * The boat class is the default shown boat class for new competitors. Set null if your competitor is - * already initialized or you don�t want a default boat class. + * @param boatToEdit + * The 'boatToEdit' parameter contains the boat which should be changed or initialized. */ - public BoatEditDialog(final StringMessages stringMessages, BoatDTO competitorToEdit, - DialogCallback callback, String boatClass) { - super(stringMessages.editCompetitor(), null, stringMessages.ok(), stringMessages + public BoatEditDialog(final StringMessages stringMessages, BoatDTO boatToEdit, + DialogCallback callback) { + super(stringMessages.edit() + " " + stringMessages.boat(), null, stringMessages.ok(), stringMessages .cancel(), new Validator() { @Override public String getErrorMessage(BoatDTO valueToValidate) { @@ -59,20 +56,20 @@ public class BoatEditDialog extends DataEntryDialog { }, /* animationEnabled */true, callback); this.ensureDebugId("BoatEditDialog"); this.stringMessages = stringMessages; - this.boatToEdit = competitorToEdit; + this.boatToEdit = boatToEdit; this.boatClassName = createSuggestBox(new BoatClassMasterdataSuggestOracle()); boatClassName.ensureDebugId("BoatClassNameSuggestBox"); - if (competitorToEdit.getBoatClass() != null) { - boatClassName.setValue(competitorToEdit.getBoatClass().getName()); + if (boatToEdit.getBoatClass() != null) { + boatClassName.setValue(boatToEdit.getBoatClass().getName()); boatClassName.setEnabled(false); } else { - boatClassName.setValue(boatClass); // widgets have to accept null values here + boatClassName.setValue(null); // widgets have to accept null values here } - this.name = createTextBox(competitorToEdit.getName()); + this.name = createTextBox(boatToEdit.getName()); name.ensureDebugId("NameTextBox"); - this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); - this.sailId = createTextBox(competitorToEdit.getSailId()); + this.displayColorTextBox = createTextBox(boatToEdit.getColor() == null ? "" : boatToEdit.getColor().getAsHtml()); + this.sailId = createTextBox(boatToEdit.getSailId()); sailId.ensureDebugId("SailIdTextBox"); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java index e6529b5d5ee..6cf46cb84fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java @@ -99,7 +99,7 @@ public class BoatPanel extends SimplePanel { } private void openAddBoatDialog() { - // boatTable.openEditBoatDialog(new CompetitorDTOImpl(), /* boat class to be used from CompetitorDTO */ null); + boatTable.openEditBoatDialog(new BoatDTO()); } public void refreshBoatList() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java index d55c7936f67..25b83b929e9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -26,6 +26,7 @@ import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; public class BoatTableWrapper> extends TableWrapper { @@ -100,14 +101,14 @@ public class BoatTableWrapper> exte } }); - TextColumn competitorIdColumn = new TextColumn() { + TextColumn boatIdColumn = new TextColumn() { @Override - public String getValue(BoatDTO competitor) { - return competitor.getIdAsString(); + public String getValue(BoatDTO boat) { + return boat.getIdAsString(); } }; - competitorIdColumn.setSortable(true); - boatColumnListHandler.setComparator(competitorIdColumn, new Comparator() { + boatIdColumn.setSortable(true); + boatColumnListHandler.setComparator(boatIdColumn, new Comparator() { @Override public int compare(BoatDTO o1, BoatDTO o2) { return new NaturalComparator(false).compare(o1.getIdAsString(), o2.getIdAsString()); @@ -117,12 +118,12 @@ public class BoatTableWrapper> exte filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterCompetitors()), new ArrayList(), table, dataProvider) { @Override - public Iterable getSearchableStrings(BoatDTO t) { + public Iterable getSearchableStrings(BoatDTO boat) { List string = new ArrayList(); - string.add(t.getName()); - string.add(t.getSailId()); - string.add(t.getBoatClass().getName()); - string.add(t.getIdAsString()); + string.add(boat.getName()); + string.add(boat.getSailId()); + string.add(boat.getBoatClass().getName()); + string.add(boat.getIdAsString()); return string; } }; @@ -135,7 +136,7 @@ public class BoatTableWrapper> exte @Override public void update(int index, final BoatDTO boat, String value) { if (BoatConfigImagesBarCell.ACTION_EDIT.equals(value)) { - openEditBoatDialog(boat, boat.getBoatClass().getName()); + openEditBoatDialog(boat); } else if (BoatConfigImagesBarCell.ACTION_REFRESH.equals(value)) { allowUpdate(Collections.singleton(boat)); } @@ -149,7 +150,7 @@ public class BoatTableWrapper> exte table.addColumn(sailIdColumn, stringMessages.sailNumber()); table.addColumn(boatClassColumn, stringMessages.boatClass()); table.addColumn(boatColorColumn, stringMessages.color()); - table.addColumn(competitorIdColumn, stringMessages.id()); + table.addColumn(boatIdColumn, stringMessages.id()); table.addColumn(boatActionColumn, stringMessages.actions()); table.ensureDebugId("BoatsTable"); } @@ -197,7 +198,7 @@ public class BoatTableWrapper> exte sailingService.getBoats(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { - errorReporter.reportError("Remote Procedure Call getCompetitors() - Failure: " + caught.getMessage()); + errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); if (callback != null) { callback.onFailure(caught); } @@ -219,39 +220,39 @@ public class BoatTableWrapper> exte filterField.updateAll(result); } - void openEditBoatDialog(final BoatDTO originalBoat, String boatClass) { -// final CompetitorEditDialog dialog = new CompetitorEditDialog(stringMessages, originalCompetitor, new DialogCallback() { -// @Override -// public void ok(final BoatDTO competitor) { -// sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { -// @Override -// public void onFailure(Throwable caught) { -// errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); -// } -// -// @Override -// public void onSuccess(BoatDTO updatedCompetitor) { -// //only reload selected competitors reloading with refreshCompetitorList(leaderboardName) -// //would not work in case the list is not based on a leaderboard e.g. AbstractCompetitorRegistrationDialog -// int editedCompetitorIndex = getFilterField().indexOf(originalCompetitor); -// getFilterField().remove(originalCompetitor); -// if (editedCompetitorIndex >= 0){ -// getFilterField().add(editedCompetitorIndex, updatedCompetitor); -// } else { -// //in case competitor was not present --> not edit, but create -// getFilterField().add(updatedCompetitor); -// } -// getDataProvider().refresh(); -// } -// }); -// } -// -// @Override -// public void cancel() { -// } -// }, boatClass); -// dialog.ensureDebugId("BoatEditDialog"); -// dialog.show(); + void openEditBoatDialog(final BoatDTO originalBoat) { + final BoatEditDialog dialog = new BoatEditDialog(stringMessages, originalBoat, new DialogCallback() { + @Override + public void ok(BoatDTO boat) { + sailingService.addOrUpdateBoat(boat, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to update boat: " + caught.getMessage()); + } + + @Override + public void onSuccess(BoatDTO updatedBoat) { + //only reload selected boats reloading with refreshBoatList(leaderboardName) + //would not work in case the list is not based on a leaderboard e.g. AbstractBoatRegistrationDialog + int editedBoatIndex = getFilterField().indexOf(originalBoat); + getFilterField().remove(originalBoat); + if (editedBoatIndex >= 0){ + getFilterField().add(editedBoatIndex, updatedBoat); + } else { + //in case boat was not present --> not edit, but create + getFilterField().add(updatedBoat); + } + getDataProvider().refresh(); + } + }); + } + + @Override + public void cancel() { + } + }); + dialog.ensureDebugId("BoatEditDialog"); + dialog.show(); } protected void allowUpdate(final Iterable boats) { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java new file mode 100644 index 00000000000..dc15cac3232 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java @@ -0,0 +1,46 @@ +package com.sap.sailing.server.operationaltransformation; + +import java.util.ArrayList; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.Util; + +public class AllowBoatResetToDefaults extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = -3698113910122095903L; + private final Iterable boatIdsAsStrings; + + public AllowBoatResetToDefaults(Iterable boatIdsAsStrings) { + super(); + final ArrayList arrayList = new ArrayList<>(); // to guarantee serializability, even if an unmodifiable or singleton is passed + this.boatIdsAsStrings = arrayList; + Util.addAll(boatIdsAsStrings, arrayList); + } + + @Override + public Void internalApplyTo(RacingEventService toState) throws Exception { + final CompetitorStore competitorAndBoatStore = toState.getBaseDomainFactory().getCompetitorStore(); + for (String boatIdAsString : boatIdsAsStrings) { + Boat boat = competitorAndBoatStore.getExistingBoatByIdAsString(boatIdAsString); + if (boat != null) { + competitorAndBoatStore.allowBoatResetToDefaults(boat); + } + } + return null; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + +} From 50ce8ef46d6cd37eb512457452f1697271f5b4c9 Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 5 Sep 2016 14:41:56 +0200 Subject: [PATCH 015/271] enabled use of AllowBoatResetToDefaults operation --- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 24e7326d5b4..e78aa39716c 100644 --- 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 @@ -390,6 +390,7 @@ import com.sap.sailing.server.operationaltransformation.AddColumnToSeries; import com.sap.sailing.server.operationaltransformation.AddCourseAreas; import com.sap.sailing.server.operationaltransformation.AddRemoteSailingServerReference; import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; +import com.sap.sailing.server.operationaltransformation.AllowBoatResetToDefaults; import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults; import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; import com.sap.sailing.server.operationaltransformation.CreateEvent; @@ -4825,7 +4826,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (BoatDTO boat : boats) { boatIdsAsStrings.add(boat.getIdAsString()); } -// getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); + getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); } @Override From 6c8edcbf9aa2a584017cf87aced7f7380c379b54 Mon Sep 17 00:00:00 2001 From: fmittag Date: Thu, 6 Oct 2016 11:42:50 +0200 Subject: [PATCH 016/271] Fixed testcase --- .../test/impl/SensorFixStoreAndLoadTest.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 0fe9590a085..12fecae8b6f 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -10,7 +10,9 @@ import java.io.Serializable; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.After; @@ -37,6 +39,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -105,13 +108,16 @@ public class SensorFixStoreAndLoadTest { protected RaceLog raceLog; protected RegattaLog regattaLog; protected SensorFixStore store; - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); - protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, + protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); + protected final Boat boat1 = DomainFactory.INSTANCE.getOrCreateBoat(comp, "Boat1", boatClass, "GER 1", null); + protected final Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "Boat2", boatClass, "GER 2", null); + protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); protected final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); - private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); private DynamicTrackedRace trackedRace; @@ -139,7 +145,10 @@ public class SensorFixStoreAndLoadTest { new MillisecondsTimePoint(1), 0, mark2)); Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp, comp2)); + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat1); + competitorsAndBoats.put(comp2, boat2); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ null, /* endDate */null, null, null, "a", null)); From 3d264fcd5e3ebce1352f53254831a552fe12394d Mon Sep 17 00:00:00 2001 From: fmittag Date: Thu, 10 Nov 2016 21:52:34 +0100 Subject: [PATCH 017/271] fixed compile issues after master merge --- .../com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java | 3 ++- .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- .../sap/sailing/server/test/ApplyScoresFromRaceLogTest.java | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java index 50187fd3ca6..8b2d7f42a44 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java @@ -6,6 +6,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle; @@ -120,7 +121,7 @@ public class BoatEditDialog extends DataEntryDialog { color = new InvalidColor(iae); } } - BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); + BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), Distance.NULL); BoatDTO boat = new BoatDTO(boatToEdit.getIdAsString(), name.getText(), boatClass, sailId.getText(), color); return boat; } 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 a7d2d8f3d38..e384047e3c1 100644 --- 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 @@ -1704,7 +1704,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Boat boatOfCompetitor = race.getBoatOfCompetitorById(competitor.getId()); if (boatOfCompetitor != null) { BoatClassDTO boatClassDTO = new BoatClassDTO(boatOfCompetitor.getBoatClass().getName(), - boatOfCompetitor.getBoatClass().getDisplayName(), boatOfCompetitor.getBoatClass().getHullLength().getMeters()); + boatOfCompetitor.getBoatClass().getDisplayName(), boatOfCompetitor.getBoatClass().getHullLength()); BoatDTO boatDTO = new BoatDTO(boatOfCompetitor.getId().toString(), boatOfCompetitor.getName(), boatClassDTO, boatOfCompetitor.getSailID(), boatOfCompetitor.getColor()); competitorBoats.put(competitorDTOsMap.get(competitor.getId().toString()), boatDTO); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java index 0db07c42e74..4ce2731bcd4 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java @@ -125,12 +125,12 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest for (int i=0; i<8; i++) { final String competitorName = "C"+i; competitors.add(service.getBaseDomainFactory().getCompetitorStore().getOrCreateCompetitor(UUID.randomUUID(), - competitorName, /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null, + competitorName, competitorName, /* displayColor */ Color.RED, /* email */ null, /* flagImageURI */ null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat", + /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName+ "Id", competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); } From 45452ac18578b1cded2407f57e3f38e42a86998f Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 30 Dec 2016 17:05:03 +0100 Subject: [PATCH 018/271] added canBoatsOfCompetitorsChangePerRace attribute to regatta (+corresponding load/store methods and admin UI) --- .../impl/DomainObjectFactoryImpl.java | 7 ++- .../domain/persistence/impl/FieldNames.java | 1 + .../impl/MongoObjectFactoryImpl.java | 1 + .../test/AbstractGPSFixStoreTest.java | 2 +- .../impl/CreateAndTrackWithRaceLogTest.java | 3 +- .../impl/RaceLogFixTrackerManagerTest.java | 2 +- .../test/impl/SensorFixStoreAndLoadTest.java | 2 +- .../TrackedRaceStartTimeInferenceTest.java | 20 ++++---- .../test/SimpleDomainFactoryTest.java | 6 ++- .../impl/DomainFactoryImpl.java | 3 +- ...stFarthestAheadWithSkippedMarkPassing.java | 3 +- ...mpleTimeOnTimeRankingWithOneUpwindLeg.java | 3 +- ...mpetitorProviderCacheInvalidationTest.java | 5 +- .../sap/sailing/domain/test/CourseTest.java | 4 +- ...pdateDuringNonAtomicSerializationTest.java | 3 +- .../test/LeaderboardCourseChangeTest.java | 2 +- .../LeaderboardScoringAndRankingTest.java | 15 ++++-- .../LeaderboardScoringAndRankingTestBase.java | 11 ++-- ...ecutionOrderProvdiderAttachDetachTest.java | 4 +- .../sailing/domain/test/ReachingLegTest.java | 3 +- ...ttaLogEventNotificationForwardingTest.java | 6 +-- .../test/SerializeRankingMetricTest.java | 4 +- .../sailing/domain/test/TrackBasedTest.java | 6 ++- .../domain/test/UpdateMarkPassingTest.java | 2 +- .../com/sap/sailing/domain/test/WindTest.java | 3 +- .../AbstractMockedRaceMarkPassingTest.java | 2 +- .../domain/test/mock/MockedTrackedRace.java | 5 ++ .../impl/DomainFactoryImpl.java | 3 +- .../sailing/domain/base/impl/RegattaImpl.java | 22 +++++--- .../impl/FlexibleLeaderboardImpl.java | 5 ++ .../regattalike/BaseRegattaLikeImpl.java | 7 ++- .../domain/regattalike/IsRegattaLike.java | 6 +++ .../ui/test/PingMarkViaRegattaLogTest.java | 3 +- .../adminconsole/CreateRegattaCallback.java | 2 +- .../adminconsole/RegattaDetailsComposite.java | 5 +- .../RegattaWithSeriesAndFleetsDialog.java | 9 ++++ .../RegattaWithSeriesAndFleetsEditDialog.java | 1 + .../sailing/gwt/ui/client/SailingService.java | 2 +- .../gwt/ui/client/SailingServiceAsync.java | 2 +- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../gwt/ui/server/SailingServiceImpl.java | 8 +-- .../sap/sailing/gwt/ui/shared/RegattaDTO.java | 2 + ...tStoringAndRetrievingRaceLogInRegatta.java | 3 +- ...estStoringAndLoadingEventsAndRegattas.java | 28 ++++++---- .../jaxrs/LeaderboardGroupResourceTest.java | 2 +- ...LeaderboardsResourceCheckinAndOutTest.java | 2 +- .../LeaderboardsResourcePingMarkTest.java | 2 +- .../test/jaxrs/LeaderboardsResourceTest.java | 2 +- .../test/jaxrs/RegattasResourceTest.java | 2 +- .../test/AbstractLogReplicationTest.java | 3 +- .../test/CompetitorReplicationTest.java | 2 +- ...tialLoadReplicationObjectIdentityTest.java | 2 +- .../test/RegattaReplicationTest.java | 28 ++++++---- .../server/test/MasterDataImportTest.java | 51 ++++++++++++------- .../server/test/RaceTrackerStartStopTest.java | 3 +- .../server/test/SearchServiceTest.java | 7 +-- .../sailing/server/RacingEventService.java | 4 +- .../server/impl/RacingEventServiceImpl.java | 14 ++--- .../AddSpecificRegatta.java | 6 ++- .../structureimport/StructureImporter.java | 3 +- 62 files changed, 243 insertions(+), 129 deletions(-) diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 5e1dcd49d65..f9352e50995 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -1151,8 +1151,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta.get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name()); final Boolean useStartTimeInference = (Boolean) dbRegatta.get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name()); final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta.get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name()); + Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); + // for backward compatibility + if(canBoatsOfCompetitorsChangePerRace == null) { + canBoatsOfCompetitorsChangePerRace = true; + } final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta); - result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, startDate, endDate, series, /* persistent */true, + result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true, loadScoringScheme(dbRegatta), id, courseArea, buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS : buoyZoneRadiusInHullLengths, useStartTimeInference == null ? true : useStartTimeInference, controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes, rankingMetricConstructor); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index 29be4a55816..8e5536c4bc6 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -37,6 +37,7 @@ public enum FieldNames { REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS, REGATTA_USE_START_TIME_INFERENCE, REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES, + REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE, SERIES_NAME, SERIES_IS_MEDAL, SERIES_IS_FLEETS_CAN_RUN_IN_PARALLEL, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index c3aa214d595..e167f77b9e1 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -654,6 +654,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbRegatta.put(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name(), regatta.getBuoyZoneRadiusInHullLengths()); dbRegatta.put(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name(), regatta.useStartTimeInference()); dbRegatta.put(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name(), regatta.isControlTrackingFromStartAndFinishTimes()); + dbRegatta.put(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name(), regatta.canBoatsOfCompetitorsChangePerRace()); dbRegatta.put(FieldNames.REGATTA_RANKING_METRIC.name(), storeRankingMetric(regatta)); regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index 8ecb5bc2114..26be8fb45fd 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -123,7 +123,7 @@ public class AbstractGPSFixStoreTest { protected DynamicTrackedRaceImpl createDynamicTrackedRace(BoatClass boatClass, RaceDefinition raceDefinition) { DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, - /* startDate */ null, /* endDate */null, null, null, "a", null)); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); return new DynamicTrackedRaceImpl(regatta, raceDefinition, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index fa6b0a6cc08..8a76fa48b6f 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -85,7 +85,8 @@ public class CreateAndTrackWithRaceLogTest { Series series = new SeriesImpl("series", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, Collections.singletonList(fleet), Collections.emptySet(), service); regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", - /* startDate */null, /* endDate */null, UUID.randomUUID(), Collections. singletonList(series), false, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + UUID.randomUUID(), Collections. singletonList(series), false, new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); series.addRaceColumn(columnName, /* trackedRegattaRegistry */null); leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {}); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java index f16e884d287..b9410a1440d 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java @@ -101,7 +101,7 @@ public class RaceLogFixTrackerManagerTest { RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, - /* startDate */ null, /* endDate */null, null, null, "a", null)); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index f9ccf1d7e4b..81f275c00df 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -153,7 +153,7 @@ public class SensorFixStoreAndLoadTest { RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, - /* startDate */ null, /* endDate */null, null, null, "a", null)); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, mock(RaceLogResolver.class)); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java index 5d883bd218a..b5cdb424e78 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java @@ -77,8 +77,8 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ - null, /* endDate */null, null, null, "a", null)); + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, @@ -143,8 +143,8 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { new WaypointImpl(mark2) })); RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ - null, /* endDate */null, null, null, "a", null)); + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, @@ -185,8 +185,8 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { new WaypointImpl(mark2) })); RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ - null, /* endDate */null, null, null, "a", null)); + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, @@ -230,8 +230,8 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { new WaypointImpl(mark2) })); RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ - null, /* endDate */null, null, null, "a", null)); + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, null, null, "a", null)); assertTrue(regatta.getRegatta().useStartTimeInference()); final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, @@ -338,8 +338,8 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { new WaypointImpl(mark2) })); RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); TrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* startDate */ - null, /* endDate */null, null, null, "a", null)); + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, null, null, "a", null)); final DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections. emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, diff --git a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SimpleDomainFactoryTest.java b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SimpleDomainFactoryTest.java index 3a01574a7e4..ac5e9530535 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SimpleDomainFactoryTest.java +++ b/java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/SimpleDomainFactoryTest.java @@ -109,7 +109,8 @@ public class SimpleDomainFactoryTest { public void testCourseConfigForMark() throws PatchFailedException { DomainFactory domainFactory = DomainFactory.INSTANCE; Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "TestEvent", - /* boatClass */ null, /*startDate*/ null, /*endDate*/ null, new RacingEventServiceImpl(), + /* boatClass */ null, /* canBoatsOfCompetitorsChangePerRace */ true, + /*startDate*/ null, /*endDate*/ null, new RacingEventServiceImpl(), com.sap.sailing.domain.base.DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null); Race race = new RaceImpl("1234", "R1", "Race 1234"); Iterable competitors = Collections.emptyList(); @@ -135,7 +136,8 @@ public class SimpleDomainFactoryTest { public void testCourseConfigForGate() throws PatchFailedException { DomainFactory domainFactory = DomainFactory.INSTANCE; Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - "TestEvent", /* boatClass */ null, /*startDate*/ null, /*endDate*/ null, new RacingEventServiceImpl(), + "TestEvent", /* boatClass */ null, /* canBoatsOfCompetitorsChangePerRace */ true, + /*startDate*/ null, /*endDate*/ null, new RacingEventServiceImpl(), com.sap.sailing.domain.base.DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null); Race race = new RaceImpl("1234", "R1", "Race 1234"); Iterable competitors = Collections.emptyList(); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 986b9b909df..3e4ff674e37 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -107,7 +107,8 @@ public class DomainFactoryImpl implements DomainFactory { Calendar calendar = Calendar.getInstance(); result = new RegattaImpl(raceLogStore, regattaLogStore, RegattaImpl.getDefaultName( "ST Regatta " + calendar.get(Calendar.YEAR) + " for race " + raceID, regattaBoatClass.getName()), - regattaBoatClass, /*startDate*/ null, /*endDate*/ null, trackedRegattaRegistry, getBaseDomainFactory().createScoringScheme( + regattaBoatClass, /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + trackedRegattaRegistry, getBaseDomainFactory().createScoringScheme( ScoringSchemeType.LOW_POINT), raceID, null); logger.info("Created regatta "+result.getName()+" ("+result.hashCode()+")"); raceIDToRegattaCache.put(raceID, result); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java index 1ffcd7ff250..07282b02af4 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java @@ -96,7 +96,8 @@ public class TestFarthestAheadWithSkippedMarkPassing { final TimePoint timePointForFixes = MillisecondsTimePoint.now(); BoatClassImpl boatClass = new BoatClassImpl("Some Handicap Boat Class", /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, + RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* courseArea */ null, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta); List waypoints = new ArrayList(); 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 3e3314e3a43..f91e21320d6 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 @@ -78,7 +78,8 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { final TimePoint timePointForFixes = MillisecondsTimePoint.now(); BoatClassImpl boatClass = new BoatClassImpl("Some Handicap Boat Class", /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, + RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* courseArea */ null, /* controlTrackingFromStartAndFinishTimes */ false, TimeOnTimeAndDistanceRankingMetric::new); TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta); List waypoints = new ArrayList(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index 1b2a504e273..620a6fc6bff 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -74,8 +74,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), courseArea); competitorProviderFlexibleLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(flexibleLeaderboard); regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl("49er", BoatClassMasterdata._49ER), /* startDate */ - null, /* endDate */null, /* trackedRegattaRegistry */null, new LowPoint(), UUID.randomUUID(), + EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl("49er", BoatClassMasterdata._49ER), + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, + /* trackedRegattaRegistry */null, new LowPoint(), UUID.randomUUID(), courseArea); regattaLeaderboard = new RegattaLeaderboardImpl(regatta, new ThresholdBasedResultDiscardingRuleImpl(new int[0])); regatta.addSeries(new SeriesImpl("Test Series", /* isMedal */false, /* isFleetsCanRunInParallel */ true, Arrays.asList(new FleetImpl("Yellow"), 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 4842e8bc283..7cad93b07da 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 @@ -308,7 +308,7 @@ public class CourseTest { final Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */new DynamicTrackedRegattaImpl( - new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), + new RegattaImpl("test", null, true, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */3000, /* millisecondsOverWhichToAverageWind */30000, @@ -342,7 +342,7 @@ public class CourseTest { final Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ new DynamicTrackedRegattaImpl( - new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), + new RegattaImpl("test", null, true, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), new RaceDefinitionImpl("Test Race", course, boatClass, competitorsAndBoats), Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 3000, /* millisecondsOverWhichToAverageWind */ 30000, 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 203e1a98b98..107bc2d3be2 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 @@ -76,7 +76,8 @@ public class CourseUpdateDuringNonAtomicSerializationTest implements Serializabl removeCalls = new HashMap<>(); course = new CourseImpl("Test Course", waypoints); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "Test Regatta", - new BoatClassImpl("505", BoatClassMasterdata._5O5), /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, + new BoatClassImpl("505", BoatClassMasterdata._5O5), + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, new LowPoint(), UUID.randomUUID(), new CourseAreaImpl("Alpha", UUID.randomUUID())); TrackedRegatta trackedRegatta = new TrackedRegattaImpl(regatta); RaceDefinition race = new RaceDefinitionImpl("Test Race", course, regatta.getBoatClass(), Collections.emptyMap()); 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 289cedf6e1f..1a62f3fa0f1 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 @@ -86,7 +86,7 @@ public class LeaderboardCourseChangeTest { RaceColumn raceColumn = series.addRaceColumn(raceColumnName, trackedRegattaRegistry); ScoringScheme scoringScheme = new LowPoint(); Regatta mockedRegatta = new RegattaImpl(RegattaImpl.getDefaultName("TestRegatta", boatClass.getName()), boatClass, - /*startDate*/ null, /*endDate*/ null, seriesSet, false, scoringScheme, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, seriesSet, false, scoringScheme, UUID.randomUUID(), mock(CourseArea.class), OneDesignRankingMetric::new); ControlPoint start = new MarkImpl("Start"); ControlPoint m1 = new MarkImpl("M1"); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index 5bcdb5ecfd1..4594c258e58 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -1336,7 +1336,8 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki public void testAdditionalScoreInformationLeadsToChangedScoreForOneColumn() throws NoWindException { TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class); Regatta dummyRegatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "Dummy", - new BoatClassImpl("Extreme40", false), /*startDate*/ null, /*endDate*/ null, trackedRegattaRegistry, + new BoatClassImpl("Extreme40", false), + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, trackedRegattaRegistry, new HighPointFirstGets10Or8AndLastBreaksTie(), "578876345345", new CourseAreaImpl("Humba", UUID.randomUUID())); trackedRegattaRegistry.getOrCreateTrackedRegatta(dummyRegatta); @@ -1908,7 +1909,8 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki series.add(finalSeries); } final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("Extreme40", /* typicallyStartsUpwind */ false); - Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT_FIRST_GETS_TEN), "123", /* course area */null, OneDesignRankingMetric::new); List competitors = createCompetitors(12); final int firstYellowCompetitorIndex = 3; @@ -2026,7 +2028,8 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki series.add(medalSeries); } final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true); - Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* course area */null, OneDesignRankingMetric::new); List competitors = createCompetitors(12); final int firstYellowCompetitorIndex = 3; @@ -2138,7 +2141,8 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki series.add(finalSeries); } final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true); - Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* course area */null, OneDesignRankingMetric::new); List competitors = createCompetitors(12); final int firstYellowCompetitorIndex = 3; @@ -2226,7 +2230,8 @@ public class LeaderboardScoringAndRankingTest extends LeaderboardScoringAndRanki series.add(finalSeries); } final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true); - Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* course area */null, OneDesignRankingMetric::new); final int TOTAL_NUMBER_OF_COMPETITORS = 100; List competitors = createCompetitors(TOTAL_NUMBER_OF_COMPETITORS); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java index 230fb300874..814e070b638 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTestBase.java @@ -125,8 +125,8 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes series.add(defaultSeries); Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, - /* startDate */null, /* endDate */null, series, /* persistent */false, scoringScheme, "123", null, - OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, series, + /* persistent */false, scoringScheme, "123", null, OneDesignRankingMetric::new); return regatta; } @@ -181,7 +181,8 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes } Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - /*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme, "123", null, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, + /* persistent */ false, scoringScheme, "123", null, OneDesignRankingMetric::new); return regatta; } @@ -226,8 +227,8 @@ public class LeaderboardScoringAndRankingTestBase extends AbstractLeaderboardTes } } Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - /*startDate*/ null, /*endDate*/ null, series, /* persistent */ false, scoringScheme, - /* ID */ "123", /* course area */ null, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, + /* persistent */ false, scoringScheme, /* ID */ "123", /* course area */ null, OneDesignRankingMetric::new); return regatta; } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java index 8b5657bd0da..3f0a7dc7d05 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java @@ -229,8 +229,8 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest raceColumnInSeries = series.addRaceColumn(RACECOLUMN_SERIES, null); ScoringScheme scoringScheme = new LowPoint(); regatta = new RegattaImpl(RegattaImpl.getDefaultName(REGATTA, boatClass.getName()), boatClass, - /* startDate */null, /* endDate */null, seriesSet, false, scoringScheme, UUID.randomUUID(), null, - OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + seriesSet, false, scoringScheme, UUID.randomUUID(), null, OneDesignRankingMetric::new); } /** 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 00632f9bf2f..d44e244d6e8 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 @@ -96,7 +96,8 @@ public class ReachingLegTest extends TrackBasedTest { Map competitorsAndBoats, TimePoint timePointForFixes) { BoatClassImpl boatClass = new BoatClassImpl(boatClassName, /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, + RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null); TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta); List waypoints = new ArrayList(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index 4ce14ad671b..d1b5b6255f7 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -115,7 +115,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa @Test public void testRegattaLeaderboardRegattaLogEventForwarding() { - Regatta regatta = new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new); + Regatta regatta = new RegattaImpl("test", null, true, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new); final RegattaLogEvent[] receivedRegattaLogEvent = new RegattaLogEvent[1]; regatta.addRaceColumnListener(new RaceColumnListenerWithDefaultAction() { private static final long serialVersionUID = -3835439531940986851L; @@ -136,7 +136,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa @Test public void testRegattaLeaderboardRegattaLogEventForwardingAfterRegattaDeserialization() throws ClassNotFoundException, IOException { - Regatta regatta = new RegattaImpl("test", null, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new); + Regatta regatta = new RegattaImpl("test", null, true, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new); Regatta deserializedRegatta = cloneBySerialization(regatta, DomainFactory.INSTANCE); final RegattaLogEvent[] receivedRegattaLogEvent = new RegattaLogEvent[1]; deserializedRegatta.addRaceColumnListener(new RaceColumnListenerWithDefaultAction() { @@ -181,7 +181,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa Series series = new SeriesImpl("Test Series", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, /* fleets */ Collections.singleton(new FleetImpl("Default")), Collections.singleton("R1"), /* trackedRegattaRegistry */ null); - Regatta regatta = new RegattaImpl("test", null, null, null, Collections.singleton(series), false, + Regatta regatta = new RegattaImpl("test", null, true, null, null, Collections.singleton(series), false, new LowPoint(), "test", null, OneDesignRankingMetric::new); return regatta; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java index ca0af2d4cfc..23eb3a1d2e0 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SerializeRankingMetricTest.java @@ -34,8 +34,8 @@ public class SerializeRankingMetricTest extends AbstractSerializationTest { final BoatClass _49er = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); final TrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl( new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "Regatta", /* boatClass */ _49er, - /* startDate */ null, /* endDate */ null, /* trackedRegattaRegistry */ null, - new LowPoint(), UUID.randomUUID(), /* courseArea */ null)), + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */ null, + /* trackedRegattaRegistry */ null, new LowPoint(), UUID.randomUUID(), /* courseArea */ null)), new RaceDefinitionImpl("Race", new CourseImpl("Course", Collections.emptyList()) , /* boatClass */ _49er, Collections.emptyMap()), Collections. emptyList(), EmptyWindStore.INSTANCE, 0l, 0l, 0l, 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 1daaa3f2724..a3170c9d05a 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 @@ -159,7 +159,8 @@ public abstract class TrackBasedTest { Map competitorsAndBoats, TimePoint timePointForFixes, boolean useMarkPassingCalculator, RaceLogResolver raceLogResolver) { BoatClassImpl boatClass = new BoatClassImpl(boatClassName, /* typicallyStartsUpwind */ true); Regatta regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, + RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null); TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta); List waypoints = new ArrayList(); @@ -209,7 +210,8 @@ public abstract class TrackBasedTest { TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class); Series series = new SeriesImpl("series name", isMedal, /* isFleetsCanRunInParallel */ true, regattaFleets, raceColumnNames, trackedRegattaRegistry); Iterable regattaSeries = Collections.singleton(series); - return new RegattaImpl(regattaName, boatClass, startDate, endDate, regattaSeries, persistent, scoringScheme, regatteId , courseArea, OneDesignRankingMetric::new); + return new RegattaImpl(regattaName, boatClass, /* canBoatsOfCompetitorsChangePerRace */ true, + startDate, endDate, regattaSeries, persistent, scoringScheme, regatteId , courseArea, OneDesignRankingMetric::new); } public static void assignRacesToRegattaLeaderboardColumns(RegattaLeaderboard leaderboard, Collection raceIdentifiers) { 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 9b2c3427171..02bea2cdc35 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 @@ -46,7 +46,7 @@ public class UpdateMarkPassingTest { when(race.getBoatClass()).thenReturn(new BoatClassImpl("49er", /* typicallyStartsUpwind */ true)); when(race.getCompetitors()).thenReturn(Collections.singleton(competitor)); DynamicTrackedRaceImpl trackedRace = new DynamicTrackedRaceImpl( - /* trackedRegatta */new DynamicTrackedRegattaImpl(new RegattaImpl("test", null, null, null, new HashSet(), false, null, + /* trackedRegatta */new DynamicTrackedRegattaImpl(new RegattaImpl("test", null, true, null, null, new HashSet(), false, null, "test", null, OneDesignRankingMetric::new)), race, Collections. emptyList(), EmptyWindStore.INSTANCE, /* delayToLiveInMillis */1000, /* millisecondsOverWhichToAverageWind */30000, 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 3911b2040a3..f92ae9abb89 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 @@ -286,7 +286,8 @@ public class WindTest { competitorsAndBoats.put(competitor, boat); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl( new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, domainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", null)), new RaceDefinitionImpl("Test Race", new CourseImpl("Test Course", Arrays.asList(new Waypoint[] { w1, w2, w3 })), 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 cf0a56d3050..6c7872091fb 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 @@ -72,7 +72,7 @@ public class AbstractMockedRaceMarkPassingTest { Waypoint w4 = new WaypointImpl(m, PassingInstruction.Starboard); Waypoint w5 = new WaypointImpl(cp, PassingInstruction.Line); waypoints = Arrays.asList(w1, w2, w3, w4, w5); - Regatta r = new RegattaImpl(RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + Regatta r = new RegattaImpl(RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, Arrays.asList(new SeriesImpl("Series", true, /* isFleetsCanRunInParallel */ true, Arrays.asList(new FleetImpl("fleet")), new ArrayList(), null)), true, new HighPoint(), "ID", new CourseAreaImpl("area", new UUID(5, 5)), OneDesignRankingMetric::new); Course course = new CourseImpl("course", waypoints); 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 9bdc1222e40..a3b0e4911b1 100644 --- 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 @@ -329,6 +329,11 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } + @Override + public boolean canBoatsOfCompetitorsChangePerRace() { + return false; + } + @Override public void addRace(RaceDefinition race) { } 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 4481d187e99..953bf894106 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 @@ -369,7 +369,8 @@ public class DomainFactoryImpl implements DomainFactory { // Then, there is no way but restart the server to get rid of this stale cache entry here. if (result == null) { result = new RegattaImpl(raceLogStore, regattaLogStore, RegattaImpl.getDefaultName( - defaultRegattaNameAndBoatClass.getA(), boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, + defaultRegattaNameAndBoatClass.getA(), boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, trackedRegattaRegistry, // use the low-point system as the default scoring scheme getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), race.getId(), null); 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 9d848c551cb..e1bd48e91b7 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 @@ -147,6 +147,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene */ private boolean controlTrackingFromStartAndFinishTimes; + private final boolean canBoatsOfCompetitorsChangePerRace; + /** * Defaults to true. See {@link Regatta#useStartTimeInference()}. */ @@ -160,10 +162,10 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene * Constructs a regatta with an empty {@link RaceLogStore} and with * {@link Regatta#isControlTrackingFromStartAndFinishTimes()} set to {@code false}. */ - public RegattaImpl(String name, BoatClass boatClass, TimePoint startDate, TimePoint endDate, + public RegattaImpl(String name, BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) { - this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, startDate, endDate, series, + this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, persistent, scoringScheme, id, courseArea, 0.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, rankingMetricConstructor); } @@ -181,9 +183,9 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene * carried out. */ public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, BoatClass boatClass, - TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry, + boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea) { - this(raceLogStore, regattaLogStore, name, boatClass, startDate, endDate, trackedRegattaRegistry, scoringScheme, + this(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, trackedRegattaRegistry, scoringScheme, id, courseArea, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); } @@ -198,10 +200,10 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene * carried out. */ public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, BoatClass boatClass, - TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry, + boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) { - this(raceLogStore, regattaLogStore, name, boatClass, startDate, endDate, Collections + this(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, Collections .singletonList(new SeriesImpl(LeaderboardNameConstants.DEFAULT_SERIES_NAME, /* isMedal */false, /* isFleetsCanRunInParallel */ true, Collections .singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)), @@ -216,7 +218,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene * this new regatta. */ public RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name, - BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable series, boolean persistent, + BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) { super(name); @@ -229,6 +231,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene regattaListeners = new HashSet(); raceColumnListeners = new RaceColumnListeners(); this.boatClass = boatClass; + this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace; this.startDate = startDate; this.endDate = endDate; final List seriesList = new ArrayList(); @@ -706,6 +709,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return useStartTimeInference; } + @Override + public boolean canBoatsOfCompetitorsChangePerRace() { + return canBoatsOfCompetitorsChangePerRace; + } + @Override public RegattaLog getRegattaLog() { return regattaLikeHelper.getRegattaLog(); 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 2ccdd8dfb56..23f86749cc7 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 @@ -366,4 +366,9 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements protected LeaderboardType getLeaderboardType() { return LeaderboardType.FlexibleLeaderboard; } + + @Override + public boolean canBoatsOfCompetitorsChangePerRace() { + return false; + } } 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 aa65fedcf79..6af52a166ce 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 @@ -60,7 +60,12 @@ public abstract class BaseRegattaLikeImpl implements IsRegattaLike { public void removeListener(RegattaLikeListener listener) { listeners.remove(listener); } - + + @Override + public boolean canBoatsOfCompetitorsChangePerRace() { + return false; + } + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); listeners = new HashSet<>(); 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 b7643151fd6..00ff5e42d8e 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 @@ -26,6 +26,12 @@ public interface IsRegattaLike extends Serializable { */ RegattaLog getRegattaLog(); + /** + * Indicates whether the competitors use the same boat for the whole regatta or change the boat used during the competition + * @return true when the competitors change their boats, false otherwise + */ + boolean canBoatsOfCompetitorsChangePerRace(); + RaceColumn getRaceColumnByName(String raceColumnName); RegattaLikeIdentifier getRegattaLikeIdentifier(); diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java index e15055ff800..464a6c921b1 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java @@ -39,7 +39,8 @@ public class PingMarkViaRegattaLogTest { service.getMongoObjectFactory().getDatabase().dropDatabase(); Series series = new SeriesImpl("series", false, /* isFleetsCanRunInParallel */ true, Collections.singletonList(fleet), Collections.singletonList(columnName), service); - Regatta regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", /*startDate*/ null, /*endDate*/ null, + Regatta regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Collections.singletonList(series), false, new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.ONE_DESIGN)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java index aeb4a68096c..f4f84e696df 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java @@ -64,7 +64,7 @@ public class CreateRegattaCallback implements DialogCallback{ seriesStructure.put(seriesDTO.getName(), seriesPair); } sailingService.createRegatta(newRegatta.getName(), newRegatta.boatClass==null?null:newRegatta.boatClass.getName(), - newRegatta.startDate, newRegatta.endDate, + newRegatta.canBoatsOfCompetitorsChangePerRace, newRegatta.startDate, newRegatta.endDate, new RegattaCreationParametersDTO(seriesStructure), true, newRegatta.scoringScheme, newRegatta.defaultCourseAreaUuid, newRegatta.buoyZoneRadiusInHullLengths, newRegatta.useStartTimeInference, newRegatta.controlTrackingFromStartAndFinishTimes, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java index 3888df7821e..81330db815f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java @@ -60,6 +60,7 @@ public class RegattaDetailsComposite extends Composite { private final Label defaultCourseArea; private final Label useStartTimeInference; private final Label controlTrackingFromStartAndFinishTimes; + private final Label canBoatsOfCompetitorsChangePerRace; private final Label configuration; private final Label buoyZoneRadiusInHullLengths; @@ -80,7 +81,7 @@ public class RegattaDetailsComposite extends Composite { VerticalPanel vPanel = new VerticalPanel(); mainPanel.add(vPanel); - int rows = 12; + int rows = 13; Grid grid = new Grid(rows, 2); vPanel.add(grid); @@ -93,6 +94,7 @@ public class RegattaDetailsComposite extends Composite { defaultCourseArea = createLabelAndValueWidget(grid, currentRow++, stringMessages.courseArea(), "CourseAreaLabel"); useStartTimeInference = createLabelAndValueWidget(grid, currentRow++, stringMessages.useStartTimeInference(), "UseStartTimeInferenceLabel"); controlTrackingFromStartAndFinishTimes = createLabelAndValueWidget(grid, currentRow++, stringMessages.controlTrackingFromStartAndFinishTimes(), "UseStartTimeInferenceLabel"); + canBoatsOfCompetitorsChangePerRace = createLabelAndValueWidget(grid, currentRow++, stringMessages.canBoatsOfCompetitorsChangePerRace(), "CanBoatsOfCompetitorsChangePerRaceLabel"); buoyZoneRadiusInHullLengths = createLabelAndValueWidget(grid, currentRow++, stringMessages.buoyZoneRadiusInHullLengths(), "BuoyZoneRadiusInHullLengthsLabel"); configuration = createLabelAndValueWidget(grid, currentRow++, stringMessages.racingProcedureConfiguration(), "RacingProcedureLabel"); scoringSystem = createLabelAndValueWidget(grid, currentRow++, stringMessages.scoringSystem(), "ScoringSystemLabel"); @@ -400,6 +402,7 @@ public class RegattaDetailsComposite extends Composite { defaultCourseArea.setText(regatta.defaultCourseAreaUuid == null ? "" : regatta.defaultCourseAreaName); useStartTimeInference.setText(regatta.useStartTimeInference ? stringMessages.yes() : stringMessages.no()); controlTrackingFromStartAndFinishTimes.setText(regatta.controlTrackingFromStartAndFinishTimes ? stringMessages.yes() : stringMessages.no()); + canBoatsOfCompetitorsChangePerRace.setText(regatta.canBoatsOfCompetitorsChangePerRace ? stringMessages.yes() : stringMessages.no()); buoyZoneRadiusInHullLengths.setText(String.valueOf(regatta.buoyZoneRadiusInHullLengths)); if (regatta.configuration != null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java index e3192b400f0..de9ce788096 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java @@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; +import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SuggestBox; @@ -20,6 +21,7 @@ import com.sap.sse.gwt.client.controls.listedit.ListEditorComposite; public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWithSeriesAndFleetsDialog { protected TextBox nameEntryField; protected SuggestBox boatClassEntryField; + protected CheckBox canBoatsOfCompetitorsChangePerRaceCheckBox; public RegattaWithSeriesAndFleetsDialog(RegattaDTO regatta, Iterable series, List existingEvents, EventDTO defaultEvent, String title, String okButton, StringMessages stringMessages, @@ -35,6 +37,9 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi if (regatta.boatClass != null) { boatClassEntryField.setText(regatta.boatClass.getName()); } + canBoatsOfCompetitorsChangePerRaceCheckBox = createCheckbox(""); + canBoatsOfCompetitorsChangePerRaceCheckBox.ensureDebugId("CanBoatsOfCompetitorsChangePerRaceCheckBox"); + canBoatsOfCompetitorsChangePerRaceCheckBox.setValue(regatta.canBoatsOfCompetitorsChangePerRace); } @Override @@ -49,16 +54,20 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi RegattaDTO result = getRegattaDTO(); result.setName(nameEntryField.getText().trim()); // trim to particularly avoid trailing blanks result.boatClass = new BoatClassDTO(boatClassEntryField.getText(), Distance.NULL); + result.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRaceCheckBox.getValue(); return result; } @Override protected void setupAdditionalWidgetsOnPanel(VerticalPanel panel, Grid formGrid) { + formGrid.insertRow(0); formGrid.insertRow(0); formGrid.insertRow(0); formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":")); formGrid.setWidget(0, 1, nameEntryField); formGrid.setWidget(1, 0, new Label(stringMessages.boatClass() + ":")); formGrid.setWidget(1, 1, boatClassEntryField); + formGrid.setWidget(2, 0, new Label(stringMessages.canBoatsOfCompetitorsChangePerRace() + ":")); + formGrid.setWidget(2, 1, canBoatsOfCompetitorsChangePerRaceCheckBox); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java index b6ea7c13731..889c2e0e7f4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java @@ -51,6 +51,7 @@ public class RegattaWithSeriesAndFleetsEditDialog extends RegattaWithSeriesAndFl nameEntryField.setEnabled(false); boatClassEntryField.setEnabled(false); + canBoatsOfCompetitorsChangePerRaceCheckBox.setEnabled(false); scoringSchemeListBox.setEnabled(false); sailingEventsListBox.setEnabled(true); courseAreaListBox.setEnabled(true); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 4363f9b251e..033d98dc11d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -217,7 +217,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS void moveLeaderboardColumnDown(String leaderboardName, String columnName); - RegattaDTO createRegatta(String regattaName, String boatClassName, Date startDate, Date endDate, + RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, Date startDate, Date endDate, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetrics rankingMetricType); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 68232142db5..b9a98d6d147 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -438,7 +438,7 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName, AsyncCallback callback); - void createRegatta(String regattaName, String boatClassName, Date startDate, Date endDate, + void createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, Date startDate, Date endDate, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetrics rankingMetricType, 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 c23c2692b61..0a3399e026f 100644 --- 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 @@ -1169,6 +1169,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String setTimeToNow(); String useStartTimeInference(); String controlTrackingFromStartAndFinishTimes(); + String canBoatsOfCompetitorsChangePerRace(); String numberOfQueueMessagesSent(); String totalSize(); String averageMessageSize(); 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 67d7492673c..3885c5c3d53 100644 --- 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 @@ -1142,6 +1142,7 @@ lastScoreCorrectionsComment=Last score correction comment setTimeToNow=Set time to ''now'' useStartTimeInference=Use start time inference from start mark passings controlTrackingFromStartAndFinishTimes=Control tracking from start and finish times +canBoatsOfCompetitorsChangePerRace=Can boats of competitors change per race numberOfQueueMessagesSent=Number of queue messages sent totalSize=Total Size averageMessageSize=Average size per message in bytes 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 ef791f7e1b0..062fcfc32e3 100644 --- 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 @@ -1133,6 +1133,7 @@ lastScoreCorrectionsComment=Letzter Kommentar der Punktzahl-Korrektur setTimeToNow=Setze den Zeitpunkt auf ''Jetzt'' useStartTimeInference=Startzeit aus Startlinienüberquerungen automatisch ableiten controlTrackingFromStartAndFinishTimes=Tracking durch Start- und Ende-Zeiten automatisch steuern +canBoatsOfCompetitorsChangePerRace=Das Boot des Teilnehmers kann sich pro Wettfahrt ändern numberOfQueueMessagesSent=Anzahl verschickter Queue Nachrichten totalSize=Gesamtgröße averageMessageSize=Durchschnittsgrösse einer Nachricht 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 2c20452135d..3c72cf051c2 100644 --- 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 @@ -895,6 +895,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S regattaDTO.buoyZoneRadiusInHullLengths = regatta.getBuoyZoneRadiusInHullLengths(); regattaDTO.useStartTimeInference = regatta.useStartTimeInference(); regattaDTO.controlTrackingFromStartAndFinishTimes = regatta.isControlTrackingFromStartAndFinishTimes(); + regattaDTO.canBoatsOfCompetitorsChangePerRace = regatta.canBoatsOfCompetitorsChangePerRace(); regattaDTO.configuration = convertToRegattaConfigurationDTO(regatta.getRegattaConfiguration()); regattaDTO.rankingMetricType = regatta.getRankingMetricType(); return regattaDTO; @@ -2884,6 +2885,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S regatta = getService().createRegatta( RegattaImpl.getDefaultName(replayRaceDTO.rsc, boatClass.trim()), boatClass.trim(), + /* canBoatsOfCompetitorsChangePerRace */ false, /* startDate*/ null, /*endDate*/ null, RegattaImpl.getDefaultName(replayRaceDTO.rsc, replayRaceDTO.boat_class), Collections.singletonList(new SeriesImpl(LeaderboardNameConstants.DEFAULT_SERIES_NAME, @@ -4102,7 +4104,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public RegattaDTO createRegatta(String regattaName, String boatClassName, Date startDate, Date endDate, + public RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, Date startDate, Date endDate, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetrics rankingMetricType) { @@ -4111,7 +4113,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; Regatta regatta = getService().apply( new AddSpecificRegatta( - regattaName, boatClassName, startTimePoint, endTimePoint, UUID.randomUUID(), + regattaName, boatClassName, canBoatsOfCompetitorsChangePerRace, startTimePoint, endTimePoint, UUID.randomUUID(), seriesNamesWithFleetNamesAndFleetOrderingAndMedal, persistent, baseDomainFactory.createScoringScheme(scoringSchemeType), defaultCourseAreaId, buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes, rankingMetricType)); @@ -4362,7 +4364,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private void createRegattaFromRegattaDTO(RegattaDTO regatta) { SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regatta.getName())); - this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.startDate, regatta.endDate, + this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.canBoatsOfCompetitorsChangePerRace, regatta.startDate, regatta.endDate, new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)), true, regatta.scoringScheme, regatta.defaultCourseAreaUuid, regatta.buoyZoneRadiusInHullLengths, regatta.useStartTimeInference, regatta.controlTrackingFromStartAndFinishTimes, regatta.rankingMetricType); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaDTO.java index 2b019f95b24..03de8ac8867 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaDTO.java @@ -36,6 +36,7 @@ public class RegattaDTO extends NamedDTO { public DeviceConfigurationDTO.RegattaConfigurationDTO configuration; public boolean useStartTimeInference = true; public boolean controlTrackingFromStartAndFinishTimes = false; + public boolean canBoatsOfCompetitorsChangePerRace = true; public RankingMetrics rankingMetricType; public Double buoyZoneRadiusInHullLengths; @@ -68,6 +69,7 @@ public class RegattaDTO extends NamedDTO { this.configuration = other.configuration; this.useStartTimeInference = other.useStartTimeInference; this.controlTrackingFromStartAndFinishTimes = other.controlTrackingFromStartAndFinishTimes; + this.canBoatsOfCompetitorsChangePerRace = other.canBoatsOfCompetitorsChangePerRace; this.buoyZoneRadiusInHullLengths = other.buoyZoneRadiusInHullLengths; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractTestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractTestStoringAndRetrievingRaceLogInRegatta.java index c1650c821cc..9232d8071bb 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractTestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/AbstractTestStoringAndRetrievingRaceLogInRegatta.java @@ -61,7 +61,8 @@ public abstract class AbstractTestStoringAndRetrievingRaceLogInRegatta extends R boolean persistent, ScoringScheme scoringScheme, CourseArea courseArea) { List series = createSeriesForTestRegatta(); Regatta regatta = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), RegattaImpl.getDefaultName(regattaBaseName, - boatClass == null ? null : boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, series, persistent, scoringScheme, "123", + boatClass == null ? null : boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, series, persistent, scoringScheme, "123", courseArea, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); return regatta; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index d956a341ac1..6f27e9444f5 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -215,7 +215,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final String regattaBaseName = "Kieler Woche"; BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); Regatta regatta = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), courseArea, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), courseArea, OneDesignRankingMetric::new); mof.storeRegatta(regatta); DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); @@ -407,9 +407,10 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final String regattaBaseName = "Kieler Woche"; BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); final String regattaName = regattaProxy.getName(); - Regatta regatta = res.createRegatta(regattaName, regattaProxy.getBoatClass().getName(), regattaStartDate, regattaEndDate, + Regatta regatta = res.createRegatta(regattaName, regattaProxy.getBoatClass().getName(), + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); @@ -450,8 +451,10 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final int numberOfFinalRaces = 7; final String regattaBaseName = "Kieler Woche"; - Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - Regatta regatta = res.createRegatta(regattaProxy.getName(), regattaProxy.getBoatClass().getName(), regattaProxy.getStartDate(), regattaProxy.getEndDate(), + Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + Regatta regatta = res.createRegatta(regattaProxy.getName(), regattaProxy.getBoatClass().getName(), + regattaProxy.canBoatsOfCompetitorsChangePerRace(), regattaProxy.getStartDate(), regattaProxy.getEndDate(), "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); trackedRegatta[0] = new DynamicTrackedRegattaImpl(regatta); addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); @@ -729,7 +732,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final String regattaBaseName = "Kieler Woche"; BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegatta(regattaName, boatClass, regattaStartDate, regattaEndDate, + Regatta regatta = createRegatta(regattaName, boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, /* persistent */ false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); mof.storeRegatta(regatta); @@ -785,8 +789,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest private Regatta createRegattaAndAddRaceColumns(final int numberOfQualifyingRaces, final int numberOfFinalRaces, final String regattaName, BoatClass boatClass, TimePoint startDate, TimePoint endDate, boolean persistent, ScoringScheme scoringScheme, RankingMetricConstructor rankingMetricConstructor) { - Regatta regatta = createRegatta(regattaName, boatClass, startDate, endDate, persistent, scoringScheme, null, - rankingMetricConstructor); + Regatta regatta = createRegatta(regattaName, boatClass, /* canBoatsOfCompetitorsChangePerRace */ true, + startDate, endDate, persistent, scoringScheme, null, rankingMetricConstructor); addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); return regatta; } @@ -807,7 +811,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest addRaceColumnsToSeries(medalRaceColumnNames, regatta.getSeriesByName("Medal")); } - private Regatta createRegatta(final String regattaName, BoatClass boatClass, TimePoint startDate, + private Regatta createRegatta(final String regattaName, BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, boolean persistent, ScoringScheme scoringScheme, CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) { List emptyRaceColumnNames = Collections.emptyList(); @@ -833,7 +837,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest medalFleets.add(new FleetImpl("Medal")); Series medalSeries = new SeriesImpl("Medal", /* isMedal */ true, /* isFleetsCanRunInParallel */ true, medalFleets, emptyRaceColumnNames, /* trackedRegattaRegistry */ null); series.add(medalSeries); - Regatta regatta = new RegattaImpl(regattaName, boatClass, startDate, endDate, series, persistent, scoringScheme, "123", courseArea, rankingMetricConstructor); + Regatta regatta = new RegattaImpl(regattaName, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, + series, persistent, scoringScheme, "123", courseArea, rankingMetricConstructor); return regatta; } @@ -847,7 +852,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest public void testRegattaRaceAssociationStore() throws Exception { BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("112er", /* typicallyStartsUpwind */ true); Regatta regatta = createRegatta(RegattaImpl.getDefaultName("Cologne Masters", boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, regattaStartDate, regattaEndDate, /* persistent */ true, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); Map competitorsAndBoats = new LinkedHashMap<>(); Competitor c = new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardGroupResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardGroupResourceTest.java index c0c5132937a..1d4bebd46f1 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardGroupResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardGroupResourceTest.java @@ -50,7 +50,7 @@ public class LeaderboardGroupResourceTest extends AbstractJaxRsApiTest { raceColumnNames, /* trackedRegattaRegistry */null); series.add(testSeries); regatta = racingEventService.createRegatta(RegattaImpl.getDefaultName(regattaName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /*persistent*/ true, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /*persistent*/ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); testSeries.addRaceColumn("R1", /* trackedRegattaRegistry */ null); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index c88e3076be0..469690a1bfd 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -49,7 +49,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), + Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), /* canBoatsOfCompetitorsChangePerRace */ true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, /* isFleetsCanRunInParallel */ true, Collections .singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false, new HighPoint(), 0, null, OneDesignRankingMetric::new); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourcePingMarkTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourcePingMarkTest.java index ce141bf47c3..10705706767 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourcePingMarkTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourcePingMarkTest.java @@ -61,7 +61,7 @@ public class LeaderboardsResourcePingMarkTest extends AbstractJaxRsApiTest { super.setUp(); mark = racingEventService.getBaseDomainFactory().getOrCreateMark("id", "name"); - Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), MillisecondsTimePoint.now(), + Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), /* canBoatsOfCompetitorsChangePerRace */ true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, /* isFleetsCanRunInParallel */ true, Collections .singleton(new FleetImpl("fleet")), Arrays.asList("column"), racingEventService)), false, new HighPoint(), 0, null, OneDesignRankingMetric::new); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceTest.java index 58f4d3e582c..61806efaa6c 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceTest.java @@ -57,7 +57,7 @@ public class LeaderboardsResourceTest extends AbstractJaxRsApiTest { raceColumnNames, /* trackedRegattaRegistry */null); series.add(testSeries); regatta = racingEventService.createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /*persistent*/ true, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /*persistent*/ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); testSeries.addRaceColumn("R1", /* trackedRegattaRegistry */ null); diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceTest.java index 99f46567a63..dd363517f30 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceTest.java @@ -48,7 +48,7 @@ public class RegattasResourceTest extends AbstractJaxRsApiTest { Series testSeries = new SeriesImpl("TestSeries", /* isMedal */false, /* isFleetsCanRunInParallel */ true, fleets, raceColumnNames, /* trackedRegattaRegistry */null); series.add(testSeries); racingEventService.createRegatta(RegattaImpl.getDefaultName(regattaName, boatClassName), boatClassName, - startDate, endDate, UUID.randomUUID(), series, /*persistent*/ true, + /* canBoatsOfCompetitorsChangePerRace */ true, startDate, endDate, UUID.randomUUID(), series, /*persistent*/ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); testSeries.addRaceColumn("R1", /* trackedRegattaRegistry */ null); testSeries.addRaceColumn("R2", /* trackedRegattaRegistry */ null); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java index fc6dd8c1197..7b8e6f76915 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/AbstractLogReplicationTest.java @@ -103,7 +103,8 @@ public abstract class AbstractLogReplicationTest series = Collections.emptyList(); Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, regattaId, series, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, regattaId, series, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); Iterable emptyWaypointList = Collections.emptyList(); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index bf29cc24a07..053ad36af0d 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -126,7 +126,7 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl final String boatClassName = "49er"; final Iterable series = Collections.emptyList(); Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric.CONSTRUCTOR); assertNotNull(master.getRegatta(masterRegatta.getRegattaIdentifier())); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java index 02bb785a886..60014a81a3d 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java @@ -45,8 +45,9 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { final Iterable series = Collections.emptyList(); final UUID regattaId = UUID.randomUUID(); Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, - /*startDate*/ null, /*endDate*/ null, regattaId, series, - /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, regattaId, series, + /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, + /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); Thread.sleep(1000); @@ -74,7 +75,8 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { UUID currentCourseAreaId = null; Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName("Kiel Week 2012", "49er"), "49er", - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Collections.emptyList(), + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + UUID.randomUUID(), Collections.emptyList(), /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), currentCourseAreaId, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); @@ -124,7 +126,9 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { master.addCourseAreas(event.getId(), new String[] {"TV"}, new UUID[] {tvCourseAreaId}); master.addCourseAreas(event.getId(), new String[] {"Golf"}, new UUID[] {golfCourseAreaId}); final String regattaName = RegattaImpl.getDefaultName("Kiel Week 2012", "49er"); - Regatta masterRegatta = master.createRegatta(regattaName, "49er", /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Collections.emptyList(), + Regatta masterRegatta = master.createRegatta(regattaName, "49er", + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + UUID.randomUUID(), Collections.emptyList(), /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), tvCourseAreaId, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event = master.getEvent(event.getId()); @@ -151,7 +155,9 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { master.addCourseAreas(event.getId(), new String[] {"Alpha"}, new UUID[] {alphaCourseAreaId}); UUID currentCourseAreaId = null; - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName("RR", "49er"), "49er", /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Collections.emptyList(), + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName("RR", "49er"), "49er", + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + UUID.randomUUID(), Collections.emptyList(), true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), currentCourseAreaId, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); @@ -198,7 +204,8 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { Arrays.asList(new Fleet[] { new FleetImpl("Gold", 1), new FleetImpl("Silver", 2) }), emptyRaceColumnNamesList, /* trackedRegattaRegistry */ null); Series medal = new SeriesImpl("Medal", /* isMedal */ true, /* isFleetsCanRunInParallel */ true, Arrays.asList(new Fleet[] { new FleetImpl("Medal") }), emptyRaceColumnNamesList, /* trackedRegattaRegistry */ null); - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Arrays.asList(new Series[] { qualification, finals, medal }), /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); Thread.sleep(1000); @@ -234,7 +241,8 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { final List emptyRaceColumnNamesList = Collections.emptyList(); Series qualification = new SeriesImpl("Qualification", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, Arrays.asList(new Fleet[] { new FleetImpl("Yellow"), new FleetImpl("Blue") }), emptyRaceColumnNamesList, /* trackedRegattaRegistry */ null); - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Arrays.asList(new Series[] { qualification }), /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); Thread.sleep(1000); @@ -278,7 +286,8 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { final List emptyRaceColumnNamesList = Collections.emptyList(); Series qualification = new SeriesImpl("Qualification", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, Arrays.asList(new Fleet[] { new FleetImpl("Yellow"), new FleetImpl("Blue") }), emptyRaceColumnNamesList, /* trackedRegattaRegistry */ null); - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClassName), boatClassName, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), Arrays.asList(new Series[] { qualification }), /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, @@ -316,7 +325,8 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { Event masterEvent = master.addEvent(eventName, /* eventDescription */ null, eventStartDate, eventEndDate, venueName, isPublic, UUID.randomUUID()); CourseArea masterCourseArea = master.addCourseAreas(masterEvent.getId(), new String[] {courseArea}, new UUID[] {UUID.randomUUID()})[0]; - Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(eventName, boatClassName), boatClassName, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, + Regatta masterRegatta = master.createRegatta(RegattaImpl.getDefaultName(eventName, boatClassName), boatClassName, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), series, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), masterCourseArea.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); Thread.sleep(1000); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index adfbd8ca5f1..520c58117d9 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -230,7 +230,7 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -522,7 +522,8 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -680,8 +681,9 @@ public class MasterDataImportTest { series.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, - /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -844,7 +846,8 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -1004,7 +1007,8 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -1117,8 +1121,9 @@ public class MasterDataImportTest { seriesNotToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsNotToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaNotToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, + regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regattaNotToOverride); for (String name : raceColumnNamesNotToOverride) { @@ -1206,7 +1211,8 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -1315,8 +1321,9 @@ public class MasterDataImportTest { seriesToOverride.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleetsToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, + regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regattaToOverride); for (String name : raceColumnNamesToOverride) { @@ -1425,7 +1432,8 @@ public class MasterDataImportTest { new UUID[] { UUID.randomUUID() })[0]; Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, UUID.randomUUID(), new ArrayList(), true, new LowPoint(), defaultCourseArea.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); // Let's use the setters directly because we are not testing replication @@ -1508,8 +1516,10 @@ public class MasterDataImportTest { Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), - defaultCourseArea.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), + defaultCourseArea.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, + /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); } @@ -1642,7 +1652,8 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -1886,7 +1897,7 @@ public class MasterDataImportTest { UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { @@ -2116,8 +2127,9 @@ public class MasterDataImportTest { seriesOnTarget.add(new SeriesImpl("testSeries", false, /* isFleetsCanRunInParallel */ true, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ - null, /* endDate */null, regattaUUID, seriesOnSource, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, + regattaUUID, seriesOnSource, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); for (String name : raceColumnNames) { seriesOnSource.get(0).addRaceColumn(name, sourceService); @@ -2245,7 +2257,8 @@ public class MasterDataImportTest { Regatta regattaOnTarget = destService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /* startDate */null, /* endDate */null, regattaUUID, seriesOnTarget, true, new LowPoint(), + /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */null, /* endDate */null, + regattaUUID, seriesOnTarget, true, new LowPoint(), courseAreaUUID, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java index b04779260ea..b674977589d 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java @@ -70,7 +70,8 @@ public class RaceTrackerStartStopTest { racingEventService = new RacingEventServiceImplMock(){}; boatClass = new BoatClassImpl(BOATCLASSNAME, /* typicallyStartsUpwind */ true); regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName(EVENTNAME, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ + RegattaImpl.getDefaultName(EVENTNAME, boatClass.getName()), boatClass, + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), UUID.randomUUID(), null); racingEventService.getRegattasByName().put(EVENTNAME, regatta); TrackedRegatta trackedRegatta1 = racingEventService.getOrCreateTrackedRegatta(regatta); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java index f252b863ca5..acdda0a43af 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java @@ -139,7 +139,7 @@ public class SearchServiceTest { /* medal */false, /* fleetsCanRunInParallel */ true, /* startsWithZero */false, /* firstColumnIsNonDiscardableCarryForward */false, /* discardingThresholds */null, /* hasSplitFleetContiguousScoring */false, /* maximumNumberOfDiscards */ null)); pfingstbusch29er = server.apply(new AddSpecificRegatta(RegattaImpl.getDefaultName("Pfingstbusch", "29er"), "29er", - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), new RegattaCreationParametersDTO(seriesCreationParams), /* persistent */ true, new LowPoint(), kielAlpha.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, RankingMetrics.ONE_DESIGN)); server.apply(new AddColumnToSeries(pfingstbusch29er.getRegattaIdentifier(), "Default", "R1")); @@ -148,7 +148,8 @@ public class SearchServiceTest { RegattaLeaderboard pfingstbusch29erLeaderboard = server.apply(new CreateRegattaLeaderboard(pfingstbusch29er.getRegattaIdentifier(), /* leaderboardDisplayName */ null, /* discardThresholds */ new int[0])); pfingstbusch470 = server.apply(new AddSpecificRegatta(RegattaImpl.getDefaultName("Pfingstbusch", "470"), "470", - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), new RegattaCreationParametersDTO(seriesCreationParams), /* persistent */ + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + UUID.randomUUID(), new RegattaCreationParametersDTO(seriesCreationParams), /* persistent */ true, new LowPoint(), kielBravo.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, RankingMetrics.ONE_DESIGN)); server.apply(new AddColumnToSeries(pfingstbusch470.getRegattaIdentifier(), "Default", "R1")); server.apply(new AddColumnToSeries(pfingstbusch470.getRegattaIdentifier(), "Default", "R2")); @@ -170,7 +171,7 @@ public class SearchServiceTest { final CourseAreaImpl flensburgStandard = new CourseAreaImpl("Standard", UUID.randomUUID()); flensburg.addCourseArea(flensburgStandard); aalRegatta = server.apply(new AddSpecificRegatta(RegattaImpl.getDefaultName("Aalregatta", "ORC"), "ORC", - /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), + /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, UUID.randomUUID(), new RegattaCreationParametersDTO(seriesCreationParams), /* persistent */ true, new LowPoint(), flensburgStandard.getId(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, RankingMetrics.ONE_DESIGN)); server.apply(new AddColumnToSeries(aalRegatta.getRegattaIdentifier(), "Default", "R1")); 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 8e8a5c4965c..90ca45964e5 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 @@ -313,7 +313,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch * @param series the series must not have any {@link RaceColumn}s yet * @param controlTrackingFromStartAndFinishTimes TODO */ - Regatta createRegatta(String regattaName, String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, + Regatta createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor); @@ -463,7 +463,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch * the call */ Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, String boatClassName, - TimePoint startDate, TimePoint endDate, Serializable id, + boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor); 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 be1feeff867..efd09e8911a 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 @@ -1217,7 +1217,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes Regatta result = regattasByName.get(name); if (result == null) { result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, getBaseDomainFactory() - .getOrCreateBoatClass(boatClassName), /* startDate */null, /* endDate */null, this, + .getOrCreateBoatClass(boatClassName), /* canBoatsOfCompetitorsChangePerRace*/ false, + /* startDate */null, /* endDate */null, this, getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), id, null); logger.info("Created default regatta " + result.getName() + " (" + hashCode() + ") on " + this); onRegattaLikeAdded(result); @@ -1236,12 +1237,12 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } @Override - public Regatta createRegatta(String fullRegattaName, String boatClassName, TimePoint startDate, TimePoint endDate, + public Regatta createRegatta(String fullRegattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) { com.sap.sse.common.Util.Pair regattaWithCreatedFlag = getOrCreateRegattaWithoutReplication( - fullRegattaName, boatClassName, startDate, endDate, id, series, persistent, scoringScheme, + fullRegattaName, boatClassName, canBoatsOfCompetitorsChangePerRace, startDate, endDate, id, series, persistent, scoringScheme, defaultCourseAreaId, buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes, rankingMetricConstructor); Regatta regatta = regattaWithCreatedFlag.getA(); if (regattaWithCreatedFlag.getB()) { @@ -1273,13 +1274,13 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes @Override public com.sap.sse.common.Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, - String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, + String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) { CourseArea courseArea = getCourseArea(defaultCourseAreaId); Regatta regatta = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), fullRegattaName, - getBaseDomainFactory().getOrCreateBoatClass(boatClassName), startDate, endDate, series, persistent, + getBaseDomainFactory().getOrCreateBoatClass(boatClassName), canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, persistent, scoringScheme, id, courseArea, buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes, rankingMetricConstructor); boolean wasCreated = addAndConnectRegatta(persistent, defaultCourseAreaId, regatta); if (wasCreated) { @@ -1459,7 +1460,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes courseAreaId = regatta.getDefaultCourseArea().getId(); } replicate(new AddSpecificRegatta(regatta.getName(), regatta.getBoatClass() == null ? null : regatta - .getBoatClass().getName(), regatta.getStartDate(), regatta.getEndDate(), regatta.getId(), + .getBoatClass().getName(), regatta.canBoatsOfCompetitorsChangePerRace(), + regatta.getStartDate(), regatta.getEndDate(), regatta.getId(), getSeriesWithoutRaceColumnsConstructionParametersAsMap(regatta), regatta.isPersistent(), regatta.getScoringScheme(), courseAreaId, regatta.getBuoyZoneRadiusInHullLengths(), regatta.useStartTimeInference(), regatta.isControlTrackingFromStartAndFinishTimes(), regatta.getRankingMetricType())); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AddSpecificRegatta.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AddSpecificRegatta.java index a1f9a123357..f4a837a8525 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AddSpecificRegatta.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AddSpecificRegatta.java @@ -32,13 +32,15 @@ public class AddSpecificRegatta extends AbstractAddRegattaOperation { private final Double buoyZoneRadiusInHullLengths; private final boolean useStartTimeInference; private final boolean controlTrackingFromStartAndFinishTimes; + private final boolean canBoatsOfCompetitorsChangePerRace; private final RankingMetrics rankingMetricType; - public AddSpecificRegatta(String regattaName, String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, + public AddSpecificRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, TimePoint startDate, TimePoint endDate, Serializable id, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds, boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, RankingMetrics rankingMetricType) { super(regattaName, boatClassName, startDate, endDate, id); + this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace; this.seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndStartsWithZeroScoreAndDiscardingThresholds = seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds; this.persistent = persistent; this.scoringScheme = scoringScheme; @@ -51,7 +53,7 @@ public class AddSpecificRegatta extends AbstractAddRegattaOperation { @Override public Regatta internalApplyTo(RacingEventService toState) throws Exception { - Regatta regatta = toState.createRegatta(getRegattaName(), getBoatClassName(), getStartDate(), getEndDate(), getId(), createSeries(toState), + Regatta regatta = toState.createRegatta(getRegattaName(), getBoatClassName(), canBoatsOfCompetitorsChangePerRace, getStartDate(), getEndDate(), getId(), createSeries(toState), persistent, scoringScheme, defaultCourseAreaId, buoyZoneRadiusInHullLengths, useStartTimeInference, controlTrackingFromStartAndFinishTimes, RankingMetricsFactory.getRankingMetricConstructor(rankingMetricType)); return regatta; } diff --git a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java index 8c395a0ee1d..a695bfbaddc 100755 --- a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java +++ b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java @@ -100,7 +100,8 @@ public class StructureImporter { final TimePoint endDate = null; // TODO can regatta end time be inferred from XRR document? RegattaImpl regatta = new RegattaImpl(RegattaImpl.getDefaultName(event.getTitle(), ((Division) event .getRaceOrDivisionOrRegattaSeriesResult().get(0)).getTitle()), - baseDomainFactory.getOrCreateBoatClass(result.getA().getBoatClass()), startDate, endDate, getSeries(buildStructure), false, + baseDomainFactory.getOrCreateBoatClass(result.getA().getBoatClass()), + /* canBoatsOfCompetitorsChangePerRace */ true, startDate, endDate, getSeries(buildStructure), false, this.baseDomainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT), event.getEventID(), null, OneDesignRankingMetric::new); addSpecificRegattas.add(regatta); } From fbd07215d38d184fff9c866a919a19d5c5b6a9f5 Mon Sep 17 00:00:00 2001 From: fmittag Date: Tue, 3 Jan 2017 13:05:35 +0100 Subject: [PATCH 019/271] added some simple load/store and replication tests for new 'canBoatsOfCompetitorsChangePerRace' attribute of regatta --- ...estStoringAndLoadingEventsAndRegattas.java | 36 +++++++++++++++++++ .../test/RegattaReplicationTest.java | 30 +++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 6f27e9444f5..67629cfc5db 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -670,6 +670,42 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest assertFalse(loadedRegatta.getSeriesByName("Medal").isFleetsCanRunInParallel()); } + @Test + public void testLoadStoreRegattaWithCompetitorsWhichCanChangeBoats() { + final boolean canBoatsOfCompetitorsChangePerRace = true; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegatta(regattaName, boatClass, canBoatsOfCompetitorsChangePerRace, + null, null, /* persistent */false, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertEquals(regattaName, loadedRegatta.getName()); + assertEquals(loadedRegatta.canBoatsOfCompetitorsChangePerRace(), canBoatsOfCompetitorsChangePerRace); + } + + @Test + public void testLoadStoreRegattaWithCompetitorsWhichCanNotChangeBoats() { + final boolean canBoatsOfCompetitorsChangePerRace = false; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegatta(regattaName, boatClass, canBoatsOfCompetitorsChangePerRace, + null, null, /* persistent */false, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertEquals(regattaName, loadedRegatta.getName()); + assertEquals(loadedRegatta.canBoatsOfCompetitorsChangePerRace(), canBoatsOfCompetitorsChangePerRace); + } + @Test public void testLoadStoreSimpleRegattaWithHighPointScoringScheme() { final int numberOfQualifyingRaces = 5; diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java index 60014a81a3d..97f6e7492d5 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaReplicationTest.java @@ -59,7 +59,35 @@ public class RegattaReplicationTest extends AbstractServerReplicationTest { assertTrue(regattaId.equals(replicatedRegatta.getId())); assertNull(replicatedRegatta.getRegattaConfiguration()); } - + + @Test + public void testSpecificRegattaReplicationWithDifferentBoatsOfCompetitorsCanChangePerRaceSettings() throws InterruptedException { + final String baseEventName = "Kiel Week 2012"; + final String boatClass1Name = "49er"; + final String boatClass2Name = "49erFX"; + final boolean canBoatsOfCompetitorsChangePerRaceRegatta1 = true; + final boolean canBoatsOfCompetitorsChangePerRaceRegatta2 = false; + final Iterable series = Collections.emptyList(); + final UUID regattaId = UUID.randomUUID(); + Regatta masterRegatta1 = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClass1Name), boatClass1Name, + canBoatsOfCompetitorsChangePerRaceRegatta1, /*startDate*/ null, /*endDate*/ null, regattaId, series, + /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, + /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); + Regatta masterRegatta2 = master.createRegatta(RegattaImpl.getDefaultName(baseEventName, boatClass2Name), boatClass2Name, + canBoatsOfCompetitorsChangePerRaceRegatta2, /*startDate*/ null, /*endDate*/ null, regattaId, series, + /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, + /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); + + Thread.sleep(1000); + + Regatta replicatedRegatta1 = replica.getRegatta(new RegattaName(masterRegatta1.getName())); + assertNotNull(replicatedRegatta1); + assertEquals(replicatedRegatta1.canBoatsOfCompetitorsChangePerRace(), canBoatsOfCompetitorsChangePerRaceRegatta1); + Regatta replicatedRegatta2 = replica.getRegatta(new RegattaName(masterRegatta2.getName())); + assertNotNull(replicatedRegatta2); + assertEquals(replicatedRegatta2.canBoatsOfCompetitorsChangePerRace(), canBoatsOfCompetitorsChangePerRaceRegatta2); + } + @Test public void testUpdateSpecificRegattaReplicationForCourseArea() throws InterruptedException { Regatta replicatedRegatta; From 637786c106d5dffec9ed659c5e4dff8d9479d8ab Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 8 Mar 2017 16:27:39 -0300 Subject: [PATCH 020/271] fixed some compile errors after last master merge --- .../com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java | 2 +- .../test/RaceLogConnectivityParamsLoadAndStoreTest.java | 2 +- .../com/sap/sailing/server/test/RemoveLeaderboardTest.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java index 8b2d7f42a44..3edea0107f5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java @@ -121,7 +121,7 @@ public class BoatEditDialog extends DataEntryDialog { color = new InvalidColor(iae); } } - BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), Distance.NULL); + BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), Distance.NULL, Distance.NULL); BoatDTO boat = new BoatDTO(boatToEdit.getIdAsString(), name.getText(), boatClass, sailId.getText(), color); return boat; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java index e910cea8b78..29a0693f869 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java @@ -49,7 +49,7 @@ public class RaceLogConnectivityParamsLoadAndStoreTest extends AbstractConnectiv final SeriesImpl theSeries = new SeriesImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, Arrays.asList(fleet), Collections.emptyList(), racingEventService); final Iterable series = Arrays.asList(theSeries); - final Regatta regatta = racingEventService.createRegatta("My Regatta", "12mR", MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus(Duration.ONE_DAY), + final Regatta regatta = racingEventService.createRegatta("My Regatta", "12mR", true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus(Duration.ONE_DAY), UUID.randomUUID(), series, /* persistent */ true, new LowPoint(), new CourseAreaImpl("Default", UUID.randomUUID()), /* buoyZoneRadiusInHullLengths */ 2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ true, OneDesignRankingMetric::new); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RemoveLeaderboardTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RemoveLeaderboardTest.java index 96112e72802..61dab1c7173 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RemoveLeaderboardTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RemoveLeaderboardTest.java @@ -18,7 +18,6 @@ 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.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Fleet; @@ -89,14 +88,15 @@ public class RemoveLeaderboardTest { boatClass = new BoatClassImpl(BOATCLASSNAME, /* typicallyStartsUpwind */ true); regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - RegattaImpl.getDefaultName(EVENTNAME, boatClass.getName()), boatClass, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ + RegattaImpl.getDefaultName(EVENTNAME, boatClass.getName()), boatClass, /* canBoatsOfCompetitorsChangePerRace*/ true, + /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), UUID.randomUUID(), null); TrackedRegatta trackedRegatta1 = server.getOrCreateTrackedRegatta(regatta); defaultFleet = new FleetImpl("Default"); regatta.addSeries(new SeriesImpl(SERIES_NAME, /* is medal */ false, /* can fleets run in parallel */ true, Collections.singleton(defaultFleet), Collections.singleton(R1), /* regatta registry */ server)); - raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList()), boatClass, new ArrayList()); + raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList()), boatClass, new HashMap<>()); regatta.addRace(raceDef1); trackedRace = trackedRegatta1.createTrackedRace(raceDef1, Collections. emptyList(), /* windStore */ EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 0l, From ac19dfef7e700a98fe58da82c895b42c21727979 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 13 Mar 2017 14:18:44 -0300 Subject: [PATCH 021/271] added selenium test case for boat creation --- .../mock/MockedTrackedRaceWithFixedRank.java | 5 ++ ...edRaceWithFixedRankAndManyCompetitors.java | 5 ++ .../sailing/domain/base/RaceDefinition.java | 3 + .../domain/base/impl/RaceDefinitionImpl.java | 5 ++ .../DummyMarkPassingWithTimePointOnly.java | 1 - ...java => TrackedRacesBoatEditDialogPO.java} | 82 +++++++++---------- .../tracking/TrackedRacesBoatTablePO.java | 64 +++++++++++++++ .../tracking/TrackedRacesBoatsPanelPO.java | 22 +++++ .../test/adminconsole/TestBoatCreation.java | 60 ++++++++++++++ 9 files changed, 205 insertions(+), 42 deletions(-) rename java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/{TrackedRacesCompetitorCreateDialogPO.java => TrackedRacesBoatEditDialogPO.java} (85%) create mode 100644 java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatTablePO.java create mode 100644 java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestBoatCreation.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java index b3fbb339f7c..6511d289a69 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java @@ -67,6 +67,11 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { return MockedTrackedRaceWithFixedRank.this.competitorsAndBoats.values(); } + @Override + public Map getCompetitorsAndTheirBoats() { + return MockedTrackedRaceWithFixedRank.this.competitorsAndBoats; + } + @Override public BoatClass getBoatClass() { return boatClass; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java index 54b0cedbf42..85f8f41b578 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; +import java.util.Map; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; @@ -33,6 +34,10 @@ public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrac return competitorsAndBoats.values(); } @Override + public Map getCompetitorsAndTheirBoats() { + return competitorsAndBoats; + } + @Override public Competitor getCompetitorById(Serializable competitorID) { for (Competitor competitor : competitorsAndBoats.keySet()) { if (competitorID.equals(competitor.getId())) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java index b40d9056934..6258d3bb9e1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.base; import java.io.Serializable; +import java.util.Map; import com.sap.sailing.domain.common.RaceCompetitorIdsAsStringWithMD5Hash; import com.sap.sse.common.NamedWithID; @@ -28,6 +29,8 @@ public interface RaceDefinition extends NamedWithID { Competitor getCompetitorById(Serializable competitorID); + Map getCompetitorsAndTheirBoats(); + /** * Gets the boat used by the competitor for this race. */ diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java index d41a14d80fa..02842fe6ac7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java @@ -84,6 +84,11 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { return Collections.unmodifiableCollection(competitorsAndTheirBoats.values()); } + @Override + public Map getCompetitorsAndTheirBoats() { + return Collections.unmodifiableMap(competitorsAndTheirBoats); + } + @Override public byte[] getCompetitorMD5() { return raceCompetitorsMD5Hash.getMd5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java index 98ccd4dc139..4a3e38f1fa9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java @@ -62,7 +62,6 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing { public Boat getBoat() { return null; } - @Override public IsManagedByCache resolve(SharedDomainFactory domainFactory) { return this; diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatEditDialogPO.java similarity index 85% rename from java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java rename to java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatEditDialogPO.java index b7b4f317153..dfe7c012281 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatEditDialogPO.java @@ -1,41 +1,41 @@ -package com.sap.sailing.selenium.pages.adminconsole.tracking; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import com.sap.sailing.selenium.core.BySeleniumId; -import com.sap.sailing.selenium.core.FindBy; -import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; - -public class TrackedRacesCompetitorCreateDialogPO extends DataEntryDialogPO { - @FindBy(how = BySeleniumId.class, using = "NameTextBox") - private WebElement nameTextBox; - - @FindBy(how = BySeleniumId.class, using = "SailIdTextBox") - private WebElement sailIdTextBox; - - @FindBy(how = BySeleniumId.class, using = "BoatClassNameSuggestBox") - private WebElement boatClassNameSuggestBox; - - @FindBy(how = BySeleniumId.class, using = "OkButton") - private WebElement okButton; - - public TrackedRacesCompetitorCreateDialogPO(WebDriver driver, WebElement element) { - super(driver, element); - } - - public void setNameTextBox(String name) { - this.nameTextBox.clear(); - this.nameTextBox.sendKeys(name); - } - - public void setSailIdTextBox(String sailId) { - this.sailIdTextBox.clear(); - this.sailIdTextBox.sendKeys(sailId); - } - - public void setBoatClassNameSuggestBox(String boatClassName) { - this.boatClassNameSuggestBox.clear(); - this.boatClassNameSuggestBox.sendKeys(boatClassName); - } -} +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; + +public class TrackedRacesBoatEditDialogPO extends DataEntryDialogPO { + @FindBy(how = BySeleniumId.class, using = "NameTextBox") + private WebElement nameTextBox; + + @FindBy(how = BySeleniumId.class, using = "SailIdTextBox") + private WebElement sailIdTextBox; + + @FindBy(how = BySeleniumId.class, using = "BoatClassNameSuggestBox") + private WebElement boatClassNameSuggestBox; + + @FindBy(how = BySeleniumId.class, using = "OkButton") + private WebElement okButton; + + public TrackedRacesBoatEditDialogPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + public void setNameTextBox(String name) { + this.nameTextBox.clear(); + this.nameTextBox.sendKeys(name); + } + + public void setSailIdTextBox(String sailId) { + this.sailIdTextBox.clear(); + this.sailIdTextBox.sendKeys(sailId); + } + + public void setBoatClassNameSuggestBox(String boatClassName) { + this.boatClassNameSuggestBox.clear(); + this.boatClassNameSuggestBox.sendKeys(boatClassName); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatTablePO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatTablePO.java new file mode 100644 index 00000000000..df47b722041 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatTablePO.java @@ -0,0 +1,64 @@ +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.pages.gwt.CellTablePO; +import com.sap.sailing.selenium.pages.gwt.DataEntryPO; +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.adminconsole.ActionsHelper; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesBoatTablePO.BoatEntry; + +public class TrackedRacesBoatTablePO extends CellTablePO { + public static class BoatEntry extends DataEntryPO { + @FindBy(how = BySeleniumId.class, using = "ACTION_EDIT") + private WebElement editButton; + + private static final String NAME_COLUMN = "Name"; + private static final String SAILID_COLUMN = "Sail number"; + private static final String BOATCLASSNAME_COLUMN = "Boat Class"; + private static final String ID_COLUMN = "ID"; + + protected BoatEntry(TrackedRacesBoatTablePO table, WebElement element) { + super(table, element); + } + + @Override + public String getIdentifier() { + return getId(); + } + + public String getId() { + return getColumnContent(ID_COLUMN); + } + + public String getName() { + return getColumnContent(NAME_COLUMN); + } + + public String getSailId() { + return getColumnContent(SAILID_COLUMN); + } + + public String getBoatClassName() { + return getColumnContent(BOATCLASSNAME_COLUMN); + } + + public TrackedRacesCompetitorEditDialogPO clickEditButton() { + WebElement action = ActionsHelper.findEditAction(getWebElement()); + action.click(); + WebElement dialog = findElementBySeleniumId(this.driver, "BoatEditDialog"); + return new TrackedRacesCompetitorEditDialogPO(this.driver, dialog); + } + } + + public TrackedRacesBoatTablePO(WebDriver driver, WebElement element) { + super(driver, element); + } + + @Override + protected BoatEntry createDataEntry(WebElement element) { + return new BoatEntry(this, element); + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java index 4aa31add0d1..d100ef1c056 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java @@ -8,6 +8,12 @@ import com.sap.sailing.selenium.core.FindBy; import com.sap.sailing.selenium.pages.PageArea; public class TrackedRacesBoatsPanelPO extends PageArea { + @FindBy(how = BySeleniumId.class, using = "RefreshButton") + private WebElement refreshButton; + + @FindBy(how = BySeleniumId.class, using = "AddBoatButton") + private WebElement addButton; + @FindBy(how = BySeleniumId.class, using = "BoatsTable") private WebElement boatsTable; @@ -17,4 +23,20 @@ public class TrackedRacesBoatsPanelPO extends PageArea { super(driver, element); this.driver = driver; } + + public TrackedRacesBoatEditDialogPO pushAddButton() { + this.addButton.click(); + waitForAjaxRequests(); + WebElement dialog = findElementBySeleniumId(this.driver, "BoatEditDialog"); + return new TrackedRacesBoatEditDialogPO(this.driver, dialog); + } + + public void pushRefreshButton() { + this.refreshButton.click(); + waitForAjaxRequests(); + } + + public TrackedRacesBoatTablePO getBoatsTable() { + return new TrackedRacesBoatTablePO(this.driver, this.boatsTable); + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestBoatCreation.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestBoatCreation.java new file mode 100644 index 00000000000..012ed850ffb --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestBoatCreation.java @@ -0,0 +1,60 @@ +package com.sap.sailing.selenium.test.adminconsole; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesBoatEditDialogPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesBoatTablePO.BoatEntry; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesBoatsPanelPO; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; + +public class TestBoatCreation extends AbstractSeleniumTest { + @Override + @Before + public void setUp() { + clearState(getContextRoot()); + super.setUp(); + } + + @Test + public void testOpenCreateBoatDialog() { + final TrackedRacesBoatsPanelPO competitorsPanel = goToBoatsPanel(); + final TrackedRacesBoatEditDialogPO dialog = competitorsPanel.pushAddButton(); // fails with an exception if the dialog is not found + assertNotNull(dialog); + } + + private TrackedRacesBoatsPanelPO goToBoatsPanel() { + final AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + final TrackedRacesBoatsPanelPO boatsPanel = adminConsole.goToTrackedRacesBoats(); + return boatsPanel; + } + + @Test + public void testBoatCreation() { + final TrackedRacesBoatsPanelPO boatsPanel = goToBoatsPanel(); + final TrackedRacesBoatEditDialogPO dialog = boatsPanel.pushAddButton(); + final String name = ""+System.currentTimeMillis(); + dialog.setNameTextBox(name); + String sailId = ""+System.currentTimeMillis(); + dialog.setSailIdTextBox(sailId); + final String boatClassName = "49er"; + dialog.setBoatClassNameSuggestBox(boatClassName); + dialog.pressOk(); + boolean found = false; + for (final BoatEntry it : boatsPanel.getBoatsTable().getEntries()) { + String itName = it.getName(); + if (itName.equals(name)) { + found = true; + // found a candidate: + assertEquals(sailId, it.getSailId()); + assertEquals(boatClassName, it.getBoatClassName()); + } + } + assertTrue(found); + } +} From fd8fee5d58e7a9da7a5489b56498de9a9380f4ef Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Fri, 28 Apr 2017 09:08:00 +0200 Subject: [PATCH 022/271] work commit in the middle of refactoring competitor.getBoat() --- .../tracking/impl/BoatJsonConstants.java | 14 ++ .../impl/DomainObjectFactoryImpl.java | 6 +- .../impl/MongoObjectFactoryImpl.java | 3 +- .../test/AbstractGPSFixStoreTest.java | 2 +- .../impl/CreateAndTrackWithRaceLogTest.java | 4 +- .../impl/RaceLogFixTrackerManagerTest.java | 2 +- .../test/impl/SensorFixStoreAndLoadTest.java | 6 +- .../test/impl/TrackedRaceLoadsFixesTest.java | 2 +- .../TrackedRaceStartTimeInferenceTest.java | 10 +- .../impl/RaceLogRaceTracker.java | 17 +- .../impl/RaceLogTrackingAdapterImpl.java | 7 +- .../test/CompetitorDeregistrationTest.java | 4 +- .../test/DeviceMappingFinderTest.java | 4 +- .../sap/sailing/domain/base/Competitor.java | 3 - .../domain/base/CompetitorAndBoat.java | 13 ++ .../domain/base/CompetitorChangeListener.java | 2 +- .../domain/base/CompetitorFactory.java | 2 +- .../sailing/domain/base/CompetitorStore.java | 2 +- .../domain/base/CompetitorWithBoat.java | 22 +- .../base/impl/CompetitorAndBoatImpl.java | 26 +++ .../domain/base/impl/CompetitorImpl.java | 13 +- .../base/impl/CompetitorWithBoatImpl.java | 53 ++--- .../domain/base/impl/DynamicCompetitor.java | 2 - .../base/impl/SharedDomainFactoryImpl.java | 4 +- .../impl/TransientCompetitorStoreImpl.java | 13 +- .../impl/DomainFactoryImpl.java | 8 +- .../SwissTimingReplayAdapterServiceTest.java | 10 +- .../impl/CandidateFinderImplWhiteBoxTest.java | 4 +- ...stFarthestAheadWithSkippedMarkPassing.java | 6 +- ...mpleTimeOnTimeRankingWithOneUpwindLeg.java | 6 +- .../domain/test/AbstractLeaderboardTest.java | 27 ++- .../domain/test/CompetitorListenerTest.java | 31 --- .../sap/sailing/domain/test/CourseTest.java | 6 +- ...eInvalidationAfterLoadingFinishedTest.java | 4 +- .../test/LeaderboardCourseChangeTest.java | 3 +- .../domain/test/LeaderboardOfflineTest.java | 20 +- .../sailing/domain/test/LineAnalysisTest.java | 4 +- .../domain/test/OfflineSerializationTest.java | 4 +- .../sailing/domain/test/ReachingLegTest.java | 8 +- .../domain/test/StoredTrackBasedTest.java | 30 +-- .../com/sap/sailing/domain/test/TackTest.java | 4 +- .../sailing/domain/test/TrackBasedTest.java | 16 +- ...rtTimeUpdateForDependentStartTimeTest.java | 4 +- .../domain/test/UpdateMarkPassingTest.java | 4 +- ...WindEstimationOnConstructedTracksTest.java | 10 +- .../com/sap/sailing/domain/test/WindTest.java | 4 +- .../AbstractMockedRaceMarkPassingTest.java | 6 +- .../domain/test/mock/MockedTrackedRace.java | 5 + .../mock/MockedTrackedRaceWithFixedRank.java | 6 +- ...edRaceWithFixedRankAndManyCompetitors.java | 6 +- ...ockedTrackedRaceWithStartTimeAndRanks.java | 5 + .../impl/BravoFixTrackSerializationTest.java | 4 +- .../impl/DomainFactoryImpl.java | 7 +- .../sap/sailing/domain/base/RaceColumn.java | 17 ++ .../domain/base/impl/AbstractRaceColumn.java | 28 +++ .../base/impl/DynamicCompetitorStore.java | 2 +- .../domain/leaderboard/Leaderboard.java | 9 +- .../leaderboard/LeaderboardCacheManager.java | 5 - .../impl/AbstractLeaderboardImpl.java | 8 + .../impl/AbstractSimpleLeaderboardImpl.java | 2 + .../impl/FlexibleLeaderboardImpl.java | 2 + .../impl/RegattaLeaderboardImpl.java | 1 + .../meta/AbstractMetaLeaderboard.java | 8 +- .../domain/ranking/AbstractRankingMetric.java | 2 +- .../tracking/TrackedLegOfCompetitor.java | 3 + .../sailing/domain/tracking/TrackedRace.java | 3 + .../impl/AbstractRaceRankComparator.java | 2 +- .../DummyMarkPassingWithTimePointOnly.java | 5 - .../domain/tracking/impl/TrackedLegImpl.java | 2 +- .../impl/TrackedLegOfCompetitorImpl.java | 16 +- .../domain/tracking/impl/TrackedRaceImpl.java | 8 +- .../gwt/ui/test/MockedTrackedRace.java | 6 + .../gwt/ui/server/SailingServiceImpl.java | 18 +- .../StoreAndLoadDeviceIdentifierTest.java | 2 +- .../test/StoreAndLoadRaceLogEventsTest.java | 2 +- .../mongodb/test/StoreGPSFixTrackTest.java | 2 +- ...estStoringAndLoadingEventsAndRegattas.java | 6 +- ...StoringAndRetrievingLeaderboardGroups.java | 26 +-- .../TestStoringAndRetrievingLeaderboards.java | 34 +-- ...ingAndRetrievingRaceLogInLeaderboards.java | 6 +- ...tStoringAndRetrievingRaceLogInRegatta.java | 4 +- ...EstimationFromManeuversOnAFew505Races.java | 4 +- .../ManeuverBasedWindEstimationTrackImpl.java | 31 ++- ...onToHasConfidenceAndIsScalableAdapter.java | 2 +- .../impl/CompetitorJsonDeserializer.java | 193 +++++++++--------- .../CompetitorWithBoatJsonDeserializer.java | 105 ++++++++++ .../impl/CompetitorJsonSerializer.java | 174 ++++++++-------- .../CompetitorWithBoatJsonSerializer.java | 39 ++++ ...ourseDesignChangedEventSerializerTest.java | 4 +- .../racelog/RaceLogEventSerializerTest.java | 2 +- ...sitioningConfirmedEventSerializerTest.java | 4 +- .../RaceLogWindFixEventSerializerTest.java | 4 +- .../TrackingTimesEventSerializerTest.java | 5 +- ...petitorWithChangingBoatJsonSerializer.java | 49 ----- .../impl/ManeuversJsonSerializer.java | 14 +- .../impl/MarkPassingsJsonSerializer.java | 12 +- .../impl/RaceEntriesJsonSerializer.java | 18 +- .../gateway/test/AbstractJsonExportTest.java | 8 +- .../test/jaxrs/AbstractJaxRsApiTest.java | 8 +- .../CompetitorsResourceTeamImageTest.java | 8 +- .../test/jaxrs/CompetitorsResourceTest.java | 6 +- ...LeaderboardsResourceCheckinAndOutTest.java | 3 +- .../impl/rc/CompetitorsJsonExportServlet.java | 8 +- .../gateway/jaxrs/api/BoatsResource.java | 47 +++++ .../jaxrs/api/CompetitorsResource.java | 5 +- .../jaxrs/api/LeaderboardsResource.java | 5 +- .../gateway/jaxrs/api/RegattasResource.java | 27 ++- .../test/CompetitorReplicationTest.java | 12 +- ...LeaderboardCorrectionsReplicationTest.java | 4 +- ...tialLoadReplicationObjectIdentityTest.java | 4 +- .../test/RegattaLogReplicationTest.java | 4 +- ...BoatCompetitorMetadataReplicationTest.java | 3 +- .../TrackedRaceContentsReplicationTest.java | 2 - ...ithGPSFixStoreContentsReplicationTest.java | 2 - .../test/ApplyScoresFromRaceLogTest.java | 5 +- .../server/test/CompetitorStoreTest.java | 14 +- .../test/LeaderboardDiscardingRulesTest.java | 16 +- .../server/test/LeaderboardStorageTest.java | 9 +- .../server/test/MasterDataImportTest.java | 40 ++-- .../server/test/SearchServiceTest.java | 14 +- .../server/test/WindByRaceLogTest.java | 13 +- .../impl/CompetitorDataRetriever.java | 22 +- .../impl/PersistentCompetitorStore.java | 4 +- .../server/impl/RacingEventServiceImpl.java | 4 +- .../server/masterdata/DummyTrackedRace.java | 5 + .../UpdateCompetitor.java | 8 +- .../simulator/impl/PathGeneratorTracTrac.java | 6 +- .../sap/sailing/xmlexport/FoilingData.java | 2 +- .../sailing/xmlexport/LeaderboardData.java | 17 +- .../structureimport/StructureImporter.java | 2 +- .../Security UI sdm.launch | 2 +- .../app/data/OfflineDataManager.java | 10 +- .../app/data/OnlineDataManager.java | 4 +- .../app/services/RaceStateService.java | 32 +-- .../app/ui/adapters/CompetitorAdapter.java | 9 +- 135 files changed, 994 insertions(+), 777 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BoatJsonConstants.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorAndBoat.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java delete mode 100644 java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithChangingBoatJsonSerializer.java create mode 100644 java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BoatJsonConstants.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BoatJsonConstants.java new file mode 100644 index 00000000000..31afcbd48f2 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BoatJsonConstants.java @@ -0,0 +1,14 @@ +package com.sap.sailing.domain.common.tracking.impl; + +/** + * Used to assemble a compatible JSON string by themselves, using the constants from here.The field identified by this + * name tells the fully-qualified class name from which the value of the field identified by {@link #FIELD_ID} has been + * created. When deserializing, the ID needs to be re-constructed as an instance of that type. + */ +public class BoatJsonConstants { + public static final String FIELD_ID = "id"; + public static final String FIELD_NAME = "name"; + public static final String FIELD_SAIL_ID = "sailID"; + public static final String FIELD_COLOR = "color"; + public static final String FIELD_BOAT_CLASS_NAME = "boatClassName"; +} diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index ff7f7c94700..0dc91a3c062 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -213,7 +213,7 @@ import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer; @@ -240,7 +240,7 @@ import com.sap.sse.util.ThreadPoolUtil; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); - private final CompetitorJsonDeserializer competitorDeserializer; + private final CompetitorWithBoatJsonDeserializer competitorDeserializer; private final BoatJsonDeserializer boatDeserializer; private final DB database; @@ -270,7 +270,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { this.raceTrackingConnectivityParamsServiceFinder = null; } this.baseDomainFactory = baseDomainFactory; - this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); + this.competitorDeserializer = CompetitorWithBoatJsonDeserializer.create(baseDomainFactory); this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 592ae3a4883..d99e81f4c78 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -114,6 +114,7 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; import com.sap.sse.common.Duration; @@ -131,7 +132,7 @@ import com.sap.sse.shared.media.VideoDescriptor; public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; - private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); + private final CompetitorWithBoatJsonSerializer competitorSerializer = CompetitorWithBoatJsonSerializer.create(); private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinder raceTrackingConnectivityParamsServiceFinder; diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index cb828475edb..0cc695add3b 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -65,7 +65,7 @@ public class AbstractGPSFixStoreTest { protected RegattaLog regattaLog; protected SensorFixStore store; protected final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); - protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); protected final Boat boat = DomainFactory.INSTANCE.getOrCreateBoat(comp, "boat", boatClass, "GER 234", null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index 9d28af119c9..cc253fa866d 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -176,7 +176,7 @@ public class CreateAndTrackWithRaceLogTest { assertFalse(raceLog.isEmpty()); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c", null, null, null, null, null, + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10))); @@ -217,7 +217,7 @@ public class CreateAndTrackWithRaceLogTest { adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race"); // add a mapping and one fix in, one out of mapping - Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c1", null, null, null, null, null, + Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c1", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java index b9410a1440d..379c678f901 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RaceLogFixTrackerManagerTest.java @@ -70,7 +70,7 @@ public class RaceLogFixTrackerManagerTest { protected RegattaLog regattaLog; protected SensorFixStore store; protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c2", null, null, null, - null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); protected final Boat boat = DomainFactory.INSTANCE.getOrCreateBoat(comp, "boat", boatClass, "USA 123", null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 2471c04fd3e..75a991e6675 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -111,14 +111,14 @@ public class SensorFixStoreAndLoadTest { protected RegattaLog regattaLog; protected SensorFixStore store; protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, - null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null, null, - null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); protected final Boat boat1 = DomainFactory.INSTANCE.getOrCreateBoat(comp, "Boat1", boatClass, "GER 1", null); protected final Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "Boat2", boatClass, "GER 2", null); private final Competitor compNotPartOfRace = DomainFactory.INSTANCE.getOrCreateCompetitor("comp3", "comp3", null, null, null, null, - null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); protected final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); 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 10df3b93f73..50b6b21c1cd 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 @@ -49,7 +49,7 @@ public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); private final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); private final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, - null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); private final Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); private final Course course = new CourseImpl("course", Arrays.asList(new WaypointImpl(mark), new WaypointImpl(mark2))); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java index b5cdb424e78..36c2409739b 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/TrackedRaceStartTimeInferenceTest.java @@ -63,7 +63,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeInferencePrecedenceOrder() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); Map competitorsAndBoats = new HashMap<>(); @@ -130,7 +130,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeChangeNotificationForFirstUpdateThroughRaceLog() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); Map competitorsAndBoats = new HashMap<>(); @@ -172,7 +172,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartTimeChangeNotificationForFirstUpdateThroughStartMarkPassing() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); Map competitorsAndBoats = new HashMap<>(); @@ -217,7 +217,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartAndEndTrackingTimeInferencePrecedenceOrderTriggersListener() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); Map competitorsAndBoats = new HashMap<>(); @@ -325,7 +325,7 @@ public class TrackedRaceStartTimeInferenceTest extends AbstractGPSFixStoreTest { @Test public void testStartAndEndOfTrackingTimeChangeNotificationForFirstUpdateThroughRaceLog() throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, null, + Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); Map competitorsAndBoats = new HashMap<>(); 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 2ca1b225838..86fe71dca5a 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 @@ -46,7 +46,6 @@ 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.Waypoint; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; @@ -300,21 +299,9 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } throw new RaceNotCreatedException(String.format("Race for racelog (%s) has already been created", raceLog)); } - Iterable competitors = raceColumn.getAllCompetitors(params.getFleet()); + Map competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(params.getFleet()); Serializable raceId = denoteEvent.getRaceId(); - // TODO: How do we retrieve the boats for the competitors of this raceColumn - // For now we create the boats here which MUST be corrected later on - Map competitorsAndBoats = new HashMap<>(); - for (Competitor c: competitors) { - Boat b; - if (c.getBoat() != null) { - b = new BoatImpl(c.getId(), c.getBoat().getName(), boatClass, c.getBoat().getSailID(), c.getBoat().getColor()); - } else { - b = new BoatImpl(c.getId(), c.getShortName(), boatClass, c.getShortName(), null); - } - competitorsAndBoats.put(c, b); - } - final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndBoats, raceId); + final RaceDefinition raceDef = new RaceDefinitionImpl(raceName, course, boatClass, competitorsAndTheirBoats, raceId); Iterable sidelines = Collections. emptyList(); // set race definition, so race is linked to leaderboard automatically trackedRegatta.getRegatta().addRace(raceDef); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index f3fbae990b0..2669506e62f 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -35,6 +35,7 @@ import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackin import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; @@ -150,7 +151,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { boatClass = findDominatingBoatClass(raceColumn.getAllCompetitors()); } else if (!Util.isEmpty(leaderboard.getAllCompetitors())) { boatClass = findDominatingBoatClass(leaderboard.getAllCompetitors()); - } else { + } else { throw new NotDenotableForRaceLogTrackingException("Couldn't infer boat class, no competitors on race and leaderboard"); } } @@ -167,8 +168,8 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { raceLog.add(event); } - private BoatClass findDominatingBoatClass(Iterable allCompetitors) { - return Util.getDominantObject(()->StreamSupport.stream(allCompetitors.spliterator(), /* parallel */ false).map(c->c.getBoat().getBoatClass()).iterator()); + private BoatClass findDominatingBoatClass(Iterable allBoats) { + return Util.getDominantObject(()->StreamSupport.stream(allBoats.spliterator(), /* parallel */ false).map(b->b.getBoatClass()).iterator()); } @Override diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java index 3546861f905..276e7e8ba2d 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java @@ -19,8 +19,8 @@ import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); @Test public void testCompetitorDeregistration() { diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java index 5109e8af33a..07dd91ff2b8 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/DeviceMappingFinderTest.java @@ -27,8 +27,8 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; import junit.framework.Assert; public class DeviceMappingFinderTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); private final DeviceIdentifier device = new SmartphoneImeiIdentifier("imei"); private int time = 0; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java index dc50facafe7..bcb4058f8c5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java @@ -14,9 +14,6 @@ public interface Competitor extends NamedWithID, IsManagedByCache competitors); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java index c11fe0b3200..ae23b7c6ca3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java @@ -1,8 +1,14 @@ -package com.sap.sailing.domain.base; - -import java.io.Serializable; - -public interface CompetitorWithBoat extends Serializable { - Competitor getCompetitor(); - Boat getBoat(); -} +package com.sap.sailing.domain.base; + +import com.sap.sse.datamining.annotations.Connector; + +/** + * A competitor having an assigned boat + * This makes sense e.g. in the context of a race where a competitor needs a boat in order to compete + * @author fmittag + * + */ +public interface CompetitorWithBoat extends Competitor { + @Connector(messageKey = "Boat", ordinal = 10) + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java new file mode 100644 index 00000000000..ba7e2563dc2 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java @@ -0,0 +1,26 @@ +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; + +public class CompetitorAndBoatImpl implements CompetitorAndBoat { + private static final long serialVersionUID = 6057339511208358777L; + private final Competitor competitor; + private final Boat boat; + + public CompetitorAndBoatImpl(Competitor competitor, Boat boat) { + this.competitor = competitor; + this.boat = boat; + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + @Override + public Boat getBoat() { + return boat; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java index 84ad336ad14..e9069948313 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorImpl.java @@ -17,7 +17,6 @@ import com.sap.sse.common.Util; public class CompetitorImpl implements DynamicCompetitor { private static final long serialVersionUID = 294603681016643157L; private final DynamicTeam team; - private final DynamicBoat boat; private final Serializable id; private String name; private String shortName; @@ -29,12 +28,11 @@ public class CompetitorImpl implements DynamicCompetitor { private Double timeOnTimeFactor; private Duration timeOnDistanceAllowancePerNauticalMile; - public CompetitorImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + public CompetitorImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { this.id = id; this.name = name; this.shortName = shortName; this.team = team; - this.boat = boat; this.color = color; this.email = email; this.flagImage = flagImage; @@ -97,16 +95,11 @@ public class CompetitorImpl implements DynamicCompetitor { return team; } - @Override - public DynamicBoat getBoat() { - return boat; - } - @Override public Competitor resolve(SharedDomainFactory domainFactory) { Competitor result = domainFactory .getOrCreateCompetitor(getId(), getName(), getShortName(), getColor(), getEmail(), getFlagImage(), getTeam(), - getBoat(), getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag); + getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag); return result; } @@ -130,7 +123,6 @@ public class CompetitorImpl implements DynamicCompetitor { synchronized (listeners) { listeners.add(listener); } - getBoat().addBoatChangeListener(listener); getTeam().addNationalityChangeListener(listener); } @@ -139,7 +131,6 @@ public class CompetitorImpl implements DynamicCompetitor { synchronized (listeners) { listeners.remove(listener); } - getBoat().removeBoatChangeListener(listener); getTeam().removeNationalityChangeListener(listener); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java index b7d050b8d37..57b85639e34 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java @@ -1,26 +1,27 @@ -package com.sap.sailing.domain.base.impl; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; - -public class CompetitorWithBoatImpl implements CompetitorWithBoat { - private static final long serialVersionUID = 6057339511208358777L; - private final Competitor competitor; - private final Boat boat; - - public CompetitorWithBoatImpl(Competitor competitor, Boat boat) { - this.competitor = competitor; - this.boat = boat; - } - - @Override - public Competitor getCompetitor() { - return competitor; - } - @Override - public Boat getBoat() { - return boat; - } - -} +package com.sap.sailing.domain.base.impl; + +import java.io.Serializable; +import java.net.URI; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +public class CompetitorWithBoatImpl extends CompetitorImpl implements CompetitorWithBoat { + private static final long serialVersionUID = 22679449208503264L; + private final Boat boat; + + public CompetitorWithBoatImpl(Serializable id, String name, String shortName, Color color, String email, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, + String searchTag, Boat boat) { + super(id, name, shortName, color, email, flagImage, team, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, + searchTag); + this.boat = boat; + } + + @Override + public Boat getBoat() { + return boat; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java index 29405dfb0a5..ef8e4096550 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitor.java @@ -8,8 +8,6 @@ import com.sap.sse.common.Color; import com.sap.sse.common.Duration; public interface DynamicCompetitor extends Competitor, Renamable { - DynamicBoat getBoat(); - DynamicTeam getTeam(); void setColor(Color displayColor); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 41ceff5524f..9af99bd0ec5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -349,13 +349,13 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { @Override public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortname, Color displayColor, String email, - URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { if (logger.isLoggable(Level.FINEST)) { logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this); } return getCompetitorStore().getOrCreateCompetitor(competitorId, name, shortname, displayColor, email, flagImage, team, - boat, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index f77c03a6aaa..e0f36db1099 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -88,8 +88,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } private Competitor createCompetitor(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, - DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = new CompetitorImpl(id, name, shortName, displayColor, email, flagImage, team, boat, + DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + Competitor result = new CompetitorImpl(id, name, shortName, displayColor, email, flagImage, team, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); addNewCompetitor(id, result); if (logger.isLoggable(Level.FINEST)) { @@ -115,7 +115,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab @Override public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, - URI flagImage, DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access if (result == null) { @@ -123,14 +123,14 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab try { result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock if (result == null) { - result = createCompetitor(competitorId, name, shortName, displayColor, email, flagImage, team, boat, + result = createCompetitor(competitorId, name, shortName, displayColor, email, flagImage, team, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } } finally { LockUtil.unlockAfterWrite(lock); } } else if (isCompetitorToUpdateDuringGetOrCreate(result)) { - updateCompetitor(result.getId().toString(), name, shortName, displayColor, email, boat.getSailID(), team.getNationality(), + updateCompetitor(result.getId().toString(), name, shortName, displayColor, email, team.getNationality(), team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); competitorNoLongerToUpdateDuringGetOrCreate(result); } @@ -216,7 +216,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab @Override public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, - String newSailId, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString); if (competitor != null) { @@ -227,7 +227,6 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitor.setColor(newDisplayColor); competitor.setEmail(newEmail); competitor.setFlagImage(newFlagImageUri); - competitor.getBoat().setSailId(newSailId); competitor.getTeam().setNationality(newNationality); competitor.getTeam().setImage(newTeamImageUri); competitor.setTimeOnTimeFactor(timeOnTimeFactor); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 0884dd3c9a7..7926cf0781a 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -20,9 +20,7 @@ import com.sap.sailing.domain.base.Nationality; 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.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -121,7 +119,6 @@ public class DomainFactoryImpl implements DomainFactory { CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); Competitor domainCompetitor = competitorAndBoatStore.getExistingCompetitorByIdAsString(competitor.getID()); if (domainCompetitor == null || competitorAndBoatStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) { - DynamicBoat boat = new BoatImpl(domainCompetitor.getId(), competitor.getName(), boatClass, competitor.getBoatID()); List teamMembers = new ArrayList(); for (CrewMember crewMember: competitor.getCrew()) { DynamicPerson person = new PersonImpl(crewMember.getName().trim(), getOrCreateNationality(crewMember.getNationality()), @@ -129,7 +126,7 @@ public class DomainFactoryImpl implements DomainFactory { teamMembers.add(person); } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); - domainCompetitor = competitorAndBoatStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team, boat, + domainCompetitor = competitorAndBoatStore.getOrCreateCompetitor(competitor.getID(), competitor.getName(), null /* shortName */, null /*displayColor*/, null /*email*/, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } Boat domainBoat = competitorAndBoatStore.getOrCreateBoat(domainCompetitor, competitor.getName(), boatClass, competitor.getBoatID(), null); @@ -146,9 +143,8 @@ public class DomainFactoryImpl implements DomainFactory { } DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null); String competitorID = getCompetitorID(competitor.getBoatID(), raceId, boatClass); - DynamicBoat boat = new BoatImpl(competitorID, competitor.getName(), boatClass, competitor.getBoatID()); Competitor domainCompetitor = competitorAndBoatStore.getOrCreateCompetitor(competitorID, - competitor.getName(), null /* short name */, null /*displayColor*/, null /*email*/, null, team, boat, + competitor.getName(), null /* short name */, null /*displayColor*/, null /*email*/, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat domainBoat = competitorAndBoatStore.getOrCreateBoat(domainCompetitor, competitor.getName(), boatClass, competitor.getBoatID(), null); return new Pair(domainCompetitor, domainBoat); 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 1cdb1ec1218..4edbfcb06a0 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,11 +1,11 @@ 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; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -13,11 +13,13 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.List; +import java.util.Map.Entry; import org.junit.Ignore; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; @@ -202,9 +204,9 @@ public class SwissTimingReplayAdapterServiceTest { new SwissTimingReplayParserImpl().readData(getClass().getResourceAsStream("/SAW005905.20120805.replay"), replayListener); Iterable trackedRaces = replayListener.getTrackedRaces(); TrackedRace trackedRace = trackedRaces.iterator().next(); - for (Competitor competitor : trackedRace.getRace().getCompetitors()) { - assertSame(DomainFactory.INSTANCE.getBaseDomainFactory().getOrCreateBoatClass("470"), competitor.getBoat().getBoatClass()); - Distance distanceToLineAtStart = trackedRace.getDistanceToStartLine(competitor, trackedRace.getStartOfRace()); + for (Entry competitorAndBoatEntry : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { + assertSame(DomainFactory.INSTANCE.getBaseDomainFactory().getOrCreateBoatClass("470"), competitorAndBoatEntry.getValue().getBoatClass()); + Distance distanceToLineAtStart = trackedRace.getDistanceToStartLine(competitorAndBoatEntry.getKey(), trackedRace.getStartOfRace()); assertTrue(distanceToLineAtStart.getMeters() > 0); assertTrue(distanceToLineAtStart.getMeters() < 20); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java index 752c4f89c56..9459d7e3fa8 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassingcalculation/impl/CandidateFinderImplWhiteBoxTest.java @@ -20,7 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.ReadonlyRacingProcedureFactory; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; import com.sap.sailing.domain.common.Position; @@ -63,7 +63,7 @@ public class CandidateFinderImplWhiteBoxTest { @Before public void setUp() { now = MillisecondsTimePoint.now(); - CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Competitor"); + CompetitorAndBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Competitor"); competitor = competitorAndBoat.getCompetitor(); Map competitorAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); trackedRace = TrackBasedTest.createTestTrackedRace("Test Regatta", "Test Race", "505", competitorAndBoats, now, /* useMarkPassingCalculator */ true); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java index 07282b02af4..93707e3610a 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/ranking/TestFarthestAheadWithSkippedMarkPassing.java @@ -17,7 +17,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -82,9 +82,9 @@ public class TestFarthestAheadWithSkippedMarkPassing { private Waypoint finish; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - CompetitorWithBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + CompetitorAndBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); c1 = fastCompetitorAndBoat.getCompetitor(); - CompetitorWithBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + CompetitorAndBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); c2 = slowCompetitorAndBoat.getCompetitor(); trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat)); rankingMetric = trackedRace.getRankingMetric(); 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 f91e21320d6..a5c92869dbd 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 @@ -17,7 +17,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -64,9 +64,9 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg { private Competitor c1, c2; private void setUp(TimeOnTimeFactorMapping timeOnTimeFactors, Function timeOnDistanceFactors) { - CompetitorWithBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); + CompetitorAndBoat fastCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("FastBoat"); c1 = fastCompetitorAndBoat.getCompetitor(); - CompetitorWithBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); + CompetitorAndBoat slowCompetitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SlowBoat"); c2 = slowCompetitorAndBoat.getCompetitor(); trackedRace = createTrackedRace(TrackBasedTest.createCompetitorAndBoatsMap(fastCompetitorAndBoat, slowCompetitorAndBoat), timeOnTimeFactors, timeOnDistanceFactors); tot = trackedRace.getRankingMetric(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 772a387fa88..7863b224c81 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -7,11 +7,11 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorFactory; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -20,37 +20,36 @@ import com.sap.sse.common.Color; public abstract class AbstractLeaderboardTest { private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); - public static CompetitorWithBoat createCompetitorAndBoat(String competitorName) { + public static CompetitorAndBoat createCompetitorAndBoat(String competitorName) { Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", - competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorWithBoatImpl(c, b); + return new CompetitorAndBoatImpl(c, b); } - public static CompetitorWithBoat createCompetitorAndBoat(String competitorName, CompetitorFactory competitorFactory) { + public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, CompetitorFactory competitorFactory) { Competitor c = competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("id12345", - competitorName + "'s boat", boatClass, /* sailID */ null), + /* dateOfBirth */null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorWithBoatImpl(c, b); + return new CompetitorAndBoatImpl(c, b); } - public static CompetitorWithBoat createCompetitorAndBoat(String competitorName, Serializable id) { + public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, Serializable id) { Competitor c = new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(id, - competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorWithBoatImpl(c, b); + return new CompetitorAndBoatImpl(c, b); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java index 98f8aed2e45..cf40261d2da 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorListenerTest.java @@ -37,9 +37,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { private Object whatChangedNationality; private Object oldNationality; private Object newNationality; - private boolean sailIdChanged; - private String oldSailId; - private String newSailId; private boolean nameChanged; private String oldName; private String newName; @@ -75,9 +72,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { whatChangedNationality = null; oldNationality = null; newNationality = null; - sailIdChanged = false; - oldSailId = null; - newSailId = null; nameChanged = false; oldName = null; newName = null; @@ -113,13 +107,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { CompetitorListenerTest.this.newNationality = newNationality; } - @Override - public void sailIdChanged(String oldSailId, String newSailId) { - sailIdChanged = true; - CompetitorListenerTest.this.oldSailId = oldSailId; - CompetitorListenerTest.this.newSailId = newSailId; - } - @Override public void nameChanged(String oldName, String newName) { nameChanged = true; @@ -215,7 +202,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { assertTrue(nameChanged); assertEquals("Hasso", oldName); assertEquals("Dr. Hasso Plattner", newName); - assertFalse(sailIdChanged); assertFalse(colorChanged); assertFalse(nationalityChanged); } @@ -252,25 +238,12 @@ public class CompetitorListenerTest extends AbstractSerializationTest { assertEquals("hasso", newSearchTag); } - @Test - public void testSimpleCompetitorListenerPatternForSailId() { - final String myOldSailId = competitor.getBoat().getSailID(); - competitor.getBoat().setSailId("POR 40"); - assertFalse(nameChanged); - assertTrue(sailIdChanged); - assertEquals(myOldSailId, oldSailId); - assertEquals("POR 40", newSailId); - assertFalse(colorChanged); - assertFalse(nationalityChanged); - } - @Test public void testSimpleCompetitorListenerPatternForColor() { final Color myOldColor = competitor.getColor(); final RGBColor myNewColor = new RGBColor(123, 12, 234); competitor.setColor(myNewColor); assertFalse(nameChanged); - assertFalse(sailIdChanged); assertTrue(colorChanged); assertEquals(myOldColor, oldColor); assertEquals(myNewColor, newColor); @@ -283,7 +256,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { final Nationality myNewNationality = DomainFactory.INSTANCE.getOrCreateNationality("POR"); competitor.getTeam().setNationality(myNewNationality); assertFalse(nameChanged); - assertFalse(sailIdChanged); assertFalse(colorChanged); assertTrue(nationalityChanged); assertEquals(myOldNationality, oldNationality); @@ -296,13 +268,11 @@ public class CompetitorListenerTest extends AbstractSerializationTest { DomainFactory baseDomainFactory = new DomainFactoryImpl((srlid)->null); DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory); clonedCompetitor.setName("Dr. Hasso Plattner"); - clonedCompetitor.getBoat().setSailId("POR 40"); final RGBColor myNewColor = new RGBColor(123, 12, 234); clonedCompetitor.setColor(myNewColor); final Nationality myNewNationality = baseDomainFactory.getOrCreateNationality("POR"); clonedCompetitor.getTeam().setNationality(myNewNationality); assertFalse(nameChanged); - assertFalse(sailIdChanged); assertFalse(colorChanged); assertFalse(nationalityChanged); } @@ -328,7 +298,6 @@ public class CompetitorListenerTest extends AbstractSerializationTest { DynamicCompetitor clonedCompetitor = cloneBySerialization(competitor, baseDomainFactory); competitor = clonedCompetitor; competitor.addCompetitorChangeListener(listener); - testSimpleCompetitorListenerPatternForSailId(); } @Test 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 7cad93b07da..4db450125e8 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 @@ -21,7 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -304,7 +304,7 @@ public class CourseTest { Course course = new CourseImpl("Test Course", waypoints); assertWaypointIndexes(course); final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); - final CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); + final CompetitorAndBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); final Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */new DynamicTrackedRegattaImpl( @@ -338,7 +338,7 @@ public class CourseTest { waypoints.add(wp2); Course course = new CourseImpl("Test Course", waypoints); final BoatClass boatClass = new BoatClassImpl("505", /* upwind start */true); - final CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); + final CompetitorAndBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Hasso"); final Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(hasso.getCompetitor(), hasso.getBoat()); DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(/* trackedRegatta */ new DynamicTrackedRegattaImpl( diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java index 0b8ee569f04..86c949b2f19 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DistanceCacheInvalidationAfterLoadingFinishedTest.java @@ -10,7 +10,7 @@ import org.junit.Test; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.TrackedRaceStatusEnum; @@ -40,7 +40,7 @@ public class DistanceCacheInvalidationAfterLoadingFinishedTest extends TrackBase @Before public void setUp() { - CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat("Test Competitor"); + CompetitorAndBoat competitorAndBoat = createCompetitorAndBoat("Test Competitor"); Map competitorsAndBoats = TrackBasedTest.createCompetitorAndBoatsMap(competitorAndBoat); competitor = competitorAndBoat.getCompetitor(); trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", competitorsAndBoats, MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); 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 1a62f3fa0f1..3315d79bd61 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 @@ -29,7 +29,6 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; @@ -160,7 +159,7 @@ public class LeaderboardCourseChangeTest { Set competitors = new HashSet<>(); competitors.add(new CompetitorImpl(UUID.randomUUID(), "TestCompetitor", "BYC", Color.BLACK, null, null, - mock(DynamicTeam.class), new BoatImpl("123", "boat", boatClass, "GER 124"), + mock(DynamicTeam.class), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); return competitors; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 34073d2fd15..513345a2616 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -24,7 +24,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -49,7 +49,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class LeaderboardOfflineTest extends AbstractLeaderboardTest { private Set testRaces; private Map raceColumnsInLeaderboard; - private CompetitorWithBoat competitorWithBoat; + private CompetitorAndBoat competitorWithBoat; @Before public void setUp() { @@ -164,8 +164,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { public void testMaxPointsDiscard() throws NoWindException { testRaces = new HashSet(); raceColumnsInLeaderboard = new HashMap(); - CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); - CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); + CompetitorAndBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorAndBoat c3 = createCompetitorAndBoat("Robert Stanjek"); for (int i=0; i<3; i++) { MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitorWithBoat, i+1, /* started */ true); r.addCompetitorAndBoat(c2); @@ -198,8 +198,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void testCarriedPointsCountInSorting() throws NoWindException { raceColumnsInLeaderboard = new HashMap(); - CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); - CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); + CompetitorAndBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorAndBoat c3 = createCompetitorAndBoat("Robert Stanjek"); TimePoint now = MillisecondsTimePoint.now(); MockedTrackedRaceWithFixedRankAndManyCompetitors testRace = new MockedTrackedRaceWithFixedRankAndManyCompetitors( competitorWithBoat, /* rank */ 1, /* started */true); @@ -226,8 +226,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void testDNDNotDiscardedInUntrackedRace() throws NoWindException { raceColumnsInLeaderboard = new HashMap(); - CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); - CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); + CompetitorAndBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorAndBoat c3 = createCompetitorAndBoat("Robert Stanjek"); MockedTrackedRaceWithFixedRankAndManyCompetitors testRace = new MockedTrackedRaceWithFixedRankAndManyCompetitors( competitorWithBoat, /* rank */ 1, /* started */true); testRace.addCompetitorAndBoat(c2); @@ -250,8 +250,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { public void testNoDNDDiscard() throws NoWindException { testRaces = new HashSet(); raceColumnsInLeaderboard = new HashMap(); - CompetitorWithBoat c2 = createCompetitorAndBoat("Marcus Baur"); - CompetitorWithBoat c3 = createCompetitorAndBoat("Robert Stanjek"); + CompetitorAndBoat c2 = createCompetitorAndBoat("Marcus Baur"); + CompetitorAndBoat c3 = createCompetitorAndBoat("Robert Stanjek"); for (int i=0; i<3; i++) { MockedTrackedRaceWithFixedRankAndManyCompetitors r = new MockedTrackedRaceWithFixedRankAndManyCompetitors(competitorWithBoat, i+1, /* started */ true); r.addCompetitorAndBoat(c2); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java index 6285272ee28..11d18cd2544 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LineAnalysisTest.java @@ -5,7 +5,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.Distance; @@ -26,7 +26,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class LineAnalysisTest extends TrackBasedTest { private TimePoint now; private DynamicTrackedRace trackedRace; - private CompetitorWithBoat competitorWithBoat; + private CompetitorAndBoat competitorWithBoat; @Before public void setUp() { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index b337738fc62..c79056f208b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -29,7 +29,6 @@ import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; @@ -192,8 +191,7 @@ public class OfflineSerializationTest extends AbstractSerializationTest { new PersonImpl(competitorName, senderDomainFactory.getOrCreateNationality("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", senderDomainFactory.getOrCreateNationality("GER"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", senderDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Competitor receiversCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); Competitor receiversSecondCopyOfCompetitor1 = cloneBySerialization(sendersCompetitor1, receiverDomainFactory); assertSame(receiversCompetitor1, receiversSecondCopyOfCompetitor1); 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 708747e72e0..cdba51d479a 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 @@ -18,7 +18,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -75,13 +75,13 @@ public class ReachingLegTest extends TrackBasedTest { @Before public void setUp() { competitorsAndBoats = new LinkedHashMap<>(); - CompetitorWithBoat hungerWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); + CompetitorAndBoat hungerWithBoat = createCompetitorAndBoat("Wolfgang Hunger"); hunger = hungerWithBoat.getCompetitor(); competitorsAndBoats.put(hungerWithBoat.getCompetitor(), hungerWithBoat.getBoat()); - CompetitorWithBoat plattnerWithBoat = createCompetitorAndBoat("Dr. Hasso Plattner"); + CompetitorAndBoat plattnerWithBoat = createCompetitorAndBoat("Dr. Hasso Plattner"); plattner = plattnerWithBoat.getCompetitor(); competitorsAndBoats.put(plattnerWithBoat.getCompetitor(), plattnerWithBoat.getBoat()); - CompetitorWithBoat schomaekerWithBoat = createCompetitorAndBoat("Meike Schom�ker"); + CompetitorAndBoat schomaekerWithBoat = createCompetitorAndBoat("Meike Schom�ker"); schomaeker = schomaekerWithBoat.getCompetitor(); competitorsAndBoats.put(schomaekerWithBoat.getCompetitor(), schomaekerWithBoat.getBoat()); start = new MillisecondsTimePoint(new GregorianCalendar(2011, 05, 23).getTime()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java index 7c120543834..517c5f3bd03 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/StoredTrackBasedTest.java @@ -16,6 +16,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.impl.BoatClassImpl; @@ -41,10 +42,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public abstract class StoredTrackBasedTest extends TrackBasedTest { private static final String RESOURCES = "resources/"; - protected DynamicGPSFixTrack readTrack(Competitor competitor, String regattaName) throws FileNotFoundException, IOException { + protected DynamicGPSFixTrack readTrack(Competitor competitor, Boat boat, String regattaName) throws FileNotFoundException, IOException { DynamicGPSFixTrack track = null; - if (getFile(competitor, regattaName).exists()) { - ObjectInput oi = getInputStream(competitor, regattaName); + if (getFile(competitor, boat, regattaName).exists()) { + ObjectInput oi = getInputStream(competitor, boat, regattaName); track = new DynamicGPSFixMovingTrackImpl(competitor, /* millisecondsOverWhichToAverage */ 40000); try { @@ -59,17 +60,17 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { return track; } - ObjectInput getInputStream(Competitor competitor, String regattaName) throws FileNotFoundException, IOException { - return new ObjectInputStream(new FileInputStream(getFile(competitor, regattaName))); + ObjectInput getInputStream(Competitor competitor, Boat boat, String regattaName) throws FileNotFoundException, IOException { + return new ObjectInputStream(new FileInputStream(getFile(competitor, boat, regattaName))); } - ObjectOutput getOutputStream(Competitor competitor, String regattaName) throws FileNotFoundException, IOException { - return new ObjectOutputStream(new FileOutputStream(getFile(competitor, regattaName))); + ObjectOutput getOutputStream(Competitor competitor, Boat boat, String regattaName) throws FileNotFoundException, IOException { + return new ObjectOutputStream(new FileOutputStream(getFile(competitor, boat, regattaName))); } - private File getFile(Competitor competitor, String regattaName) { + private File getFile(Competitor competitor, Boat boat, String regattaName) { return new File(RESOURCES + regattaName + "-" + competitor.getName() - + (competitor.getBoat().getSailID() == null ? "" : "-" + competitor.getBoat().getSailID())); + + (boat.getSailID() == null ? "" : "-" + boat.getSailID())); } public static ObjectInputStream getObjectInputStream(String fileNameWithinResources) throws FileNotFoundException, IOException { @@ -103,9 +104,9 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { return new GPSFixMovingImpl(position, timePoint, speedWithBearing); } - protected void storeTrack(Competitor competitor, DynamicGPSFixTrack track, String regattaName) + protected void storeTrack(Competitor competitor, Boat boat, DynamicGPSFixTrack track, String regattaName) throws FileNotFoundException, IOException { - ObjectOutput oo = getOutputStream(competitor, regattaName); + ObjectOutput oo = getOutputStream(competitor, boat, regattaName); for (GPSFixMoving fix : track.getRawFixes()) { writeGPSFixMoving(fix, oo); } @@ -115,13 +116,14 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest { protected Map> loadTracks() throws FileNotFoundException, IOException { Map> tracks = new HashMap>(); final String KIELER_WOCHE = "Kieler Woche"; - final BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) { DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null); DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null); Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, t, - new BoatImpl("123", competitorName, boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - DynamicGPSFixTrack track = readTrack(c, KIELER_WOCHE); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + Boat b = new BoatImpl("123", competitorName, boatClass, null); + DynamicGPSFixTrack track = readTrack(c, b, KIELER_WOCHE); if (track != null) { tracks.put(c, track); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java index 454a5b3239b..2a43dc661f8 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TackTest.java @@ -44,8 +44,8 @@ public class TackTest extends StoredTrackBasedTestWithTrackedRace { new PersonImpl("Wolfgang Hunger", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - "Wolfgang Hunger's boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat = new BoatImpl(competitor.getId(), "Wolfgang Hunger's boat", boatClass, "123", null); Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(competitor, boat); 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 a3170c9d05a..c22c95b4637 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 @@ -16,7 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.CourseArea; @@ -32,7 +32,7 @@ import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseImpl; @@ -88,23 +88,23 @@ public abstract class TrackBasedTest { } @SafeVarargs - public static Map createCompetitorAndBoatsMap(CompetitorWithBoat... competitorsAndBoats) { + public static Map createCompetitorAndBoatsMap(CompetitorAndBoat... competitorsAndBoats) { Map result = new LinkedHashMap<>(); - for (CompetitorWithBoat competitorAndBoat: competitorsAndBoats) { + for (CompetitorAndBoat competitorAndBoat: competitorsAndBoats) { result.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); } return result; } - public static CompetitorWithBoat createCompetitorAndBoat(String competitorName) { + public static CompetitorAndBoat createCompetitorAndBoat(String competitorName) { Competitor c = new CompetitorImpl(UUID.randomUUID(), competitorName, "HP", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat b = new BoatImpl(c.getId(), competitorName + "'s boat", boatClass, null, null); - return new CompetitorWithBoatImpl(c, b); + return new CompetitorAndBoatImpl(c, b); } /** diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java index 2fadd5ffb20..0af4c688ee0 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStartTimeUpdateForDependentStartTimeTest.java @@ -18,7 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEve import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.tracking.StartTimeChangedListener; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.Duration; @@ -28,7 +28,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class TrackedRaceStartTimeUpdateForDependentStartTimeTest extends TrackBasedTest { @Test public void testStartTimeUpdateForRaceWithDependentStartTime() { - final CompetitorWithBoat hasso = createCompetitorAndBoat("Hasso"); + final CompetitorAndBoat hasso = createCompetitorAndBoat("Hasso"); final RaceLog r1RaceLog = new RaceLogImpl("r1RaceLog"); final RaceLog r2RaceLog = new RaceLogImpl("r2RaceLog"); final RaceLogResolver raceLogResolver = new RaceLogResolver() { 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 02bea2cdc35..3cd7570fc9e 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 @@ -12,7 +12,7 @@ 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.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Series; @@ -41,7 +41,7 @@ public class UpdateMarkPassingTest { when(race.getName()).thenReturn("Test Race"); Course c = new CourseImpl("Test Course", Collections.singleton(waypoint)); when(race.getCourse()).thenReturn(c); - CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + CompetitorAndBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); Competitor competitor = competitorAndBoat.getCompetitor(); when(race.getBoatClass()).thenReturn(new BoatClassImpl("49er", /* typicallyStartsUpwind */ true)); when(race.getCompetitors()).thenReturn(Collections.singleton(competitor)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java index 165e9cfc861..0590d04ba41 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindEstimationOnConstructedTracksTest.java @@ -20,7 +20,7 @@ import org.junit.Test; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.LegType; @@ -50,7 +50,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest { private List competitors; - private List competitorsWithBoats; + private List competitorsWithBoats; private static final String[] competitorNames = new String[] { "Wolfgang Hunger", "Dr. Hasso Plattner", "Robert Stanjek", "Simon Grotelueschen" }; @Before @@ -58,16 +58,16 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest competitorsWithBoats = new ArrayList<>(); competitors = new ArrayList<>(); for (String name : competitorNames) { - CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat(name); + CompetitorAndBoat competitorAndBoat = createCompetitorAndBoat(name); competitorsWithBoats.add(competitorAndBoat); competitors.add(competitorAndBoat.getCompetitor()); } } private void initRace(int numberOfCompetitorsToUse, int[] numberOfMarksPassed, TimePoint timePointForFixes) { - List subList = competitorsWithBoats.subList(0, numberOfCompetitorsToUse); + List subList = competitorsWithBoats.subList(0, numberOfCompetitorsToUse); Map competitorsAndBoats = new HashMap<>(); - for (CompetitorWithBoat competitorAndBoat: subList) { + for (CompetitorAndBoat competitorAndBoat: subList) { competitorsAndBoats.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); } setTrackedRace(createTestTrackedRace("Kieler Woche", "505 Race 2", "505", 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 d5ce2f6181a..8e11e3c6767 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 @@ -296,8 +296,8 @@ public class WindTest { new PersonImpl("Test Competitor", new NationalityImpl("GER"), /* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - "Test Competitor" + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat = new BoatImpl("123", "Test Competitor" + "'s boat", boatClass, null); Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(competitor, boat); 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 6c7872091fb..0160d8248ec 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 @@ -48,9 +48,9 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class AbstractMockedRaceMarkPassingTest { final BoatClassImpl boatClass = new BoatClassImpl("boat", true, "boat", new MeterDistance(10), new MeterDistance(5), null); - protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, new BoatImpl("123", "boat", boatClass, "boot"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ron = new CompetitorImpl("Ron", "Ron", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor tom = new CompetitorImpl("Tom", "Tom", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + protected Competitor ben = new CompetitorImpl("Ben", "Ben", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); protected Boat boatRon = new BoatImpl("123", "boat1", boatClass, "GER 123"); protected Boat boatTom = new BoatImpl("456", "boat2", boatClass, "GER 456"); protected Boat boatBen = new BoatImpl("789", "boat3", boatClass, "GER 789"); 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 4e7f2079ff3..7818a48ff18 100644 --- 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 @@ -1149,4 +1149,9 @@ public class MockedTrackedRace implements DynamicTrackedRace { public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { return null; } + + @Override + public Boat getBoatOfCompetitor(Serializable competitorId) { + return null; + } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java index 6511d289a69..cdfdd1a7dde 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java @@ -10,7 +10,7 @@ import java.util.Map; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; @@ -26,7 +26,7 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { private final BoatClass boatClass; protected RaceDefinition raceDefinition; - public MockedTrackedRaceWithFixedRank(CompetitorWithBoat competitorWithBoat, int rank, boolean started, BoatClass boatClass) { + public MockedTrackedRaceWithFixedRank(CompetitorAndBoat competitorWithBoat, int rank, boolean started, BoatClass boatClass) { this.rank = rank; this.started = started; this.competitorsAndBoats = new HashMap<>(); @@ -35,7 +35,7 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { this.competitorsAndBoats.put(competitorWithBoat.getCompetitor(), competitorWithBoat.getBoat()); } - public MockedTrackedRaceWithFixedRank(CompetitorWithBoat competitorWithBoat,int rank, boolean started) { + public MockedTrackedRaceWithFixedRank(CompetitorAndBoat competitorWithBoat,int rank, boolean started) { this(competitorWithBoat, rank, started, /* boatClass */ null); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java index 85f8f41b578..c086f2b4081 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java @@ -6,14 +6,14 @@ import java.util.Map; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrackedRaceWithFixedRank { private static final long serialVersionUID = -6189437610363552577L; - public MockedTrackedRaceWithFixedRankAndManyCompetitors(CompetitorWithBoat competitorWithBoat, int rank, boolean started) { + public MockedTrackedRaceWithFixedRankAndManyCompetitors(CompetitorAndBoat competitorWithBoat, int rank, boolean started) { super(competitorWithBoat, rank, started); this.raceDefinition = new RaceDefinition() { private static final long serialVersionUID = 8878878939443845646L; @@ -66,7 +66,7 @@ public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrac }; } - public void addCompetitorAndBoat(CompetitorWithBoat competitorWithBoat) { + public void addCompetitorAndBoat(CompetitorAndBoat competitorWithBoat) { competitorsAndBoats.put(competitorWithBoat.getCompetitor(), competitorWithBoat.getBoat()); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java index bcac10f0a62..b398ff93ee6 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java @@ -703,4 +703,9 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { return null; } + + @Override + public Boat getBoatOfCompetitor(Serializable competitorId) { + return null; + } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java index 7d03c81d414..64bba04ee30 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java @@ -15,7 +15,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.impl.BravoFixImpl; import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl; @@ -31,7 +31,7 @@ public class BravoFixTrackSerializationTest { @Before public void setUp() { - CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SAP Extreme Sailing Team"); + CompetitorAndBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("SAP Extreme Sailing Team"); track = new BravoFixTrackImpl(competitorAndBoat.getCompetitor(), BravoFixTrack.TRACK_NAME); } 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 722dae1cad9..069777680cc 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 @@ -37,7 +37,6 @@ import com.sap.sailing.domain.base.Sideline; 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.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.KilometersPerHourSpeedWithBearingImpl; @@ -252,7 +251,6 @@ public class DomainFactoryImpl implements DomainFactory { CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); Competitor result = competitorStore.getExistingCompetitorById(competitorId); if (result == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)) { - BoatClass boatClass = getOrCreateBoatClass(competitorClassName); Nationality nationality; try { nationality = getOrCreateNationality(nationalityAsString); @@ -262,9 +260,8 @@ public class DomainFactoryImpl implements DomainFactory { logger.log(Level.SEVERE, "Unknown nationality "+nationalityAsString+" for competitor "+name+"; leaving null", iae); } DynamicTeam team = createTeam(name, nationality, competitorId); - DynamicBoat boat = new BoatImpl(competitorId, shortName, boatClass, shortName); result = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, - null /* email */, null /* flagImag */, team, boat, (double) timeOnTimeFactor, + null /* email */, null /* flagImag */, team, (double) timeOnTimeFactor, new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); } return result; @@ -606,7 +603,7 @@ public class DomainFactoryImpl implements DomainFactory { } return competitorBoatInfos; } - + @Override public Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index 994ed805998..f6607b3a4b4 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.base; +import java.util.Map; + import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; @@ -255,6 +257,21 @@ public interface RaceColumn extends Named { * Same as {@link #getAllCompetitors()}, but restricted to the single race identified by the fleet parameter. */ Iterable getAllCompetitors(Fleet fleet); + + /** + * Provides the combined set of competitors and their boats from all {@link #getTrackedRace(Fleet) tracked races attached to this + * column} or, in case a fleet does not have a tracked race attached, the competitors registered through the + * respective {@link RaceLog} {@link #getRaceLog(Fleet)} attached to this column for that fleet (if this is + * {@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabled) or registered through the {@link #getRegattaLog() + * regatta log}. + */ + Map getAllCompetitorsAndTheirBoats(); + + /** + * Same as {@link #getAllCompetitorsAndTheirBoats()}, but restricted to the single race identified by the fleet parameter. + */ + Map getAllCompetitorsAndTheirBoats(Fleet fleet); + /** * Provides the combined set of marks from the courses of all {@link #getTrackedRace(Fleet) tracked races attached diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index aede43cf677..de60e758c8f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -27,6 +27,7 @@ import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetito import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.Fleet; @@ -274,6 +275,33 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem return result; } + @Override + public Map getAllCompetitorsAndTheirBoats() { + Map result = new HashMap<>(); + for (Fleet fleet : getFleets()) { + result.putAll(getAllCompetitorsAndTheirBoats(fleet)); + } + return result; + } + + @Override + public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { + Map result = new HashMap<>(); + TrackedRace trackedRace = getTrackedRace(fleet); + if (trackedRace != null) { + result = trackedRace.getRace().getCompetitorsAndTheirBoats(); + } else { + // if no tracked race is found, use competitors from race/regatta log depending on whether + // the mapping event is present or not; this assumes that if a tracked + // race exists, its competitors set takes precedence over what's in the race log. Usually, + // the tracked race will have the same competitors as those in the race log, or more because + // those from the regatta log are added to the tracked race as well. + Set viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze(); + result = viaRaceLog; + } + return result; + } + @Override public void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { registerCompetitors(Collections.singleton(competitor), fleet); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java index 14f1acddcee..a85d4e484c6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DynamicCompetitorStore.java @@ -13,7 +13,7 @@ public interface DynamicCompetitorStore extends CompetitorStore { @Override DynamicCompetitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, URI flagImage, - DynamicTeam team, DynamicBoat boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); + DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); @Override Iterable getCompetitors(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index f8ba35fa65c..5373f460c06 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -14,6 +15,7 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardBase; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.LegType; @@ -129,7 +131,12 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns { * It will, however, continue to be returned from {@link #getAllCompetitors()}. */ void setSuppressed(Competitor competitor, boolean suppressed); - + + /** + * Retrieves the boat for a given competitor. + */ + Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet); + /** * Returns the first fleet found in the sequence of this leaderboard's {@link #getRaceColumns() race columns}' * {@link RaceColumn#getFleets() fleets} whose name equals fleetName. If no such fleet is found, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index 036a7bbd7a5..5a54393f56a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -99,11 +99,6 @@ public class LeaderboardCacheManager { updateCompetitorListeners(); } - @Override - public void sailIdChanged(String oldSailId, String newSailId) { - removeFromCache(leaderboard); - } - @Override public void nationalityChanged(WithNationality what, Nationality oldNationality, Nationality newNationality) { removeFromCache(leaderboard); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index c96e1cbbf57..98490827f47 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -16,10 +16,12 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; 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.common.MaxPointsReason; import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.ScoreCorrection; @@ -101,6 +103,12 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return getOrCreateCompetitorsProvider().getAllCompetitors(raceColumn, fleet); } + @Override + public Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet) { + RaceDefinition race = raceColumn.getRaceDefinition(fleet); + return race.getBoatOfCompetitorById(competitor.getId()); + } + @Override public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { if (competitorsProvider == null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 51497d42743..b071a65050c 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.leaderboard.impl; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -31,6 +32,7 @@ import java.util.stream.StreamSupport; import com.sap.sailing.domain.abstractlog.race.InvalidatesLeaderboardCache; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; 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 eed890eaf24..fe075435790 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 @@ -15,11 +15,13 @@ import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Fleet; 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; import com.sap.sailing.domain.base.impl.AbstractRaceExecutionOrderProvider; import com.sap.sailing.domain.base.impl.RegattaLogEventAdditionForwarder; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index f935a57b775..acb97ff93aa 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java index 6c0ad316647..0bb98de7220 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/AbstractMetaLeaderboard.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -138,7 +139,7 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI public MetaLeaderboardScoreCorrection getScoreCorrection() { return (MetaLeaderboardScoreCorrection) super.getScoreCorrection(); } - + @Override public Iterable getAllCompetitors() { Set result = new HashSet(); @@ -159,6 +160,11 @@ public abstract class AbstractMetaLeaderboard extends AbstractSimpleLeaderboardI return result; } + @Override + public Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet) { + return null; + } + @Override public Fleet getFleet(String fleetName) { return fleetName.equals(metaFleet.getName()) ? metaFleet : null; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java index 04907b87a42..b3500bae388 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java @@ -135,7 +135,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * Helper instance used to encode null values in {@link ConcurrentHashMap} instances which do not accept * null as key nor value. */ - private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null, null, null); + private final static Competitor NULL_COMPETITOR = new CompetitorImpl(null, null, null, null, null, null, null, null, null, null); public abstract class AbstractRankingInfo implements RankingMetric.RankingInfo { private static final long serialVersionUID = 6845168655725234325L; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java index d46f0dbd25c..6dff4735ec2 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking; import java.io.Serializable; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.common.Bearing; @@ -22,6 +23,8 @@ public interface TrackedLegOfCompetitor extends Serializable { Competitor getCompetitor(); + Boat getBoat(); + /** * How much time did the {@link #getCompetitor competitor} spend in this {@link #getLeg() leg} at * timePoint? If the competitor hasn't started the leg yet at timePoint, null 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 314b4497209..c8137053cc8 100644 --- 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 @@ -13,6 +13,7 @@ import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProce import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Leg; @@ -709,6 +710,8 @@ public interface TrackedRace extends Serializable, IsManagedByCache> implem private final ConcurrentMap currentLeg; private final MarkPassing NULL_MARK_PASSING = new MarkPassingImpl(null, null, null); - private final TrackedLegOfCompetitor NULL_TRACKED_LEG_OF_COMPETITOR = new TrackedLegOfCompetitorImpl(null, null); + private final TrackedLegOfCompetitor NULL_TRACKED_LEG_OF_COMPETITOR = new TrackedLegOfCompetitorImpl(null, null, null); /** * @param lessIsBetter diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java index 4a3e38f1fa9..8add03be58b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DummyMarkPassingWithTimePointOnly.java @@ -2,7 +2,6 @@ package com.sap.sailing.domain.tracking.impl; import java.net.URI; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorChangeListener; import com.sap.sailing.domain.base.SharedDomainFactory; @@ -58,10 +57,6 @@ public class DummyMarkPassingWithTimePointOnly implements MarkPassing { return null; } - @Override - public Boat getBoat() { - return null; - } @Override public IsManagedByCache resolve(SharedDomainFactory domainFactory) { return this; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java index 4c521b26d60..e25f67b5d89 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java @@ -71,7 +71,7 @@ public class TrackedLegImpl implements TrackedLeg { this.trackedRace = trackedRace; trackedLegsOfCompetitors = new HashMap(); for (Competitor competitor : competitors) { - trackedLegsOfCompetitors.put(competitor, new TrackedLegOfCompetitorImpl(this, competitor)); + trackedLegsOfCompetitors.put(competitor, new TrackedLegOfCompetitorImpl(this, competitor, trackedRace.getBoatOfCompetitor(competitor.getId()))); } trackedRace.addListener(new CacheClearingRaceChangeListener()); competitorTracksOrderedByRank = new ConcurrentHashMap<>(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java index 5cba23df87e..706b473dc5d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java @@ -7,6 +7,7 @@ import java.util.ListIterator; import java.util.NavigableSet; import java.util.Set; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; @@ -50,10 +51,12 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { private static final long serialVersionUID = -7060076837717432808L; private final TrackedLegImpl trackedLeg; private final Competitor competitor; + private final Boat boat; - public TrackedLegOfCompetitorImpl(TrackedLegImpl trackedLeg, Competitor competitor) { + public TrackedLegOfCompetitorImpl(TrackedLegImpl trackedLeg, Competitor competitor, Boat boat) { this.trackedLeg = trackedLeg; this.competitor = competitor; + this.boat = boat; } @Override @@ -66,6 +69,11 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { return competitor; } + @Override + public Boat getBoat() { + return boat; + } + @Override public Leg getLeg() { return trackedLeg.getLeg(); @@ -762,7 +770,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { */ private List getFixesToConsiderForManeuverLossAnalysis(TimePoint timePointBeforeManeuver, TimePoint maneuverTimePoint, TimePoint timePointAfterManeuver) { - final long EXCESS_TIME_BEFORE_MANEUVER_END_TO_SCAN_IN_MILLIS = getCompetitor().getBoat().getBoatClass().getApproximateManeuverDurationInMilliseconds(); + final long EXCESS_TIME_BEFORE_MANEUVER_END_TO_SCAN_IN_MILLIS = getBoat().getBoatClass().getApproximateManeuverDurationInMilliseconds(); final long EXCESS_TIME_AFTER_MANEUVER_END_TO_SCAN_IN_MILLIS = 3*EXCESS_TIME_BEFORE_MANEUVER_END_TO_SCAN_IN_MILLIS; List fixes = new ArrayList<>(); NavigableSet maxima = new ArrayListNavigableSet(new TimedComparator()); @@ -811,7 +819,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } // now remove all fixes before the last maximum before the fix with the lowest speed over ground during the maneuver if // there was such a maximum; otherwise, leave all fixes from the maneuver start on in place. - final long MAX_SMOOTHENING_INTERVAL_MILLIS = getCompetitor().getBoat().getBoatClass().getApproximateManeuverDurationInMilliseconds(); + final long MAX_SMOOTHENING_INTERVAL_MILLIS = getBoat().getBoatClass().getApproximateManeuverDurationInMilliseconds(); GPSFixMoving lastMaxSpeedFixBeforeLowSpeed = maxima.lower(fixWithLowestSpeedOverGround); // now check if there's a greater one that's only a little bit earlier if (lastMaxSpeedFixBeforeLowSpeed != null) { @@ -861,7 +869,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { if (maxSpeed != null) { double speedDifferenceBetweenMaxAndMinInKnots = maxSpeed.getKnots() - minimumSpeed.getKnots(); double lowestBadness = Double.MAX_VALUE; - final long approximateManeuverTimeInMillis = getCompetitor().getBoat().getBoatClass() + final long approximateManeuverTimeInMillis = getBoat().getBoatClass() .getApproximateManeuverDurationInMilliseconds(); final GPSFixTrack track = getTrackedRace().getTrack(getCompetitor()); for (GPSFixMoving minimum : minima) { 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 576a9768a73..9894b917ed6 100644 --- 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 @@ -53,6 +53,7 @@ import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -1414,6 +1415,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl return result; } + @Override + public Boat getBoatOfCompetitor(Serializable competitorId) { + return getRace().getBoatOfCompetitorById(competitorId); + } + @Override public List getCompetitorsFromBestToWorst(TimePoint timePoint) { return getCompetitorsFromBestToWorst(timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); @@ -2902,7 +2908,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl List result = new ArrayList(); List> group = new ArrayList>(); if (!courseChangeSequenceInSameDirection.isEmpty()) { - Distance threeHullLengths = competitor.getBoat().getBoatClass().getHullLength().scale(3); + Distance threeHullLengths = getBoatOfCompetitor(competitor).getBoatClass().getHullLength().scale(3); SpeedWithBearing beforeGroupOnApproximation = speedWithBearingOnApproximationAtBeginning; // speed/bearing before group SpeedWithBearing beforeCurrentCourseChangeOnApproximation = beforeGroupOnApproximation; // speed/bearing before current course change Iterator> iter = courseChangeSequenceInSameDirection.iterator(); 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 c81115d8799..cc91be5eb81 100644 --- 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 @@ -12,6 +12,7 @@ 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.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.Leg; @@ -870,4 +871,9 @@ public class MockedTrackedRace implements DynamicTrackedRace { public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { return null; } + + @Override + public Boat getBoatOfCompetitor(Serializable competitorId) { + 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 b5eac5bd4e5..860ea27982c 100644 --- 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 @@ -136,11 +136,9 @@ import com.sap.sailing.domain.base.configuration.impl.RacingProcedureWithConfigu import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; import com.sap.sailing.domain.base.configuration.impl.SWCStartConfigurationImpl; import com.sap.sailing.domain.base.configuration.procedures.ConfigurableStartModeFlagRacingProcedureConfiguration; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -3895,9 +3893,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S FleetDTO fleetDTO = new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null); seriesDTO.getFleets().add(fleetDTO); seriesDTO.getRaceColumns().addAll(convertToRaceColumnDTOs(leaderboard.getRaceColumns())); + for(Competitor c: leaderboard.getCompetitors()) { - if(c.getBoat() != null && c.getBoat().getBoatClass() != null) { - raceGroup.boatClass = c.getBoat().getBoatClass().getDisplayName(); + Boat b = null; // TODO: How di we get the boat? + if(b != null && b.getBoatClass() != null) { + raceGroup.boatClass = b.getBoatClass().getDisplayName(); } } } @@ -4803,21 +4803,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S // new competitor if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { UUID competitorUUID = UUID.randomUUID(); - BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(competitor.getBoatClass().getName()); DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - DynamicBoat boat = new BoatImpl(competitorUUID, competitor.getName() + " boat", boatClass, competitor.getSailID()); result = getBaseDomainFactory().convertToCompetitorDTO( getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, boat, + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag())); } else { result = getBaseDomainFactory().convertToCompetitorDTO( getService().apply( new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), competitor - .getColor(), competitor.getEmail(), competitor.getSailID(), nationality, + .getColor(), competitor.getEmail(), nationality, competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), competitor.getTimeOnTimeFactor(), @@ -4852,14 +4850,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S || competitorDescriptor.getCountryCode().getThreeLetterIOCCode().isEmpty()) ? null : getBaseDomainFactory().getOrCreateNationality(competitorDescriptor.getCountryCode().getThreeLetterIOCCode()); UUID competitorUUID = UUID.randomUUID(); - BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(competitorDescriptor.getBoatClassName()); DynamicPerson sailor = new PersonImpl(competitorDescriptor.getName(), nationality, null, null); DynamicTeam team = new TeamImpl(competitorDescriptor.getName(), Collections.singleton(sailor), null); - DynamicBoat boat = new BoatImpl(competitorUUID, competitorDescriptor.getBoatName(), boatClass, competitorDescriptor.getSailNumber()); Competitor competitor = new CompetitorImpl(competitorUUID, competitorDescriptor.getName(), competitorDescriptor.getSailNumber(), /* color */ null, /* eMail */ null, /* flag image */ null, team, - boat, competitorDescriptor.getTimeOnTimeFactor(), + competitorDescriptor.getTimeOnTimeFactor(), competitorDescriptor.getTimeOnDistanceAllowancePerNauticalMile(), searchTag); return competitor; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java index 449e1e85b95..a4d7a19ee72 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java @@ -75,7 +75,7 @@ public class StoreAndLoadDeviceIdentifierTest extends AbstractMongoDBTest { private DeviceIdentifier storeAndLoad(DeviceIdentifier device, TypeBasedServiceFinderFactory forStoring, TypeBasedServiceFinderFactory forLoading) { createFactories(forStoring); - Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("a", "a", "a", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("a", "a", "a", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 0, c, device, now(), now())); createFactories(forLoading); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index 880c72d692f..c2fcbc1cf4c 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -212,7 +212,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { public void testStoreAndLoadRegisterCompetitorEvent() { RaceLogRegisterCompetitorEvent expectedEvent = new RaceLogRegisterCompetitorEventImpl(expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, DomainFactory.INSTANCE.getOrCreateCompetitor( - "comp", "comp", "c", null, null, null, null, null, + "comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java index efeb87ebde2..da36787e694 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java @@ -60,7 +60,7 @@ public class StoreGPSFixTrackTest extends AbstractMongoDBTest { public void testStoreAndLoadFixes() throws TransformationException, NoCorrespondingServiceRegisteredException { TypeBasedServiceFinderFactory factory = new MockSmartphoneImeiServiceFinderFactory(); AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0); - Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, null, + Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark"); MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService(), factory); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 2c61609591d..374b2a1edf7 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -30,7 +30,7 @@ import com.mongodb.MongoException; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.DomainFactory; @@ -432,7 +432,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest // for some reason the dropping of collections doesn't work reliably on Linux... explicitly drop those collections that we depend on getMongoService().getDB().getCollection(CollectionNames.LEADERBOARDS.name()).drop(); getMongoService().getDB().getCollection(CollectionNames.REGATTAS.name()).drop(); - CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); + CompetitorAndBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); final DynamicTrackedRegatta[] trackedRegatta = new DynamicTrackedRegatta[1]; final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { @@ -892,7 +892,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); Map competitorsAndBoats = new LinkedHashMap<>(); - Competitor c = new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Competitor c = new CompetitorImpl("Axel", "Axel Uhl", "KYC", Color.RED, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat b = new BoatImpl("123", "boat", boatClass, "GER 124"); competitorsAndBoats.put(c, b); Iterable waypoints = Collections.emptyList(); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 94d4338169a..92499203998 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -26,7 +26,7 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -118,18 +118,18 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; @@ -177,18 +177,18 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; @@ -236,18 +236,18 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorWithBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorWithBoatImpl(hasso,hassosBoat)); + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index 504684a1a4b..31d4c8758a3 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -15,13 +15,13 @@ import org.junit.Test; import com.mongodb.MongoException; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -79,14 +79,14 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat wolfgangWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat wolfgangWithBoat = createCompetitorAndBoat(); Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat hassosBoat = new BoatImpl("123", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - CompetitorWithBoat hassoWithBoat = new CompetitorWithBoatImpl(hasso, hassosBoat); + CompetitorAndBoat hassoWithBoat = new CompetitorAndBoatImpl(hasso, hassosBoat); final String raceColumnName1 = "My First Race 1"; MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors(wolfgangWithBoat, /* rank */ 1, /* started */ true); raceWithTwoCompetitors.addCompetitorAndBoat(hassoWithBoat); @@ -124,7 +124,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); final String raceColumnName1 = "My First Race 1"; leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -172,7 +172,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false); leaderboard.setCarriedPoints(competitorWithBoat.getCompetitor(), carriedPointsForWolfgangHunger); @@ -197,7 +197,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -223,7 +223,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitor = createCompetitorAndBoat(); + CompetitorAndBoat competitor = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -249,7 +249,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -276,7 +276,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -314,7 +314,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - CompetitorWithBoat competitorWithBoat = createCompetitorAndBoat(); + CompetitorAndBoat competitorWithBoat = createCompetitorAndBoat(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); RaceColumn r1 = leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -359,10 +359,10 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { Competitor competitor = domainFactory.getOrCreateCompetitor(123, "$$$Dr. Wolfgang+Hunger$$$", "WH", Color.RED, "someone@nowhere.de", null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat = domainFactory.getOrCreateBoat(competitor, "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null, null); - CompetitorWithBoat competitorWithBoat = new CompetitorWithBoatImpl(competitor, boat); + CompetitorAndBoat competitorWithBoat = new CompetitorAndBoatImpl(competitor, boat); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitorWithBoat, /* rank */ 2, /* started */ true); leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false); @@ -385,12 +385,12 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { assertEquals(maxPointsReason, loadedLeaderboard2.getScoreCorrection().getMaxPointsReason(competitor, loadedColumn2, MillisecondsTimePoint.now())); } - private CompetitorWithBoat createCompetitorAndBoat() { + private CompetitorAndBoat createCompetitorAndBoat() { Competitor competitor = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Boat boat = new BoatImpl(competitor.getId(), "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - return new CompetitorWithBoatImpl(competitor, boat); + return new CompetitorAndBoatImpl(competitor, boat); } } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index 54cd25714ee..63cb280c63d 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -307,7 +307,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", - Color.RED, "someone@nowhere.de", null, null, null, + Color.RED, "someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ @@ -331,7 +331,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEventWithContents() { Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", - Color.RED, "someone@nowhere.de", null, null, null, + Color.RED, "someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); final TimePoint finishingTimePoint = MillisecondsTimePoint.now(); @@ -402,7 +402,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, - "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + "someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null, /* comment */null)); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index 11d5c05565d..d94d8a05fba 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -208,7 +208,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, - "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + "someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList); @@ -232,7 +232,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED, - "someone@nowhere.de", null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + "someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null)); RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList); diff --git a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/windestimation/TestWindEstimationFromManeuversOnAFew505Races.java b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/windestimation/TestWindEstimationFromManeuversOnAFew505Races.java index 06da43d7720..84837478ddf 100755 --- a/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/windestimation/TestWindEstimationFromManeuversOnAFew505Races.java +++ b/java/com.sap.sailing.polars.test/src/com/sap/sailing/polars/windestimation/TestWindEstimationFromManeuversOnAFew505Races.java @@ -18,7 +18,7 @@ import java.util.stream.Stream; import org.junit.Test; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.Wind; @@ -118,7 +118,7 @@ public class TestWindEstimationFromManeuversOnAFew505Races extends OnlineTracTra setUp("event_20110609_KielerWoch-505_Race_3"); ManeuverBasedWindEstimationTrackImpl windTrack = new ManeuverBasedWindEstimationTrackImpl(new PolarDataServiceImpl(), getTrackedRace(), /* millisecondsOverWhichToAverage */ 30000, /* waitForLatest */ true); - final Map maneuvers = windTrack.getAllManeuvers(/* waitForLatest */ true); + final Map maneuvers = windTrack.getAllManeuvers(/* waitForLatest */ true); final int numberOfClusters = 16; KMeansMappingClusterer, Pair, ScalableBearingAndScalableDouble> clusterer = new KMeansMappingClusterer<>(numberOfClusters, diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverBasedWindEstimationTrackImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverBasedWindEstimationTrackImpl.java index bf20e72e5fc..f8936cde028 100755 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverBasedWindEstimationTrackImpl.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverBasedWindEstimationTrackImpl.java @@ -12,10 +12,13 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.SpeedWithBearingWithConfidenceImpl; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.Distance; @@ -169,6 +172,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { */ public class ManeuverClassification { private final Competitor competitor; + private final Boat boat; private final TimePoint timePoint; private final Position position; /** @@ -181,9 +185,10 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { private Pair>[] likelihoodAndTWSBasedOnSpeedAndAngleCache; private ScalableBearingAndScalableDouble scalableMiddleManeuverCourseAndManeuverAngleDegCache; - protected ManeuverClassification(Competitor competitor, Maneuver maneuver) { + protected ManeuverClassification(CompetitorAndBoat competitorWithBoat, Maneuver maneuver) { super(); - this.competitor = competitor; + this.competitor = competitorWithBoat.getCompetitor(); + this.boat = competitorWithBoat.getBoat(); this.timePoint = maneuver.getTimePoint(); this.position = maneuver.getPosition(); this.maneuverAngleDeg = maneuver.getDirectionChangeInDegrees(); @@ -201,6 +206,10 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { return competitor; } + public Boat getBoat() { + return boat; + } + public TimePoint getTimePoint() { return timePoint; } @@ -231,7 +240,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { public SpeedWithBearingWithConfidence getEstimatedWindSpeedAndBearing(ManeuverType maneuverType) { Pair> likelihoodAndTWSBasedOnSpeedAndAngle = polarService - .getManeuverLikelihoodAndTwsTwa(getCompetitor().getBoat().getBoatClass(), + .getManeuverLikelihoodAndTwsTwa(getBoat().getBoatClass(), getSpeedAtManeuverStart(), getManeuverAngleDeg(), maneuverType); final SpeedWithBearingWithConfidenceImpl result; // if no reasonable wind speed was found for the maneuver speed, return null @@ -277,7 +286,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { final ManeuverType maneuverType) { if (likelihoodAndTWSBasedOnSpeedAndAngleCache[maneuverType.ordinal()] == null) { likelihoodAndTWSBasedOnSpeedAndAngleCache[maneuverType.ordinal()] = polarService - .getManeuverLikelihoodAndTwsTwa(getCompetitor().getBoat().getBoatClass(), + .getManeuverLikelihoodAndTwsTwa(getBoat().getBoatClass(), getSpeedAtManeuverStart(), getManeuverAngleDeg(), maneuverType); } return likelihoodAndTWSBasedOnSpeedAndAngleCache[maneuverType.ordinal()]; @@ -378,7 +387,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { */ private Triple, Pair, ScalableBearingAndScalableDouble>>, List, Pair, ScalableBearingAndScalableDouble>>, List, Pair, ScalableBearingAndScalableDouble>>> analyzeRace( boolean waitForLatest) throws NotEnoughDataHasBeenAddedException { - final Map maneuvers = getAllManeuvers(waitForLatest); + final Map maneuvers = getAllManeuvers(waitForLatest); // cluster into eight clusters by middle COG first, then aggregate tack likelihoods for each, and jibe // likelihoods for opposite cluster final int numberOfClusters = 16; @@ -773,7 +782,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { /** * For each maneuver from maneuvers, a {@link ManeuverClassification object} is created. */ - Stream getManeuverClassifications(final Map maneuvers) { + Stream getManeuverClassifications(final Map maneuvers) { return maneuvers .entrySet() .stream() @@ -784,11 +793,13 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { /** * Package scope to let test fragment access it */ - Map getAllManeuvers(boolean waitForLatest) { - Map maneuvers = new HashMap<>(); + Map getAllManeuvers(boolean waitForLatest) { + Map maneuvers = new HashMap<>(); final Waypoint firstWaypoint = trackedRace.getRace().getCourse().getFirstWaypoint(); final Waypoint lastWaypoint = trackedRace.getRace().getCourse().getLastWaypoint(); - for (Competitor competitor : trackedRace.getRace().getCompetitors()) { + for (Map.Entry competitorAndBoat : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { + Competitor competitor = competitorAndBoat.getKey(); + Boat boat = competitorAndBoat.getValue(); final TimePoint from = Util.getFirstNonNull( firstWaypoint == null ? null : trackedRace.getMarkPassing(competitor, firstWaypoint) == null ? null : trackedRace.getMarkPassing(competitor, firstWaypoint).getTimePoint(), trackedRace @@ -798,7 +809,7 @@ public class ManeuverBasedWindEstimationTrackImpl extends WindTrackImpl { : trackedRace.getMarkPassing(competitor, lastWaypoint).getTimePoint(), trackedRace .getEndOfRace(), trackedRace.getEndOfTracking(), MillisecondsTimePoint.now()); for (Maneuver maneuver : trackedRace.getManeuvers(competitor, from, to, waitForLatest)) { - maneuvers.put(maneuver, competitor); + maneuvers.put(maneuver, new CompetitorAndBoatImpl(competitor, boat)); } } return Collections.unmodifiableMap(maneuvers); diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverClassificationToHasConfidenceAndIsScalableAdapter.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverClassificationToHasConfidenceAndIsScalableAdapter.java index 9191820a9b3..2d9117dc2ac 100755 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverClassificationToHasConfidenceAndIsScalableAdapter.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/windestimation/ManeuverClassificationToHasConfidenceAndIsScalableAdapter.java @@ -56,7 +56,7 @@ public class ManeuverClassificationToHasConfidenceAndIsScalableAdapter { - protected final CompetitorFactory competitorFactory; - protected final JsonDeserializer teamJsonDeserializer; - protected final JsonDeserializer boatJsonDeserializer; - private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName()); - - public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) { - return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( - new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); - } - - public CompetitorJsonDeserializer(CompetitorFactory competitorFactory) { - this(competitorFactory, null, /* boatDeserializer */ null); - } - - public CompetitorJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorFactory = competitorFactory; - this.teamJsonDeserializer = teamJsonDeserializer; - this.boatJsonDeserializer = boatDeserializer; - } - - @Override - public Competitor deserialize(JSONObject object) throws JsonDeserializationException { - Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); - try { - Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); - if (Number.class.isAssignableFrom(idClass)) { - Constructor constructorFromString = idClass.getConstructor(String.class); - competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); - } else if (UUID.class.isAssignableFrom(idClass)) { - competitorId = Helpers.tryUuidConversion(competitorId); - } - String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); - String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); - String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); - String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); - String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); - - URI flagImageURI = null; - String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); - if (flagImageURIAsString != null) { - try { - flagImageURI = URI.create(flagImageURIAsString); - } catch (IllegalArgumentException e) { - logger.warning("Illegal flag image URI " + e.getMessage()); - } - } - - final Color displayColor; - if (displayColorAsString == null || displayColorAsString.isEmpty()) { - displayColor = null; - } else { - displayColor = new RGBColor(displayColorAsString); - } - DynamicTeam team = null; - DynamicBoat boat = null; - if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { - team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_TEAM)); - } - if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { - boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_BOAT)); - } - final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); - final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object - .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, - flagImageURI, team, boat, timeOnTimeFactor, - timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); - return competitor; - } catch (Exception e) { - throw new JsonDeserializationException(e); - } - } -} +package com.sap.sailing.server.gateway.deserialization.impl; + +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.util.UUID; +import java.util.logging.Logger; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sse.common.Color; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.RGBColor; + +public class CompetitorJsonDeserializer implements JsonDeserializer { + protected final CompetitorFactory competitorFactory; + protected final JsonDeserializer teamJsonDeserializer; + + private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName()); + + public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) { + return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( + new NationalityJsonDeserializer(baseDomainFactory)))); + } + + public CompetitorJsonDeserializer(CompetitorFactory competitorFactory) { + this(competitorFactory, null); + } + + public CompetitorJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer) { + this.competitorFactory = competitorFactory; + this.teamJsonDeserializer = teamJsonDeserializer; + } + + @Override + public Competitor deserialize(JSONObject object) throws JsonDeserializationException { + Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); + try { + Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); + if (Number.class.isAssignableFrom(idClass)) { + Constructor constructorFromString = idClass.getConstructor(String.class); + competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); + } else if (UUID.class.isAssignableFrom(idClass)) { + competitorId = Helpers.tryUuidConversion(competitorId); + } + String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); + String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); + String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); + String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); + String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); + + URI flagImageURI = null; + String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); + if (flagImageURIAsString != null) { + try { + flagImageURI = URI.create(flagImageURIAsString); + } catch (IllegalArgumentException e) { + logger.warning("Illegal flag image URI " + e.getMessage()); + } + } + + final Color displayColor; + if (displayColorAsString == null || displayColorAsString.isEmpty()) { + displayColor = null; + } else { + displayColor = new RGBColor(displayColorAsString); + } + DynamicTeam team = null; + if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { + team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_TEAM)); + } + final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); + final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object + .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); + Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, + flagImageURI, team, timeOnTimeFactor, + timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); + return competitor; + } catch (Exception e) { + throw new JsonDeserializationException(e); + } + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java new file mode 100644 index 00000000000..1b11391733e --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java @@ -0,0 +1,105 @@ +package com.sap.sailing.server.gateway.deserialization.impl; + +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.util.UUID; +import java.util.logging.Logger; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sse.common.Color; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.RGBColor; + +public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { + protected final CompetitorFactory competitorFactory; + protected final JsonDeserializer teamJsonDeserializer; + protected final JsonDeserializer boatJsonDeserializer; + private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); + + public static CompetitorWithBoatJsonDeserializer create(SharedDomainFactory baseDomainFactory) { + return new CompetitorWithBoatJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( + new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); + } + + public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory) { + this(competitorFactory, null, /* boatDeserializer */ null); + } + + public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorFactory = competitorFactory; + this.teamJsonDeserializer = teamJsonDeserializer; + this.boatJsonDeserializer = boatDeserializer; + } + + @Override + public CompetitorAndBoat deserialize(JSONObject object) throws JsonDeserializationException { + Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); + try { + Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); + if (Number.class.isAssignableFrom(idClass)) { + Constructor constructorFromString = idClass.getConstructor(String.class); + competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); + } else if (UUID.class.isAssignableFrom(idClass)) { + competitorId = Helpers.tryUuidConversion(competitorId); + } + String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); + String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); + String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); + String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); + String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); + + URI flagImageURI = null; + String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); + if (flagImageURIAsString != null) { + try { + flagImageURI = URI.create(flagImageURIAsString); + } catch (IllegalArgumentException e) { + logger.warning("Illegal flag image URI " + e.getMessage()); + } + } + + final Color displayColor; + if (displayColorAsString == null || displayColorAsString.isEmpty()) { + displayColor = null; + } else { + displayColor = new RGBColor(displayColorAsString); + } + DynamicTeam team = null; + DynamicBoat boat = null; + if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { + team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_TEAM)); + } + if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { + boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_BOAT)); + String sailID = (String) object.get(CompetitorJsonConstants.FIELD_SAIL_ID); + boat.setSailId(sailID); + } + final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); + final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object + .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); + Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, + flagImageURI, team, timeOnTimeFactor, + timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); + + return new CompetitorAndBoatImpl(competitor, boat); + } catch (Exception e) { + throw new JsonDeserializationException(e); + } + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index 4bbca31c60c..f907d6ddcf2 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -1,93 +1,81 @@ -package com.sap.sailing.server.gateway.serialization.impl; - -import java.io.Serializable; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Nationality; -import com.sap.sailing.domain.base.Team; -import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sse.common.Color; -import com.sap.sse.common.CountryCode; - -public class CompetitorJsonSerializer implements JsonSerializer { - public static final String FIELD_ID = "id"; - - private final JsonSerializer teamJsonSerializer; - private final JsonSerializer boatJsonSerializer; - - public static CompetitorJsonSerializer create() { - return new CompetitorJsonSerializer(TeamJsonSerializer.create(), BoatJsonSerializer.create()); - } - - public CompetitorJsonSerializer() { - this(null, null); - } - - public CompetitorJsonSerializer(JsonSerializer teamJsonSerializer, JsonSerializer teamBoatSerializer) { - this.teamJsonSerializer = teamJsonSerializer; - this.boatJsonSerializer = teamBoatSerializer; - } - - public static JSONObject getCompetitorIdQuery(Competitor competitor) { - JSONObject result = new JSONObject(); - Serializable competitorId = competitor.getId() instanceof UUID ? competitor.getId().toString() : competitor.getId(); - result.put(FIELD_ID, competitorId); - return result; - } - - @Override - public JSONObject serialize(Competitor competitor) { - JSONObject result = new JSONObject(); - // Special treatment for UUIDs. They are represented as String because JSON doesn't have a way to represent them otherwise. - // However, other, e.g., numeric, types used to encode a serializable ID must be preserved according to JSON semantics. - // Also see the corresponding case distinction in the deserialized which first tries to parse a string as a UUID becore - // returning the ID as is. - result.put(CompetitorJsonConstants.FIELD_ID_TYPE, competitor.getId().getClass().getName()); - Set> entries = getCompetitorIdQuery(competitor).entrySet(); - for (Entry idKeyAndValue : entries) { - result.put(idKeyAndValue.getKey(), idKeyAndValue.getValue()); - } - result.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); - result.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); - Color color = getColor(competitor); - result.put(CompetitorJsonConstants.FIELD_DISPLAY_COLOR, color == null ? null : color.getAsHtml()); - result.put(CompetitorJsonConstants.FIELD_EMAIL, competitor.getEmail()); - result.put(CompetitorJsonConstants.FIELD_SEARCHTAG, competitor.getSearchTag()); - result.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID()); - final Nationality nationality = competitor.getTeam() == null ? null : competitor.getTeam().getNationality(); - result.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality == null ? "" : nationality.getThreeLetterIOCAcronym()); - CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - result.put(CompetitorJsonConstants.FIELD_NATIONALITY_ISO2, countryCode == null ? "" : countryCode.getTwoLetterISOCode()); - result.put(CompetitorJsonConstants.FIELD_NATIONALITY_ISO3, countryCode == null ? "" : countryCode.getThreeLetterISOCode()); - if (competitor.getFlagImage() != null) { - result.put(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI, competitor.getFlagImage().toString()); - } - if (teamJsonSerializer != null) { - result.put(CompetitorJsonConstants.FIELD_TEAM, teamJsonSerializer.serialize(competitor.getTeam())); - } - if (boatJsonSerializer != null) { - result.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(getBoat(competitor))); - } - result.put(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR, competitor.getTimeOnTimeFactor()); - result.put(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE, - competitor.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : - competitor.getTimeOnDistanceAllowancePerNauticalMile().asSeconds()); - return result; - } - - protected Color getColor(Competitor competitor ) { - return competitor.getColor(); - } - - protected Boat getBoat(Competitor competitor ) { - return competitor.getBoat(); - } - -} +package com.sap.sailing.server.gateway.serialization.impl; + +import java.io.Serializable; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Nationality; +import com.sap.sailing.domain.base.Team; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sse.common.Color; +import com.sap.sse.common.CountryCode; + +public class CompetitorJsonSerializer implements JsonSerializer { + public static final String FIELD_ID = "id"; + + private final JsonSerializer teamJsonSerializer; + + public static CompetitorJsonSerializer create() { + return new CompetitorJsonSerializer(TeamJsonSerializer.create()); + } + + public CompetitorJsonSerializer() { + this(null); + } + + public CompetitorJsonSerializer(JsonSerializer teamJsonSerializer) { + this.teamJsonSerializer = teamJsonSerializer; + } + + public static JSONObject getCompetitorIdQuery(Competitor competitor) { + JSONObject result = new JSONObject(); + Serializable competitorId = competitor.getId() instanceof UUID ? competitor.getId().toString() : competitor.getId(); + result.put(FIELD_ID, competitorId); + return result; + } + + @Override + public JSONObject serialize(Competitor competitor) { + JSONObject result = new JSONObject(); + // Special treatment for UUIDs. They are represented as String because JSON doesn't have a way to represent them otherwise. + // However, other, e.g., numeric, types used to encode a serializable ID must be preserved according to JSON semantics. + // Also see the corresponding case distinction in the deserialized which first tries to parse a string as a UUID becore + // returning the ID as is. + result.put(CompetitorJsonConstants.FIELD_ID_TYPE, competitor.getId().getClass().getName()); + Set> entries = getCompetitorIdQuery(competitor).entrySet(); + for (Entry idKeyAndValue : entries) { + result.put(idKeyAndValue.getKey(), idKeyAndValue.getValue()); + } + result.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); + result.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); + Color color = getColor(competitor); + result.put(CompetitorJsonConstants.FIELD_DISPLAY_COLOR, color == null ? null : color.getAsHtml()); + result.put(CompetitorJsonConstants.FIELD_EMAIL, competitor.getEmail()); + result.put(CompetitorJsonConstants.FIELD_SEARCHTAG, competitor.getSearchTag()); + final Nationality nationality = competitor.getTeam() == null ? null : competitor.getTeam().getNationality(); + result.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality == null ? "" : nationality.getThreeLetterIOCAcronym()); + CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); + result.put(CompetitorJsonConstants.FIELD_NATIONALITY_ISO2, countryCode == null ? "" : countryCode.getTwoLetterISOCode()); + result.put(CompetitorJsonConstants.FIELD_NATIONALITY_ISO3, countryCode == null ? "" : countryCode.getThreeLetterISOCode()); + if (competitor.getFlagImage() != null) { + result.put(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI, competitor.getFlagImage().toString()); + } + if (teamJsonSerializer != null) { + result.put(CompetitorJsonConstants.FIELD_TEAM, teamJsonSerializer.serialize(competitor.getTeam())); + } + result.put(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR, competitor.getTimeOnTimeFactor()); + result.put(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE, + competitor.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : + competitor.getTimeOnDistanceAllowancePerNauticalMile().asSeconds()); + return result; + } + + protected Color getColor(Competitor competitor ) { + return competitor.getColor(); + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java new file mode 100644 index 00000000000..9a2ba017748 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java @@ -0,0 +1,39 @@ +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class CompetitorWithBoatJsonSerializer implements JsonSerializer { + private final JsonSerializer boatJsonSerializer; + private final JsonSerializer competitorJsonSerializer; + + public static CompetitorWithBoatJsonSerializer create() { + return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); + } + + public CompetitorWithBoatJsonSerializer() { + this(null, null); + } + + public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { + this.competitorJsonSerializer = competitorJsonSerializer; + this.boatJsonSerializer = boatJsonSerializer; + } + + @Override + public JSONObject serialize(CompetitorAndBoat competitorAndBoat) { + JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getCompetitor()); + + serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitorAndBoat.getBoat() == null ? "" : competitorAndBoat.getBoat().getSailID()); + + if (boatJsonSerializer != null) { + serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitorAndBoat.getBoat())); + } + return serializedCompetitor; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java index 7a05e55e1ba..253e178a563 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java @@ -4,8 +4,6 @@ import static org.junit.Assert.assertEquals; import java.util.UUID; -import junit.framework.Assert; - import org.json.simple.JSONObject; import org.junit.Before; import org.junit.Test; @@ -45,6 +43,8 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; +import junit.framework.Assert; + public class RaceLogCourseDesignChangedEventSerializerTest { private RaceLogCourseDesignChangedEventSerializer serializer; diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 5d93aaa749e..48ad5af81ba 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -242,7 +242,7 @@ public class RaceLogEventSerializerTest { // we use the real event type here because we do not want to re-implement the dispatching. RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0, DomainFactory.INSTANCE - .getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ + .getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); serializer.serialize(event); verify(registerCompetitorEventSerializer).serialize(event); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java index 9735e2dbb04..39ecdf518d3 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -48,8 +48,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { public void setUp() { SharedDomainFactory factory = DomainFactory.INSTANCE; serializer = new RaceLogFinishPositioningConfirmedEventSerializer(new CompetitorJsonSerializer( - new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer())), null)); - deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null, /* boatDeserializer */ null)); + new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer())))); + deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null)); now = MillisecondsTimePoint.now(); positioningList = new CompetitorResultsImpl(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java index adabeedbc05..3ee5c285332 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java @@ -49,9 +49,9 @@ public class RaceLogWindFixEventSerializerTest { public void setUp() { SharedDomainFactory factory = DomainFactory.INSTANCE; serializer = new RaceLogWindFixEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer( - new PersonJsonSerializer(new NationalityJsonSerializer())), null), new WindJsonSerializer( + new PersonJsonSerializer(new NationalityJsonSerializer()))), new WindJsonSerializer( new PositionJsonSerializer())); - deserializer = new RaceLogWindFixEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null, /* boatDeserializer */ null), + deserializer = new RaceLogWindFixEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null), new WindJsonDeserializer(new PositionJsonDeserializer())); now = MillisecondsTimePoint.now(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java index 368d8c554b7..c972f350d76 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java @@ -20,8 +20,6 @@ import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeseria import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogEndOfTrackingEventDeserializer; import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogStartOfTrackingEventDeserializer; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; @@ -54,8 +52,7 @@ public class TrackingTimesEventSerializerTest { private CompetitorJsonSerializer createCompetitorSerializer() { return new CompetitorJsonSerializer(new TeamJsonSerializer( - new PersonJsonSerializer(new NationalityJsonSerializer())), new BoatJsonSerializer( - new BoatClassJsonSerializer())); + new PersonJsonSerializer(new NationalityJsonSerializer()))); } @Test diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithChangingBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithChangingBoatJsonSerializer.java deleted file mode 100644 index 3e2056ab668..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithChangingBoatJsonSerializer.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.impl; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Team; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sse.common.Color; - -/** - * This is a workaround for the serialization of a competitor with changing boats. - * The class should be removed after bug https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2822 is resolved. - * @author Frank - * - */ -public class CompetitorWithChangingBoatJsonSerializer extends CompetitorJsonSerializer { - private final RaceDefinition race; - - public CompetitorWithChangingBoatJsonSerializer() { - this(null, null, null); - } - - public CompetitorWithChangingBoatJsonSerializer(RaceDefinition race, JsonSerializer teamJsonSerializer, JsonSerializer boatSerializer) { - super(teamJsonSerializer, boatSerializer); - this.race = race; - } - - @Override - protected Color getColor(Competitor competitor ) { - if (race != null) { - Boat boatOfCompetitor = race.getBoatOfCompetitorById(competitor.getId()); - if (boatOfCompetitor != null) { - return boatOfCompetitor.getColor(); - } - } - return super.getColor(competitor); - } - - @Override - protected Boat getBoat(Competitor competitor ) { - if (race != null) { - Boat boatOfCompetitor = race.getBoatOfCompetitorById(competitor.getId()); - if (boatOfCompetitor != null) { - return boatOfCompetitor; - } - } - return super.getBoat(competitor); - } -} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java index 2a2ee0331e3..9f79007be27 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java @@ -1,9 +1,13 @@ package com.sap.sailing.server.gateway.serialization.impl; +import java.util.Map.Entry; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; @@ -12,10 +16,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public final static String MANEUVERS = "maneuvers"; - private final CompetitorJsonSerializer competitorSerializer; + private final CompetitorWithBoatJsonSerializer competitorSerializer; private final ManeuverJsonSerializer maneuverSerializer; - public ManeuversJsonSerializer(CompetitorJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { super(); this.competitorSerializer = competitorSerializer; this.maneuverSerializer = maneuverSerializer; @@ -26,10 +30,12 @@ public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializ final JSONObject result = new JSONObject(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); - for (Competitor competitor : trackedRace.getRace().getCompetitors()) { + for (Entry competitorAndBoatEntry : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { + Competitor competitor = competitorAndBoatEntry.getKey(); + Boat boat = competitorAndBoatEntry.getValue(); final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(competitor)); + forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); final JSONArray maneuvers = new JSONArray(); forCompetitorJson.put(MANEUVERS, maneuvers); for (final Maneuver maneuver : getManeuversDuringRace(trackedRace, competitor)) { diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java index 97ba39bbae6..905a043ff6f 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java @@ -1,14 +1,17 @@ package com.sap.sailing.server.gateway.serialization.impl; import java.text.SimpleDateFormat; +import java.util.Map.Entry; import java.util.NavigableSet; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; @@ -23,13 +26,16 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria public JSONObject serialize(TrackedRace trackedRace) { final Course course = trackedRace.getRace().getCourse(); JSONObject result = new JSONObject(); - CompetitorJsonSerializer competitorSerializer = new CompetitorJsonSerializer(null, BoatJsonSerializer.create()); + CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); + CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); - for (Competitor competitor : trackedRace.getRace().getCompetitors()) { + for (Entry competitorAndBoatEntry : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { + Competitor competitor = competitorAndBoatEntry.getKey(); + Boat boat = competitorAndBoatEntry.getValue(); JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(competitor)); + forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); final NavigableSet markPassingsForCompetitor = trackedRace.getMarkPassings(competitor); JSONArray markPassingsForCompetitorJson = new JSONArray(); forCompetitorJson.put(MARKPASSINGS, markPassingsForCompetitorJson); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java index 37f9c7bc4eb..859140b0d90 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java @@ -1,33 +1,39 @@ package com.sap.sailing.server.gateway.serialization.impl; +import java.util.Map.Entry; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.server.gateway.serialization.JsonSerializer; public class RaceEntriesJsonSerializer implements JsonSerializer { public static final String FIELD_NAME = "name"; public static final String FIELD_COMPETITORS = "competitors"; - private final JsonSerializer competitorSerializer; + private final JsonSerializer competitorAndBoatSerializer; public RaceEntriesJsonSerializer() { this(null); } - public RaceEntriesJsonSerializer(JsonSerializer competitorSerializer) { - this.competitorSerializer = competitorSerializer; + public RaceEntriesJsonSerializer(JsonSerializer competitorAndBoatSerializer) { + this.competitorAndBoatSerializer = competitorAndBoatSerializer; } public JSONObject serialize(RaceDefinition race) { JSONObject result = new JSONObject(); result.put(FIELD_NAME, race.getName()); - if(competitorSerializer != null) { + if(competitorAndBoatSerializer != null) { JSONArray competitorsJson = new JSONArray(); - for (Competitor competitor: race.getCompetitors()) { - competitorsJson.add(competitorSerializer.serialize(competitor)); + for (Entry competitorAndBoatEntry: race.getCompetitorsAndTheirBoats().entrySet()) { + competitorsJson.add(competitorAndBoatSerializer.serialize(new CompetitorAndBoatImpl(competitorAndBoatEntry.getKey(), + competitorAndBoatEntry.getValue()))); } result.put(FIELD_COMPETITORS, competitorsJson); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java index 9dfec145385..540e1775c1e 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/AbstractJsonExportTest.java @@ -19,10 +19,7 @@ import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -86,15 +83,14 @@ public abstract class AbstractJsonExportTest { protected List createCompetitors(int numberOfCompetitorsToCreate) { List result = new ArrayList(); - BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; Competitor competitor = new CompetitorImpl(UUID.randomUUID(), competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); result.add(competitor); } return result; diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java index 4fbc07d89ae..501898adcfe 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/AbstractJaxRsApiTest.java @@ -13,10 +13,7 @@ import java.util.List; import javax.ws.rs.core.Response; -import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -75,15 +72,14 @@ public abstract class AbstractJaxRsApiTest { protected List createCompetitors(int numberOfCompetitorsToCreate) { List result = new ArrayList(); - BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); for (int i = 1; i <= numberOfCompetitorsToCreate; i++) { String competitorName = "C" + i; Competitor competitor = new CompetitorImpl(new Integer(i), competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", boatClass, null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); result.add(competitor); } return result; diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java index 14ce55b2cbe..05a32664735 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTeamImageTest.java @@ -18,9 +18,6 @@ import org.json.simple.parser.ParseException; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -36,8 +33,6 @@ import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport; public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { private static final String name = "Heiko KRÖGER"; private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; - private static final String boatClassName = "49er"; - private static final String sailID = "GER 1"; private static final String nationality = "GER"; private static final String teamImageFile = "Bundesliga2014_Regatta6_eventteaser.jpg"; @@ -53,8 +48,7 @@ public class CompetitorsResourceTeamImageTest extends AbstractJaxRsApiTest { doReturn(storageService).when(fsmsMock).getActiveFileStorageService(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl( nationality), null, null)), null); - DynamicBoat boat = new BoatImpl("123", "My boat", new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, null, team, boat, + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, null, null, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java index fe7184ec23c..f2c00ec4128 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/CompetitorsResourceTest.java @@ -10,9 +10,6 @@ import org.json.simple.JSONValue; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -33,8 +30,7 @@ public class CompetitorsResourceTest extends AbstractJaxRsApiTest { public void setUp() { super.setUp(); DynamicTeam team = new TeamImpl(null, Collections.singleton(new PersonImpl(null, new NationalityImpl(nationality), null, null)), null); - DynamicBoat boat = new BoatImpl("123", "My boat", new BoatClassImpl(boatClassName, false), sailID); - racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, shortName, null, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + racingEventService.getBaseDomainFactory().getOrCreateCompetitor(id, name, shortName, null, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); } @Test diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index 84b3945fd21..39d05a54f2b 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -24,7 +24,6 @@ import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnaly import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; @@ -49,7 +48,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest super.setUp(); Competitor c = createCompetitors(1).get(0); competitor = racingEventService.getBaseDomainFactory().getOrCreateCompetitor(c.getId(), c.getName(), c.getShortName(), - c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), (DynamicBoat) c.getBoat(), + c.getColor(), c.getEmail(), c.getFlagImage(), (DynamicTeam) c.getTeam(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); Regatta regatta = new RegattaImpl("regatta", new BoatClassImpl("49er", false), /* canBoatsOfCompetitorsChangePerRace */ true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), Collections.singleton(new SeriesImpl("series", false, /* isFleetsCanRunInParallel */ true, Collections diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java index 8efd5107173..c081d134603 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/CompetitorsJsonExportServlet.java @@ -15,12 +15,7 @@ import com.sap.sailing.domain.common.racelog.RaceLogServletConstants; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.gateway.AbstractJsonHttpServlet; -import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; public class CompetitorsJsonExportServlet extends AbstractJsonHttpServlet { private static final long serialVersionUID = 4510175441769759252L; @@ -62,8 +57,7 @@ public class CompetitorsJsonExportServlet extends AbstractJsonHttpServlet { return; } JSONArray result = new JSONArray(); - CompetitorJsonSerializer serializer = new CompetitorJsonSerializer(new TeamJsonSerializer( - new PersonJsonSerializer(new NationalityJsonSerializer())), new BoatJsonSerializer(new BoatClassJsonSerializer())); + CompetitorJsonSerializer serializer = CompetitorJsonSerializer.create(); for (Competitor competitor : leaderboard.getCompetitors(raceColumn, fleet)) { result.add(serializer.serialize(competitor)); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java new file mode 100644 index 00000000000..822b5cfe014 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatsResource.java @@ -0,0 +1,47 @@ +package com.sap.sailing.server.gateway.jaxrs.api; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang.StringEscapeUtils; +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.common.tracking.impl.BoatJsonConstants; +import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; + +@Path("/v1/boats") +public class BoatsResource extends AbstractSailingServerResource { + + public static JSONObject getBoatJSON(Boat boat) { + JSONObject json = new JSONObject(); + json.put(BoatJsonConstants.FIELD_ID, boat.getId().toString()); + json.put(BoatJsonConstants.FIELD_NAME, boat.getName()); + json.put(BoatJsonConstants.FIELD_SAIL_ID, boat.getSailID()); + json.put(BoatJsonConstants.FIELD_BOAT_CLASS_NAME, boat.getBoatClass().getName()); + json.put(BoatJsonConstants.FIELD_COLOR, boat.getColor() != null ? boat.getColor().getAsHtml() : null); + return json; + } + + @GET + @Produces("application/json;charset=UTF-8") + @Path("{boatId}") + public Response getBoat(@PathParam("boatId") String boatIdAsString) { + Response response; + Boat boat = getService().getCompetitorStore().getExistingBoatByIdAsString(boatIdAsString); + if (boat == null) { + response = Response.status(Status.NOT_FOUND) + .entity("Could not find a competitor with id '" + StringEscapeUtils.escapeHtml(boatIdAsString) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + String jsonString = getBoatJSON(boat).toJSONString(); + response = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } + return response; + } +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 044214428e3..7cf7572c234 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -52,11 +52,10 @@ public class CompetitorsResource extends AbstractSailingServerResource { JSONObject json = new JSONObject(); json.put(CompetitorJsonConstants.FIELD_ID, competitor.getId().toString()); json.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); - json.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat().getSailID()); + json.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); final Nationality nationality = competitor.getTeam().getNationality(); json.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality==null?null:nationality.getThreeLetterIOCAcronym()); json.put(CompetitorJsonConstants.FIELD_COUNTRY_CODE, nationality==null?null:nationality.getCountryCode().getTwoLetterISOCode()); - json.put(CompetitorJsonConstants.FIELD_BOAT_CLASS_NAME, competitor.getBoat().getBoatClass().getName()); json.put(CompetitorJsonConstants.FIELD_COLOR, competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); if (competitor.getFlagImage() != null) { json.put(CompetitorJsonConstants.FIELD_FLAG_IMAGE, competitor.getFlagImage().toString()); @@ -166,7 +165,7 @@ public class CompetitorsResource extends AbstractSailingServerResource { getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), - competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), + competitor.getTeam().getNationality(), imageUri, competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, competitor.getSearchTag()); logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index d6b8a08fee3..2c49145e136 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -43,6 +43,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpe import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.OpenEndedDeviceMappingFinder; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; @@ -232,7 +233,9 @@ public class LeaderboardsResource extends AbstractSailingServerResource { final String displayName = leaderboard.getDisplayName(competitor); jsonCompetitor.put("displayName", displayName == null ? competitor.getName() : displayName); jsonCompetitor.put("id", competitor.getId().toString()); - jsonCompetitor.put("sailID", competitor.getBoat().getSailID()); + final Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); + final String sailID = boatOfCompetitor != null ? boatOfCompetitor.getSailID() : null; + jsonCompetitor.put("sailID", sailID); Nationality nationality = competitor.getTeam().getNationality(); jsonCompetitor.put("nationality", nationality != null ? nationality.getThreeLetterIOCAcronym() : null); jsonCompetitor.put("countryCode", nationality != null ? (nationality.getCountryCode() != null ? nationality diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index f7102d090a3..01af256a9c8 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -28,12 +28,14 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.sap.sailing.datamining.SailingPredefinedQueries; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; 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.Waypoint; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Position; @@ -61,11 +63,9 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSeri import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.AbstractTrackedRaceDataJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithChangingBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DefaultWindTrackJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DistanceJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer; @@ -179,8 +179,7 @@ public class RegattasResource extends AbstractSailingServerResource { } else { NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer(); CompetitorJsonSerializer competitorJsonSerializer = new CompetitorJsonSerializer(new TeamJsonSerializer( - new PersonJsonSerializer(nationalityJsonSerializer)), new BoatJsonSerializer( - new BoatClassJsonSerializer())); + new PersonJsonSerializer(nationalityJsonSerializer))); JsonSerializer regattaSerializer = new RegattaJsonSerializer(null, competitorJsonSerializer); JSONObject serializedRegatta = regattaSerializer.serialize(regatta); @@ -210,10 +209,7 @@ public class RegattasResource extends AbstractSailingServerResource { if (race == null) { response = getBadRaceErrorResponse(regattaName, raceName); } else { - NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer(); - CompetitorJsonSerializer competitorJsonSerializer = new CompetitorWithChangingBoatJsonSerializer(race, new TeamJsonSerializer( - new PersonJsonSerializer(nationalityJsonSerializer)), new BoatJsonSerializer( - new BoatClassJsonSerializer())); + CompetitorWithBoatJsonSerializer competitorJsonSerializer = CompetitorWithBoatJsonSerializer.create(); JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorJsonSerializer); JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race); @@ -283,7 +279,7 @@ public class RegattasResource extends AbstractSailingServerResource { JSONObject jsonCompetitor = new JSONObject(); jsonCompetitor.put("id", competitor.getId() != null ? competitor.getId().toString() : null); jsonCompetitor.put("name", competitor.getName()); - jsonCompetitor.put("sailNumber", competitor.getBoat().getSailID()); + jsonCompetitor.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()); jsonCompetitor.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); if(competitor.getFlagImage() != null) { jsonCompetitor.put("flagImage", competitor.getFlagImage().toString()); @@ -863,7 +859,7 @@ public class RegattasResource extends AbstractSailingServerResource { .build(); } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); - ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorJsonSerializer(), + ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorWithBoatJsonSerializer(), new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer())); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); @@ -932,10 +928,11 @@ public class RegattasResource extends AbstractSailingServerResource { return result; }); } - CompetitorJsonSerializer serializer = new CompetitorJsonSerializer(); + CompetitorWithBoatJsonSerializer serializer = new CompetitorWithBoatJsonSerializer(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { - JSONObject jsonCompetitor = serializer.serialize(c); + Boat boat = trackedRace.getBoatOfCompetitor(c.getId()); + JSONObject jsonCompetitor = serializer.serialize(new CompetitorAndBoatImpl(c, boat)); result.add(jsonCompetitor); } String json = result.toJSONString(); @@ -1049,7 +1046,7 @@ public class RegattasResource extends AbstractSailingServerResource { jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId() .toString() : null); jsonCompetitorInLeg.put("name", competitor.getName()); - jsonCompetitorInLeg.put("sailNumber", competitor.getBoat().getSailID()); + jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID()); jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor() .getAsHtml() : null); @@ -1199,7 +1196,7 @@ public class RegattasResource extends AbstractSailingServerResource { } jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId().toString() : null); jsonCompetitorInLeg.put("name", competitor.getName()); - jsonCompetitorInLeg.put("sailNumber", competitor.getBoat().getSailID()); + jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()); jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); jsonCompetitorInLeg.put("rank", rank++); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java index 98b3ddc53cb..a81bb0d66bf 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/CompetitorReplicationTest.java @@ -92,7 +92,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { /* dateOfBirth */null, "This is famous " + competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - new BoatImpl("123", competitorName + "'s boat", boatClass, /* sailID */ null), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat boat = new BoatImpl(competitor.getId(), competitorName + "'s boat", boatClass, /* sailID */ null); Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(competitor, boat); @@ -109,20 +109,22 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { assertTrue(regattaId.equals(replicatedRegatta.getId())); RaceDefinition replicatedRace = replicatedRegatta.getRaceByName(raceName); assertNotNull(replicatedRace); - Competitor replicatedCompetitor = replicatedRace.getCompetitors().iterator().next(); + Map.Entry replicatedCompetitorAndBoat = replicatedRace.getCompetitorsAndTheirBoats().entrySet().iterator().next(); + Competitor replicatedCompetitor = replicatedCompetitorAndBoat.getKey(); + Boat replicatedBoat = replicatedCompetitorAndBoat.getValue(); assertNotSame(replicatedCompetitor, competitor); assertEquals(competitor.getId(), replicatedCompetitor.getId()); assertEquals(competitor.getName(), replicatedCompetitor.getName()); assertEquals(competitor.getShortName(), replicatedCompetitor.getShortName()); assertEquals(competitor.getColor(), replicatedCompetitor.getColor()); assertEquals(competitor.getFlagImage(), replicatedCompetitor.getFlagImage()); - assertEquals(competitor.getBoat().getSailID(), replicatedCompetitor.getBoat().getSailID()); + assertEquals(boat.getSailID(), replicatedBoat.getSailID()); assertEquals(competitor.getTeam().getNationality(), replicatedCompetitor.getTeam().getNationality()); // now update competitor on master using replicating operation final String newCompetitorName = "Der Vogel, der mit dem Kiel zieht"; final String newCompetitorShortName = "VK"; - master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, newCompetitorShortName, competitor.getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + master.apply(new UpdateCompetitor(competitor.getId().toString(), newCompetitorName, newCompetitorShortName, competitor.getColor(), competitor.getEmail(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); Thread.sleep(1000); @@ -133,7 +135,7 @@ public class CompetitorReplicationTest extends AbstractServerReplicationTest { master.apply(new AllowCompetitorResetToDefaults(Collections.singleton(competitor.getId().toString()))); // modify the competitor on the master "from below" without an UpdateCompetitor operation, only locally: master.getBaseDomainFactory().getCompetitorStore().updateCompetitor(competitor.getId().toString(), competitorName, competitorShortName, Color.RED, competitor.getEmail(), - competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), + competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); final RegattaAndRaceIdentifier raceIdentifier = masterRegatta.getRaceIdentifier(raceDefinition); DynamicTrackedRace trackedRace = (DynamicTrackedRace) master.apply(new CreateTrackedRace(raceIdentifier, diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java index 4bfc2a38407..12102a6f0a9 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/DelayedLeaderboardCorrectionsReplicationTest.java @@ -14,7 +14,7 @@ import org.junit.Test; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; @@ -79,7 +79,7 @@ public class DelayedLeaderboardCorrectionsReplicationTest extends AbstractServer // resolved properly on the replica. final DomainFactory domainFactory = new DomainFactoryImpl((srlid)->null); BoatClass boatClass = domainFactory.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - CompetitorWithBoat hassoWithBoat = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore + CompetitorAndBoat hassoWithBoat = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); // don't create competitor using CompetitorStore final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hassoWithBoat, /* rank */ 1, /* started */ false, boatClass) { private static final long serialVersionUID = 1234L; @Override diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index 6c1f895fad3..cb222b07bbd 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -29,7 +29,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceColumn; @@ -256,7 +256,7 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl Regatta regatta = master.apply(addEventOperation); final String raceName1 = "Test Race 1"; final String raceName2 = "Test Race 2"; - CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("The Same Competitor"); + CompetitorAndBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("The Same Competitor"); final CourseImpl masterCourse = new CourseImpl("Test Course", new ArrayList()); final Map competitors = new HashMap<>(); competitors.put(competitorAndBoat.getCompetitor(), competitorAndBoat.getBoat()); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java index 2e9c5df82eb..fdeb83fa71a 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RegattaLogReplicationTest.java @@ -11,7 +11,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; @@ -33,7 +33,7 @@ public class RegattaLogReplicationTest extends @Before public void createEvent() throws Exception { - final CompetitorWithBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); + final CompetitorAndBoat competitorAndBoat = TrackBasedTest.createCompetitorAndBoat("Test Competitor"); regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), t(0), author, 0, competitorAndBoat.getCompetitor()); // anotherRegattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(1), author, t(1), 1, null); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java index 4b7c1667942..5a2f191dcba 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java @@ -125,7 +125,8 @@ public class TrackRaceBoatCompetitorMetadataReplicationTest extends AbstractServ for (Competitor competitor : masterCompetitors) { Competitor replicaCompetitor = findCompetitor(replicaCompetitors, competitor); - switch (competitor.getBoat().getSailID()) { + Boat competitorBoat = masterTrackedRace.getBoatOfCompetitor(competitor.getId()); + switch (competitorBoat.getSailID()) { case boat1CompetitorName: compareBoatOfCompetitors(masterTrackedRace.getRace().getBoatOfCompetitorById(competitor.getId()), replicaTrackedRace.getRace().getBoatOfCompetitorById(replicaCompetitor.getId()), boat1Name, boat1Color); 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 5b1de18ff7c..327b087100a 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 @@ -24,7 +24,6 @@ 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.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; @@ -79,7 +78,6 @@ public class TrackedRaceContentsReplicationTest extends AbstractServerReplicatio (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null), new PersonImpl("Tina Lutz", masterDomainFactory.getOrCreateNationality("GER"), null, null) }), new PersonImpl("Rigo de Mas", masterDomainFactory.getOrCreateNationality("NED"), null, null)), - new BoatImpl("123", "GER 61", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat boat = masterDomainFactory.getCompetitorStore().getOrCreateBoat(competitor, "boat123", masterDomainFactory.getOrCreateBoatClass("470", /* typicallyStartsUpwind */ true), "GER 61", null); 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 index 9fa466c6a7a..71b8d21ce8c 100644 --- 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 @@ -22,7 +22,6 @@ 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.MarkImpl; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -84,7 +83,6 @@ public class TrackedRaceWithGPSFixStoreContentsReplicationTest extends AbstractS (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("123", "GER 61", boatClass470, "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat boat = masterDomainFactory.getCompetitorStore().getOrCreateBoat(competitor, "GER 61", boatClass470, "GER 61", null); final String baseEventName = "Test Event"; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java index 8ab0086df59..1d0a1156e16 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/ApplyScoresFromRaceLogTest.java @@ -27,8 +27,6 @@ import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -67,8 +65,7 @@ public class ApplyScoresFromRaceLogTest extends LeaderboardScoringAndRankingTest new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("123", - competitorName + "'s boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null), + /* dateOfBirth */null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); } regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1, diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index 9382e0988ef..c5cda81ac0a 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -28,19 +28,19 @@ public class CompetitorStoreTest { public void testAddingCompetitorsToTransientStore() { CompetitorStore transientStore = new TransientCompetitorStoreImpl(); DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); - Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), template.getBoat(), + Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); assertTrue(competitor != template); Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - template.getBoat(), /* timeOnTimeFactor */ 1.345, + /* timeOnTimeFactor */ 1.345, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); assertSame(competitor, competitor2); assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor, competitor3); // use existing competitor despite the different team assertSame(competitor.getTeam(), competitor3.getTeam()); @@ -48,7 +48,7 @@ public class CompetitorStoreTest { // now mark the competitor as to update from defaults transientStore.allowCompetitorResetToDefaults(competitor); Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); @@ -61,7 +61,7 @@ public class CompetitorStoreTest { DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - template.getBoat(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); CompetitorStore persistentStore2 = new PersistentCompetitorStore( PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); @@ -75,7 +75,7 @@ public class CompetitorStoreTest { DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor2, competitor3); // use existing competitor despite the different team assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged @@ -84,7 +84,7 @@ public class CompetitorStoreTest { // now mark the competitor as to update from defaults persistentStore2.allowCompetitorResetToDefaults(competitor2); Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, template.getBoat(), /* timeOnTimeFactor */ + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); assertSame(competitor2, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java index 49880c43074..d9470540c08 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardDiscardingRulesTest.java @@ -8,7 +8,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; @@ -66,13 +66,13 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); + CompetitorAndBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race2, "R2", /* medalRace */false); - CompetitorWithBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); + CompetitorAndBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 124, /* started */ true, boatClass); @@ -105,19 +105,19 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", /* typicallyStartsUpwind */ true); - CompetitorWithBoat rasmus = AbstractLeaderboardTest.createCompetitorAndBoat("Rasmus"); + CompetitorAndBoat rasmus = AbstractLeaderboardTest.createCompetitorAndBoat("Rasmus"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(rasmus, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(rasmus, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race2, "R2", /* medalRace */false); - CompetitorWithBoat jes = AbstractLeaderboardTest.createCompetitorAndBoat("Jes"); + CompetitorAndBoat jes = AbstractLeaderboardTest.createCompetitorAndBoat("Jes"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(jes, /* rank */ 2, /* started */ true, boatClass); // score 2.0 leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(jes, /* rank */ 3, /* started */ true, boatClass); // score 1.0 leaderboard.addRace(race4, "R4", /* medalRace */false); - CompetitorWithBoat nobody = AbstractLeaderboardTest.createCompetitorAndBoat("Nobody"); + CompetitorAndBoat nobody = AbstractLeaderboardTest.createCompetitorAndBoat("Nobody"); final TrackedRace race5 = new MockedTrackedRaceWithFixedRank(nobody, /* rank */ 3, /* started */ true, boatClass); // score 1.0 leaderboard.addRace(race5, "R5", /* medalRace */false); @@ -149,13 +149,13 @@ public class LeaderboardDiscardingRulesTest { assertNotNull(leaderboard); BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - CompetitorWithBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); + CompetitorAndBoat hasso = AbstractLeaderboardTest.createCompetitorAndBoat("Dr. Hasso Plattner"); final TrackedRace race1 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race1, "R1", /* medalRace */false); final TrackedRace race2 = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race2, "R2", /* medalRace */false); - CompetitorWithBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); + CompetitorAndBoat wolfgang = AbstractLeaderboardTest.createCompetitorAndBoat("Wolfgang Hunger"); final TrackedRace race3 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 123, /* started */ true, boatClass); leaderboard.addRace(race3, "R3", /* medalRace */false); final TrackedRace race4 = new MockedTrackedRaceWithFixedRank(wolfgang, /* rank */ 124, /* started */ true, boatClass); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java index c6fee5c1e9a..4a38328b95f 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/LeaderboardStorageTest.java @@ -4,8 +4,6 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - import org.junit.Test; import com.mongodb.BasicDBList; @@ -14,8 +12,6 @@ import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.NationalityImpl; @@ -27,6 +23,8 @@ import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.impl.RacingEventServiceImpl; import com.sap.sse.mongodb.MongoDBService; +import junit.framework.TestCase; + public class LeaderboardStorageTest extends TestCase { private static final String LEADERBOARD_NAME = "test"; @@ -58,10 +56,9 @@ public class LeaderboardStorageTest extends TestCase { List sailorList = new ArrayList(); sailorList.add(new PersonImpl("sailor", new NationalityImpl("GER"), null, "")); DynamicTeam team = new TeamImpl("team", sailorList, null); - DynamicBoat boat = new BoatImpl("123", "woot", service.getBaseDomainFactory().getOrCreateBoatClass("H16"), "70155"); String competitorId = "testC"; Competitor competitor = service.getBaseDomainFactory().getOrCreateCompetitor(competitorId, "Test C", null, null, - null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); double carriedPoints = 2.0; leaderboard.setCarriedPoints(competitor, carriedPoints); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 9d481145247..2191196d2cb 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -259,7 +259,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -271,7 +271,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -584,7 +584,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); @@ -594,7 +594,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", "KYC", Color.RED, null, null, team2, - boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -742,7 +742,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); Map competitorsAndBoats = new HashMap<>(); competitorsAndBoats.put(competitor, boat); @@ -909,7 +909,7 @@ public class MasterDataImportTest { BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", "F", Color.RED, - "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + "noone@nowhere.de", null, team, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); @@ -919,7 +919,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, - "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1069,7 +1069,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1081,7 +1081,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -1273,7 +1273,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1285,7 +1285,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -1377,7 +1377,7 @@ public class MasterDataImportTest { DynamicBoat boatToOverride = new BoatImpl("123", "Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", - Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + Color.BLUE, "noone@nowhere.de", null, teamToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); competitorsToOverride.add(competitorToOverride); @@ -1577,7 +1577,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1589,7 +1589,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -1714,7 +1714,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1726,7 +1726,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); @@ -1962,7 +1962,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -1974,7 +1974,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -2193,7 +2193,7 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); @@ -2205,7 +2205,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); + null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); TrackedRace trackedRace = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitors), regatta, null, sourceService.getWindStore()); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java index acdda0a43af..bba469964ff 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java @@ -20,7 +20,7 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.LeaderboardGroupBase; @@ -85,12 +85,12 @@ public class SearchServiceTest { private Venue flensburg; private Event pfingstbusch; private Regatta pfingstbusch29er; - private CompetitorWithBoat hassoPlattner; - private CompetitorWithBoat alexanderRies; - private CompetitorWithBoat antonKoch; - private CompetitorWithBoat tobiasSchadewaldt; - private CompetitorWithBoat philippBuhl; - private CompetitorWithBoat dennisGehrlein; + private CompetitorAndBoat hassoPlattner; + private CompetitorAndBoat alexanderRies; + private CompetitorAndBoat antonKoch; + private CompetitorAndBoat tobiasSchadewaldt; + private CompetitorAndBoat philippBuhl; + private CompetitorAndBoat dennisGehrlein; private Regatta pfingstbusch470; private Regatta aalRegatta; private DynamicTrackedRace pfingstbusch29erTrackedR1; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index 1858f0a4ddb..bb355bab29e 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -21,15 +21,14 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; @@ -84,7 +83,7 @@ public class WindByRaceLogTest { // FIXME use master DomainFactory; see bug 592 final DomainFactory masterDomainFactory = service.getBaseDomainFactory(); BoatClass boatClass = masterDomainFactory.getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */true); - CompetitorWithBoat competitorAndBoat = createCompetitorAndBoat(masterDomainFactory, boatClass); + CompetitorAndBoat competitorAndBoat = createCompetitorAndBoat(masterDomainFactory, boatClass); int[] discardThreshold = {1, 2}; CreateFlexibleLeaderboard createLeaderboardOperation = new CreateFlexibleLeaderboard("Test Leaderboard", "Test", discardThreshold, new LowPoint(), null); service.apply(createLeaderboardOperation); @@ -111,13 +110,13 @@ public class WindByRaceLogTest { defaultFleet = Util.get(raceColumn.getFleets(), 0); } - private CompetitorWithBoat createCompetitorAndBoat(final DomainFactory masterDomainFactory, final BoatClass boatClass) { + private CompetitorAndBoat createCompetitorAndBoat(final DomainFactory masterDomainFactory, final BoatClass boatClass) { Competitor competitor = masterDomainFactory.getOrCreateCompetitor("GER 61", "Sailor", "S", Color.RED, "noone@nowhere.de", null, new TeamImpl("Sailor", (List) Arrays.asList(new PersonImpl[] { new PersonImpl("Sailor 1", DomainFactory.INSTANCE.getOrCreateNationality("GER"), null, null)}), new PersonImpl("Sailor 2", DomainFactory.INSTANCE.getOrCreateNationality("NED"), null, null)), - new BoatImpl("123", "GER 61", boatClass, "GER 61"), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); Boat boat = masterDomainFactory.getOrCreateBoat(competitor, "GER 61", boatClass, "GER 61", null); - return new CompetitorWithBoatImpl(competitor, boat); + return new CompetitorAndBoatImpl(competitor, boat); } private void attachTrackedRaceToRaceColumn() { diff --git a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/CompetitorDataRetriever.java b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/CompetitorDataRetriever.java index 8b473264152..de287f1882c 100644 --- a/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/CompetitorDataRetriever.java +++ b/java/com.sap.sailing.server.trackfiles/src/com/sap/sailing/server/trackfiles/impl/CompetitorDataRetriever.java @@ -2,33 +2,37 @@ package com.sap.sailing.server.trackfiles.impl; import java.io.IOException; import java.util.Collection; +import java.util.Map; -import slash.navigation.gpx.GpxRoute; - +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.trackfiles.TrackFilesFormat; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.trackimport.FormatNotSupportedException; import com.sap.sailing.domain.tracking.TrackedRace; +import slash.navigation.gpx.GpxRoute; + public class CompetitorDataRetriever extends AbstractDataRetriever { @Override public Collection getRoutes(TrackFilesFormat format, final TrackedRace race, boolean dataBeforeAfter, boolean rawFixes) throws FormatNotSupportedException, IOException { - TrackReaderRetriever retriever = new TrackReaderRetriever() { + TrackReaderRetriever, GPSFixMoving> retriever = new TrackReaderRetriever, GPSFixMoving>() { @Override - public TrackReader retrieveTrackReader(Competitor e) { - return new TrackReaderImpl(race.getTrack(e)); + public TrackReader, GPSFixMoving> retrieveTrackReader(Map.Entry e) { + return new TrackReaderImpl, GPSFixMoving>(race.getTrack(e.getKey())); } }; - + return getRoutes(race, dataBeforeAfter, rawFixes, GPSFixMovingToGpxPosition.INSTANCE, race.getRace() - .getCompetitors(), new NameReader() { + .getCompetitorsAndTheirBoats().entrySet(), new NameReader>() { @Override - public String getName(Competitor c) { - return c.getName() + " - " + c.getBoat().getSailID() + " - " + public String getName(Map.Entry competitorAndBoat) { + final Competitor c = competitorAndBoat.getKey(); + final Boat b = competitorAndBoat.getValue(); + return c.getName() + " - " + b.getSailID() + " - " + c.getTeam().getNationality().getThreeLetterIOCAcronym(); } }, retriever); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index eda66c624e7..7ddb4b59249 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -105,10 +105,10 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl } @Override - public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newRgbDisplayColor, String newEmail, String newSailId, + public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newRgbDisplayColor, String newEmail, Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = super.updateCompetitor(idAsString, newName, newShortName, newRgbDisplayColor, newEmail, newSailId, newNationality, + Competitor result = super.updateCompetitor(idAsString, newName, newShortName, newRgbDisplayColor, newEmail, newNationality, newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); storeTo.storeCompetitor(result); return result; 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 3583c587366..edf1206b730 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 @@ -597,7 +597,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes @Override public void competitorUpdated(Competitor competitor) { replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor.getShortName(), competitor - .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + .getColor(), competitor.getEmail(), competitor.getTeam().getNationality(), competitor.getTeam().getImage(), competitor.getFlagImage(), competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag())); @@ -2846,7 +2846,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes // competitor store competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), dynamicCompetitor.getShortName(), dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(), - dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), + dynamicCompetitor.getTeam(), dynamicCompetitor.getTimeOnTimeFactor(), dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), dynamicCompetitor.getSearchTag()); } logoutput.append("Received " + competitorStore.getCompetitorsCount() + " NEW competitors\n"); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java index 9d415b732bb..06fdc73c69d 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java @@ -623,6 +623,11 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { return null; } + @Override + public Boat getBoatOfCompetitor(Serializable competitorId) { + return null; + } + @Override public RankingMetric getRankingMetric() { return null; diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java index 03324978e2f..237ced2d9fa 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateCompetitor.java @@ -15,7 +15,6 @@ public class UpdateCompetitor extends AbstractRacingEventServiceOperation result = new ArrayList(); RaceDefinition race = this.raceHandle.getRace(); - for (Competitor competitor : race.getCompetitors()) { - result.add(competitor.getName() + ", " + competitor.getBoat().getName()); + for (Entry competitorAndBoatEntry: race.getCompetitorsAndTheirBoats().entrySet()) { + result.add(competitorAndBoatEntry.getKey().getName() + ", " + competitorAndBoatEntry.getValue().getName()); } return result; } diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java index 88f107a05ba..43043dd8a58 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java @@ -135,7 +135,7 @@ public class FoilingData { result.append("UNKNOWN").append(";"); } result.append(competitor.getName()).append(";"); - result.append(competitor.getBoat().getSailID()).append(";"); + result.append(trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()).append(";"); result.append(competitor.getId()).append(";"); result.append(speedOfCompetitor != null ? speedOfCompetitor.getKnots() : "0.0").append(";"); result.append(rideHeight).append(";"); diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java index 9610f817ad5..fd551388994 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java @@ -19,6 +19,7 @@ import javax.servlet.http.HttpServletResponse; import org.jdom.Element; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Leg; @@ -628,10 +629,11 @@ public class LeaderboardData extends ExportAction { if (shortVersion) return competitorElement; - if (competitor.getBoat() != null) { - addNamedElementWithValue(competitorElement, "sail_id", cleanSailId(competitor.getBoat().getSailID(), competitor)); - addNamedElementWithValue(competitorElement, "boat_class", competitor.getBoat().getBoatClass().getName()); - addNamedElementWithValue(competitorElement, "boat_name", competitor.getBoat().getName()); + final Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); + if (boatOfCompetitor != null) { + addNamedElementWithValue(competitorElement, "sail_id", cleanSailId(boatOfCompetitor.getSailID(), competitor)); + addNamedElementWithValue(competitorElement, "boat_class", boatOfCompetitor.getBoatClass().getName()); + addNamedElementWithValue(competitorElement, "boat_name", boatOfCompetitor.getName()); } else { addNamedElementWithValue(competitorElement, "sail_id", ""); addNamedElementWithValue(competitorElement, "boat_class", ""); @@ -946,13 +948,13 @@ public class LeaderboardData extends ExportAction { return new Util.Pair>(simpleConfidence, messages); } - private Util.Pair> checkData(Competitor competitor) throws Exception { + private Util.Pair> checkData(Competitor competitor, Boat boatOfCompetitor) throws Exception { double simpleConfidence = 1.0; Vector messages = new Vector(); if (competitor.getName() == null || competitor.getName().equals("")) { messages.add("Competitor " + competitor.getId() + " has no name!"); simpleConfidence -= 1; } - if (competitor.getBoat() == null || competitor.getBoat().getSailID() == null || competitor.getBoat().getSailID().equals("")) { + if (boatOfCompetitor == null || boatOfCompetitor.getSailID() == null || boatOfCompetitor.getSailID().equals("")) { messages.add("Competitor " + competitor.getId() + " has no sail id that can be used!"); simpleConfidence -= 1; } @@ -1029,7 +1031,8 @@ public class LeaderboardData extends ExportAction { final List racesElements = new ArrayList(); final List competitorElements = new ArrayList(); for (Competitor competitor : leaderboard.getAllCompetitors()) { - Util.Pair> competitorConfidenceAndErrorMessages = checkData(competitor); + Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); + Util.Pair> competitorConfidenceAndErrorMessages = checkData(competitor, boatOfCompetitor); competitorElements.add(createCompetitorXML(competitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); } List windData = new ArrayList(); diff --git a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java index a695bfbaddc..e47a6609c9f 100755 --- a/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java +++ b/java/com.sap.sailing.xrr.structureimport/src/com/sap/sailing/xrr/structureimport/StructureImporter.java @@ -210,7 +210,7 @@ public class StructureImporter { .toString()); BoatAndTeam boatAndTeam = getBoatAndTeam(idAsString, name, nationality, boatClass); this.baseDomainFactory.convertToCompetitorDTO(this.baseDomainFactory.getOrCreateCompetitor( - UUID.fromString(idAsString), name, shortName, color, email, flagImage, boatAndTeam.getTeam(), boatAndTeam.getBoat(), + UUID.fromString(idAsString), name, shortName, color, email, flagImage, boatAndTeam.getTeam(), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); } else { break; diff --git a/java/com.sap.sse.security.ui/Security UI sdm.launch b/java/com.sap.sse.security.ui/Security UI sdm.launch index 623e7cd30bf..42497e6bbf2 100644 --- a/java/com.sap.sse.security.ui/Security UI sdm.launch +++ b/java/com.sap.sse.security.ui/Security UI sdm.launch @@ -48,7 +48,7 @@ - + diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index 23450f46300..ab8ab0f4b8f 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -93,11 +93,11 @@ public class OfflineDataManager extends DataManager { medal), new EmptyRegattaConfiguration()); List competitors = new ArrayList(); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.BLUE, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", "Muscat", Color.LIGHT_GRAY, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", "Red Bull", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", "Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.BLUE, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", "Muscat", Color.LIGHT_GRAY, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", "Red Bull", Color.RED, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", "Korea", Color.GREEN, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", "Realteam", Color.BLACK, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); RaceLog log = new RaceLogImpl(UUID.randomUUID()); final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java index 392689013b0..188d3ebec8d 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java @@ -68,7 +68,7 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeseri import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatClassJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer; @@ -248,7 +248,7 @@ public class OnlineDataManager extends DataManager { @Override public Loader>> create(int id, Bundle args) throws Exception { ExLog.i(context, TAG, "Creating Competitor-OnlineDataLoader " + id); - JsonDeserializer competitorDeserializer = new CompetitorJsonDeserializer(domainFactory.getCompetitorStore(), + JsonDeserializer competitorDeserializer = new CompetitorWithBoatJsonDeserializer(domainFactory.getCompetitorStore(), new TeamJsonDeserializer(new PersonJsonDeserializer(new NationalityJsonDeserializer(domainFactory))), new BoatJsonDeserializer(domainFactory, new BoatClassJsonDeserializer(domainFactory))); DataParser> parser = new CompetitorsDataParser(competitorDeserializer); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java index aab0c8010bc..117e69f18e8 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java @@ -8,22 +8,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import android.annotation.TargetApi; -import android.app.AlarmManager; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.graphics.BitmapFactory; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; -import android.util.Pair; - import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; @@ -47,6 +31,22 @@ import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerialize import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer; import com.sap.sse.common.impl.MillisecondsTimePoint; +import android.annotation.TargetApi; +import android.app.AlarmManager; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Binder; +import android.os.Build; +import android.os.IBinder; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.NotificationCompat; +import android.util.Pair; + public class RaceStateService extends Service { private final static String TAG = RaceStateService.class.getName(); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java index 589c4598f17..4f83900400d 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java @@ -2,6 +2,11 @@ package com.sap.sailing.racecommittee.app.ui.adapters; import java.util.List; +import com.sap.sailing.android.shared.logging.ExLog; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.racecommittee.app.R; + import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -9,10 +14,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.sap.sailing.android.shared.logging.ExLog; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.racecommittee.app.R; - public class CompetitorAdapter extends RecyclerView.Adapter { private static final String TAG = CompetitorAdapter.class.getName(); From bc8a71f058a3ca58f8ba1780a0a190bfad73a99f Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 19 Jun 2017 21:21:31 +0200 Subject: [PATCH 023/271] Next step of the removal of Competitor.getBoat() As this affects also CompetitorDTO.getBoat() I introduced as an intermediate step CompetitorWithoutBoatDTO (CompetitorDTO extends CompetitorWithoutBoatDTO) for simpler refactoring. Added also some new RaceLog and RegattaLog events for adding a competitor/boat pair --- .../GetCompetitorInLeaderboardAction.java | 8 +- .../CompetitorSelectionListener.java | 4 +- .../CompetitorSelectionPopup.java | 10 +- .../table/CompetitorTable.java | 18 +- .../CompetitorTableRowSelectionListener.java | 4 +- .../startanalysis/StartAnalysisWidget.java | 3 +- .../StartAnalysisDTOFactory.java | 7 +- .../shared/dto/LeaderboardCompetitorsDTO.java | 8 +- .../domain/common/dto/CompetitorDTO.java | 45 +--- .../domain/common/dto/CompetitorDTOImpl.java | 183 +------------- .../common/dto/CompetitorWithoutBoatDTO.java | 44 ++++ .../dto/CompetitorWithoutBoatDTOImpl.java | 204 ++++++++++++++++ .../impl/DomainObjectFactoryImpl.java | 50 +++- .../domain/persistence/impl/FieldNames.java | 4 +- .../impl/MongoObjectFactoryImpl.java | 31 ++- .../impl/MongoRaceLogStoreVisitor.java | 7 + .../impl/MongoRegattaLogStoreVisitor.java | 6 + .../impl/RaceLogTrackingAdapterImpl.java | 6 +- .../abstractlog/race/RaceLogEventVisitor.java | 3 + .../impl/AbstractRaceLogChangedVisitor.java | 8 +- .../race/impl/BaseRaceLogEventVisitor.java | 8 +- ...RaceLogRegisterCompetitorAndBoatEvent.java | 10 + ...RegisteredCompetitorsAndBoatsAnalyzer.java | 44 ++++ ...LogRegisterCompetitorAndBoatEventImpl.java | 62 +++++ .../regatta/RegattaLogEventVisitor.java | 5 +- ...attaLogRegisterCompetitorAndBoatEvent.java | 10 + ...LogRegisterCompetitorAndBoatEventImpl.java | 39 +++ .../impl/BaseRegattaLogEventVisitor.java | 5 + .../regatta/impl/RegattaLogEventListener.java | 6 + .../CompetitorsAndBoatsInLogAnalyzer.java | 50 ++++ .../RegisterCompetitorAndBoatEvent.java | 24 ++ ...aseRegisterCompetitorAndBoatEventImpl.java | 59 +++++ .../sailing/domain/base/CompetitorStore.java | 9 +- .../base/impl/CompetitorWithoutBoatImpl.java | 226 ++++++++++++++++++ .../impl/TransientCompetitorStoreImpl.java | 44 +++- .../test/FetchTracksAndStoreLocallyTest.java | 4 +- .../domain/tractracadapter/DomainFactory.java | 4 +- .../impl/DomainFactoryImpl.java | 32 ++- .../impl/MarkPassingReceiver.java | 8 +- .../impl/RawPositionReceiver.java | 2 +- .../impl/TracTracRaceTrackerImpl.java | 7 +- .../sailing/domain/base/DomainFactory.java | 15 +- .../domain/base/impl/AbstractRaceColumn.java | 4 +- .../domain/base/impl/DomainFactoryImpl.java | 46 +++- .../impl/RaceColumnRaceLogReplicator.java | 6 + .../domain/leaderboard/Leaderboard.java | 2 +- .../impl/AbstractSimpleLeaderboardImpl.java | 16 +- .../impl/FlexibleLeaderboardImpl.java | 4 +- .../meta/MetaLeaderboardColumn.java | 14 ++ .../event/SimpleCompetitorDTO.java | 9 +- .../GetCompetitorSuggestionAction.java | 3 +- ...StoringAndRetrievingLeaderboardGroups.java | 2 +- .../racelog/impl/RaceLogEventSerializer.java | 9 +- .../jaxrs/api/LeaderboardsResource.java | 5 +- .../impl/RegattaByKeywordSearchService.java | 2 +- .../sailing/xmlexport/LeaderboardData.java | 20 +- .../app/data/OnlineDataManager.java | 21 +- .../app/ui/adapters/CompetitorAdapter.java | 7 +- .../CompetitorSailIdComparator.java | 29 ++- .../raceinfo/TrackingListFragment.java | 72 +++--- 60 files changed, 1209 insertions(+), 388 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorAndBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorAndBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java index a5cfd3fd5d0..2d5583674f1 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java @@ -1,9 +1,13 @@ package com.sap.sailing.dashboards.gwt.client.actions; +import java.util.List; + import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.dashboards.gwt.shared.dispatch.DashboardAction; import com.sap.sailing.dashboards.gwt.shared.dispatch.DashboardDispatchContext; import com.sap.sailing.dashboards.gwt.shared.dto.LeaderboardCompetitorsDTO; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.dispatch.shared.exceptions.DispatchException; @@ -29,7 +33,9 @@ public class GetCompetitorInLeaderboardAction implements DashboardAction competitorsFromBestToWorst = lb.getCompetitorsFromBestToWorst(MillisecondsTimePoint.now()); + List competitorDTOs = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorWithoutBoatDTOListTemp(competitorsFromBestToWorst); + result.setCompetitors(competitorDTOs); return result; } } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java index b4ec20fdf25..5e281844e23 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java @@ -1,8 +1,8 @@ package com.sap.sailing.dashboards.gwt.client.popups.competitorselection; -import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; public interface CompetitorSelectionListener { - public void didClickOKWithSelectedCompetitor(CompetitorDTO competitor); + public void didClickOKWithSelectedCompetitor(CompetitorWithoutBoatDTO competitor); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java index 743eb998187..84a1612c221 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java @@ -16,7 +16,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table.CompetitorTable; import com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table.CompetitorTableRowSelectionListener; import com.sap.sailing.dashboards.gwt.client.widgets.ActionPanel; -import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; public class CompetitorSelectionPopup extends Composite implements HasWidgets, CompetitorTableRowSelectionListener { @@ -38,7 +38,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C @UiField(provided = true) ActionPanel okButton; - private CompetitorDTO currentCompetitorSelected; + private CompetitorWithoutBoatDTO currentCompetitorSelected; private boolean isVisible; private CompetitorSelectionPopupResources competitorSelectionPopupResources = CompetitorSelectionPopupResources.INSTANCE; @@ -63,7 +63,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C okButton.getElement().setInnerText("OK"); } - public void show(List competitorList) { + public void show(List competitorList) { competitortable.setTableContent(competitorList); RootLayoutPanel.get().add(this); competitorselectionpopup.addStyleName(competitorSelectionPopupResources.gss().popupshow()); @@ -88,7 +88,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C this.competitorSelectionPopupListener.remove(o); } - public void notifyListenerAboutOKButtonClickedWithSelectedCompetitorName(CompetitorDTO competitor) { + public void notifyListenerAboutOKButtonClickedWithSelectedCompetitorName(CompetitorWithoutBoatDTO competitor) { for (CompetitorSelectionListener newStartAnalysisListener : competitorSelectionPopupListener) { newStartAnalysisListener.didClickOKWithSelectedCompetitor(competitor); } @@ -127,7 +127,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C } @Override - public void didSelectedRowWithCompetitorName(CompetitorDTO competitor) { + public void didSelectedRowWithCompetitorName(CompetitorWithoutBoatDTO competitor) { currentCompetitorSelected = competitor; } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java index 56ae2e648c1..cf23b175868 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java @@ -10,46 +10,46 @@ import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; -import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sse.gwt.client.celltable.BaseCelltable; public class CompetitorTable extends AbsolutePanel { - private CellTable table; + private CellTable table; private CompetitorTableRowSelectionListener competitorTableRowSelectionListener; public CompetitorTable(CompetitorTableRowSelectionListener competitorTableRowSelectionListener) { this.competitorTableRowSelectionListener = competitorTableRowSelectionListener; } - public void setTableContent(List competitorNames) { + public void setTableContent(List competitorNames) { if (table == null) { initTable(competitorNames); } } - private void initTable(List competitorNames) { + private void initTable(List competitorNames) { CellTable.Resources tableRes = GWT.create(CompetitorTableStyleResource.class); - table = new BaseCelltable(15, tableRes); + table = new BaseCelltable(15, tableRes); table.getElement().getStyle().setWidth(100, Unit.PCT); table.setSkipRowHoverStyleUpdate(true); table.setSkipRowHoverCheck(true); table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED); - final SingleSelectionModel selectionModel = new SingleSelectionModel(); + final SingleSelectionModel selectionModel = new SingleSelectionModel(); table.setSelectionModel(selectionModel); selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { public void onSelectionChange(SelectionChangeEvent event) { - CompetitorDTO selected = selectionModel.getSelectedObject(); + CompetitorWithoutBoatDTO selected = selectionModel.getSelectedObject(); if (selected != null) { competitorTableRowSelectionListener.didSelectedRowWithCompetitorName(selected); } } }); - TextColumn competitorNameCollumn = new TextColumn() { + TextColumn competitorNameCollumn = new TextColumn() { @Override - public String getValue(CompetitorDTO competitor) { + public String getValue(CompetitorWithoutBoatDTO competitor) { return competitor.getName(); } }; diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java index 3087d8745b4..c2d3907f45e 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java @@ -1,8 +1,8 @@ package com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table; -import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; public interface CompetitorTableRowSelectionListener { - public void didSelectedRowWithCompetitorName(CompetitorDTO competitor); + public void didSelectedRowWithCompetitorName(CompetitorWithoutBoatDTO competitor); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java index b808797b761..c3952e6b90c 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java @@ -41,6 +41,7 @@ import com.sap.sailing.dashboards.gwt.shared.dto.LeaderboardCompetitorsDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysesDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysisDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapResources; @@ -240,7 +241,7 @@ public class StartAnalysisWidget extends Composite implements HasWidgets, PollsL competitorSelectionPopup.addListener(new CompetitorSelectionListener() { @Override - public void didClickOKWithSelectedCompetitor(CompetitorDTO competitor) { + public void didClickOKWithSelectedCompetitor(CompetitorWithoutBoatDTO competitor) { if (competitor != null) { Cookies.removeCookie(cookieKeyForSelectedCompetitorInLeaderboard); Cookies.setCookie(cookieKeyForSelectedCompetitorInLeaderboard, competitor.getIdAsString(), new Date(new Date().getTime()+SELECTED_COMPETITOR_ID_COOKIE_KEY_EXPIRE_TIME_IN_MILLIS)); diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/util/actions/startanalysis/StartAnalysisDTOFactory.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/util/actions/startanalysis/StartAnalysisDTOFactory.java index b5d6940aac2..e6709ea5637 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/util/actions/startanalysis/StartAnalysisDTOFactory.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/util/actions/startanalysis/StartAnalysisDTOFactory.java @@ -15,6 +15,7 @@ import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysisDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysisRankingTableEntryDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartLineAdvantageDTO; import com.sap.sailing.dashboards.gwt.shared.dto.WindAndAdvantagesInfoForStartLineDTO; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.LegType; @@ -59,7 +60,8 @@ public final class StartAnalysisDTOFactory extends AbstractStartAnalysisCreation competitors.add(createStartAnalysisCompetitorDTO(dashboardDispatchContext, trackedRace, rankOfCompetitorWhilePassingSecondWaypoint, competitor)); } if (competitor != null) { - startAnalysisDTO.competitor = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorStore().convertToCompetitorDTO(competitor); + Boat boatOfCompetitor = trackedRace.getBoatOfCompetitor(competitor); + startAnalysisDTO.competitor = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorStore().convertToCompetitorDTO(competitor, boatOfCompetitor); logger.log(Level.INFO, "Created startanalysis for competitor"+competitor); } startAnalysisDTO.startAnalysisCompetitorDTOs = competitors; @@ -191,8 +193,9 @@ public final class StartAnalysisDTOFactory extends AbstractStartAnalysisCreation private static StartAnalysisCompetitorDTO createStartAnalysisCompetitorDTO(DashboardDispatchContext dashboardDispatchContext, TrackedRace trackedRace, int rank, Competitor competitor) { StartAnalysisCompetitorDTO startAnalysisCompetitorDTOsForRace = new StartAnalysisCompetitorDTO(); + Boat boatOfCompetitor = trackedRace.getBoatOfCompetitor(competitor); startAnalysisCompetitorDTOsForRace.competitorDTO = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorStore() - .convertToCompetitorDTO(competitor); + .convertToCompetitorDTO(competitor, boatOfCompetitor); startAnalysisCompetitorDTOsForRace.rankingTableEntryDTO = createRankTableEntry(trackedRace, rank, competitor); return startAnalysisCompetitorDTOsForRace; } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java index f402d3031eb..24470dfa69f 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java @@ -2,7 +2,7 @@ package com.sap.sailing.dashboards.gwt.shared.dto; import java.util.List; -import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sse.gwt.dispatch.shared.commands.Result; /** @@ -11,15 +11,15 @@ import com.sap.sse.gwt.dispatch.shared.commands.Result; */ public class LeaderboardCompetitorsDTO implements Result { - private List competitors; + private List competitors; public LeaderboardCompetitorsDTO() {} - public List getCompetitors() { + public List getCompetitors() { return competitors; } - public void setCompetitors(List competitors) { + public void setCompetitors(List competitors) { this.competitors = competitors; } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 97132feb98b..1ab152cc2f4 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -1,56 +1,15 @@ package com.sap.sailing.domain.common.dto; -import java.io.Serializable; - -import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -public interface CompetitorDTO extends Serializable, MappableToDevice { - - String getTwoLetterIsoCountryCode(); - - String getThreeLetterIocCountryCode(); - - String getCountryName(); - - String getIdAsString(); - +public interface CompetitorDTO extends CompetitorWithoutBoatDTO { String getSailID(); - - String getSearchTag(); - - /** - * If the {@code searchTag} is not contained in {@link #getSearchTag()}, appends it to the search tag, separated by a space character - */ - void addToSearchTag(String searchTag); - BoatDTO getBoat(); - BoatClassDTO getBoatClass(); - - String getName(); - String getShortName(); - - Color getColor(); + BoatDTO getBoat(); - String getEmail(); - - boolean hasEmail(); - /** * A regular instance will simply return this object. A compacted version may compute the result by looking it up * from the previous version of the enclosing leaderboard. */ CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion); - - String getFlagImageURL(); - - String getImageURL(); - - Double getTimeOnTimeFactor(); - - Duration getTimeOnDistanceAllowancePerNauticalMile(); - } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index b20ec943575..e332c25e0d4 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -5,52 +5,21 @@ import java.io.Serializable; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; -/** - * Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the - * {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the - * {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject - * to change for a competitor while the ID remains unchanged. - * - * @author Axel Uhl (d043530) - * - */ -public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serializable { - private static final long serialVersionUID = -4997852354821083154L; - private String countryName; - private String twoLetterIsoCountryCode; - private String threeLetterIocCountryCode; - private Color color; - private String shortName; - private String email; - private String searchTag; - private String idAsString; +public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements CompetitorDTO, Serializable { + private static final long serialVersionUID = 6749455739529431935L; private BoatClassDTO boatClass; private BoatDTO boat; - private String imageURL; - private String flagImageURL; - private Double timeOnTimeFactor; - private Duration timeOnDistanceAllowancePerNauticalMile; public CompetitorDTOImpl() {} public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, String countryName, String idAsString, String imageURL, String flagImageURL, BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - super(name); - this.shortName = shortName; - this.color = color; - this.email = email; - this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; - this.threeLetterIocCountryCode = threeLetterIocCountryCode; - this.countryName = countryName; - this.idAsString = idAsString; - this.imageURL = imageURL; - this.flagImageURL = flagImageURL; + super(name, shortName, color, email, twoLetterIsoCountryCode, threeLetterIocCountryCode, + countryName, idAsString, imageURL, flagImageURL, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); this.boat = boat; this.boatClass = boatClass; - this.timeOnTimeFactor = timeOnTimeFactor; - this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; - this.searchTag = searchTag; } @Override @@ -59,16 +28,6 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial int result = super.hashCode(); result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); result = prime * result + ((boat == null) ? 0 : boat.hashCode()); - result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); - result = prime * result + ((color == null) ? 0 : color.hashCode()); - result = prime * result + ((email == null) ? 0 : email.hashCode()); - result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); - result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); - result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode()); - result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode()); - result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode()); - result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode()); - result = prime * result + ((searchTag == null) ? 0 : searchTag.hashCode()); return result; } @@ -91,146 +50,22 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial return false; } else if (!boat.equals(other.boat)) return false; - if (idAsString == null) { - if (other.idAsString != null) - return false; - } else if (!idAsString.equals(other.idAsString)) - return false; - if (threeLetterIocCountryCode == null) { - if (other.threeLetterIocCountryCode != null) - return false; - } else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode)) - return false; - if (color == null) { - if (other.color != null) - return false; - } else if (!color.equals(other.color)) - return false; - if (email == null) { - if (other.email != null) - return false; - } else if (!email.equals(other.email)) - return false; - if (shortName == null) { - if (other.shortName != null) - return false; - } else if (!shortName.equals(other.shortName)) - return false; - if (imageURL == null) { - if (other.imageURL != null) - return false; - } else if (!imageURL.equals(other.imageURL)) - return false; - if (flagImageURL == null) { - if (other.flagImageURL != null) - return false; - } else if (!flagImageURL.equals(other.flagImageURL)) - return false; - if (timeOnTimeFactor == null) { - if (other.timeOnTimeFactor != null) - return false; - } else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor)) - return false; - if (timeOnDistanceAllowancePerNauticalMile == null) { - if (other.timeOnDistanceAllowancePerNauticalMile != null) - return false; - } else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile)) - return false; - if (searchTag == null) { - if (other.searchTag != null) - return false; - } else if (!searchTag.equals(other.searchTag)) - return false; return true; } - @Override - public String getTwoLetterIsoCountryCode() { - return twoLetterIsoCountryCode; - } - - @Override - public String getThreeLetterIocCountryCode() { - return threeLetterIocCountryCode; - } - - @Override - public String getCountryName() { - return countryName; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getSailID() { - return boat==null?null:boat.getSailId(); - } - - @Override - public String getImageURL() { - return imageURL; - } - - @Override - public String getFlagImageURL() { - return flagImageURL; - } - - @Override - public String getIdAsString() { - return idAsString; - } - - @Override - public BoatClassDTO getBoatClass() { - return boatClass; - } - @Override public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) { return this; } @Override - public Color getColor() { - return color; - } - - @Override - public String getSearchTag() { - return searchTag; + public String getSailID() { + return boat==null?null:boat.getSailId(); } @Override - public void addToSearchTag(String searchTag) { - if (this.searchTag == null) { - this.searchTag = searchTag; - } else if (!this.searchTag.contains(searchTag)) { - this.searchTag += " "+searchTag; - } - } - - @Override - public String getEmail() { - return email; - } - - @Override - public boolean hasEmail() { - return email != null && !email.isEmpty(); - } - - @Override - public Double getTimeOnTimeFactor() { - return timeOnTimeFactor; - } - - @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile() { - return timeOnDistanceAllowancePerNauticalMile; + public BoatClassDTO getBoatClass() { + return boatClass; } @Override diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java new file mode 100644 index 00000000000..68ace767363 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java @@ -0,0 +1,44 @@ +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +public interface CompetitorWithoutBoatDTO extends Serializable, MappableToDevice { + + String getTwoLetterIsoCountryCode(); + + String getThreeLetterIocCountryCode(); + + String getCountryName(); + + String getIdAsString(); + + String getSearchTag(); + + /** + * If the {@code searchTag} is not contained in {@link #getSearchTag()}, appends it to the search tag, separated by a space character + */ + void addToSearchTag(String searchTag); + + String getName(); + + String getShortName(); + + Color getColor(); + + String getEmail(); + + boolean hasEmail(); + + String getFlagImageURL(); + + String getImageURL(); + + Double getTimeOnTimeFactor(); + + Duration getTimeOnDistanceAllowancePerNauticalMile(); + +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java new file mode 100644 index 00000000000..229af7af490 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java @@ -0,0 +1,204 @@ +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the + * {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the + * {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject + * to change for a competitor while the ID remains unchanged. + * + * @author Axel Uhl (d043530) + * + */ +public class CompetitorWithoutBoatDTOImpl extends NamedDTO implements CompetitorWithoutBoatDTO, Serializable { + private static final long serialVersionUID = -4997852354821083154L; + private String countryName; + private String twoLetterIsoCountryCode; + private String threeLetterIocCountryCode; + private Color color; + private String shortName; + private String email; + private String searchTag; + private String idAsString; + private String imageURL; + private String flagImageURL; + private Double timeOnTimeFactor; + private Duration timeOnDistanceAllowancePerNauticalMile; + + public CompetitorWithoutBoatDTOImpl() {} + + public CompetitorWithoutBoatDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, + String countryName, String idAsString, String imageURL, String flagImageURL, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + super(name); + this.shortName = shortName; + this.color = color; + this.email = email; + this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; + this.threeLetterIocCountryCode = threeLetterIocCountryCode; + this.countryName = countryName; + this.idAsString = idAsString; + this.imageURL = imageURL; + this.flagImageURL = flagImageURL; + this.timeOnTimeFactor = timeOnTimeFactor; + this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; + this.searchTag = searchTag; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); + result = prime * result + ((color == null) ? 0 : color.hashCode()); + result = prime * result + ((email == null) ? 0 : email.hashCode()); + result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); + result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); + result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode()); + result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode()); + result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode()); + result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode()); + result = prime * result + ((searchTag == null) ? 0 : searchTag.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CompetitorWithoutBoatDTOImpl other = (CompetitorWithoutBoatDTOImpl) obj; + if (idAsString == null) { + if (other.idAsString != null) + return false; + } else if (!idAsString.equals(other.idAsString)) + return false; + if (threeLetterIocCountryCode == null) { + if (other.threeLetterIocCountryCode != null) + return false; + } else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode)) + return false; + if (color == null) { + if (other.color != null) + return false; + } else if (!color.equals(other.color)) + return false; + if (email == null) { + if (other.email != null) + return false; + } else if (!email.equals(other.email)) + return false; + if (shortName == null) { + if (other.shortName != null) + return false; + } else if (!shortName.equals(other.shortName)) + return false; + if (imageURL == null) { + if (other.imageURL != null) + return false; + } else if (!imageURL.equals(other.imageURL)) + return false; + if (flagImageURL == null) { + if (other.flagImageURL != null) + return false; + } else if (!flagImageURL.equals(other.flagImageURL)) + return false; + if (timeOnTimeFactor == null) { + if (other.timeOnTimeFactor != null) + return false; + } else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor)) + return false; + if (timeOnDistanceAllowancePerNauticalMile == null) { + if (other.timeOnDistanceAllowancePerNauticalMile != null) + return false; + } else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile)) + return false; + if (searchTag == null) { + if (other.searchTag != null) + return false; + } else if (!searchTag.equals(other.searchTag)) + return false; + return true; + } + + @Override + public String getTwoLetterIsoCountryCode() { + return twoLetterIsoCountryCode; + } + + @Override + public String getThreeLetterIocCountryCode() { + return threeLetterIocCountryCode; + } + + @Override + public String getCountryName() { + return countryName; + } + + @Override + public String getShortName() { + return shortName; + } + + @Override + public String getImageURL() { + return imageURL; + } + + @Override + public String getFlagImageURL() { + return flagImageURL; + } + + @Override + public String getIdAsString() { + return idAsString; + } + + @Override + public Color getColor() { + return color; + } + + @Override + public String getSearchTag() { + return searchTag; + } + + @Override + public void addToSearchTag(String searchTag) { + if (this.searchTag == null) { + this.searchTag = searchTag; + } else if (!this.searchTag.contains(searchTag)) { + this.searchTag += " "+searchTag; + } + } + + @Override + public String getEmail() { + return email; + } + + @Override + public boolean hasEmail() { + return email != null && !email.isEmpty(); + } + + @Override + public Double getTimeOnTimeFactor() { + return timeOnTimeFactor; + } + + @Override + public Duration getTimeOnDistanceAllowancePerNauticalMile() { + return timeOnDistanceAllowancePerNauticalMile; + } +} diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 0dc91a3c062..8b7e340109e 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -89,10 +89,12 @@ import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformat import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; @@ -102,6 +104,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEnde import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -111,6 +114,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl; @@ -213,7 +217,7 @@ import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer; @@ -240,7 +244,7 @@ import com.sap.sse.util.ThreadPoolUtil; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); - private final CompetitorWithBoatJsonDeserializer competitorDeserializer; + private final CompetitorJsonDeserializer competitorDeserializer; private final BoatJsonDeserializer boatDeserializer; private final DB database; @@ -270,7 +274,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { this.raceTrackingConnectivityParamsServiceFinder = null; } this.baseDomainFactory = baseDomainFactory; - this.competitorDeserializer = CompetitorWithBoatJsonDeserializer.create(baseDomainFactory); + this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } @@ -1413,6 +1417,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { + return loadRaceLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogAdditionalScoringInformationEvent.class.getSimpleName())) { return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())){ @@ -1469,6 +1475,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, comp); } + private RaceLogEvent loadRaceLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + Serializable id, Integer passId, List competitors, DBObject dbObject) { + Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); + Serializable boatId = (Serializable) dbObject.get(FieldNames.RACE_LOG_BOAT_ID.name()); + Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); + Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); + return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, comp, boat); + } + private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Object additionalScoringInformationTypeInfo = dbObject.get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); @@ -1705,6 +1720,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass.equals(RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { + return loadRegattaLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnTimeFactorEvent.class.getSimpleName())) { return loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) { @@ -1723,6 +1740,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return comp; } + private Boat getBoatByID(DBObject dbObject) { + Serializable boatId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()); + Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); + return boat; + } + private RegattaLogEvent loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); @@ -1770,6 +1793,27 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return result; } + private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + Competitor comp = getCompetitorByID(dbObject); + Boat boat = getBoatByID(dbObject); + final RegattaLogRegisterCompetitorAndBoatEvent result; + if (comp == null || boat == null) { + result = null; + if (comp == null) { + logger.log(Level.SEVERE, "Couldn't resolve competitor with ID "+dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name())+ + " from registration event with ID "+id+". Skipping this competitor registration."); + } + if (boat == null) { + logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ + " from registration event with ID "+id+". Skipping this competitor registration."); + } + } else { + result = new RegattaLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, comp, boat); + } + return result; + } + private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get( diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index 8e5536c4bc6..e19af70698d 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -100,7 +100,7 @@ public enum FieldNames { RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE, RACE_LOG_PROTEST_START_TIME, RACE_LOG_PROTEST_END_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE, RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, - RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, + RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, @@ -116,7 +116,7 @@ public enum FieldNames { // did not reuse RACE_LOG* types, as this would require handling old versions of all events REGATTA_LOG_IDENTIFIER_TYPE, REGATTA_LOG_IDENTIFIER_NAME, REGATTA_LOG_EVENT_ID, REGATTA_LOG_EVENT_CREATED_AT, REGATTA_LOG_EVENT_AUTHOR_NAME, REGATTA_LOG_EVENT_AUTHOR_PRIORITY, REGATTA_LOG_EVENT_CLASS, REGATTA_LOG_REVOKED_EVENT_ID, REGATTA_LOG_REVOKED_EVENT_TYPE, REGATTA_LOG_REVOKED_EVENT_SHORT_INFO, - REGATTA_LOG_REVOKED_REASON, REGATTA_LOG_COMPETITOR_ID, REGATTA_LOG_DEVICE_MAPPING_EVENT_ID, REGATTA_LOG_CLOSING_TIMEPOINT, + REGATTA_LOG_REVOKED_REASON, REGATTA_LOG_COMPETITOR_ID, REGATTA_LOG_BOAT_ID, REGATTA_LOG_DEVICE_MAPPING_EVENT_ID, REGATTA_LOG_CLOSING_TIMEPOINT, REGATTA_LOG_FROM, REGATTA_LOG_TO, REGATTA_LOG_EVENT, REGATTA_LOG_MARK, // remote server reference fields diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index d99e81f4c78..e4daed19086 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -46,6 +46,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -56,6 +57,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompeti import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -114,7 +116,6 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; import com.sap.sse.common.Duration; @@ -132,7 +133,7 @@ import com.sap.sse.shared.media.VideoDescriptor; public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; - private final CompetitorWithBoatJsonSerializer competitorSerializer = CompetitorWithBoatJsonSerializer.create(); + private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinder raceTrackingConnectivityParamsServiceFinder; @@ -879,7 +880,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorEvent(event)); return result; } - + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorAndBoatEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorAndBoatEvent(event)); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogEndOfTrackingEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1021,6 +1029,15 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + private Object storeRaceLogRegisterCompetitorAndBoatEvent(RaceLogRegisterCompetitorAndBoatEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.RACE_LOG_BOAT_ID.name(), event.getBoat().getId()); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseCompetitorsFromRaceLogEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1471,6 +1488,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorAndBoatEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.REGATTA_LOG_BOAT_ID.name(), event.getBoat().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogCloseOpenEndedDeviceMappingEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java index a65b20e14ad..f5aa8f03605 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java @@ -25,6 +25,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -146,6 +147,12 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { mongoObjectFactory.storeRaceLogEventEvent(object); } + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + mongoObjectFactory.storeRaceLogEventEvent(object); + } + @Override public void visit(RaceLogAdditionalScoringInformationEvent event) { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java index 09398ffcbaa..2dd3aa01f86 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -57,6 +58,11 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); } + @Override + public void visit(RegattaLogRegisterCompetitorAndBoatEvent event) { + mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); + } + @Override public void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 2669506e62f..6dc3530251f 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -146,11 +146,11 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { boatClass = rLeaderboard.getRegatta().getBoatClass(); } else { if (!Util.isEmpty(raceColumn.getAllCompetitors(fleet))) { - boatClass = findDominatingBoatClass(raceColumn.getAllCompetitors(fleet)); + boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values()); } else if (!Util.isEmpty(raceColumn.getAllCompetitors())) { - boatClass = findDominatingBoatClass(raceColumn.getAllCompetitors()); + boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats().values()); } else if (!Util.isEmpty(leaderboard.getAllCompetitors())) { - boatClass = findDominatingBoatClass(leaderboard.getAllCompetitors()); + boatClass = leaderboard.getBoatClass(); } else { throw new NotDenotableForRaceLogTrackingException("Couldn't infer boat class, no competitors on race and leaderboard"); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java index fb4f8d3d823..8bc1dcfdafa 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.abstractlog.race; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -42,6 +43,8 @@ public interface RaceLogEventVisitor { public void visit(RaceLogRegisterCompetitorEvent event); + public void visit(RaceLogRegisterCompetitorAndBoatEvent event); + public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation); public void visit(RaceLogFixedMarkPassingEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java index 8407d6f2d86..9f036e7adfa 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java @@ -23,6 +23,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -108,7 +109,12 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit public void visit(RaceLogRegisterCompetitorEvent event) { notifyListenerAboutEventAdded(event); } - + + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + notifyListenerAboutEventAdded(event); + } + @Override public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { notifyListenerAboutEventAdded(additionalScoringInformation); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java index bff059adf00..c6fdaaa1c9c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java @@ -22,6 +22,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -115,7 +116,12 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { public void visit(RaceLogRegisterCompetitorEvent event) { } - + + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + + } + @Override public void visit(RaceLogAdditionalScoringInformationEvent event) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorAndBoatEvent.java new file mode 100644 index 00000000000..4c48ba84796 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorAndBoatEvent.java @@ -0,0 +1,10 @@ +package com.sap.sailing.domain.abstractlog.race.tracking; + +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; + +public interface RaceLogRegisterCompetitorAndBoatEvent + extends RaceLogEvent, RegisterCompetitorAndBoatEvent { + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java new file mode 100644 index 00000000000..a05c26e9e81 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java @@ -0,0 +1,44 @@ +package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl; + +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; + +/** + * Used to find competitors (including their boats) of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the + * competitors for the given race are registered on the RaceLog via {@link RaceLogUsesOwnCompetitorsAnalyzer} or on the + * RegattaLog and fetches the competitors appropriately. + * + * Should not be used by clients directly. Instead, get the competitor set from the {@code RaceColumn}, using either one + * of {@code getAllCompetitorsAndTheirBoats()} and {@code getAllCompetitorsAndTheirBoats(Fleet)}. Those methods automatically check whether a + * tracked race is present, which takes precedence over the Race/RegattaLog. + * + * @author Jan Bross (D056848) + * + */ +public class RegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer> { + private RegattaLog regattaLog; + + public RegisteredCompetitorsAndBoatsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) { + super(raceLog); + this.regattaLog = regattaLog; + } + + @Override + protected Map performAnalysis() { + final Map result; + if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { + // get Events from RaceLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); + } else { + // get Events from RegattaLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(regattaLog).analyze(); + } + return result; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java new file mode 100644 index 00000000000..50daed3a0cd --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java @@ -0,0 +1,62 @@ +package com.sap.sailing.domain.abstractlog.race.tracking.impl; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventData; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.TimePoint; + +public class RaceLogRegisterCompetitorAndBoatEventImpl extends BaseRegisterCompetitorAndBoatEventImpl implements + RaceLogRegisterCompetitorAndBoatEvent { + private static final long serialVersionUID = 1395401990335109923L; + private final RaceLogEventData raceLogEventData; + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RaceLogRegisterCompetitorAndBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, int passId, Competitor competitor, Boat boat) + throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, competitor, boat); + this.raceLogEventData = new RaceLogEventDataImpl(null, passId); + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RaceLogRegisterCompetitorAndBoatEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int passId, Competitor competitor, Boat boat) + throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), passId, competitor, boat); + } + + @Override + public int getPassId() { + return raceLogEventData.getPassId(); + } + + @Override + public List getInvolvedBoats() { + return Collections.singletonList(getCompetitor()); + } + + @Override + public String toString() { + return raceLogEventData.toString(); + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index 19780a1174b..feb61797389 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -5,6 +5,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -22,7 +23,9 @@ public interface RegattaLogEventVisitor { void visit(RegattaLogCloseOpenEndedDeviceMappingEvent event); void visit(RegattaLogRegisterCompetitorEvent event); - + + void visit(RegattaLogRegisterCompetitorAndBoatEvent event); + void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event); void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java new file mode 100644 index 00000000000..9c39e217079 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java @@ -0,0 +1,10 @@ +package com.sap.sailing.domain.abstractlog.regatta.events; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; + +public interface RegattaLogRegisterCompetitorAndBoatEvent + extends RegattaLogEvent, RegisterCompetitorAndBoatEvent { + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorAndBoatEventImpl.java new file mode 100644 index 00000000000..b264687eb85 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorAndBoatEventImpl.java @@ -0,0 +1,39 @@ +package com.sap.sailing.domain.abstractlog.regatta.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.TimePoint; + +public class RegattaLogRegisterCompetitorAndBoatEventImpl extends BaseRegisterCompetitorAndBoatEventImpl + implements RegattaLogRegisterCompetitorAndBoatEvent { + private static final long serialVersionUID = 3577775910921730978L; + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterCompetitorAndBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, Competitor competitor, Boat boat) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, competitor, boat); + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterCompetitorAndBoatEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Competitor competitor, Boat boat) throws IllegalArgumentException { + super(logicalTimePoint, author, competitor, boat); + } + + @Override + public void accept(RegattaLogEventVisitor visitor) { + visitor.visit(this); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java index 808a9b9af97..df2c6e92249 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java @@ -6,6 +6,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -37,6 +38,10 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor { public void visit(RegattaLogRegisterCompetitorEvent event) { } + @Override + public void visit(RegattaLogRegisterCompetitorAndBoatEvent event) { + } + @Override public void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java index bf9d9fd1cb2..dbe0f594062 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java @@ -7,6 +7,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -40,6 +41,11 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor eventAdded(event); } + @Override + public void visit(RegattaLogRegisterCompetitorAndBoatEvent event) { + eventAdded(event); + } + @Override public void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { eventAdded(event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java new file mode 100644 index 00000000000..409dbc641aa --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java @@ -0,0 +1,50 @@ +package com.sap.sailing.domain.abstractlog.shared.analyzing; + +import java.util.HashMap; +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; + +/** + * This class searches for RegisterCompetitorEvents in the given log. + * + * TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredCompetitorsAnalyzer} or {@link RaceLogRegisteredCompetitorsAnalyzer} + * + * Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered competitors for the race + * corresponding to the RaceLog/the races corresponding to the RegattaLog. + * + * This is the case as by default the competitors registered on the RegattaLog are used for each race of the regatta + * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the + * {@link RaceLogUseCompetitorsFromRaceLogEvent}. Is an event of this type present, the competitors written into the + * RaceLog are used instead of the competitors in the RegattaLog. + * + */ +public class CompetitorsAndBoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public CompetitorsAndBoatsInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Map performAnalysis() { + Map result = new HashMap<>(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegisterCompetitorAndBoatEvent) { + RegisterCompetitorAndBoatEvent competitorAndBoatEvent = (RegisterCompetitorAndBoatEvent) event; + result.put(competitorAndBoatEvent.getCompetitor(), competitorAndBoatEvent.getBoat()); + } + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java new file mode 100644 index 00000000000..2b5298f7a19 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java @@ -0,0 +1,24 @@ +package com.sap.sailing.domain.abstractlog.shared.events; + +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.IsManagedByCache; + +/** + * Register a competitor and the boat for that race using the {@link RaceLog} in racelog-tracked races. + * + * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, + * if the competitor is known to already exist on the server, as it is + * {@link IsManagedByCache#resolve(com.sap.sailing.domain.base.SharedDomainFactory) resolved} + * on arrival. + * @author Frank Mittag + * + */ +public interface RegisterCompetitorAndBoatEvent extends AbstractLogEvent, Revokable { + Competitor getCompetitor(); + + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java new file mode 100644 index 00000000000..4803a13a1bf --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java @@ -0,0 +1,59 @@ +package com.sap.sailing.domain.abstractlog.shared.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.TimePoint; + +public abstract class BaseRegisterCompetitorAndBoatEventImpl extends AbstractLogEventImpl implements + RegisterCompetitorAndBoatEvent { + private static final long serialVersionUID = 7528972504689931986L; + private final Competitor competitor; + private final Boat boat; + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public BaseRegisterCompetitorAndBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor competitor, Boat boat) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, pId); + checkCompetitor(competitor); + this.competitor = competitor; + this.boat = boat; + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public BaseRegisterCompetitorAndBoatEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Competitor competitor, Boat boat) throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), competitor, boat); + } + + private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { + if (competitor == null) { + throw new IllegalArgumentException("Competitor may not be null"); + } + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + + @Override + public Boat getBoat() { + return boat; + } + + @Override + public String getShortInfo() { + return "competitor: " + getCompetitor().toString() + " with boat " + getBoat().toString(); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 8f6f8265e52..53a038bb847 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -7,6 +7,7 @@ import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; @@ -75,8 +76,12 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { void addCompetitors(Iterable competitors); - CompetitorDTO convertToCompetitorDTO(Competitor c); - + CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); + + CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); + + CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); + /** * Listeners added here are notified whenever {@link #updateCompetitor(String, String, Color, String, Nationality)} is called * for any competitor in this store. diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java new file mode 100644 index 00000000000..31da5747bda --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java @@ -0,0 +1,226 @@ +package com.sap.sailing.domain.base.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.net.URI; +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorChangeListener; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; +import com.sap.sse.common.Util; + +public class CompetitorWithoutBoatImpl implements DynamicCompetitor { + private static final long serialVersionUID = 294603681016643157L; + private final DynamicTeam team; + private final Serializable id; + private String name; + private String shortName; + private String searchTag; + private Color color; + private transient Set listeners; + private String email; + private URI flagImage; + private Double timeOnTimeFactor; + private Duration timeOnDistanceAllowancePerNauticalMile; + + public CompetitorWithoutBoatImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + this.id = id; + this.name = name; + this.shortName = shortName; + this.team = team; + this.color = color; + this.email = email; + this.flagImage = flagImage; + this.timeOnTimeFactor = timeOnTimeFactor; + this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; + this.searchTag = searchTag; + this.listeners = new HashSet(); + } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + listeners = new HashSet(); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getShortName() { + return shortName; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public void setName(String newName) { + final String oldName = this.name; + if (!Util.equalsWithNull(oldName, newName)) { + this.name = newName; + for (CompetitorChangeListener listener : getListeners()) { + listener.nameChanged(oldName, newName); + } + } + } + + @Override + public void setShortName(String newShortName) { + final String oldShortName = this.shortName; + if (!Util.equalsWithNull(oldShortName, newShortName)) { + this.shortName = newShortName; + for (CompetitorChangeListener listener : getListeners()) { + listener.shortNameChanged(oldShortName, newShortName); + } + } + } + + + @Override + public Serializable getId() { + return id; + } + + @Override + public DynamicTeam getTeam() { + return team; + } + + @Override + public Competitor resolve(SharedDomainFactory domainFactory) { + Competitor result = domainFactory + .getOrCreateCompetitor(getId(), getName(), getShortName(), getColor(), getEmail(), getFlagImage(), getTeam(), + getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag); + return result; + } + + @Override + public Color getColor() { + return color; + } + + public void setColor(Color color) { + final Color oldColor = this.color; + if (!Util.equalsWithNull(oldColor, color)) { + this.color = color; + for (CompetitorChangeListener listener : getListeners()) { + listener.colorChanged(oldColor, color); + } + } + } + + @Override + public void addCompetitorChangeListener(CompetitorChangeListener listener) { + synchronized (listeners) { + listeners.add(listener); + } + getTeam().addNationalityChangeListener(listener); + } + + @Override + public void removeCompetitorChangeListener(CompetitorChangeListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + getTeam().removeNationalityChangeListener(listener); + } + + private Iterable getListeners() { + synchronized (listeners) { + return new HashSet(listeners); + } + } + + @Override + public String getSearchTag() { + return searchTag; + } + + public void setSearchTag(String newSearchTag) { + final String oldSearchTag = this.searchTag; + if (!Util.equalsWithNull(oldSearchTag, newSearchTag)) { + this.searchTag = newSearchTag; + for (CompetitorChangeListener listener : getListeners()) { + listener.searchTagChanged(oldSearchTag, newSearchTag); + } + } + } + + @Override + public String getEmail() { + return email; + } + + public void setEmail(String newEmail) { + final String oldEmail = this.email; + if (!Util.equalsWithNull(oldEmail, newEmail)) { + this.email = newEmail; + for (CompetitorChangeListener listener : getListeners()) { + listener.emailChanged(oldEmail, newEmail); + } + } + } + + @Override + public boolean hasEmail(){ + return email != null && !email.isEmpty(); + } + + @Override + public URI getFlagImage() { + return flagImage; + } + + @Override + public void setFlagImage(URI flagImage) { + final URI oldFlagImage = this.flagImage; + this.flagImage = flagImage; + if (!Util.equalsWithNull(oldFlagImage, flagImage)) { + for (CompetitorChangeListener listener : getListeners()) { + listener.flagImageChanged(oldFlagImage, flagImage); + } + } + } + + @Override + public Double getTimeOnTimeFactor() { + return timeOnTimeFactor; + } + + @Override + public Duration getTimeOnDistanceAllowancePerNauticalMile() { + return timeOnDistanceAllowancePerNauticalMile; + } + + @Override + public void setTimeOnTimeFactor(Double timeOnTimeFactor) { + Double oldTimeOnTimeFactor = this.timeOnTimeFactor; + this.timeOnTimeFactor = timeOnTimeFactor; + if (!Util.equalsWithNull(oldTimeOnTimeFactor, timeOnTimeFactor)) { + for (CompetitorChangeListener listener : getListeners()) { + listener.timeOnTimeFactorChanged(oldTimeOnTimeFactor, timeOnTimeFactor); + } + } + } + + @Override + public void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile) { + Duration oldTimeOnDistanceAllowancePerNauticalMile = this.timeOnDistanceAllowancePerNauticalMile; + this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; + if (!Util.equalsWithNull(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile)) { + for (CompetitorChangeListener listener : getListeners()) { + listener.timeOnDistanceAllowancePerNauticalMileChanged(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile); + } + } + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index e0f36db1099..023aeaa0764 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -18,12 +18,15 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTOImpl; import com.sap.sse.common.Color; import com.sap.sse.common.CountryCode; import com.sap.sse.common.Duration; @@ -47,7 +50,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab */ private final Set competitorsToUpdateDuringGetOrCreate; - private transient WeakHashMap weakCompetitorDTOCache; + private transient WeakHashMap weakCompetitorDTOCache; private final Set boatsToUpdateDuringGetOrCreate; @@ -60,7 +63,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitorCache = new HashMap(); competitorsByIdAsString = new HashMap(); competitorsToUpdateDuringGetOrCreate = new HashSet(); - weakCompetitorDTOCache = new WeakHashMap(); + weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); boatCache = new HashMap(); boatsByIdAsString = new HashMap(); @@ -71,7 +74,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); - weakCompetitorDTOCache = new WeakHashMap(); + weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); weakBoatDTOCache = new WeakHashMap(); boatUpdateListeners = Collections.synchronizedSet(new HashSet()); @@ -246,11 +249,11 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } @Override - public CompetitorDTO convertToCompetitorDTO(Competitor c) { + public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { LockUtil.lockForRead(lock); boolean needToUnlockReadLock = true; try { - CompetitorDTO competitorDTO = weakCompetitorDTOCache.get(c); + CompetitorWithoutBoatDTO competitorDTO = weakCompetitorDTOCache.get(c); if (competitorDTO == null) { LockUtil.unlockAfterRead(lock); needToUnlockReadLock = false; @@ -259,18 +262,12 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab if (competitorDTO == null) { final Nationality nationality = c.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - Boat b = c.getBoat(); - BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), b.getBoatClass().getDisplayName(), - b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam()); - BoatDTO boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); - competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" + competitorDTO = new CompetitorWithoutBoatDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c.getId().toString(), c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), c.getFlagImage() == null ? null : c.getFlagImage().toString(), - boatDTO, - boatClassDTO, c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); weakCompetitorDTOCache.put(c, competitorDTO); } @@ -285,6 +282,29 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } } + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { + return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); + } + @Override + public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat b) { + CompetitorWithoutBoatDTO c = convertToCompetitorWithoutBoatDTO(competitor); + BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), b.getBoatClass().getDisplayName(), + b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam()); + BoatDTO boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); + CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getTwoLetterIsoCountryCode(), + c.getThreeLetterIocCountryCode(), + c.getCountryName(), + c.getIdAsString(), + c.getImageURL(), + c.getFlagImageURL(), + boatDTO, + boatClassDTO, + c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); + + return competitorDTO; + } + @Override public void allowCompetitorResetToDefaults(Competitor competitor) { LockUtil.lockForWrite(lock); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java index ec229e6350c..8ccd78f5069 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java @@ -10,6 +10,7 @@ import java.util.Map; import org.junit.Ignore; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; @@ -159,8 +160,9 @@ public class FetchTracksAndStoreLocallyTest extends OnlineTracTracBasedTest { private void storeTracks() throws FileNotFoundException, IOException { for (Map.Entry> competitorAndTrack : tracks.entrySet()) { Competitor competitor = competitorAndTrack.getKey(); + Boat boatOfCompetitor = trackedRace.getRace().getBoatOfCompetitorById(competitor); DynamicGPSFixTrack track = competitorAndTrack.getValue(); - storeTrack(competitor, track, getTracTracEvent().getName()+"-"+trackedRace.getRace().getName()); + storeTrack(competitor, boatOfCompetitor, track, getTracTracEvent().getName()+"-"+trackedRace.getRace().getName()); } } 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 9f8e9f08003..d53c5ce9122 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 @@ -77,9 +77,9 @@ public interface DomainFactory { Sideline createSideline(String name, Iterable controlPoints); - com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(ICompetitor competitor); + com.sap.sailing.domain.base.CompetitorAndBoat getOrCreateCompetitorAndBoat(ICompetitor competitor); - com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(UUID competitorId, String competitorClassName, + com.sap.sailing.domain.base.CompetitorAndBoat getOrCreateCompetitorAndBoat(UUID competitorId, String competitorClassName, String nationalityAsString, String name, String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag); /** 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 069777680cc..cde248f48c1 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 @@ -26,6 +26,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -35,7 +36,7 @@ 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.Waypoint; -import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; @@ -73,6 +74,7 @@ import com.sap.sailing.domain.tractracadapter.ReceiverType; import com.sap.sailing.domain.tractracadapter.TracTracConfiguration; import com.sap.sailing.domain.tractracadapter.TracTracControlPoint; import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker; +import com.sap.sse.common.Color; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -233,24 +235,25 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public Competitor getOrCreateCompetitor(ICompetitor competitor) { + public CompetitorAndBoat getOrCreateCompetitorAndBoat(ICompetitor competitor) { final UUID competitorId = competitor.getId(); final String competitorClassName = competitor.getCompetitorClass()==null?null:competitor.getCompetitorClass().getName(); final String nationalityAsString = competitor.getNationality(); final String name = competitor.getName(); final String shortName = competitor.getShortName(); - Competitor result = getOrCreateCompetitor(competitorId, competitorClassName, nationalityAsString, name, + CompetitorAndBoat result = getOrCreateCompetitorAndBoat(competitorId, competitorClassName, nationalityAsString, name, shortName, competitor.getHandicapToT(), competitor.getHandicapToD(), null); return result; } @Override - public Competitor getOrCreateCompetitor(final UUID competitorId, final String competitorClassName, + public CompetitorAndBoat getOrCreateCompetitorAndBoat(final UUID competitorId, final String competitorClassName, final String nationalityAsString, final String name, final String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag) { CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); - Competitor result = competitorStore.getExistingCompetitorById(competitorId); - if (result == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(result)) { + Competitor domainCompetitor = competitorStore.getExistingCompetitorById(competitorId); + Boat domainBoat = competitorStore.getExistingBoatById(competitorId); + if (domainCompetitor == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) { Nationality nationality; try { nationality = getOrCreateNationality(nationalityAsString); @@ -260,11 +263,17 @@ public class DomainFactoryImpl implements DomainFactory { logger.log(Level.SEVERE, "Unknown nationality "+nationalityAsString+" for competitor "+name+"; leaving null", iae); } DynamicTeam team = createTeam(name, nationality, competitorId); - result = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, + domainCompetitor = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, null /* email */, null /* flagImag */, team, (double) timeOnTimeFactor, new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); } - return result; + return new CompetitorAndBoatImpl(domainCompetitor, domainBoat); + } + + private Boat getOrCreateBoat(Serializable competitorId, Serializable boatId, String boatName, BoatClass boatClass, String sailId, Color boatColor) { + CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); + Boat boat = competitorAndBoatStore.getOrCreateBoat(competitorId, boatName, boatClass, sailId, boatColor); + return boat; } private DynamicTeam createTeam(String name, Nationality nationality, UUID competitorId) { @@ -594,9 +603,10 @@ public class DomainFactoryImpl implements DomainFactory { final Map competitorBoatInfos = new HashMap<>(); for (IRaceCompetitor rc : race.getRaceCompetitors()) { Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); - Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); + CompetitorAndBoat existingCompetitorAndBoat = getOrCreateCompetitorAndBoat(rc.getCompetitor()); + Competitor existingCompetitor = existingCompetitorAndBoat.getCompetitor(); if (existingCompetitor != null && competitorBoatInfo != null) { - Boat boatOfCompetitor = new BoatImpl(competitorBoatInfo.getB(), + Boat boatOfCompetitor = getOrCreateBoat(existingCompetitor.getId(), competitorBoatInfo.getB(), competitorBoatInfo.getA(), defaultBoatClass, null, AbstractColor.getCssColor(competitorBoatInfo.getC())); competitorBoatInfos.put(existingCompetitor, boatOfCompetitor); } @@ -612,7 +622,7 @@ public class DomainFactoryImpl implements DomainFactory { for (IRaceCompetitor rc : race.getRaceCompetitors()) { // also add those whose race class doesn't match the dominant one (such as camera boats) // because they may still send data that we would like to record in some tracks - competitors.add(getOrCreateCompetitor(rc.getCompetitor())); + competitors.add(getOrCreateCompetitorAndBoat(rc.getCompetitor()).getCompetitor()); competitorClasses.add(rc.getCompetitor().getCompetitorClass()); } BoatClass dominantBoatClass = getDominantBoatClass(competitorClasses); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java index 96b25bbbca3..0aac8f92c8b 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java @@ -69,11 +69,11 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue REMOVE later on */ CompetitorDTO convertToCompetitorDTO(Competitor c); + CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); + + CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); + BoatDTO convertToBoatDTO(Boat boat); FleetDTO convertToFleetDTO(Fleet fleet); @@ -69,7 +77,12 @@ public interface DomainFactory extends SharedDomainFactory { PlacemarkDTO convertToPlacemarkDTO(Placemark placemark); - List getCompetitorDTOList(List competitors); + List getCompetitorDTOList(List competitors); + + /** Temporary function -> REMOVE later on */ + List getCompetitorWithoutBoatDTOListTemp(List competitors); + + List getCompetitorDTOListTemp(List competitors); TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index de60e758c8f..138eec9bd1e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -22,6 +22,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; @@ -296,8 +297,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem // race exists, its competitors set takes precedence over what's in the race log. Usually, // the tracked race will have the same competitors as those in the race log, or more because // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze(); - result = viaRaceLog; + result = new RegisteredCompetitorsAndBoatsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze(); } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 66e512243b6..2c38cc3e6a1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; @@ -26,6 +27,7 @@ import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; import com.sap.sailing.domain.common.dto.PlacemarkOrderDTO; @@ -48,10 +50,10 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBre import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBreaksTie2017; import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointMatchRacing; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEight; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterpolation; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; -import com.sap.sailing.domain.leaderboard.impl.HighPointMatchRacing; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard; @@ -140,10 +142,25 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain } @Override - public CompetitorDTO convertToCompetitorDTO(Competitor c) { + public CompetitorDTO convertToCompetitorDTO(Competitor competitor) { + return competitorAndBoatStore.convertToCompetitorDTO(competitor, null); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { + return competitorAndBoatStore.convertToCompetitorDTO(competitor, boat); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c) { return competitorAndBoatStore.convertToCompetitorDTO(c); } + @Override + public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { + return competitorAndBoatStore.convertToCompetitorWithoutBoatDTO(c); + } + @Override public BoatDTO convertToBoatDTO(Boat boat) { return competitorAndBoatStore.convertToBoatDTO(boat); @@ -196,6 +213,7 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain // GPS data statisticsDTO.hasGPSData = trackedRace.hasGPSData(); Competitor leaderOrWinner = null; + Boat leaderOrWinnerBoat = null; TimePoint now = MillisecondsTimePoint.now(); try { if (trackedRace.isLive(now)) { @@ -205,13 +223,14 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); if (fleetOfCompetitor != null && fleetOfCompetitor.equals(fleet)) { leaderOrWinner = competitor; + leaderOrWinnerBoat = trackedRace.getBoatOfCompetitor(leaderOrWinner); break; } } } if (leaderOrWinner != null) { statisticsDTO.hasLeaderOrWinnerData = true; - statisticsDTO.leaderOrWinner = convertToCompetitorDTO(leaderOrWinner); + statisticsDTO.leaderOrWinner = convertToCompetitorDTO(leaderOrWinner, leaderOrWinnerBoat); GPSFixTrack track = trackedRace.getTrack(leaderOrWinner); if (track != null) { statisticsDTO.averageGPSDataSampleInterval = track.getAverageIntervalBetweenRawFixes(); @@ -345,12 +364,29 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain } @Override - public List getCompetitorDTOList(List competitors) { + public List getCompetitorDTOList(List competitors) { + List result = new ArrayList(); + for (CompetitorWithBoat competitor : competitors) { + result.add(convertToCompetitorDTO(competitor)); + } + return result; + } + + @Override + public List getCompetitorDTOListTemp(List competitors) { List result = new ArrayList(); for (Competitor competitor : competitors) { result.add(convertToCompetitorDTO(competitor)); } return result; } - + + @Override + public List getCompetitorWithoutBoatDTOListTemp(List competitors) { + List result = new ArrayList(); + for (Competitor competitor : competitors) { + result.add(convertToCompetitorWithoutBoatDTO(competitor)); + } + return result; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java index 55ac0fcd741..811a3b17436 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java @@ -25,6 +25,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -134,6 +135,11 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali notifyOnAdd(event); } + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + notifyOnAdd(event); + } + @Override public void visit(RaceLogFixedMarkPassingEvent event) { notifyOnAdd(event); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index 5373f460c06..7f5888970ae 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -133,7 +133,7 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns { void setSuppressed(Competitor competitor, boolean suppressed); /** - * Retrieves the boat for a given competitor. + * Retrieves the boat of a given competitor for the specified raceColumn and fleet. */ Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index b071a65050c..cc69753aed7 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -2,7 +2,6 @@ package com.sap.sailing.domain.leaderboard.impl; import java.io.IOException; import java.io.ObjectInputStream; -import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,6 +34,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; @@ -57,6 +57,7 @@ import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.dto.BasicRaceDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO; @@ -1307,8 +1308,10 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null, fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race, isMetaLeaderboardColumn); } + // List getCompetitorWithoutBoatDTOList(List competitors); + // List getCompetitorDTOList(List competitors); Future> task = executor.submit( - () -> baseDomainFactory.getCompetitorDTOList(AbstractSimpleLeaderboardImpl.this.getCompetitorsFromBestToWorst(raceColumn, timePoint))); + () -> baseDomainFactory.getCompetitorDTOListTemp(AbstractSimpleLeaderboardImpl.this.getCompetitorsFromBestToWorst(raceColumn, timePoint))); competitorsFromBestToWorstTasks.put(raceColumn, task); } // wait for the competitor orderings to have been computed for all race columns before continuing; subsequent tasks may depend on these data @@ -2012,8 +2015,13 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race @Override public BoatClass getBoatClass() { - return Util.getDominantObject(StreamSupport.stream(getCompetitors().spliterator(), /* parallel */ false). - map(c->c.getBoat().getBoatClass()).collect(Collectors.toList())); + Set allBoats = new HashSet<>(); + for (final RaceColumn raceColumn : getRaceColumns()) { + Map competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(); + allBoats.addAll(competitorsAndTheirBoats.values()); + } + return Util.getDominantObject(StreamSupport.stream(allBoats.spliterator(), /* parallel */ false). + map(b->b.getBoatClass()).collect(Collectors.toList())); } protected abstract LeaderboardType getLeaderboardType(); 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 fe075435790..4e464ccd500 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 @@ -15,13 +15,11 @@ import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Fleet; 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; import com.sap.sailing.domain.base.impl.AbstractRaceExecutionOrderProvider; import com.sap.sailing.domain.base.impl.RegattaLogEventAdditionForwarder; @@ -110,7 +108,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements this.regattaLikeHelper.addListener(new RegattaLogEventAdditionForwarder(getRaceColumnListeners())); this.raceExecutionOrderProvider = new RaceExecutionOrderCache(); } - + /** * Deserialization has to be maintained in lock-step with {@link #writeObject(ObjectOutputStream) serialization}. * When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 85f2cfa40fe..46ca0ff849a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -1,10 +1,12 @@ package com.sap.sailing.domain.leaderboard.meta; import java.util.Collections; +import java.util.Map; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; @@ -284,4 +286,16 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R @Override public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { } + + @Override + public Map getAllCompetitorsAndTheirBoats() { + // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + + @Override + public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { + // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java index ebde9a2c6af..9890e1e95ee 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java @@ -4,6 +4,7 @@ import java.io.Serializable; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.NamedDTO; @@ -22,13 +23,17 @@ public class SimpleCompetitorDTO extends NamedDTO implements DTO, Serializable, } @GwtIncompatible - public SimpleCompetitorDTO(Competitor competitor) { + public SimpleCompetitorDTO(C competitor) { super(competitor.getName()); final Nationality nationality = competitor.getTeam().getNationality(); CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - this.sailID = competitor.getBoat().getSailID(); this.twoLetterIsoCountryCode = countryCode == null ? null : countryCode.getTwoLetterISOCode(); this.flagImageURL = competitor.getFlagImage() == null ? null : competitor.getFlagImage().toString(); + if (competitor instanceof CompetitorWithBoat) { + this.sailID = ((CompetitorWithBoat) competitor).getBoat().getSailID(); + } else { + this.sailID = null; + } } @GwtIncompatible diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorSuggestionAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorSuggestionAction.java index 8b70fe591f4..e3a7dd6aadb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorSuggestionAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/user/profile/GetCompetitorSuggestionAction.java @@ -31,8 +31,7 @@ public class GetCompetitorSuggestionAction implements SailingAction competitorFilter = new AbstractListFilter() { @Override public Iterable getStrings(Competitor competitor) { - if (competitor.getBoat() == null) return Arrays.asList(competitor.getName()); - return Arrays.asList(competitor.getBoat().getSailID(), competitor.getName()); + return Arrays.asList(competitor.getName()); } }; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 92499203998..9ac3ed86858 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -25,8 +25,8 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index 9f466062a45..33cd593911b 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -25,6 +25,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -258,11 +259,17 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac public void visit(RaceLogRevokeEvent event) { chosenSerializer = revokeSerializer; } + @Override public void visit(RaceLogRegisterCompetitorEvent event) { chosenSerializer = registerCompetitorSerializer; } - + + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + chosenSerializer = registerCompetitorSerializer; + } + @Override public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { chosenSerializer = additionalScoringInformationSerializer; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 2c49145e136..50efe111107 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -43,7 +43,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpe import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.impl.OpenEndedDeviceMappingFinder; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; @@ -230,12 +229,10 @@ public class LeaderboardsResource extends AbstractSailingServerResource { for (Competitor competitor : leaderboard.getCompetitors()) { JSONObject jsonCompetitor = new JSONObject(); jsonCompetitor.put("name", competitor.getName()); + jsonCompetitor.put("shortName", competitor.getShortName()); final String displayName = leaderboard.getDisplayName(competitor); jsonCompetitor.put("displayName", displayName == null ? competitor.getName() : displayName); jsonCompetitor.put("id", competitor.getId().toString()); - final Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); - final String sailID = boatOfCompetitor != null ? boatOfCompetitor.getSailID() : null; - jsonCompetitor.put("sailID", sailID); Nationality nationality = competitor.getTeam().getNationality(); jsonCompetitor.put("nationality", nationality != null ? nationality.getThreeLetterIOCAcronym() : null); jsonCompetitor.put("countryCode", nationality != null ? (nationality.getCountryCode() != null ? nationality diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java index 2b9b9d93488..0c501a4abcd 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java @@ -72,7 +72,7 @@ public class RegattaByKeywordSearchService { leaderboardStrings.add(leaderboard.getDisplayName()); for (Competitor competitor : leaderboard.getCompetitors()) { leaderboardStrings.add(competitor.getName()); - leaderboardStrings.add(competitor.getBoat().getSailID()); + leaderboardStrings.add(competitor.getShortName()); String competitorDisplayName = leaderboard.getDisplayName(competitor); if (competitorDisplayName != null) { leaderboardStrings.add(competitorDisplayName); diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java index fd551388994..46fcd6cfac1 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java @@ -238,7 +238,8 @@ public class LeaderboardData extends ExportAction { MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { // add this competitor to the list to have him evaluated - Element competitorElement = createCompetitorXML(competitorInLeaderboard, leaderboard, /*shortVersion*/ true, null); + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); Element competitorRaceDataElement = new Element("competitor_race_data"); MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); @@ -399,7 +400,8 @@ public class LeaderboardData extends ExportAction { if (fleetCompetitorIsSailingIn != null && fleetCompetitorIsSailingIn.equals(fleet) && !competitorsForColumn.contains(competitorInLeaderboard)) { if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { // add this competitor to the list to have him evaluated - Element competitorElement = createCompetitorXML(competitorInLeaderboard, leaderboard, /*shortVersion*/ true, null); + Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitorInLeaderboard, column, fleetCompetitorIsSailingIn); + Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); Element competitorRaceDataElement = new Element("competitor_race_data"); MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, race.getEndOfRace()); addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); @@ -420,7 +422,8 @@ public class LeaderboardData extends ExportAction { int raceRank = 0; for (Competitor competitor : allCompetitors) { - Element competitorElement = createCompetitorXML(competitor, leaderboard, /*shortVersion*/ true, null); + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); Element competitorRaceDataElement = new Element("competitor_race_data"); MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, column, race.getEndOfRace()); if (maxPointsReason != null && !maxPointsReason.equals(MaxPointsReason.NONE)) { @@ -620,7 +623,8 @@ public class LeaderboardData extends ExportAction { * Creates xml elements related to a competitor. * @param shortVersion when set to true then only the name and UUID is returned */ - private Element createCompetitorXML(Competitor competitor, Leaderboard leaderboard, boolean shortVersion, Util.Pair> competitorConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { + private Element createCompetitorXML(Competitor competitor, Boat boatOfCompetitor, Leaderboard leaderboard, + boolean shortVersion, Util.Pair> competitorConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { TimePoint timeSpent = MillisecondsTimePoint.now(); Element competitorElement = new Element("competitor"); addNamedElementWithValue(competitorElement, "uuid", competitor.getId().toString()); @@ -629,7 +633,6 @@ public class LeaderboardData extends ExportAction { if (shortVersion) return competitorElement; - final Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); if (boatOfCompetitor != null) { addNamedElementWithValue(competitorElement, "sail_id", cleanSailId(boatOfCompetitor.getSailID(), competitor)); addNamedElementWithValue(competitorElement, "boat_class", boatOfCompetitor.getBoatClass().getName()); @@ -732,7 +735,8 @@ public class LeaderboardData extends ExportAction { addNamedElementWithValue(legElement, "great_circle_distance_at_end_of_race_in_meters", trackedLeg.getGreatCircleDistance(trackedLeg.getTrackedRace().getEndOfRace()).getMeters()); for (Competitor competitor : trackedLeg.getTrackedRace().getCompetitorsFromBestToWorst(/*timePoint*/ trackedLeg.getTrackedRace().getEndOfRace())) { - Element competitorElement = createCompetitorXML(competitor, leaderboard, /*shortVersion*/ true, null); + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); Element competitorLegDataElement = new Element("competitor_leg_data"); TrackedLegOfCompetitor competitorLeg = trackedLeg.getTrackedLeg(competitor); @@ -1031,9 +1035,9 @@ public class LeaderboardData extends ExportAction { final List racesElements = new ArrayList(); final List competitorElements = new ArrayList(); for (Competitor competitor : leaderboard.getAllCompetitors()) { - Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitor); + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? Util.Pair> competitorConfidenceAndErrorMessages = checkData(competitor, boatOfCompetitor); - competitorElements.add(createCompetitorXML(competitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); + competitorElements.add(createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); } List windData = new ArrayList(); TrackedRace raceBefore = null; int sameDayGroupIndex = 0; int raceCounter = 0; diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java index 188d3ebec8d..f406fcf140a 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java @@ -8,12 +8,6 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; -import android.content.Loader; -import android.os.Bundle; -import android.util.Log; - import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.services.sending.MessageSendingService; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; @@ -66,9 +60,7 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.CourseBase import com.sap.sailing.server.gateway.deserialization.coursedata.impl.GateDeserializer; import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer; import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.BoatClassJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer; @@ -82,6 +74,12 @@ import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer import com.sap.sailing.server.gateway.deserialization.racegroup.impl.RaceGroupDeserializer; import com.sap.sse.common.Util; +import android.app.LoaderManager.LoaderCallbacks; +import android.content.Context; +import android.content.Loader; +import android.os.Bundle; +import android.util.Log; + /** * Enables accessing of data. */ @@ -248,9 +246,8 @@ public class OnlineDataManager extends DataManager { @Override public Loader>> create(int id, Bundle args) throws Exception { ExLog.i(context, TAG, "Creating Competitor-OnlineDataLoader " + id); - JsonDeserializer competitorDeserializer = new CompetitorWithBoatJsonDeserializer(domainFactory.getCompetitorStore(), - new TeamJsonDeserializer(new PersonJsonDeserializer(new NationalityJsonDeserializer(domainFactory))), - new BoatJsonDeserializer(domainFactory, new BoatClassJsonDeserializer(domainFactory))); + JsonDeserializer competitorDeserializer = new CompetitorJsonDeserializer(domainFactory.getCompetitorStore(), + new TeamJsonDeserializer(new PersonJsonDeserializer(new NationalityJsonDeserializer(domainFactory)))); DataParser> parser = new CompetitorsDataParser(competitorDeserializer); DataHandler> handler = new CompetitorsDataHandler(OnlineDataManager.this, managedRace); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java index 4f83900400d..1627cd9aef1 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAdapter.java @@ -39,8 +39,11 @@ public class CompetitorAdapter extends RecyclerView.Adapter { @@ -14,17 +16,24 @@ public class CompetitorSailIdComparator implements Comparator { } @Override - public int compare(Competitor left, Competitor right) { - // if left is null, right will be greater - if (left == null || left.getBoat() == null || left.getBoat().getSailID() == null) { - return -1; - } + public int compare(Competitor leftCompetitor, Competitor rightCompetitor) { + if (leftCompetitor != null && leftCompetitor instanceof CompetitorWithBoat && + rightCompetitor != null && rightCompetitor instanceof CompetitorWithBoat) { + Boat leftBoat = ((CompetitorWithBoat) leftCompetitor).getBoat(); + Boat rightBoat = ((CompetitorWithBoat) rightCompetitor).getBoat(); + + // if left is null, right will be greater + if (leftBoat == null || leftBoat.getSailID() == null) { + return -1; + } - // if right is null, left will be greater - if (right == null || right.getBoat() == null || right.getBoat().getSailID() == null) { - return 1; - } + // if right is null, left will be greater + if (rightBoat == null || rightBoat.getSailID() == null) { + return 1; + } - return comparator.compare(left.getBoat().getSailID(), right.getBoat().getSailID()); + return comparator.compare(leftBoat.getSailID(), rightBoat.getSailID()); + } + return 0; } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java index 1c6ace1b64c..2c31be255e2 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java @@ -6,6 +6,39 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator; +import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager; +import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager; +import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager; +import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; +import com.sap.sailing.android.shared.util.AppUtils; +import com.sap.sailing.android.shared.util.ViewHelper; +import com.sap.sailing.domain.abstractlog.race.CompetitorResult; +import com.sap.sailing.domain.abstractlog.race.CompetitorResults; +import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl; +import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.racecommittee.app.AppConstants; +import com.sap.sailing.racecommittee.app.R; +import com.sap.sailing.racecommittee.app.data.DataManager; +import com.sap.sailing.racecommittee.app.data.OnlineDataManager; +import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager; +import com.sap.sailing.racecommittee.app.data.clients.LoadClient; +import com.sap.sailing.racecommittee.app.domain.impl.CompetitorResultWithIdImpl; +import com.sap.sailing.racecommittee.app.ui.adapters.CompetitorAdapter; +import com.sap.sailing.racecommittee.app.ui.adapters.FinishListAdapter; +import com.sap.sailing.racecommittee.app.ui.adapters.StringArraySpinnerAdapter; +import com.sap.sailing.racecommittee.app.ui.comparators.CompetitorSailIdComparator; +import com.sap.sailing.racecommittee.app.ui.comparators.NaturalNamedComparator; +import com.sap.sailing.racecommittee.app.ui.layouts.CompetitorEditLayout; +import com.sap.sailing.racecommittee.app.ui.layouts.HeaderLayout; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; + import android.content.Context; import android.content.DialogInterface; import android.content.Loader; @@ -27,38 +60,6 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; -import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator; -import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager; -import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager; -import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager; -import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; -import com.sap.sailing.android.shared.util.AppUtils; -import com.sap.sailing.android.shared.util.ViewHelper; -import com.sap.sailing.domain.abstractlog.race.CompetitorResult; -import com.sap.sailing.domain.abstractlog.race.CompetitorResults; -import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultImpl; -import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.racecommittee.app.AppConstants; -import com.sap.sailing.racecommittee.app.R; -import com.sap.sailing.racecommittee.app.data.DataManager; -import com.sap.sailing.racecommittee.app.data.OnlineDataManager; -import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager; -import com.sap.sailing.racecommittee.app.data.clients.LoadClient; -import com.sap.sailing.racecommittee.app.domain.impl.CompetitorResultWithIdImpl; -import com.sap.sailing.racecommittee.app.ui.adapters.CompetitorAdapter; -import com.sap.sailing.racecommittee.app.ui.adapters.FinishListAdapter; -import com.sap.sailing.racecommittee.app.ui.adapters.StringArraySpinnerAdapter; -import com.sap.sailing.racecommittee.app.ui.comparators.CompetitorSailIdComparator; -import com.sap.sailing.racecommittee.app.ui.comparators.NaturalNamedComparator; -import com.sap.sailing.racecommittee.app.ui.layouts.CompetitorEditLayout; -import com.sap.sailing.racecommittee.app.ui.layouts.HeaderLayout; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; - public class TrackingListFragment extends BaseFragment implements CompetitorAdapter.CompetitorClick, FinishListAdapter.FinishEvents, View.OnClickListener, AdapterView.OnItemSelectedListener { @@ -356,8 +357,11 @@ public class TrackingListFragment extends BaseFragment private void moveCompetitorToFinishList(Competitor competitor) { String name = ""; - if (competitor.getBoat() != null) { - name += competitor.getBoat().getSailID(); + if (competitor instanceof CompetitorWithBoat) { + CompetitorWithBoat competitorWithBoat = (CompetitorWithBoat) competitor; + if (competitorWithBoat.getBoat() != null) { + name += competitorWithBoat.getBoat().getSailID(); + } } name += " - " + competitor.getName(); mFinishedData.add(new CompetitorResultWithIdImpl(mId, competitor.getId(), name, mFinishedData.size() + 1, MaxPointsReason.NONE, From 7ce231fa4d221bbe4f401b8f185a2f677fe2222c Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 19 Jun 2017 21:26:11 +0200 Subject: [PATCH 024/271] removed unused class (from an old refactoring try) --- .../base/impl/CompetitorWithoutBoatImpl.java | 226 ------------------ 1 file changed, 226 deletions(-) delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java deleted file mode 100644 index 31da5747bda..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithoutBoatImpl.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.sap.sailing.domain.base.impl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.net.URI; -import java.util.HashSet; -import java.util.Set; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorChangeListener; -import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; -import com.sap.sse.common.Util; - -public class CompetitorWithoutBoatImpl implements DynamicCompetitor { - private static final long serialVersionUID = 294603681016643157L; - private final DynamicTeam team; - private final Serializable id; - private String name; - private String shortName; - private String searchTag; - private Color color; - private transient Set listeners; - private String email; - private URI flagImage; - private Double timeOnTimeFactor; - private Duration timeOnDistanceAllowancePerNauticalMile; - - public CompetitorWithoutBoatImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - this.id = id; - this.name = name; - this.shortName = shortName; - this.team = team; - this.color = color; - this.email = email; - this.flagImage = flagImage; - this.timeOnTimeFactor = timeOnTimeFactor; - this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; - this.searchTag = searchTag; - this.listeners = new HashSet(); - } - - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - ois.defaultReadObject(); - listeners = new HashSet(); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String toString() { - return getName(); - } - - @Override - public void setName(String newName) { - final String oldName = this.name; - if (!Util.equalsWithNull(oldName, newName)) { - this.name = newName; - for (CompetitorChangeListener listener : getListeners()) { - listener.nameChanged(oldName, newName); - } - } - } - - @Override - public void setShortName(String newShortName) { - final String oldShortName = this.shortName; - if (!Util.equalsWithNull(oldShortName, newShortName)) { - this.shortName = newShortName; - for (CompetitorChangeListener listener : getListeners()) { - listener.shortNameChanged(oldShortName, newShortName); - } - } - } - - - @Override - public Serializable getId() { - return id; - } - - @Override - public DynamicTeam getTeam() { - return team; - } - - @Override - public Competitor resolve(SharedDomainFactory domainFactory) { - Competitor result = domainFactory - .getOrCreateCompetitor(getId(), getName(), getShortName(), getColor(), getEmail(), getFlagImage(), getTeam(), - getTimeOnTimeFactor(), getTimeOnDistanceAllowancePerNauticalMile(), searchTag); - return result; - } - - @Override - public Color getColor() { - return color; - } - - public void setColor(Color color) { - final Color oldColor = this.color; - if (!Util.equalsWithNull(oldColor, color)) { - this.color = color; - for (CompetitorChangeListener listener : getListeners()) { - listener.colorChanged(oldColor, color); - } - } - } - - @Override - public void addCompetitorChangeListener(CompetitorChangeListener listener) { - synchronized (listeners) { - listeners.add(listener); - } - getTeam().addNationalityChangeListener(listener); - } - - @Override - public void removeCompetitorChangeListener(CompetitorChangeListener listener) { - synchronized (listeners) { - listeners.remove(listener); - } - getTeam().removeNationalityChangeListener(listener); - } - - private Iterable getListeners() { - synchronized (listeners) { - return new HashSet(listeners); - } - } - - @Override - public String getSearchTag() { - return searchTag; - } - - public void setSearchTag(String newSearchTag) { - final String oldSearchTag = this.searchTag; - if (!Util.equalsWithNull(oldSearchTag, newSearchTag)) { - this.searchTag = newSearchTag; - for (CompetitorChangeListener listener : getListeners()) { - listener.searchTagChanged(oldSearchTag, newSearchTag); - } - } - } - - @Override - public String getEmail() { - return email; - } - - public void setEmail(String newEmail) { - final String oldEmail = this.email; - if (!Util.equalsWithNull(oldEmail, newEmail)) { - this.email = newEmail; - for (CompetitorChangeListener listener : getListeners()) { - listener.emailChanged(oldEmail, newEmail); - } - } - } - - @Override - public boolean hasEmail(){ - return email != null && !email.isEmpty(); - } - - @Override - public URI getFlagImage() { - return flagImage; - } - - @Override - public void setFlagImage(URI flagImage) { - final URI oldFlagImage = this.flagImage; - this.flagImage = flagImage; - if (!Util.equalsWithNull(oldFlagImage, flagImage)) { - for (CompetitorChangeListener listener : getListeners()) { - listener.flagImageChanged(oldFlagImage, flagImage); - } - } - } - - @Override - public Double getTimeOnTimeFactor() { - return timeOnTimeFactor; - } - - @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile() { - return timeOnDistanceAllowancePerNauticalMile; - } - - @Override - public void setTimeOnTimeFactor(Double timeOnTimeFactor) { - Double oldTimeOnTimeFactor = this.timeOnTimeFactor; - this.timeOnTimeFactor = timeOnTimeFactor; - if (!Util.equalsWithNull(oldTimeOnTimeFactor, timeOnTimeFactor)) { - for (CompetitorChangeListener listener : getListeners()) { - listener.timeOnTimeFactorChanged(oldTimeOnTimeFactor, timeOnTimeFactor); - } - } - } - - @Override - public void setTimeOnDistanceAllowancePerNauticalMile(Duration timeOnDistanceAllowancePerNauticalMile) { - Duration oldTimeOnDistanceAllowancePerNauticalMile = this.timeOnDistanceAllowancePerNauticalMile; - this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; - if (!Util.equalsWithNull(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile)) { - for (CompetitorChangeListener listener : getListeners()) { - listener.timeOnDistanceAllowancePerNauticalMileChanged(oldTimeOnDistanceAllowancePerNauticalMile, timeOnDistanceAllowancePerNauticalMile); - } - } - } - -} From b3a9cc22fd18ac420643c0341098376df4aee367 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 12:05:16 +0200 Subject: [PATCH 025/271] removed some warnings --- .../domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java | 2 -- .../src/com/sap/sailing/server/test/CompetitorStoreTest.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index cc69753aed7..31209d7d2e5 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -34,7 +34,6 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; @@ -57,7 +56,6 @@ import com.sap.sailing.domain.common.Speed; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.dto.BasicRaceDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index c5cda81ac0a..207b07033ce 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -96,7 +96,7 @@ public class CompetitorStoreTest { PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); DynamicBoat template = new BoatImpl("id-12345", "Morning Glory", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), "GER 1234", new RGBColor(255, 0, 0)); - DynamicBoat boat = (DynamicBoat) persistentStore1.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + persistentStore1.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), template.getSailID(), template.getColor()); CompetitorStore persistentStore2 = new PersistentCompetitorStore( From 1f55480836882752dd08fb4301d4743ee4425f0e Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 12:06:14 +0200 Subject: [PATCH 026/271] fixed illegal change of serialialization UUID caused by a refactoring try --- .../com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java | 2 +- .../sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index e332c25e0d4..411f0f1da39 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -6,7 +6,7 @@ import com.sap.sse.common.Color; import com.sap.sse.common.Duration; public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements CompetitorDTO, Serializable { - private static final long serialVersionUID = 6749455739529431935L; + private static final long serialVersionUID = -4997852354821083154L; private BoatClassDTO boatClass; private BoatDTO boat; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java index 229af7af490..b755dbe715a 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java @@ -15,7 +15,7 @@ import com.sap.sse.common.Duration; * */ public class CompetitorWithoutBoatDTOImpl extends NamedDTO implements CompetitorWithoutBoatDTO, Serializable { - private static final long serialVersionUID = -4997852354821083154L; + private static final long serialVersionUID = 3019126418065082622L; private String countryName; private String twoLetterIsoCountryCode; private String threeLetterIocCountryCode; From 91fb1dfc7341602a5e4cffbb5fa524abbbad3614 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 12:16:12 +0200 Subject: [PATCH 027/271] fix for craeting CompetitorDTOs with boat=null --- .../base/impl/TransientCompetitorStoreImpl.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 023aeaa0764..146f573bb77 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -286,12 +286,17 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); } + @Override - public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat b) { + public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { CompetitorWithoutBoatDTO c = convertToCompetitorWithoutBoatDTO(competitor); - BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), b.getBoatClass().getDisplayName(), - b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam()); - BoatDTO boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); + BoatClassDTO boatClassDTO = null; + BoatDTO boatDTO = null; + if (boat != null) { + boatClassDTO = new BoatClassDTO(boat.getBoatClass().getName(), boat.getBoatClass().getDisplayName(), + boat.getBoatClass().getHullLength(), boat.getBoatClass().getHullBeam()); + boatDTO = new BoatDTO(boat.getId().toString(), boat.getName(), boatClassDTO, boat.getSailID(), boat.getColor()); + } CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getTwoLetterIsoCountryCode(), c.getThreeLetterIocCountryCode(), c.getCountryName(), From a8364175613c137d427e4ecb55c71643b0f205a9 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 12:39:26 +0200 Subject: [PATCH 028/271] Removed strange function getBoatsOfLeaderboard(String leaderboardName) from SailingService for now... maybe we add a getBoatsOfRegatta() function later on --- .../gwt/ui/adminconsole/BoatPanel.java | 16 +---- .../gwt/ui/adminconsole/BoatTableWrapper.java | 62 +++++-------------- .../sailing/gwt/ui/client/SailingService.java | 2 - .../gwt/ui/client/SailingServiceAsync.java | 2 - .../gwt/ui/server/SailingServiceImpl.java | 8 +-- 5 files changed, 20 insertions(+), 70 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java index 6cf46cb84fd..cf0983f097b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatPanel.java @@ -23,17 +23,9 @@ import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; public class BoatPanel extends SimplePanel { private final BoatTableWrapper> boatTable; private final RefreshableMultiSelectionModel refreshableBoatSelectionModel; - private final String leaderboardName; - public BoatPanel(final SailingServiceAsync sailingService, final StringMessages stringMessages, - final ErrorReporter errorReporter) { - this(sailingService, null, stringMessages, errorReporter); - } - - public BoatPanel(final SailingServiceAsync sailingService, final String leaderboardName, - final StringMessages stringMessages, final ErrorReporter errorReporter) { + public BoatPanel(final SailingServiceAsync sailingService, final StringMessages stringMessages, final ErrorReporter errorReporter) { super(); - this.leaderboardName = leaderboardName; this.boatTable = new BoatTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ false); this.refreshableBoatSelectionModel = (RefreshableMultiSelectionModel) boatTable.getSelectionModel(); VerticalPanel mainPanel = new VerticalPanel(); @@ -92,10 +84,6 @@ public class BoatPanel extends SimplePanel { } }); allowReloadButton.setEnabled(!refreshableBoatSelectionModel.getSelectedSet().isEmpty()); - - if (leaderboardName != null) { - refreshBoatList(); - } } private void openAddBoatDialog() { @@ -103,6 +91,6 @@ public class BoatPanel extends SimplePanel { } public void refreshBoatList() { - boatTable.refreshBoatList(leaderboardName); + boatTable.refreshBoatList(null); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java index 25b83b929e9..2b3db0eb8bb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -163,57 +163,29 @@ public class BoatTableWrapper> exte return filterField; } - public void refreshBoatList(Iterable boats) { + public void filterBoats(Iterable boats) { getFilteredBoats(boats); } - public void refreshBoatList(String leaderboardName) { - refreshBoatList(leaderboardName, null); - } - - /** - * @param leaderboardName If null, all existing boats are loaded - */ - public void refreshBoatList(String leaderboardName, final Callback, - Throwable> callback) { - if (leaderboardName != null) { - sailingService.getBoatsOfLeaderboard(leaderboardName, new AsyncCallback>() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Remote Procedure Call getCompetitors() - Failure: " + caught.getMessage()); - if (callback != null) { - callback.onFailure(caught); - } + public void refreshBoatList(final Callback, Throwable> callback) { + sailingService.getBoats(new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); + if (callback != null) { + callback.onFailure(caught); } + } - @Override - public void onSuccess(Iterable result) { - refreshBoatList(result); - if (callback != null) { - callback.onSuccess(result); - } + @Override + public void onSuccess(Iterable result) { + getFilteredBoats(result); + filterBoats(result); + if (callback != null) { + callback.onSuccess(result); } - }); - } else { - sailingService.getBoats(new AsyncCallback>() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); - if (callback != null) { - callback.onFailure(caught); - } - } - - @Override - public void onSuccess(Iterable result) { - getFilteredBoats(result); - refreshBoatList(result); - if (callback != null) { - callback.onSuccess(result); - } - } - }); - } + } + }); } private void getFilteredBoats(Iterable result) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index fa16acd9c07..4d0ac76934f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -442,8 +442,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Iterable getBoats(); - Iterable getBoatsOfLeaderboard(String leaderboardName); - BoatDTO addOrUpdateBoat(BoatDTO boat) throws Exception; void allowBoatResetToDefaults(Iterable boats); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 49bee674e78..f1e1d5b7aae 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -596,8 +596,6 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void getBoats(AsyncCallback> asyncCallback); - void getBoatsOfLeaderboard(String leaderboardName, AsyncCallback> asyncCallback); - void addOrUpdateBoat(BoatDTO boat, AsyncCallback asyncCallback); void allowBoatResetToDefaults(Iterable boats, AsyncCallback asyncCallback); 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 860ea27982c..6fc9104bc84 100644 --- 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 @@ -3895,7 +3895,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S seriesDTO.getRaceColumns().addAll(convertToRaceColumnDTOs(leaderboard.getRaceColumns())); for(Competitor c: leaderboard.getCompetitors()) { - Boat b = null; // TODO: How di we get the boat? + Boat b = null; // TODO bug2822: How do we get the boat? if(b != null && b.getBoatClass() != null) { raceGroup.boatClass = b.getBoatClass().getDisplayName(); } @@ -4875,12 +4875,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return convertToBoatDTOs(getService().getBaseDomainFactory().getCompetitorStore().getBoats()); } - @Override - public Iterable getBoatsOfLeaderboard(String leaderboardName) { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - return Collections.emptyList(); //convertToBoatDTOs(leaderboard.getAllBoats()); - } - @Override public BoatDTO addOrUpdateBoat(BoatDTO boat) { Boat existingBoat = getService().getCompetitorStore().getExistingBoatByIdAsString(boat.getIdAsString()); From f8b1e1b499b76337299e266e26ee633dfca29186 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 14:43:01 +0200 Subject: [PATCH 029/271] fixed two compile errors after last merge --- .../domain/tractracadapter/impl/MarkPassingReceiver.java | 3 +-- .../com/sap/sailing/gwt/ui/adminconsole/BoatEditDialog.java | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java index 3eb62f0ec63..fc2534d8528 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java @@ -68,8 +68,7 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue { public String getAsHtml() { return stringMessages.invalidColor(exception.getMessage()); } + + @Override + public Color invert() { + return null; + } } From c03f64aa7ef003f8c680dd90bcd86cb86c3416f1 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 14:52:12 +0200 Subject: [PATCH 030/271] adaption of 2 new testcases to new competitor/boat relationship --- .../domain/test/NonCompetingCompetitorTest.java | 8 +++++--- .../domain/test/TrackedRaceStatusUpdateTest.java | 10 ++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/NonCompetingCompetitorTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/NonCompetingCompetitorTest.java index 8a7759ea7d2..70f144eda75 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/NonCompetingCompetitorTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/NonCompetingCompetitorTest.java @@ -8,10 +8,12 @@ import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.text.ParseException; +import java.util.Map.Entry; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.tractracadapter.ReceiverType; @@ -43,9 +45,9 @@ public class NonCompetingCompetitorTest extends AbstractManeuverDetectionTestCas */ @Test public void testNoNonCompetingCompetitors() throws ParseException, NoWindException { - for (final Competitor competitor : getTrackedRace().getRace().getCompetitors()) { - assertFalse(competitor.getName().startsWith("Ump")); - assertSame(getDomainFactory().getOrCreateBoatClass("GC32"), competitor.getBoat().getBoatClass()); + for (final Entry competitorAndBoatEntry : getTrackedRace().getRace().getCompetitorsAndTheirBoats().entrySet()) { + assertFalse(competitorAndBoatEntry.getKey().getName().startsWith("Ump")); + assertSame(getDomainFactory().getOrCreateBoatClass("GC32"), competitorAndBoatEntry.getValue().getBoatClass()); } } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStatusUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStatusUpdateTest.java index 1bb230d7ddb..53a6a739a15 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStatusUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackedRaceStatusUpdateTest.java @@ -2,12 +2,10 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertSame; -import java.util.Collections; - import org.junit.Before; import org.junit.Test; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.common.TrackedRaceStatusEnum; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.TrackingDataLoader; @@ -21,13 +19,13 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; * */ public class TrackedRaceStatusUpdateTest extends TrackBasedTest { - private Competitor competitor; + private CompetitorAndBoat competitor; private DynamicTrackedRace trackedRace; @Before public void setUp() { - competitor = createCompetitor("Test Competitor"); - trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", Collections.singleton(competitor), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); + competitor = createCompetitorAndBoat("Test Competitor"); + trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", createCompetitorAndBoatsMap(competitor), MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ false); } @Test From ee7588689cfa740ea9b4737e5b7f0f42447fe14b Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Tue, 20 Jun 2017 14:59:48 +0200 Subject: [PATCH 031/271] removed unused import --- .../sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index acb97ff93aa..f935a57b775 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; From e1b469cc694d50ccaa819c663a693fd277ed08b5 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 21 Jun 2017 10:58:15 +0200 Subject: [PATCH 032/271] Cleanup of boat creation in tractrac connector --- .../domain/tractracadapter/DomainFactory.java | 9 +- .../tractracadapter/MetadataParser.java | 12 ++- .../impl/DomainFactoryImpl.java | 92 +++++++++++++------ .../impl/MarkPassingReceiver.java | 9 +- .../impl/MetadataParserImpl.java | 28 +++++- .../impl/RaceCourseReceiver.java | 4 +- .../impl/RawPositionReceiver.java | 2 +- .../impl/TracTracRaceTrackerImpl.java | 4 +- 8 files changed, 111 insertions(+), 49 deletions(-) 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 1a4d9207949..4081c549ab9 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 @@ -46,6 +46,7 @@ import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl; import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver; import com.sap.sailing.domain.tractracadapter.impl.RaceTrackingConnectivityParametersImpl; import com.sap.sailing.domain.tractracadapter.impl.Simulator; +import com.sap.sse.common.Color; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -80,9 +81,11 @@ public interface DomainFactory { Sideline createSideline(String name, Iterable controlPoints); - com.sap.sailing.domain.base.CompetitorAndBoat getOrCreateCompetitorAndBoat(ICompetitor competitor); + com.sap.sailing.domain.base.Boat getOrCreateBoat(Serializable boatId, String boatName, BoatClass boatClass, String sailId, Color boatColor); - com.sap.sailing.domain.base.CompetitorAndBoat getOrCreateCompetitorAndBoat(UUID competitorId, String competitorClassName, + com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(ICompetitor competitor); + + com.sap.sailing.domain.base.Competitor getOrCreateCompetitor(UUID competitorId, String competitorClassName, String nationalityAsString, String name, String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag); /** @@ -261,7 +264,7 @@ public interface DomainFactory { */ RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds); - Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass); + Map getCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass); Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java index ca6ac5041a5..37299636e07 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java @@ -8,7 +8,6 @@ import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver; import com.sap.sse.common.Color; import com.sap.sse.common.Named; -import com.sap.sse.common.Util; import com.tractrac.model.lib.api.event.IRaceCompetitor; /** @@ -34,7 +33,12 @@ public interface MetadataParser { String getPattern(); Serializable getId(); } - + + public interface BoatMetaData extends Named { + String getId(); + String getColor(); + } + Map parsePassingInstructionData(String routeMetadataString, Iterable controlPoints); /** @@ -59,7 +63,7 @@ public interface MetadataParser { /** * Parses the boat name, boad id and the boat color for a competitor (entry) of a race. * @param competitor - * @return a Triple containing the boat name, boat id and boat color or null if no metadata is availalble + * @return the boat metadata or null if no metadata is availalble */ - Util.Triple parseCompetitorBoat(IRaceCompetitor competitor); + BoatMetaData parseCompetitorBoat(IRaceCompetitor competitor); } 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 56a0d0d62bb..13e4efd3b5e 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 @@ -29,7 +29,6 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.Course; @@ -39,7 +38,6 @@ 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.Waypoint; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; @@ -71,13 +69,14 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tractracadapter.DomainFactory; import com.sap.sailing.domain.tractracadapter.JSONService; import com.sap.sailing.domain.tractracadapter.MetadataParser; +import com.sap.sailing.domain.tractracadapter.MetadataParser.BoatMetaData; import com.sap.sailing.domain.tractracadapter.MetadataParser.ControlPointMetaData; import com.sap.sailing.domain.tractracadapter.Receiver; import com.sap.sailing.domain.tractracadapter.ReceiverType; import com.sap.sailing.domain.tractracadapter.TracTracConfiguration; import com.sap.sailing.domain.tractracadapter.TracTracControlPoint; import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker; -import com.sap.sse.common.Color; +import com.sap.sse.common.Color; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -240,25 +239,24 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public CompetitorAndBoat getOrCreateCompetitorAndBoat(ICompetitor competitor) { + public Competitor getOrCreateCompetitor(ICompetitor competitor) { final UUID competitorId = competitor.getId(); final String competitorClassName = competitor.getCompetitorClass()==null?null:competitor.getCompetitorClass().getName(); final String nationalityAsString = competitor.getNationality(); final String name = competitor.getName(); final String shortName = competitor.getShortName(); - CompetitorAndBoat result = getOrCreateCompetitorAndBoat(competitorId, competitorClassName, nationalityAsString, name, + Competitor result = getOrCreateCompetitor(competitorId, competitorClassName, nationalityAsString, name, shortName, competitor.getHandicapToT(), competitor.getHandicapToD(), null); return result; } @Override - public CompetitorAndBoat getOrCreateCompetitorAndBoat(final UUID competitorId, final String competitorClassName, + public Competitor getOrCreateCompetitor(final UUID competitorId, final String competitorClassName, final String nationalityAsString, final String name, final String shortName, float timeOnTimeFactor, float timeOnDistanceAllowanceInSecondsPerNauticalMile, String searchTag) { CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); - Competitor domainCompetitor = competitorStore.getExistingCompetitorById(competitorId); - Boat domainBoat = competitorStore.getExistingBoatById(competitorId); - if (domainCompetitor == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) { + Competitor domainCompetitor = competitorStore.getExistingCompetitorById(competitorId); + if (domainCompetitor == null || competitorStore.isCompetitorToUpdateDuringGetOrCreate(domainCompetitor)) { Nationality nationality; try { nationality = getOrCreateNationality(nationalityAsString); @@ -268,17 +266,20 @@ public class DomainFactoryImpl implements DomainFactory { logger.log(Level.SEVERE, "Unknown nationality "+nationalityAsString+" for competitor "+name+"; leaving null", iae); } DynamicTeam team = createTeam(name, nationality, competitorId); - domainCompetitor = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, + domainCompetitor = competitorStore.getOrCreateCompetitor(competitorId, name, shortName, null /* displayColor */, null /* email */, null /* flagImag */, team, (double) timeOnTimeFactor, new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); } - return new CompetitorAndBoatImpl(domainCompetitor, domainBoat); - } - - private Boat getOrCreateBoat(Serializable competitorId, Serializable boatId, String boatName, BoatClass boatClass, String sailId, Color boatColor) { - CompetitorStore competitorAndBoatStore = baseDomainFactory.getCompetitorStore(); - Boat boat = competitorAndBoatStore.getOrCreateBoat(competitorId, boatName, boatClass, sailId, boatColor); - return boat; + return domainCompetitor; + } + + public Boat getOrCreateBoat(Serializable boatId, String boatName, BoatClass boatClass, String sailId, Color boatColor) { + CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); + Boat domainBoat = competitorStore.getExistingBoatById(boatId); + if (domainBoat == null) { + domainBoat = baseDomainFactory.getCompetitorStore().getOrCreateBoat(boatId, boatName, boatClass, sailId, boatColor); + } + return domainBoat; } private DynamicTeam createTeam(String name, Nationality nationality, UUID competitorId) { @@ -638,22 +639,55 @@ public class DomainFactoryImpl implements DomainFactory { raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver); } + /** + * Obtains the boats for the given competitors. + * There are 2 cases to distinguish: + * 1. Races with boat information in the competitor metadata field + * 2. Races without any boat information + */ @Override - public Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass) { - final Map competitorBoatInfos = new HashMap<>(); + public Map getCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass) { + + final Map competitorsAndBoats = new HashMap<>(); getCompetingCompetitors(race).forEach(rc->{ - Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); - CompetitorAndBoat existingCompetitorAndBoat = getOrCreateCompetitorAndBoat(rc.getCompetitor()); - Competitor existingCompetitor = existingCompetitorAndBoat.getCompetitor(); - if (existingCompetitor != null && competitorBoatInfo != null) { - Boat boatOfCompetitor = getOrCreateBoat(existingCompetitor.getId(), competitorBoatInfo.getB(), - competitorBoatInfo.getA(), defaultBoatClass, null, AbstractColor.getCssColor(competitorBoatInfo.getC())); - competitorBoatInfos.put(existingCompetitor, boatOfCompetitor); + BoatMetaData competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); + Boat boatOfCompetitor; + String sailId = rc.getCompetitor().getShortName(); + // Case 1 + if (competitorBoatInfo != null) { + // create an unique for such a boot an search in the boat store for it + Serializable boatId = createUniqueBoatIdentifierFromBoatMetadata(race, competitorBoatInfo); + boatOfCompetitor = getOrCreateBoat(boatId, competitorBoatInfo.getName(), + defaultBoatClass, sailId, AbstractColor.getCssColor(competitorBoatInfo.getColor()) ); + } else { + // Case 2 + Serializable boatId = createUniqueBoatIdentifierFromCompetitor(race, rc); + boatOfCompetitor = getOrCreateBoat(boatId, "Boat of " + sailId, defaultBoatClass, sailId, null); } + + Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); + competitorsAndBoats.put(existingCompetitor, boatOfCompetitor); }); - return competitorBoatInfos; + return competitorsAndBoats; } + /** + * Create an unique key for a boat derived from the tractrac event UUID and the boat Id given by the boat metadata + * @return the unique key (per tractrac event) + */ + private String createUniqueBoatIdentifierFromBoatMetadata(IRace race, BoatMetaData boatMetadata) { + UUID eventUUID = race.getEvent().getId(); + String boatIdentifier = eventUUID.toString() + '#' + boatMetadata.getId(); + return boatIdentifier; + } + + private String createUniqueBoatIdentifierFromCompetitor(IRace race, IRaceCompetitor competitor) { + UUID eventUUID = race.getEvent().getId(); + UUID competitorUUID = competitor.getCompetitor().getId(); + String boatIdentifier = eventUUID.toString() + '#' + competitorUUID.toString(); + return boatIdentifier; + } + /** * Obtains those {@link IRace#getRaceCompetitors() competitors} that are actually competing in the race * ({@link ICompetitor#isNonCompeting()}=={@code false}) @@ -661,7 +695,7 @@ public class DomainFactoryImpl implements DomainFactory { private Stream getCompetingCompetitors(IRace race) { return race.getRaceCompetitors().stream().filter(rc->!rc.getCompetitor().isNonCompeting()); } - + @Override public Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race) { List competitorClasses = new ArrayList(); @@ -669,7 +703,7 @@ public class DomainFactoryImpl implements DomainFactory { getCompetingCompetitors(race).forEach(rc->{ // also add those whose race class doesn't match the dominant one (such as camera boats) // because they may still send data that we would like to record in some tracks - competitors.add(getOrCreateCompetitorAndBoat(rc.getCompetitor()).getCompetitor()); + competitors.add(getOrCreateCompetitor(rc.getCompetitor())); competitorClasses.add(rc.getCompetitor().getCompetitorClass()); }); BoatClass dominantBoatClass = getDominantBoatClass(competitorClasses); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java index fc2534d8528..06e326b4d60 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPassingReceiver.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.tracking.DynamicTrackedRace; @@ -72,7 +73,7 @@ public class MarkPassingReceiver extends AbstractReceiverWithQueue parseCompetitorBoat(IRaceCompetitor competitor) { - Util.Triple result = null; + public BoatMetaData parseCompetitorBoat(IRaceCompetitor competitor) { + BoatMetaData result = null; String parsedBoatName = null; String parsedBoatId = null; String parsedColor = null; @@ -230,7 +250,7 @@ public class MetadataParserImpl implements MetadataParser { } } if (parsedBoatName != null && parsedBoatId != null && parsedColor != null) { - result = new Util.Triple(parsedBoatName, parsedBoatId, parsedColor); + result = new BoatMetaDataImpl(parsedBoatName, parsedBoatId, parsedColor); } } return result; 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 afcf427f429..0682b77b922 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 @@ -157,10 +157,10 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue, BoatClass> competitorsAndDominantBoatClass = getDomainFactory().getCompetitorsAndDominantBoatClass(tractracRace); - Map competitorBoats = getDomainFactory().getBoatsInfoForCompetitors(tractracRace, competitorsAndDominantBoatClass.getB()); + Map competitorAndBoats = getDomainFactory().getCompetitorsAndTheirBoats(tractracRace, competitorsAndDominantBoatClass.getB()); trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace( getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getA(), - competitorsAndDominantBoatClass.getB(), competitorBoats, course, sidelines, windStore, delayToLiveInMillis, + competitorsAndDominantBoatClass.getB(), competitorAndBoats, course, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, tracTracUpdateURI, getTracTracEvent().getId(), tracTracUsername, tracTracPassword, useInternalMarkPassingAlgorithm, raceLogResolver, tr->updateRaceTimes(tractracRace, tr), tractracRace); addAllMarksFromCourseArea(trackedRace); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java index d0bc1fb6e92..651c3830da8 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RawPositionReceiver.java @@ -59,7 +59,7 @@ public class RawPositionReceiver extends AbstractReceiverWithQueue Date: Wed, 21 Jun 2017 11:30:30 +0200 Subject: [PATCH 033/271] Normalized line endings --- .../domain/common/dto/CompetitorDTO.java | 30 +- .../domain/common/dto/CompetitorDTOImpl.java | 150 +- .../common/dto/CompetitorWithoutBoatDTO.java | 88 +- .../dto/CompetitorWithoutBoatDTOImpl.java | 408 +-- .../domain/persistence/impl/FieldNames.java | 330 +-- .../impl/MongoObjectFactoryImpl.java | 54 +- .../test/impl/TrackedRaceLoadsFixesTest.java | 1060 +++---- .../abstractlog/race/RaceLogEventVisitor.java | 122 +- ...RegisteredCompetitorsAndBoatsAnalyzer.java | 88 +- .../regatta/RegattaLogEventVisitor.java | 68 +- .../domain/base/BoatChangeListener.java | 22 +- .../sap/sailing/domain/base/BoatFactory.java | 62 +- .../domain/base/CompetitorAndBoat.java | 26 +- .../sailing/domain/base/CompetitorStore.java | 288 +- .../base/impl/CompetitorAndBoatImpl.java | 52 +- .../sailing/domain/base/impl/DynamicBoat.java | 24 +- .../impl/TransientCompetitorStoreImpl.java | 1078 +++---- .../test/FetchTracksAndStoreLocallyTest.java | 338 +-- .../sap/sailing/domain/test/TrackTest.java | 2598 ++++++++--------- .../sailing/domain/base/DomainFactory.java | 194 +- .../domain/base/impl/DomainFactoryImpl.java | 784 ++--- .../impl/RaceColumnRaceLogReplicator.java | 354 +-- .../domain/leaderboard/Leaderboard.java | 1116 +++---- .../meta/MetaLeaderboardColumn.java | 602 ++-- .../sailing/domain/tracking/TrackedRace.java | 1972 ++++++------- ...LogConnectivityParamsLoadAndStoreTest.java | 178 +- ...StoringAndRetrievingLeaderboardGroups.java | 968 +++--- .../tracking/TrackedRacesBoatsPanelPO.java | 84 +- .../CompetitorWithBoatJsonDeserializer.java | 210 +- .../CompetitorWithBoatJsonSerializer.java | 78 +- .../racelog/impl/RaceLogEventSerializer.java | 614 ++-- .../impl/ManeuversJsonSerializer.java | 128 +- .../server/test/CompetitorStoreTest.java | 242 +- .../AllowBoatResetToDefaults.java | 92 +- .../operationaltransformation/UpdateBoat.java | 106 +- .../sailing/xmlexport/LeaderboardData.java | 2152 +++++++------- .../app/data/OfflineDataManager.java | 530 ++-- 37 files changed, 8645 insertions(+), 8645 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 1ab152cc2f4..dba6af298db 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -1,15 +1,15 @@ -package com.sap.sailing.domain.common.dto; - -public interface CompetitorDTO extends CompetitorWithoutBoatDTO { - String getSailID(); - - BoatClassDTO getBoatClass(); - - BoatDTO getBoat(); - - /** - * A regular instance will simply return this object. A compacted version may compute the result by looking it up - * from the previous version of the enclosing leaderboard. - */ - CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion); -} +package com.sap.sailing.domain.common.dto; + +public interface CompetitorDTO extends CompetitorWithoutBoatDTO { + String getSailID(); + + BoatClassDTO getBoatClass(); + + BoatDTO getBoat(); + + /** + * A regular instance will simply return this object. A compacted version may compute the result by looking it up + * from the previous version of the enclosing leaderboard. + */ + CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion); +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 411f0f1da39..57cf3bab7e7 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -1,75 +1,75 @@ -package com.sap.sailing.domain.common.dto; - -import java.io.Serializable; - -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements CompetitorDTO, Serializable { - private static final long serialVersionUID = -4997852354821083154L; - private BoatClassDTO boatClass; - private BoatDTO boat; - - public CompetitorDTOImpl() {} - - public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, - String countryName, String idAsString, String imageURL, String flagImageURL, - BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - super(name, shortName, color, email, twoLetterIsoCountryCode, threeLetterIocCountryCode, - countryName, idAsString, imageURL, flagImageURL, - timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); - this.boat = boat; - this.boatClass = boatClass; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); - result = prime * result + ((boat == null) ? 0 : boat.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - CompetitorDTOImpl other = (CompetitorDTOImpl) obj; - if (boatClass == null) { - if (other.boatClass != null) - return false; - } else if (!boatClass.equals(other.boatClass)) - return false; - if (boat == null) { - if (other.boat != null) - return false; - } else if (!boat.equals(other.boat)) - return false; - return true; - } - - @Override - public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) { - return this; - } - - @Override - public String getSailID() { - return boat==null?null:boat.getSailId(); - } - - @Override - public BoatClassDTO getBoatClass() { - return boatClass; - } - - @Override - public BoatDTO getBoat() { - return boat; - } -} +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements CompetitorDTO, Serializable { + private static final long serialVersionUID = -4997852354821083154L; + private BoatClassDTO boatClass; + private BoatDTO boat; + + public CompetitorDTOImpl() {} + + public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, + String countryName, String idAsString, String imageURL, String flagImageURL, + BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + super(name, shortName, color, email, twoLetterIsoCountryCode, threeLetterIocCountryCode, + countryName, idAsString, imageURL, flagImageURL, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + this.boat = boat; + this.boatClass = boatClass; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); + result = prime * result + ((boat == null) ? 0 : boat.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CompetitorDTOImpl other = (CompetitorDTOImpl) obj; + if (boatClass == null) { + if (other.boatClass != null) + return false; + } else if (!boatClass.equals(other.boatClass)) + return false; + if (boat == null) { + if (other.boat != null) + return false; + } else if (!boat.equals(other.boat)) + return false; + return true; + } + + @Override + public CompetitorDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) { + return this; + } + + @Override + public String getSailID() { + return boat==null?null:boat.getSailId(); + } + + @Override + public BoatClassDTO getBoatClass() { + return boatClass; + } + + @Override + public BoatDTO getBoat() { + return boat; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java index 68ace767363..3a22072d24d 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java @@ -1,44 +1,44 @@ -package com.sap.sailing.domain.common.dto; - -import java.io.Serializable; - -import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -public interface CompetitorWithoutBoatDTO extends Serializable, MappableToDevice { - - String getTwoLetterIsoCountryCode(); - - String getThreeLetterIocCountryCode(); - - String getCountryName(); - - String getIdAsString(); - - String getSearchTag(); - - /** - * If the {@code searchTag} is not contained in {@link #getSearchTag()}, appends it to the search tag, separated by a space character - */ - void addToSearchTag(String searchTag); - - String getName(); - - String getShortName(); - - Color getColor(); - - String getEmail(); - - boolean hasEmail(); - - String getFlagImageURL(); - - String getImageURL(); - - Double getTimeOnTimeFactor(); - - Duration getTimeOnDistanceAllowancePerNauticalMile(); - -} +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +public interface CompetitorWithoutBoatDTO extends Serializable, MappableToDevice { + + String getTwoLetterIsoCountryCode(); + + String getThreeLetterIocCountryCode(); + + String getCountryName(); + + String getIdAsString(); + + String getSearchTag(); + + /** + * If the {@code searchTag} is not contained in {@link #getSearchTag()}, appends it to the search tag, separated by a space character + */ + void addToSearchTag(String searchTag); + + String getName(); + + String getShortName(); + + Color getColor(); + + String getEmail(); + + boolean hasEmail(); + + String getFlagImageURL(); + + String getImageURL(); + + Double getTimeOnTimeFactor(); + + Duration getTimeOnDistanceAllowancePerNauticalMile(); + +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java index b755dbe715a..601b4631d76 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTOImpl.java @@ -1,204 +1,204 @@ -package com.sap.sailing.domain.common.dto; - -import java.io.Serializable; - -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -/** - * Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the - * {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the - * {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject - * to change for a competitor while the ID remains unchanged. - * - * @author Axel Uhl (d043530) - * - */ -public class CompetitorWithoutBoatDTOImpl extends NamedDTO implements CompetitorWithoutBoatDTO, Serializable { - private static final long serialVersionUID = 3019126418065082622L; - private String countryName; - private String twoLetterIsoCountryCode; - private String threeLetterIocCountryCode; - private Color color; - private String shortName; - private String email; - private String searchTag; - private String idAsString; - private String imageURL; - private String flagImageURL; - private Double timeOnTimeFactor; - private Duration timeOnDistanceAllowancePerNauticalMile; - - public CompetitorWithoutBoatDTOImpl() {} - - public CompetitorWithoutBoatDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, - String countryName, String idAsString, String imageURL, String flagImageURL, - Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - super(name); - this.shortName = shortName; - this.color = color; - this.email = email; - this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; - this.threeLetterIocCountryCode = threeLetterIocCountryCode; - this.countryName = countryName; - this.idAsString = idAsString; - this.imageURL = imageURL; - this.flagImageURL = flagImageURL; - this.timeOnTimeFactor = timeOnTimeFactor; - this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; - this.searchTag = searchTag; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); - result = prime * result + ((color == null) ? 0 : color.hashCode()); - result = prime * result + ((email == null) ? 0 : email.hashCode()); - result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); - result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); - result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode()); - result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode()); - result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode()); - result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode()); - result = prime * result + ((searchTag == null) ? 0 : searchTag.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - CompetitorWithoutBoatDTOImpl other = (CompetitorWithoutBoatDTOImpl) obj; - if (idAsString == null) { - if (other.idAsString != null) - return false; - } else if (!idAsString.equals(other.idAsString)) - return false; - if (threeLetterIocCountryCode == null) { - if (other.threeLetterIocCountryCode != null) - return false; - } else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode)) - return false; - if (color == null) { - if (other.color != null) - return false; - } else if (!color.equals(other.color)) - return false; - if (email == null) { - if (other.email != null) - return false; - } else if (!email.equals(other.email)) - return false; - if (shortName == null) { - if (other.shortName != null) - return false; - } else if (!shortName.equals(other.shortName)) - return false; - if (imageURL == null) { - if (other.imageURL != null) - return false; - } else if (!imageURL.equals(other.imageURL)) - return false; - if (flagImageURL == null) { - if (other.flagImageURL != null) - return false; - } else if (!flagImageURL.equals(other.flagImageURL)) - return false; - if (timeOnTimeFactor == null) { - if (other.timeOnTimeFactor != null) - return false; - } else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor)) - return false; - if (timeOnDistanceAllowancePerNauticalMile == null) { - if (other.timeOnDistanceAllowancePerNauticalMile != null) - return false; - } else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile)) - return false; - if (searchTag == null) { - if (other.searchTag != null) - return false; - } else if (!searchTag.equals(other.searchTag)) - return false; - return true; - } - - @Override - public String getTwoLetterIsoCountryCode() { - return twoLetterIsoCountryCode; - } - - @Override - public String getThreeLetterIocCountryCode() { - return threeLetterIocCountryCode; - } - - @Override - public String getCountryName() { - return countryName; - } - - @Override - public String getShortName() { - return shortName; - } - - @Override - public String getImageURL() { - return imageURL; - } - - @Override - public String getFlagImageURL() { - return flagImageURL; - } - - @Override - public String getIdAsString() { - return idAsString; - } - - @Override - public Color getColor() { - return color; - } - - @Override - public String getSearchTag() { - return searchTag; - } - - @Override - public void addToSearchTag(String searchTag) { - if (this.searchTag == null) { - this.searchTag = searchTag; - } else if (!this.searchTag.contains(searchTag)) { - this.searchTag += " "+searchTag; - } - } - - @Override - public String getEmail() { - return email; - } - - @Override - public boolean hasEmail() { - return email != null && !email.isEmpty(); - } - - @Override - public Double getTimeOnTimeFactor() { - return timeOnTimeFactor; - } - - @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile() { - return timeOnDistanceAllowancePerNauticalMile; - } -} +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the + * {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the + * {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject + * to change for a competitor while the ID remains unchanged. + * + * @author Axel Uhl (d043530) + * + */ +public class CompetitorWithoutBoatDTOImpl extends NamedDTO implements CompetitorWithoutBoatDTO, Serializable { + private static final long serialVersionUID = 3019126418065082622L; + private String countryName; + private String twoLetterIsoCountryCode; + private String threeLetterIocCountryCode; + private Color color; + private String shortName; + private String email; + private String searchTag; + private String idAsString; + private String imageURL; + private String flagImageURL; + private Double timeOnTimeFactor; + private Duration timeOnDistanceAllowancePerNauticalMile; + + public CompetitorWithoutBoatDTOImpl() {} + + public CompetitorWithoutBoatDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, + String countryName, String idAsString, String imageURL, String flagImageURL, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + super(name); + this.shortName = shortName; + this.color = color; + this.email = email; + this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; + this.threeLetterIocCountryCode = threeLetterIocCountryCode; + this.countryName = countryName; + this.idAsString = idAsString; + this.imageURL = imageURL; + this.flagImageURL = flagImageURL; + this.timeOnTimeFactor = timeOnTimeFactor; + this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; + this.searchTag = searchTag; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); + result = prime * result + ((color == null) ? 0 : color.hashCode()); + result = prime * result + ((email == null) ? 0 : email.hashCode()); + result = prime * result + ((shortName == null) ? 0 : shortName.hashCode()); + result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); + result = prime * result + ((imageURL == null) ? 0 : imageURL.hashCode()); + result = prime * result + ((flagImageURL == null) ? 0 : flagImageURL.hashCode()); + result = prime * result + ((timeOnTimeFactor == null) ? 0 : timeOnTimeFactor.hashCode()); + result = prime * result + ((timeOnDistanceAllowancePerNauticalMile == null) ? 0 : timeOnDistanceAllowancePerNauticalMile.hashCode()); + result = prime * result + ((searchTag == null) ? 0 : searchTag.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CompetitorWithoutBoatDTOImpl other = (CompetitorWithoutBoatDTOImpl) obj; + if (idAsString == null) { + if (other.idAsString != null) + return false; + } else if (!idAsString.equals(other.idAsString)) + return false; + if (threeLetterIocCountryCode == null) { + if (other.threeLetterIocCountryCode != null) + return false; + } else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode)) + return false; + if (color == null) { + if (other.color != null) + return false; + } else if (!color.equals(other.color)) + return false; + if (email == null) { + if (other.email != null) + return false; + } else if (!email.equals(other.email)) + return false; + if (shortName == null) { + if (other.shortName != null) + return false; + } else if (!shortName.equals(other.shortName)) + return false; + if (imageURL == null) { + if (other.imageURL != null) + return false; + } else if (!imageURL.equals(other.imageURL)) + return false; + if (flagImageURL == null) { + if (other.flagImageURL != null) + return false; + } else if (!flagImageURL.equals(other.flagImageURL)) + return false; + if (timeOnTimeFactor == null) { + if (other.timeOnTimeFactor != null) + return false; + } else if (!timeOnTimeFactor.equals(other.timeOnTimeFactor)) + return false; + if (timeOnDistanceAllowancePerNauticalMile == null) { + if (other.timeOnDistanceAllowancePerNauticalMile != null) + return false; + } else if (!timeOnDistanceAllowancePerNauticalMile.equals(other.timeOnDistanceAllowancePerNauticalMile)) + return false; + if (searchTag == null) { + if (other.searchTag != null) + return false; + } else if (!searchTag.equals(other.searchTag)) + return false; + return true; + } + + @Override + public String getTwoLetterIsoCountryCode() { + return twoLetterIsoCountryCode; + } + + @Override + public String getThreeLetterIocCountryCode() { + return threeLetterIocCountryCode; + } + + @Override + public String getCountryName() { + return countryName; + } + + @Override + public String getShortName() { + return shortName; + } + + @Override + public String getImageURL() { + return imageURL; + } + + @Override + public String getFlagImageURL() { + return flagImageURL; + } + + @Override + public String getIdAsString() { + return idAsString; + } + + @Override + public Color getColor() { + return color; + } + + @Override + public String getSearchTag() { + return searchTag; + } + + @Override + public void addToSearchTag(String searchTag) { + if (this.searchTag == null) { + this.searchTag = searchTag; + } else if (!this.searchTag.contains(searchTag)) { + this.searchTag += " "+searchTag; + } + } + + @Override + public String getEmail() { + return email; + } + + @Override + public boolean hasEmail() { + return email != null && !email.isEmpty(); + } + + @Override + public Double getTimeOnTimeFactor() { + return timeOnTimeFactor; + } + + @Override + public Duration getTimeOnDistanceAllowancePerNauticalMile() { + return timeOnDistanceAllowancePerNauticalMile; + } +} diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index e19af70698d..b7dedebb728 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -1,165 +1,165 @@ -package com.sap.sailing.domain.persistence.impl; - - -public enum FieldNames { - // general: - TIME_AS_MILLIS, KNOT_SPEED, DEGREE_BEARING, LAT_DEG, LNG_DEG, - - FLEET, RACE_IDENTIFIERS, - - /** - * TODO this will have to be renamed to REGATTA_NAME, but compatibility concerns keep us from doing so at the moment - */ - EVENT_NAME, - EVENT_DESCRIPTION, - EVENT_ID, - EVENT_IS_PUBLIC, - EVENT_START_DATE, - EVENT_END_DATE, - EVENT_IMAGE_URLS, - EVENT_VIDEO_URLS, - EVENT_SPONSOR_IMAGE_URLS, - EVENT_IMAGES, - EVENT_VIDEOS, - EVENT_OFFICIAL_WEBSITE_URL, - EVENT_BASE_URL, - EVENT_SAILORS_INFO_WEBSITE_URL, - EVENT_SAILORS_INFO_WEBSITES, - EVENT_LOGO_IMAGE_URL, - - REGATTA_NAME, - REGATTA_ID, - REGATTA_BASE_NAME, - REGATTA_START_DATE, - REGATTA_END_DATE, - REGATTA_SERIES, - REGATTA_REGATTA_CONFIGURATION, - REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS, - REGATTA_USE_START_TIME_INFERENCE, - REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES, - REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE, - SERIES_NAME, - SERIES_IS_MEDAL, - SERIES_IS_FLEETS_CAN_RUN_IN_PARALLEL, - SERIES_MAXIMUM_NUMBER_OF_DISCARDS, - SERIES_STARTS_WITH_ZERO_SCORE, - SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING, - SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD, - SERIES_FLEETS, - SERIES_RACE_COLUMNS, - SERIES_DISCARDING_THRESHOLDS, - FLEET_NAME, - FLEET_ORDERING, - FLEET_COLOR, - - SCORING_SCHEME_TYPE, - - RACE_NAME, - RACE_ID, - - VENUE, - VENUE_NAME, - - COURSE_AREAS, - COURSE_AREA_NAME, - COURSE_AREA_ID, - - BOAT_CLASS_NAME, - BOAT_CLASS_TYPICALLY_STARTS_UPWIND, - - // wind: - WIND_SOURCE_NAME, WIND_SOURCE_ID, WIND, IS_MAGNETIC, - - // SwissTiming configuration parameters: - ST_CONFIG_NAME, ST_CONFIG_HOSTNAME, ST_CONFIG_PORT, - - COMPETITOR_ID, COMPETITOR_DISPLAY_NAME, - - // leaderboard: - LEADERBOARD_NAME, LEADERBOARD_DISPLAY_NAME, LEADERBOARD_SUPPRESSED_COMPETITORS, LEADERBOARD_SUPPRESSED_COMPETITOR_IDS, - LEADERBOARD_COLUMNS, LEADERBOARD_COLUMN_NAME, LEADERBOARD_COMPETITOR_DISPLAY_NAMES, - LEADERBOARD_IS_MEDAL_RACE_COLUMN, LEADERBOARD_CARRIED_POINTS, LEADERBOARD_CARRIED_POINTS_BY_ID, - LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS, - LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON, LEADERBOARD_CORRECTED_SCORE, LEADERBOARD_SCORE_CORRECTION_TIMESTAMP, - LEADERBOARD_RANK, LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_COLUMN_FACTORS, - - // leaderboard group - LEADERBOARD_GROUP_UUID, LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION, - LEADERBOARD_GROUP_DISPLAY_NAME, LEADERBOARD_GROUP_LEADERBOARDS, LEADERBOARD_GROUP_OVERALL_LEADERBOARD, - LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER, - - // race ID to regatta name - RACE_ID_AS_STRING, - - // race log - RACE_LOG_IDENTIFIER, RACE_LOG_EVENT, RACE_LOG_EVENT_PASS_ID, RACE_LOG_EVENT_ID, RACE_LOG_EVENT_CREATED_AT, RACE_LOG_EVENT_AUTHOR_NAME, - RACE_LOG_EVENT_AUTHOR_PRIORITY, RACE_LOG_EVENT_INVOLVED_BOATS, RACE_LOG_EVENT_FLAG_UPPER, RACE_LOG_EVENT_FLAG_LOWER, RACE_LOG_EVENT_FLAG_DISPLAYED, - RACE_LOG_EVENT_START_TIME, RACE_LOG_EVENT_CLASS, RACE_LOG_EVENT_NEXT_STATUS, RACE_LOG_COURSE_DESIGN, RACE_LOG_COURSE_DESIGNER_MODE, WAYPOINT_ID, WAYPOINT_NAME, - WAYPOINT_PASSINGINSTRUCTIONS, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE, - CONTROLPOINT_VALUE, CONTROLPOINTWITHTWOMARKS_ID, CONTROLPOINTWITHTWOMARKS_NAME, CONTROLPOINTWITHTWOMARKS_LEFT, CONTROLPOINTWITHTWOMARKS_RIGHT, - RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE, - RACE_LOG_PROTEST_START_TIME, RACE_LOG_PROTEST_END_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE, - RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, - RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, - RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, - RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, - /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, - /** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO, - /** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK, - /** @deprecated Replaced by WAYPOINT_PASSINGINSTRUCTIONS, still used to migrate old races*/ @Deprecated WAYPOINT_PASSINGSIDE, - /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_ID, still used to migrate old races*/ @Deprecated GATE_ID, - /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_NAME, still used to migrate old races*/ @Deprecated GATE_NAME, - /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_LEFT, still used to migrate old races*/ @Deprecated GATE_LEFT, - /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_RIGHT, still used to migrate old races*/ @Deprecated GATE_RIGHT, - - // regatta log - // did not reuse RACE_LOG* types, as this would require handling old versions of all events - REGATTA_LOG_IDENTIFIER_TYPE, REGATTA_LOG_IDENTIFIER_NAME, REGATTA_LOG_EVENT_ID, REGATTA_LOG_EVENT_CREATED_AT, REGATTA_LOG_EVENT_AUTHOR_NAME, - REGATTA_LOG_EVENT_AUTHOR_PRIORITY, REGATTA_LOG_EVENT_CLASS, REGATTA_LOG_REVOKED_EVENT_ID, REGATTA_LOG_REVOKED_EVENT_TYPE, REGATTA_LOG_REVOKED_EVENT_SHORT_INFO, - REGATTA_LOG_REVOKED_REASON, REGATTA_LOG_COMPETITOR_ID, REGATTA_LOG_BOAT_ID, REGATTA_LOG_DEVICE_MAPPING_EVENT_ID, REGATTA_LOG_CLOSING_TIMEPOINT, - REGATTA_LOG_FROM, REGATTA_LOG_TO, REGATTA_LOG_EVENT, REGATTA_LOG_MARK, - - // remote server reference fields - SERVER_NAME, - SERVER_URL, - - // local server instance fields - SERVER_IS_STANDALONE, - - // configurations - CONFIGURATION_MATCHER, CONFIGURATION_CONFIG, CONFIGURATION_MATCHER_ID, CONFIGURATION_MATCHER_CLIENTS, - CONFIGURATION_CONFIG_ALLOWED_COURSE_AREA_NAMES, CONFIGURATION_CONFIG_MIN_ROUNDS, CONFIGURATION_CONFIG_MAX_ROUNDS, CONFIGURATION_CONFIG_RESULTS_MAIL, - CONFIGURATION_CONFIG_PROCEDURES, - - // GPSFixes - DEVICE_TYPE_SPECIFIC_ID, DEVICE_ID, DEVICE_TYPE, GPSFIX_TYPE, GPSFIX, DEVICE_STRING_REPRESENTATION, - - // GPSFixes metadata - TIMERANGE, NUM_FIXES, - - // Timespan - FROM_MILLIS, TO_MILLIS, - - // Result Import url fields - RESULT_PROVIDERNAME, RESULT_URL, - - // type of additional scoring information - RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE, - - // Handicap factors - REGATTA_LOG_TIME_ON_TIME_FACTOR, REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE, REGATTA_RANKING_METRIC, REGATTA_RANKING_METRIC_TYPE, - - // image fields - IMAGE_URL, IMAGE_LOCALE, IMAGE_TITLE, IMAGE_SUBTITLE, IMAGE_MIMETYPE, IMAGE_COPYRIGHT, IMAGE_CREATEDATDATE, - IMAGE_WIDTH_IN_PX, IMAGE_HEIGHT_IN_PX, IMAGE_TAGS, - - // video fields - VIDEO_URL, VIDEO_LOCALE, VIDEO_TITLE, VIDEO_SUBTITLE, VIDEO_MIMETYPE, VIDEO_COPYRIGHT, VIDEO_CREATEDATDATE, - VIDEO_TAGS, VIDEO_THUMBNAIL_URL, VIDEO_LENGTH_IN_SECONDS, - - // sailors info fileds - SAILORS_INFO_URL, SAILORS_INFO_LOCALE, - - // double vector fixes - FIX; -} +package com.sap.sailing.domain.persistence.impl; + + +public enum FieldNames { + // general: + TIME_AS_MILLIS, KNOT_SPEED, DEGREE_BEARING, LAT_DEG, LNG_DEG, + + FLEET, RACE_IDENTIFIERS, + + /** + * TODO this will have to be renamed to REGATTA_NAME, but compatibility concerns keep us from doing so at the moment + */ + EVENT_NAME, + EVENT_DESCRIPTION, + EVENT_ID, + EVENT_IS_PUBLIC, + EVENT_START_DATE, + EVENT_END_DATE, + EVENT_IMAGE_URLS, + EVENT_VIDEO_URLS, + EVENT_SPONSOR_IMAGE_URLS, + EVENT_IMAGES, + EVENT_VIDEOS, + EVENT_OFFICIAL_WEBSITE_URL, + EVENT_BASE_URL, + EVENT_SAILORS_INFO_WEBSITE_URL, + EVENT_SAILORS_INFO_WEBSITES, + EVENT_LOGO_IMAGE_URL, + + REGATTA_NAME, + REGATTA_ID, + REGATTA_BASE_NAME, + REGATTA_START_DATE, + REGATTA_END_DATE, + REGATTA_SERIES, + REGATTA_REGATTA_CONFIGURATION, + REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS, + REGATTA_USE_START_TIME_INFERENCE, + REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES, + REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE, + SERIES_NAME, + SERIES_IS_MEDAL, + SERIES_IS_FLEETS_CAN_RUN_IN_PARALLEL, + SERIES_MAXIMUM_NUMBER_OF_DISCARDS, + SERIES_STARTS_WITH_ZERO_SCORE, + SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING, + SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD, + SERIES_FLEETS, + SERIES_RACE_COLUMNS, + SERIES_DISCARDING_THRESHOLDS, + FLEET_NAME, + FLEET_ORDERING, + FLEET_COLOR, + + SCORING_SCHEME_TYPE, + + RACE_NAME, + RACE_ID, + + VENUE, + VENUE_NAME, + + COURSE_AREAS, + COURSE_AREA_NAME, + COURSE_AREA_ID, + + BOAT_CLASS_NAME, + BOAT_CLASS_TYPICALLY_STARTS_UPWIND, + + // wind: + WIND_SOURCE_NAME, WIND_SOURCE_ID, WIND, IS_MAGNETIC, + + // SwissTiming configuration parameters: + ST_CONFIG_NAME, ST_CONFIG_HOSTNAME, ST_CONFIG_PORT, + + COMPETITOR_ID, COMPETITOR_DISPLAY_NAME, + + // leaderboard: + LEADERBOARD_NAME, LEADERBOARD_DISPLAY_NAME, LEADERBOARD_SUPPRESSED_COMPETITORS, LEADERBOARD_SUPPRESSED_COMPETITOR_IDS, + LEADERBOARD_COLUMNS, LEADERBOARD_COLUMN_NAME, LEADERBOARD_COMPETITOR_DISPLAY_NAMES, + LEADERBOARD_IS_MEDAL_RACE_COLUMN, LEADERBOARD_CARRIED_POINTS, LEADERBOARD_CARRIED_POINTS_BY_ID, + LEADERBOARD_SCORE_CORRECTIONS, LEADERBOARD_DISCARDING_THRESHOLDS, + LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON, LEADERBOARD_CORRECTED_SCORE, LEADERBOARD_SCORE_CORRECTION_TIMESTAMP, + LEADERBOARD_RANK, LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_COLUMN_FACTORS, + + // leaderboard group + LEADERBOARD_GROUP_UUID, LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION, + LEADERBOARD_GROUP_DISPLAY_NAME, LEADERBOARD_GROUP_LEADERBOARDS, LEADERBOARD_GROUP_OVERALL_LEADERBOARD, + LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER, + + // race ID to regatta name + RACE_ID_AS_STRING, + + // race log + RACE_LOG_IDENTIFIER, RACE_LOG_EVENT, RACE_LOG_EVENT_PASS_ID, RACE_LOG_EVENT_ID, RACE_LOG_EVENT_CREATED_AT, RACE_LOG_EVENT_AUTHOR_NAME, + RACE_LOG_EVENT_AUTHOR_PRIORITY, RACE_LOG_EVENT_INVOLVED_BOATS, RACE_LOG_EVENT_FLAG_UPPER, RACE_LOG_EVENT_FLAG_LOWER, RACE_LOG_EVENT_FLAG_DISPLAYED, + RACE_LOG_EVENT_START_TIME, RACE_LOG_EVENT_CLASS, RACE_LOG_EVENT_NEXT_STATUS, RACE_LOG_COURSE_DESIGN, RACE_LOG_COURSE_DESIGNER_MODE, WAYPOINT_ID, WAYPOINT_NAME, + WAYPOINT_PASSINGINSTRUCTIONS, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE, + CONTROLPOINT_VALUE, CONTROLPOINTWITHTWOMARKS_ID, CONTROLPOINTWITHTWOMARKS_NAME, CONTROLPOINTWITHTWOMARKS_LEFT, CONTROLPOINTWITHTWOMARKS_RIGHT, + RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_GOLF_DOWN_TIME, RACE_LOG_START_PROCEDURE_TYPE, + RACE_LOG_PROTEST_START_TIME, RACE_LOG_PROTEST_END_TIME, RACE_LOG_COURSE_DESIGN_NAME, RACE_LOG_REVOKED_EVENT_ID, RACE_LOG_REVOKED_EVENT_TYPE, + RACE_LOG_REVOKED_EVENT_SHORT_INFO, RACE_LOG_REVOKED_REASON, RACE_LOG_DEVICE_MAPPING_EVENT_ID, + RACE_LOG_CLOSING_TIMEPOINT, TIMEPOINT_OF_FIXED_MARKPASSING, INDEX_OF_PASSED_WAYPOINT,INDEX_OF_FIRST_SUPPRESSED_WAYPOINT, MARK, RACE_LOG_COMPETITOR_ID, RACE_LOG_BOAT_ID, + RACE_LOG_DEPDENDENT_ON_FLEET, RACE_LOG_DEPDENDENT_ON_RACECOLUMN, RACE_LOG_DEPDENDENT_ON_REGATTALIKE, + RACE_LOG_START_TIME_DIFFERENCE_IN_MS, RACE_LOG_FINISHING_TIME_AS_MILLIS, + /** @deprecated Replaced by {@link #REGATTA_LOG_FROM}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_FROM, + /** @deprecated Replaced by {@link #REGATTA_LOG_TO}; auto-migration from race log device mappings to regatta log is implemented */ @Deprecated RACE_LOG_TO, + /** @deprecated Replaced by a regatta log entry with type {@link #REGATTA_LOG_MARK} */ @Deprecated RACE_LOG_MARK, + /** @deprecated Replaced by WAYPOINT_PASSINGINSTRUCTIONS, still used to migrate old races*/ @Deprecated WAYPOINT_PASSINGSIDE, + /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_ID, still used to migrate old races*/ @Deprecated GATE_ID, + /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_NAME, still used to migrate old races*/ @Deprecated GATE_NAME, + /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_LEFT, still used to migrate old races*/ @Deprecated GATE_LEFT, + /** @deprecated Replaced by CONTROLPOINTWITHTWOMARKS_RIGHT, still used to migrate old races*/ @Deprecated GATE_RIGHT, + + // regatta log + // did not reuse RACE_LOG* types, as this would require handling old versions of all events + REGATTA_LOG_IDENTIFIER_TYPE, REGATTA_LOG_IDENTIFIER_NAME, REGATTA_LOG_EVENT_ID, REGATTA_LOG_EVENT_CREATED_AT, REGATTA_LOG_EVENT_AUTHOR_NAME, + REGATTA_LOG_EVENT_AUTHOR_PRIORITY, REGATTA_LOG_EVENT_CLASS, REGATTA_LOG_REVOKED_EVENT_ID, REGATTA_LOG_REVOKED_EVENT_TYPE, REGATTA_LOG_REVOKED_EVENT_SHORT_INFO, + REGATTA_LOG_REVOKED_REASON, REGATTA_LOG_COMPETITOR_ID, REGATTA_LOG_BOAT_ID, REGATTA_LOG_DEVICE_MAPPING_EVENT_ID, REGATTA_LOG_CLOSING_TIMEPOINT, + REGATTA_LOG_FROM, REGATTA_LOG_TO, REGATTA_LOG_EVENT, REGATTA_LOG_MARK, + + // remote server reference fields + SERVER_NAME, + SERVER_URL, + + // local server instance fields + SERVER_IS_STANDALONE, + + // configurations + CONFIGURATION_MATCHER, CONFIGURATION_CONFIG, CONFIGURATION_MATCHER_ID, CONFIGURATION_MATCHER_CLIENTS, + CONFIGURATION_CONFIG_ALLOWED_COURSE_AREA_NAMES, CONFIGURATION_CONFIG_MIN_ROUNDS, CONFIGURATION_CONFIG_MAX_ROUNDS, CONFIGURATION_CONFIG_RESULTS_MAIL, + CONFIGURATION_CONFIG_PROCEDURES, + + // GPSFixes + DEVICE_TYPE_SPECIFIC_ID, DEVICE_ID, DEVICE_TYPE, GPSFIX_TYPE, GPSFIX, DEVICE_STRING_REPRESENTATION, + + // GPSFixes metadata + TIMERANGE, NUM_FIXES, + + // Timespan + FROM_MILLIS, TO_MILLIS, + + // Result Import url fields + RESULT_PROVIDERNAME, RESULT_URL, + + // type of additional scoring information + RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE, + + // Handicap factors + REGATTA_LOG_TIME_ON_TIME_FACTOR, REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE, REGATTA_RANKING_METRIC, REGATTA_RANKING_METRIC_TYPE, + + // image fields + IMAGE_URL, IMAGE_LOCALE, IMAGE_TITLE, IMAGE_SUBTITLE, IMAGE_MIMETYPE, IMAGE_COPYRIGHT, IMAGE_CREATEDATDATE, + IMAGE_WIDTH_IN_PX, IMAGE_HEIGHT_IN_PX, IMAGE_TAGS, + + // video fields + VIDEO_URL, VIDEO_LOCALE, VIDEO_TITLE, VIDEO_SUBTITLE, VIDEO_MIMETYPE, VIDEO_COPYRIGHT, VIDEO_CREATEDATDATE, + VIDEO_TAGS, VIDEO_THUMBNAIL_URL, VIDEO_LENGTH_IN_SECONDS, + + // sailors info fileds + SAILORS_INFO_URL, SAILORS_INFO_LOCALE, + + // double vector fixes + FIX; +} diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index c1ebafb439b..1c81ef63857 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -46,7 +46,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -57,7 +57,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompeti import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; @@ -133,7 +133,7 @@ import com.sap.sse.shared.media.VideoDescriptor; public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; - private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); + private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinder raceTrackingConnectivityParamsServiceFinder; @@ -881,13 +881,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorAndBoatEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorAndBoatEvent(event)); - return result; - } - + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorAndBoatEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorAndBoatEvent(event)); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogEndOfTrackingEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1029,15 +1029,15 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - private Object storeRaceLogRegisterCompetitorAndBoatEvent(RaceLogRegisterCompetitorAndBoatEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - result.put(FieldNames.RACE_LOG_BOAT_ID.name(), event.getBoat().getId()); - return result; - } - + private Object storeRaceLogRegisterCompetitorAndBoatEvent(RaceLogRegisterCompetitorAndBoatEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.RACE_LOG_BOAT_ID.name(), event.getBoat().getId()); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseCompetitorsFromRaceLogEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1488,14 +1488,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorAndBoatEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - result.put(FieldNames.REGATTA_LOG_BOAT_ID.name(), event.getBoat().getId()); - storeRegattaLogEvent(regattaLikeId, result); - } - + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorAndBoatEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.REGATTA_LOG_BOAT_ID.name(), event.getBoat().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogCloseOpenEndedDeviceMappingEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); 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 79a69faaad5..907859bcd3c 100755 --- 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 @@ -1,534 +1,534 @@ -package com.sap.sailing.domain.racelogtracking.test.impl; - -import static junit.framework.Assert.assertEquals; - -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.Timeout; - -import com.mongodb.MongoException; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Course; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.WaypointImpl; -import com.sap.sailing.domain.common.racelog.tracking.TransformationException; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sailing.domain.racelogtracking.impl.fixtracker.FixLoaderAndTracker; -import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.GPSTrackListener; -import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; -import com.sap.sse.common.NoCorrespondingServiceRegisteredException; +package com.sap.sailing.domain.racelogtracking.test.impl; + +import static junit.framework.Assert.assertEquals; + +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; + +import com.mongodb.MongoException; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Course; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.WaypointImpl; +import com.sap.sailing.domain.common.racelog.tracking.TransformationException; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sailing.domain.racelogtracking.impl.fixtracker.FixLoaderAndTracker; +import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.GPSTrackListener; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; +import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Timed; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.impl.TimeRangeImpl; - -public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { - private static final Logger logger = Logger.getLogger(TrackedRaceLoadsFixesTest.class.getName()); - - private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); - private final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); - private final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, - null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); - private final Course course = new CourseImpl("course", Arrays.asList(new WaypointImpl(mark), new WaypointImpl(mark2))); - - private RaceDefinition raceDefinition; - - @Before - public void setUp() throws UnknownHostException, MongoException { - Map competitorsAndBoats = new HashMap<>(); - competitorsAndBoats.put(comp, boat); - competitorsAndBoats.put(comp2, boat2); - this.raceDefinition = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); - } - - @Rule - public Timeout TrackedRaceLoadsFixesTestTimeout = new Timeout(3 * 60 * 1000); - - @Test - public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException, - NoCorrespondingServiceRegisteredException, InterruptedException { - - DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2"); - defineMarksOnRegattaLog(mark, mark2); - - map(comp, device, 0, 10000); - map(mark, markDevice, 0, 10000); - - store.storeFix(device, createFix(100, 10, 20, 30, 40)); // before - store.storeFix(device, createFix(1100, 10, 20, 30, 40)); // in - store.storeFix(device, createFix(2100, 10, 20, 30, 40)); // after - store.storeFix(markDevice, createFix(100, 10, 20)); - store.storeFix(markDevice, createFix(1100, 10, 20)); - store.storeFix(markDevice, createFix(2100, 10, 20)); - - final DynamicTrackedRaceImpl trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); - trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(1000)); - trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2000)); - new FixLoaderAndTracker(trackedRace, store, null); - - trackedRace.attachRaceLog(raceLog); - trackedRace.attachRegattaLog(regattaLog); - trackedRace.waitForLoadingToFinish(); - - testNumberOfRawFixes(trackedRace.getTrack(comp), 1); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - // now extend the tracking interval of the tracked race and assert that the additional fixes are loaded - trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2500), /* wait for fixes to load */ true); +import com.sap.sse.common.Timed; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.impl.TimeRangeImpl; + +public class TrackedRaceLoadsFixesTest extends AbstractGPSFixStoreTest { + private static final Logger logger = Logger.getLogger(TrackedRaceLoadsFixesTest.class.getName()); + + private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); + private final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); + private final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", "c2", null, null, null, + null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final Boat boat2 = DomainFactory.INSTANCE.getOrCreateBoat(comp2, "boat2", boatClass, "USA 123", null); + private final Course course = new CourseImpl("course", Arrays.asList(new WaypointImpl(mark), new WaypointImpl(mark2))); + + private RaceDefinition raceDefinition; + + @Before + public void setUp() throws UnknownHostException, MongoException { + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(comp, boat); + competitorsAndBoats.put(comp2, boat2); + this.raceDefinition = new RaceDefinitionImpl("race", course, boatClass, competitorsAndBoats); + } + + @Rule + public Timeout TrackedRaceLoadsFixesTestTimeout = new Timeout(3 * 60 * 1000); + + @Test + public void doesRaceLoadOnlyBetweenStartAndEndOfTracking() throws TransformationException, + NoCorrespondingServiceRegisteredException, InterruptedException { + + DeviceIdentifier markDevice = new SmartphoneImeiIdentifier("imei2"); + defineMarksOnRegattaLog(mark, mark2); + + map(comp, device, 0, 10000); + map(mark, markDevice, 0, 10000); + + store.storeFix(device, createFix(100, 10, 20, 30, 40)); // before + store.storeFix(device, createFix(1100, 10, 20, 30, 40)); // in + store.storeFix(device, createFix(2100, 10, 20, 30, 40)); // after + store.storeFix(markDevice, createFix(100, 10, 20)); + store.storeFix(markDevice, createFix(1100, 10, 20)); + store.storeFix(markDevice, createFix(2100, 10, 20)); + + final DynamicTrackedRaceImpl trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); + trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(1000)); + trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2000)); + new FixLoaderAndTracker(trackedRace, store, null); + + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); trackedRace.waitForLoadingToFinish(); - testNumberOfRawFixes(trackedRace.getTrack(comp), 2); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(0), /* wait for fixes to load */ true); + + testNumberOfRawFixes(trackedRace.getTrack(comp), 1); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + // now extend the tracking interval of the tracked race and assert that the additional fixes are loaded + trackedRace.setEndOfTrackingReceived(new MillisecondsTimePoint(2500), /* wait for fixes to load */ true); trackedRace.waitForLoadingToFinish(); - testNumberOfRawFixes(trackedRace.getTrack(comp), 3); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 3); - } - - @Test - public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException, - InterruptedException { - defineMarksOnRegattaLog(mark, mark2); - DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2"); - DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3"); - - map(comp, device, 0, 20000); - map(comp2, device2, 0, 600); - // reuse device for two marks - map(mark, device3, 0, 600); - map(mark2, device3, 0, 600); - - store.storeFix(device, createFix(100, 10, 20, 30, 40)); - store.storeFix(device, createFix(200, 10, 20, 30, 40)); - store.storeFix(device2, createFix(100, 10, 20, 30, 40)); - store.storeFix(device3, createFix(100, 10, 20)); - store.storeFix(device3, createFix(100, 10, 20)); - - for (int i = 0; i < 10000; i++) { - store.storeFix(device, createFix(i + 1000, 10, 20, 30, 40)); - } - - DynamicTrackedRace trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); - - new FixLoaderAndTracker(trackedRace, store, null); - + testNumberOfRawFixes(trackedRace.getTrack(comp), 2); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + trackedRace.setStartOfTrackingReceived(new MillisecondsTimePoint(0), /* wait for fixes to load */ true); + trackedRace.waitForLoadingToFinish(); + testNumberOfRawFixes(trackedRace.getTrack(comp), 3); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 3); + } + + @Test + public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException, + InterruptedException { + defineMarksOnRegattaLog(mark, mark2); + DeviceIdentifier device2 = new SmartphoneImeiIdentifier("imei2"); + DeviceIdentifier device3 = new SmartphoneImeiIdentifier("imei3"); + + map(comp, device, 0, 20000); + map(comp2, device2, 0, 600); + // reuse device for two marks + map(mark, device3, 0, 600); + map(mark2, device3, 0, 600); + + store.storeFix(device, createFix(100, 10, 20, 30, 40)); + store.storeFix(device, createFix(200, 10, 20, 30, 40)); + store.storeFix(device2, createFix(100, 10, 20, 30, 40)); + store.storeFix(device3, createFix(100, 10, 20)); + store.storeFix(device3, createFix(100, 10, 20)); + + for (int i = 0; i < 10000; i++) { + store.storeFix(device, createFix(i + 1000, 10, 20, 30, 40)); + } + + DynamicTrackedRace trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); + + new FixLoaderAndTracker(trackedRace, store, null); + raceLog.add(new RaceLogStartOfTrackingEventImpl(TimePoint.BeginningOfTime, author, 0)); - trackedRace.attachRaceLog(raceLog); - trackedRace.attachRegattaLog(regattaLog); - trackedRace.waitForLoadingToFinish(); - - testNumberOfRawFixes(trackedRace.getTrack(comp), 10002); - testNumberOfRawFixes(trackedRace.getTrack(comp2), 1); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1); - } - - @Test - public void testFixesForCompetitorsAreNotLoadedIfMappingDoesNotIntersectWithTrackingInterval() - throws InterruptedException { - testFixes(/* start of tracking */ 200, /* end of tracking */ 300, /* mappings and fixes */ () -> { - map(comp, device, 0, 100); - store.storeFix(device, createFix(10, 10, 20, 30, 40)); - store.storeFix(device, createFix(20, 10, 20, 30, 40)); - }, /* tests and expectations */ trackedRace -> testNumberOfRawFixes(trackedRace.getTrack(comp), 0)); - } - - @Test - public void testFixesForCompetitorsAreLoadedIfMappingDoesIntersectWithTrackingIntervalFixesWithinIntersectionOnly() - throws InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings and fixes */ () -> { - map(comp, device, 0, 200); - store.storeFix(device, createFix(50, 10, 20, 30, 40)); - store.storeFix(device, createFix(150, 10, 20, 30, 40)); - store.storeFix(device, createFix(250, 10, 20, 30, 40)); - map(comp, device, 350, 500); - store.storeFix(device, createFix(400, 10, 20, 30, 40)); - store.storeFix(device, createFix(450, 10, 20, 30, 40)); - }, /* tests and expectations */ trackedRace -> testNumberOfRawFixes(trackedRace.getTrack(comp), 1)); - } - - @Test - public void testAddingMappingLoadsFixesPreviouslyNotCovered() throws InterruptedException { - testFixes(/* start of tracking */ 10, /* end of tracking */ 500, /* mappings and fixes */ () -> { - map(comp, device, 0, 200); - map(comp, device, 300, 400); - store.storeFix(device, createFix(50, 10, 20, 30, 40)); // in first mapping - store.storeFix(device, createFix(150, 10, 20, 30, 40)); // in first mapping - store.storeFix(device, createFix(250, 10, 20, 30, 40)); // outside both mappings - store.storeFix(device, createFix(350, 10, 20, 30, 40)); // in second mapping - }, /* tests and expectations */ trackedRace -> { - final int[] fixInsertionCount = new int[1]; - trackedRace.getTrack(comp).addListener(new GPSTrackListener() { - private static final long serialVersionUID = 1933664210766279523L; - - @Override - public boolean isTransient() { - return true; - } - - @Override - public void gpsFixReceived(GPSFixMoving fix, Competitor item, boolean firstFixInTrack) { - fixInsertionCount[0]++; - } - - @Override - public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, - long newMillisecondsOverWhichToAverage) { - // no-op - } - }); - testNumberOfRawFixes(trackedRace.getTrack(comp), 3); - map(comp, device, 0, 500); // covers fix at 250ms; assert that only that fix is loaded - try { - trackedRace.waitForLoadingToFinish(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Exception waiting for loading to finish", e); - } - testNumberOfRawFixes(trackedRace.getTrack(comp), 4); - assertEquals(1, fixInsertionCount[0]); - }); - } - - @Test - public void testAddingMappingDoesNotLoadFixesAlreadyCoveredByExistingMapping() throws InterruptedException { - testFixes(/* start of tracking */ 10, /* end of tracking */ 500, /* mappings and fixes */ () -> { - map(comp, device, 0, 200); - map(comp, device, 300, 400); - store.storeFix(device, createFix(50, 10, 20, 30, 40)); // in first mapping - store.storeFix(device, createFix(150, 10, 20, 30, 40)); // in first mapping - store.storeFix(device, createFix(250, 10, 20, 30, 40)); // outside both mappings - store.storeFix(device, createFix(350, 10, 20, 30, 40)); // in second mapping - }, /* tests and expectations */ trackedRace -> { - map(comp, device, 0, 500); // covers fix at 250ms - try { - trackedRace.waitForLoadingToFinish(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Exception waiting for loading to finish", e); - } - store.storeFix(device, createFix(400, 10, 20, 30, 40)); // in third mapping - testNumberOfRawFixes(trackedRace.getTrack(comp), 5); - }); - } - - /** - * Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008
- * Updated for bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 - */ - @Test - public void testFixesForMarkAreLoadedIfMappingDoesNotIntersectWithTrackingInterval() throws InterruptedException { - final long startOfTracking = 200; - final long bestFixOffset = 20; - testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ 300, /* mappings and fixes */ () -> { - map(mark, device, 0, 100); - store.storeFix(device, createFix(10, 10, 20)); - store.storeFix(device, createFix(bestFixOffset, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - assertEquals(bestFixOffset, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - }); - } - - /** Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008 */ - @Test - public void testFixesForTwoMarksAreLoadedIfMappingsDoNotIntersectWithTrackingInterval() - throws InterruptedException { - testFixes(/* start of tracking */ 400, /* end of tracking */ 500, /* mappings and fixes */ () -> { - map(mark, device, 0, 100); - store.storeFix(device, createFix(50, 10, 20)); - map(mark2, device, 200, 300); - store.storeFix(device, createFix(250, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1); - }); - } - - /** Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008 */ - @Test - public void testFixesForMarkAreLoadedIfMappingDoesIntersectWithTrackingIntervalFixesWithinIntersectionOnly() - throws InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings and fixes */ () -> { - map(mark, device, 0, 200); - store.storeFix(device, createFix(50, 10, 20)); - store.storeFix(device, createFix(150, 10, 20)); - store.storeFix(device, createFix(250, 10, 20)); - - map(mark, device, 350, 500); - store.storeFix(device, createFix(400, 10, 20)); - store.storeFix(device, createFix(450, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - /** - * Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008
- * Updated for bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 - */ - @Test - public void testFixesForMarkAreLoadedIfMappingDoesIntersectWithTrackingIntervalAllFixesBecauseOfNoFixesWithIntersection() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - final long bestFixBeforeStartOfTrackingOffset = 50; - final long bestFixAfterEndOfTrackingOffset = 400; - final long startOfTracking = 100; - final long endOfTracking = 300; - testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { - map(mark, device, 0, 200); - store.storeFix(device, createFix(bestFixBeforeStartOfTrackingOffset, 10, 20)); - store.storeFix(device, createFix(250, 10, 20)); - map(mark, device, 350, 500); - store.storeFix(device, createFix(bestFixAfterEndOfTrackingOffset, 10, 20)); - store.storeFix(device, createFix(450, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - assertEquals(bestFixBeforeStartOfTrackingOffset, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - assertEquals(bestFixAfterEndOfTrackingOffset, trackedRace.getOrCreateTrack(mark) - .getFirstFixAfter(new MillisecondsTimePoint(endOfTracking)).getTimePoint().asMillis()); - }); - } - - /** Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 */ - @Test - public void testThatOnlyTheBestFixesAreLoadedForMarksIfMultipleMappingsAreAvailable() - throws InterruptedException { - final long bestFixBeforeStartOfTrackingOffset = 140; - final long bestFixAfterEndOfTrackingOffset = 360; - final long startOfTracking = 200; - final long endOfTracking = 300; - testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { - map(mark, device, 0, 80); - store.storeFix(device, createFix(50, 10, 20)); - store.storeFix(device, createFix(70, 10, 20)); - map(mark, device, 100, 150); - store.storeFix(device, createFix(120, 10, 20)); - store.storeFix(device, createFix(bestFixBeforeStartOfTrackingOffset, 10, 20)); - - map(mark, device, 400, 500); - store.storeFix(device, createFix(420, 10, 20)); - store.storeFix(device, createFix(450, 10, 20)); - store.storeFix(device, createFix(480, 10, 20)); - map(mark, device, 350, 390); - store.storeFix(device, createFix(bestFixAfterEndOfTrackingOffset, 10, 20)); - store.storeFix(device, createFix(380, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - assertEquals(bestFixBeforeStartOfTrackingOffset, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - assertEquals(bestFixAfterEndOfTrackingOffset, trackedRace.getOrCreateTrack(mark) - .getFirstFixAfter(new MillisecondsTimePoint(endOfTracking)).getTimePoint().asMillis()); - }); - } - - /** Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 */ - @Test - public void testYoungestFixIsAccurateOnSeveralAdditionsOfFixes() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - final long bestFix1 = 50; - final long bestFix2 = 100; - final long startOfTracking = 200; - final long endOfTracking = 300; - testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { - map(mark, device, bestFix1 - 20, bestFix1 + 10); - store.storeFix(device, createFix(bestFix1 - 10, 10, 20)); - store.storeFix(device, createFix(bestFix1, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - store.storeFix(device, createFix(bestFix2 - 10, 10, 20)); - store.storeFix(device, createFix(bestFix2, 10, 20)); - map(mark, device, bestFix2 - 20, bestFix2 + 10); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - assertEquals(bestFix2, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - }); - } - - /** - * Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009
- */ - @Test - public void testLoadingOfFixesOutsideOfTrackingIntervalsEndsIfFixInIntervalIsFound() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - final long bestFix1 = 50; - final long bestFix2 = 100; - final long startOfTracking = 200; - final long endOfTracking = 300; - testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { - map(mark, device, bestFix1 - 10, bestFix1 + 10); - store.storeFix(device, createFix(bestFix1, 10, 20)); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - store.storeFix(device, createFix(startOfTracking + 10, 10, 20)); - map(mark, device, startOfTracking, startOfTracking + 20); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - // would be the new best fix if there wasn't a fix in the tracking interval - store.storeFix(device, createFix(bestFix2, 10, 20)); - map(mark, device, bestFix2 - 10, bestFix2 + 10); - }, /* tests and expectations */ trackedRace -> { - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) - .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); - }); - } - - @Test - public void testFixForMarkIsAddedIfBeforeTrackingIntervalAndNoOtherFixExists() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 200), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(50, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - @Test - public void testFixForMarkIsAddedIfAfterTrackingIntervalAndNoOtherFixExists() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(350, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - @Test - public void testFixForMarkIsAddedIfBeforeTrackingIntervalAndBetterThanAnExistingOne() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(50, 10, 20)); - store.storeFix(device, createFix(75, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - }); - } - - @Test - public void testFixForMarkIsNotAddedIfBeforeTrackingIntervalAndWorseThanAnExistingOne() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(75, 10, 20)); - store.storeFix(device, createFix(50, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - @Test - public void testFixForMarkIsAddedIfAfterTrackingIntervalAndBetterThanAnExistingOne() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(375, 10, 20)); - store.storeFix(device, createFix(350, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); - }); - } - - @Test - public void testFixForMarkIsNotAddedIfAfterTrackingIntervalAndWorseThanAnExistingOne() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(350, 10, 20)); - store.storeFix(device, createFix(375, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - @Test - public void testFixForMarkIsNotAddedIfNotWithinTrackingIntervalAndFixWithinTrackingIntervalExists() - throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { - testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), - /* fixes and tests/expectations */ trackedRace -> { - store.storeFix(device, createFix(200, 10, 20)); - store.storeFix(device, createFix(50, 10, 20)); - store.storeFix(device, createFix(350, 10, 20)); - testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); - }); - } - - @SafeVarargs - private final void testFixes(long startOfTracking, long endOfTracking, Runnable beforeTrackingStarted, - Consumer... afterTrackingStartedConsumers) throws InterruptedException { - defineMarksOnRegattaLog(mark, mark2); - raceLog.add(new RaceLogStartOfTrackingEventImpl(new MillisecondsTimePoint(startOfTracking), author, 0)); - raceLog.add(new RaceLogEndOfTrackingEventImpl(new MillisecondsTimePoint(endOfTracking), author, 0)); - beforeTrackingStarted.run(); - DynamicTrackedRace trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); - trackedRace.attachRaceLog(raceLog); - trackedRace.attachRegattaLog(regattaLog); - new FixLoaderAndTracker(trackedRace, store, null); - for(Consumer afterTrackingStarted : afterTrackingStartedConsumers) { - trackedRace.waitForLoadingToFinish(); - afterTrackingStarted.accept(trackedRace); - } - } - - @Test - public void metadataStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException { - assertEquals(0, store.getNumberOfFixes(device)); - assertEquals(null, store.getTimeRangeCoveredByFixes(device)); - map(comp, device, 0, 600); - store.storeFix(device, createFix(100, 10, 20, 30, 40)); - store.storeFix(device, createFix(200, 10, 20, 30, 40)); - assertEquals(2, store.getNumberOfFixes(device)); - assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device)); - } - - @Test - public void testFindLatestFixForMapping() throws TransformationException, NoCorrespondingServiceRegisteredException { - store.storeFix(device, createFix(100, 10, 20, 30, 40)); - store.storeFix(device, createFix(1100, 10, 20, 30, 40)); - store.storeFix(device, createFix(2100, 10, 20, 30, 40)); - final Map lastFixes = store.getLastFix(Collections.singleton(device)); - assertEquals(1, lastFixes.size()); - Timed lastFix = lastFixes.get(device); - assertEquals(2100, lastFix.getTimePoint().asMillis()); - store.storeFix(device, createFix(2000, 10, 20, 30, 40)); - final Map lastFixes2 = store.getLastFix(Collections.singleton(device)); - assertEquals(1, lastFixes2.size()); - Timed lastFix2 = lastFixes2.get(device); - assertEquals(2100, lastFix2.getTimePoint().asMillis()); - store.storeFix(device, createFix(2200, 10, 20, 30, 40)); - final Map lastFixes3 = store.getLastFix(Collections.singleton(device)); - assertEquals(1, lastFixes3.size()); - Timed lastFix3 = lastFixes3.get(device); - assertEquals(2200, lastFix3.getTimePoint().asMillis()); - final DeviceIdentifier device2 = new SmartphoneImeiIdentifier("b"); - store.storeFix(device2, createFix(1200, 10, 20, 30, 40)); - store.storeFix(device2, createFix(1100, 10, 20, 30, 40)); - final Map lastFixes4 = store.getLastFix(Arrays.asList(device, device2)); - assertEquals(2, lastFixes4.size()); - Timed lastFix4 = lastFixes4.get(device); - assertEquals(2200, lastFix4.getTimePoint().asMillis()); - Timed lastFixDevice2 = lastFixes4.get(device2); - assertEquals(1200, lastFixDevice2.getTimePoint().asMillis()); - } -} + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + trackedRace.waitForLoadingToFinish(); + + testNumberOfRawFixes(trackedRace.getTrack(comp), 10002); + testNumberOfRawFixes(trackedRace.getTrack(comp2), 1); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1); + } + + @Test + public void testFixesForCompetitorsAreNotLoadedIfMappingDoesNotIntersectWithTrackingInterval() + throws InterruptedException { + testFixes(/* start of tracking */ 200, /* end of tracking */ 300, /* mappings and fixes */ () -> { + map(comp, device, 0, 100); + store.storeFix(device, createFix(10, 10, 20, 30, 40)); + store.storeFix(device, createFix(20, 10, 20, 30, 40)); + }, /* tests and expectations */ trackedRace -> testNumberOfRawFixes(trackedRace.getTrack(comp), 0)); + } + + @Test + public void testFixesForCompetitorsAreLoadedIfMappingDoesIntersectWithTrackingIntervalFixesWithinIntersectionOnly() + throws InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings and fixes */ () -> { + map(comp, device, 0, 200); + store.storeFix(device, createFix(50, 10, 20, 30, 40)); + store.storeFix(device, createFix(150, 10, 20, 30, 40)); + store.storeFix(device, createFix(250, 10, 20, 30, 40)); + map(comp, device, 350, 500); + store.storeFix(device, createFix(400, 10, 20, 30, 40)); + store.storeFix(device, createFix(450, 10, 20, 30, 40)); + }, /* tests and expectations */ trackedRace -> testNumberOfRawFixes(trackedRace.getTrack(comp), 1)); + } + + @Test + public void testAddingMappingLoadsFixesPreviouslyNotCovered() throws InterruptedException { + testFixes(/* start of tracking */ 10, /* end of tracking */ 500, /* mappings and fixes */ () -> { + map(comp, device, 0, 200); + map(comp, device, 300, 400); + store.storeFix(device, createFix(50, 10, 20, 30, 40)); // in first mapping + store.storeFix(device, createFix(150, 10, 20, 30, 40)); // in first mapping + store.storeFix(device, createFix(250, 10, 20, 30, 40)); // outside both mappings + store.storeFix(device, createFix(350, 10, 20, 30, 40)); // in second mapping + }, /* tests and expectations */ trackedRace -> { + final int[] fixInsertionCount = new int[1]; + trackedRace.getTrack(comp).addListener(new GPSTrackListener() { + private static final long serialVersionUID = 1933664210766279523L; + + @Override + public boolean isTransient() { + return true; + } + + @Override + public void gpsFixReceived(GPSFixMoving fix, Competitor item, boolean firstFixInTrack) { + fixInsertionCount[0]++; + } + + @Override + public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, + long newMillisecondsOverWhichToAverage) { + // no-op + } + }); + testNumberOfRawFixes(trackedRace.getTrack(comp), 3); + map(comp, device, 0, 500); // covers fix at 250ms; assert that only that fix is loaded + try { + trackedRace.waitForLoadingToFinish(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Exception waiting for loading to finish", e); + } + testNumberOfRawFixes(trackedRace.getTrack(comp), 4); + assertEquals(1, fixInsertionCount[0]); + }); + } + + @Test + public void testAddingMappingDoesNotLoadFixesAlreadyCoveredByExistingMapping() throws InterruptedException { + testFixes(/* start of tracking */ 10, /* end of tracking */ 500, /* mappings and fixes */ () -> { + map(comp, device, 0, 200); + map(comp, device, 300, 400); + store.storeFix(device, createFix(50, 10, 20, 30, 40)); // in first mapping + store.storeFix(device, createFix(150, 10, 20, 30, 40)); // in first mapping + store.storeFix(device, createFix(250, 10, 20, 30, 40)); // outside both mappings + store.storeFix(device, createFix(350, 10, 20, 30, 40)); // in second mapping + }, /* tests and expectations */ trackedRace -> { + map(comp, device, 0, 500); // covers fix at 250ms + try { + trackedRace.waitForLoadingToFinish(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Exception waiting for loading to finish", e); + } + store.storeFix(device, createFix(400, 10, 20, 30, 40)); // in third mapping + testNumberOfRawFixes(trackedRace.getTrack(comp), 5); + }); + } + + /** + * Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008
+ * Updated for bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 + */ + @Test + public void testFixesForMarkAreLoadedIfMappingDoesNotIntersectWithTrackingInterval() throws InterruptedException { + final long startOfTracking = 200; + final long bestFixOffset = 20; + testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ 300, /* mappings and fixes */ () -> { + map(mark, device, 0, 100); + store.storeFix(device, createFix(10, 10, 20)); + store.storeFix(device, createFix(bestFixOffset, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + assertEquals(bestFixOffset, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + }); + } + + /** Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008 */ + @Test + public void testFixesForTwoMarksAreLoadedIfMappingsDoNotIntersectWithTrackingInterval() + throws InterruptedException { + testFixes(/* start of tracking */ 400, /* end of tracking */ 500, /* mappings and fixes */ () -> { + map(mark, device, 0, 100); + store.storeFix(device, createFix(50, 10, 20)); + map(mark2, device, 200, 300); + store.storeFix(device, createFix(250, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark2), 1); + }); + } + + /** Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008 */ + @Test + public void testFixesForMarkAreLoadedIfMappingDoesIntersectWithTrackingIntervalFixesWithinIntersectionOnly() + throws InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings and fixes */ () -> { + map(mark, device, 0, 200); + store.storeFix(device, createFix(50, 10, 20)); + store.storeFix(device, createFix(150, 10, 20)); + store.storeFix(device, createFix(250, 10, 20)); + + map(mark, device, 350, 500); + store.storeFix(device, createFix(400, 10, 20)); + store.storeFix(device, createFix(450, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + /** + * Regression test for bug 4008 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4008
+ * Updated for bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 + */ + @Test + public void testFixesForMarkAreLoadedIfMappingDoesIntersectWithTrackingIntervalAllFixesBecauseOfNoFixesWithIntersection() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + final long bestFixBeforeStartOfTrackingOffset = 50; + final long bestFixAfterEndOfTrackingOffset = 400; + final long startOfTracking = 100; + final long endOfTracking = 300; + testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { + map(mark, device, 0, 200); + store.storeFix(device, createFix(bestFixBeforeStartOfTrackingOffset, 10, 20)); + store.storeFix(device, createFix(250, 10, 20)); + map(mark, device, 350, 500); + store.storeFix(device, createFix(bestFixAfterEndOfTrackingOffset, 10, 20)); + store.storeFix(device, createFix(450, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + assertEquals(bestFixBeforeStartOfTrackingOffset, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + assertEquals(bestFixAfterEndOfTrackingOffset, trackedRace.getOrCreateTrack(mark) + .getFirstFixAfter(new MillisecondsTimePoint(endOfTracking)).getTimePoint().asMillis()); + }); + } + + /** Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 */ + @Test + public void testThatOnlyTheBestFixesAreLoadedForMarksIfMultipleMappingsAreAvailable() + throws InterruptedException { + final long bestFixBeforeStartOfTrackingOffset = 140; + final long bestFixAfterEndOfTrackingOffset = 360; + final long startOfTracking = 200; + final long endOfTracking = 300; + testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { + map(mark, device, 0, 80); + store.storeFix(device, createFix(50, 10, 20)); + store.storeFix(device, createFix(70, 10, 20)); + map(mark, device, 100, 150); + store.storeFix(device, createFix(120, 10, 20)); + store.storeFix(device, createFix(bestFixBeforeStartOfTrackingOffset, 10, 20)); + + map(mark, device, 400, 500); + store.storeFix(device, createFix(420, 10, 20)); + store.storeFix(device, createFix(450, 10, 20)); + store.storeFix(device, createFix(480, 10, 20)); + map(mark, device, 350, 390); + store.storeFix(device, createFix(bestFixAfterEndOfTrackingOffset, 10, 20)); + store.storeFix(device, createFix(380, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + assertEquals(bestFixBeforeStartOfTrackingOffset, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + assertEquals(bestFixAfterEndOfTrackingOffset, trackedRace.getOrCreateTrack(mark) + .getFirstFixAfter(new MillisecondsTimePoint(endOfTracking)).getTimePoint().asMillis()); + }); + } + + /** Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009 */ + @Test + public void testYoungestFixIsAccurateOnSeveralAdditionsOfFixes() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + final long bestFix1 = 50; + final long bestFix2 = 100; + final long startOfTracking = 200; + final long endOfTracking = 300; + testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { + map(mark, device, bestFix1 - 20, bestFix1 + 10); + store.storeFix(device, createFix(bestFix1 - 10, 10, 20)); + store.storeFix(device, createFix(bestFix1, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + store.storeFix(device, createFix(bestFix2 - 10, 10, 20)); + store.storeFix(device, createFix(bestFix2, 10, 20)); + map(mark, device, bestFix2 - 20, bestFix2 + 10); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + assertEquals(bestFix2, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + }); + } + + /** + * Test for changes of bug 4009 - https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4009
+ */ + @Test + public void testLoadingOfFixesOutsideOfTrackingIntervalsEndsIfFixInIntervalIsFound() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + final long bestFix1 = 50; + final long bestFix2 = 100; + final long startOfTracking = 200; + final long endOfTracking = 300; + testFixes(/* start of tracking */ startOfTracking, /* end of tracking */ endOfTracking, /* mappings and fixes */ () -> { + map(mark, device, bestFix1 - 10, bestFix1 + 10); + store.storeFix(device, createFix(bestFix1, 10, 20)); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + store.storeFix(device, createFix(startOfTracking + 10, 10, 20)); + map(mark, device, startOfTracking, startOfTracking + 20); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + // would be the new best fix if there wasn't a fix in the tracking interval + store.storeFix(device, createFix(bestFix2, 10, 20)); + map(mark, device, bestFix2 - 10, bestFix2 + 10); + }, /* tests and expectations */ trackedRace -> { + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + assertEquals(bestFix1, trackedRace.getOrCreateTrack(mark) + .getLastFixBefore(new MillisecondsTimePoint(startOfTracking)).getTimePoint().asMillis()); + }); + } + + @Test + public void testFixForMarkIsAddedIfBeforeTrackingIntervalAndNoOtherFixExists() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 200), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(50, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + @Test + public void testFixForMarkIsAddedIfAfterTrackingIntervalAndNoOtherFixExists() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(350, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + @Test + public void testFixForMarkIsAddedIfBeforeTrackingIntervalAndBetterThanAnExistingOne() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(50, 10, 20)); + store.storeFix(device, createFix(75, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + }); + } + + @Test + public void testFixForMarkIsNotAddedIfBeforeTrackingIntervalAndWorseThanAnExistingOne() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(75, 10, 20)); + store.storeFix(device, createFix(50, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + @Test + public void testFixForMarkIsAddedIfAfterTrackingIntervalAndBetterThanAnExistingOne() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(375, 10, 20)); + store.storeFix(device, createFix(350, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 2); + }); + } + + @Test + public void testFixForMarkIsNotAddedIfAfterTrackingIntervalAndWorseThanAnExistingOne() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(350, 10, 20)); + store.storeFix(device, createFix(375, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + @Test + public void testFixForMarkIsNotAddedIfNotWithinTrackingIntervalAndFixWithinTrackingIntervalExists() + throws TransformationException, NoCorrespondingServiceRegisteredException, InterruptedException { + testFixes(/* start of tracking */ 100, /* end of tracking */ 300, /* mappings */ () -> map(mark, device, 0, 400), + /* fixes and tests/expectations */ trackedRace -> { + store.storeFix(device, createFix(200, 10, 20)); + store.storeFix(device, createFix(50, 10, 20)); + store.storeFix(device, createFix(350, 10, 20)); + testNumberOfRawFixes(trackedRace.getOrCreateTrack(mark), 1); + }); + } + + @SafeVarargs + private final void testFixes(long startOfTracking, long endOfTracking, Runnable beforeTrackingStarted, + Consumer... afterTrackingStartedConsumers) throws InterruptedException { + defineMarksOnRegattaLog(mark, mark2); + raceLog.add(new RaceLogStartOfTrackingEventImpl(new MillisecondsTimePoint(startOfTracking), author, 0)); + raceLog.add(new RaceLogEndOfTrackingEventImpl(new MillisecondsTimePoint(endOfTracking), author, 0)); + beforeTrackingStarted.run(); + DynamicTrackedRace trackedRace = createDynamicTrackedRace(boatClass, raceDefinition); + trackedRace.attachRaceLog(raceLog); + trackedRace.attachRegattaLog(regattaLog); + new FixLoaderAndTracker(trackedRace, store, null); + for(Consumer afterTrackingStarted : afterTrackingStartedConsumers) { + trackedRace.waitForLoadingToFinish(); + afterTrackingStarted.accept(trackedRace); + } + } + + @Test + public void metadataStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException { + assertEquals(0, store.getNumberOfFixes(device)); + assertEquals(null, store.getTimeRangeCoveredByFixes(device)); + map(comp, device, 0, 600); + store.storeFix(device, createFix(100, 10, 20, 30, 40)); + store.storeFix(device, createFix(200, 10, 20, 30, 40)); + assertEquals(2, store.getNumberOfFixes(device)); + assertEquals(TimeRangeImpl.create(100, 200), store.getTimeRangeCoveredByFixes(device)); + } + + @Test + public void testFindLatestFixForMapping() throws TransformationException, NoCorrespondingServiceRegisteredException { + store.storeFix(device, createFix(100, 10, 20, 30, 40)); + store.storeFix(device, createFix(1100, 10, 20, 30, 40)); + store.storeFix(device, createFix(2100, 10, 20, 30, 40)); + final Map lastFixes = store.getLastFix(Collections.singleton(device)); + assertEquals(1, lastFixes.size()); + Timed lastFix = lastFixes.get(device); + assertEquals(2100, lastFix.getTimePoint().asMillis()); + store.storeFix(device, createFix(2000, 10, 20, 30, 40)); + final Map lastFixes2 = store.getLastFix(Collections.singleton(device)); + assertEquals(1, lastFixes2.size()); + Timed lastFix2 = lastFixes2.get(device); + assertEquals(2100, lastFix2.getTimePoint().asMillis()); + store.storeFix(device, createFix(2200, 10, 20, 30, 40)); + final Map lastFixes3 = store.getLastFix(Collections.singleton(device)); + assertEquals(1, lastFixes3.size()); + Timed lastFix3 = lastFixes3.get(device); + assertEquals(2200, lastFix3.getTimePoint().asMillis()); + final DeviceIdentifier device2 = new SmartphoneImeiIdentifier("b"); + store.storeFix(device2, createFix(1200, 10, 20, 30, 40)); + store.storeFix(device2, createFix(1100, 10, 20, 30, 40)); + final Map lastFixes4 = store.getLastFix(Arrays.asList(device, device2)); + assertEquals(2, lastFixes4.size()); + Timed lastFix4 = lastFixes4.get(device); + assertEquals(2200, lastFix4.getTimePoint().asMillis()); + Timed lastFixDevice2 = lastFixes4.get(device2); + assertEquals(1200, lastFixDevice2.getTimePoint().asMillis()); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java index 8bc1dcfdafa..2bad51f8c54 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java @@ -1,61 +1,61 @@ -package com.sap.sailing.domain.abstractlog.race; - -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; - - -public interface RaceLogEventVisitor { - public void visit(RaceLogRevokeEvent event); - - public void visit(RaceLogFlagEvent event); - - public void visit(RaceLogPassChangeEvent event); - - public void visit(RaceLogRaceStatusEvent event); - - public void visit(RaceLogStartTimeEvent event); - - public void visit(RaceLogCourseAreaChangedEvent event); - - public void visit(RaceLogCourseDesignChangedEvent event); - - public void visit(RaceLogFinishPositioningListChangedEvent event); - - public void visit(RaceLogFinishPositioningConfirmedEvent event); - - public void visit(RaceLogPathfinderEvent event); - - public void visit(RaceLogGateLineOpeningTimeEvent event); - - public void visit(RaceLogStartProcedureChangedEvent event); - - public void visit(RaceLogProtestStartTimeEvent event); - - public void visit(RaceLogWindFixEvent event); - - public void visit(RaceLogDenoteForTrackingEvent event); - - public void visit(RaceLogStartTrackingEvent event); - - public void visit(RaceLogRegisterCompetitorEvent event); - - public void visit(RaceLogRegisterCompetitorAndBoatEvent event); - - public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation); - - public void visit(RaceLogFixedMarkPassingEvent event); - - public void visit(RaceLogSuppressedMarkPassingsEvent event); - - public void visit(RaceLogDependentStartTimeEvent event); - - public void visit(RaceLogStartOfTrackingEvent event); - - public void visit(RaceLogEndOfTrackingEvent event); - - public void visit(RaceLogUseCompetitorsFromRaceLogEvent event); -} +package com.sap.sailing.domain.abstractlog.race; + +import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; + + +public interface RaceLogEventVisitor { + public void visit(RaceLogRevokeEvent event); + + public void visit(RaceLogFlagEvent event); + + public void visit(RaceLogPassChangeEvent event); + + public void visit(RaceLogRaceStatusEvent event); + + public void visit(RaceLogStartTimeEvent event); + + public void visit(RaceLogCourseAreaChangedEvent event); + + public void visit(RaceLogCourseDesignChangedEvent event); + + public void visit(RaceLogFinishPositioningListChangedEvent event); + + public void visit(RaceLogFinishPositioningConfirmedEvent event); + + public void visit(RaceLogPathfinderEvent event); + + public void visit(RaceLogGateLineOpeningTimeEvent event); + + public void visit(RaceLogStartProcedureChangedEvent event); + + public void visit(RaceLogProtestStartTimeEvent event); + + public void visit(RaceLogWindFixEvent event); + + public void visit(RaceLogDenoteForTrackingEvent event); + + public void visit(RaceLogStartTrackingEvent event); + + public void visit(RaceLogRegisterCompetitorEvent event); + + public void visit(RaceLogRegisterCompetitorAndBoatEvent event); + + public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation); + + public void visit(RaceLogFixedMarkPassingEvent event); + + public void visit(RaceLogSuppressedMarkPassingsEvent event); + + public void visit(RaceLogDependentStartTimeEvent event); + + public void visit(RaceLogStartOfTrackingEvent event); + + public void visit(RaceLogEndOfTrackingEvent event); + + public void visit(RaceLogUseCompetitorsFromRaceLogEvent event); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java index a05c26e9e81..a6606a2aae7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java @@ -1,44 +1,44 @@ -package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl; - -import java.util.Map; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; - -/** - * Used to find competitors (including their boats) of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the - * competitors for the given race are registered on the RaceLog via {@link RaceLogUsesOwnCompetitorsAnalyzer} or on the - * RegattaLog and fetches the competitors appropriately. - * - * Should not be used by clients directly. Instead, get the competitor set from the {@code RaceColumn}, using either one - * of {@code getAllCompetitorsAndTheirBoats()} and {@code getAllCompetitorsAndTheirBoats(Fleet)}. Those methods automatically check whether a - * tracked race is present, which takes precedence over the Race/RegattaLog. - * - * @author Jan Bross (D056848) - * - */ -public class RegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer> { - private RegattaLog regattaLog; - - public RegisteredCompetitorsAndBoatsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) { - super(raceLog); - this.regattaLog = regattaLog; - } - - @Override - protected Map performAnalysis() { - final Map result; - if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { - // get Events from RaceLog - result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); - } else { - // get Events from RegattaLog - result = new CompetitorsAndBoatsInLogAnalyzer<>(regattaLog).analyze(); - } - return result; - } -} +package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl; + +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; + +/** + * Used to find competitors (including their boats) of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the + * competitors for the given race are registered on the RaceLog via {@link RaceLogUsesOwnCompetitorsAnalyzer} or on the + * RegattaLog and fetches the competitors appropriately. + * + * Should not be used by clients directly. Instead, get the competitor set from the {@code RaceColumn}, using either one + * of {@code getAllCompetitorsAndTheirBoats()} and {@code getAllCompetitorsAndTheirBoats(Fleet)}. Those methods automatically check whether a + * tracked race is present, which takes precedence over the Race/RegattaLog. + * + * @author Jan Bross (D056848) + * + */ +public class RegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer> { + private RegattaLog regattaLog; + + public RegisteredCompetitorsAndBoatsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) { + super(raceLog); + this.regattaLog = regattaLog; + } + + @Override + protected Map performAnalysis() { + final Map result; + if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { + // get Events from RaceLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); + } else { + // get Events from RegattaLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(regattaLog).analyze(); + } + return result; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index feb61797389..08837b2c531 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -1,34 +1,34 @@ -package com.sap.sailing.domain.abstractlog.regatta; - -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; - -public interface RegattaLogEventVisitor { - void visit(RegattaLogRevokeEvent event); - - void visit(RegattaLogDeviceMarkMappingEvent event); - - void visit(RegattaLogDeviceCompetitorMappingEvent event); - - void visit(RegattaLogDeviceCompetitorSensorDataMappingEvent event); - - void visit(RegattaLogCloseOpenEndedDeviceMappingEvent event); - - void visit(RegattaLogRegisterCompetitorEvent event); - - void visit(RegattaLogRegisterCompetitorAndBoatEvent event); - - void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event); - - void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event); - - void visit(RegattaLogDefineMarkEvent event); -} +package com.sap.sailing.domain.abstractlog.regatta; + +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; + +public interface RegattaLogEventVisitor { + void visit(RegattaLogRevokeEvent event); + + void visit(RegattaLogDeviceMarkMappingEvent event); + + void visit(RegattaLogDeviceCompetitorMappingEvent event); + + void visit(RegattaLogDeviceCompetitorSensorDataMappingEvent event); + + void visit(RegattaLogCloseOpenEndedDeviceMappingEvent event); + + void visit(RegattaLogRegisterCompetitorEvent event); + + void visit(RegattaLogRegisterCompetitorAndBoatEvent event); + + void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event); + + void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event); + + void visit(RegattaLogDefineMarkEvent event); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java index 93c7185c130..6127dad6b2e 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatChangeListener.java @@ -1,11 +1,11 @@ -package com.sap.sailing.domain.base; - -import com.sap.sse.common.Color; - -public interface BoatChangeListener { - void nameChanged(String oldName, String newName); - - void colorChanged(Color oldColor, Color newColor); - - void sailIdChanged(String oldSailId, String newSailId); -} +package com.sap.sailing.domain.base; + +import com.sap.sse.common.Color; + +public interface BoatChangeListener { + void nameChanged(String oldName, String newName); + + void colorChanged(Color oldColor, Color newColor); + + void sailIdChanged(String oldSailId, String newSailId); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java index 2ad9809f175..d718bed9b2c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatFactory.java @@ -1,31 +1,31 @@ -package com.sap.sailing.domain.base; - -import java.io.Serializable; - -import com.sap.sse.common.Color; - -/** - * Base interface for classes managing a set of {@link Boat} objects. - */ -public interface BoatFactory { - /** - * If a valid boat is returned and the caller has information available that could be used to update the boat, - * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Boat)}, and if true, - * must call {@link #getOrCreateBoat()} to cause an update of the boat's values. - */ - Boat getExistingBoatById(Serializable boatId); - - /** - * Checks if the boat shall be updated from the default provided by, e.g., a tracking infrastructure. - * Callers of {@link #getExistingBoatById(Serializable)} or {@link #getExistingBoatByIdAsString(String)} - * must call this method in case they retrieve a valid boat by ID and have data available that can be used to update - * the . - */ - boolean isBoatToUpdateDuringGetOrCreate(Boat result); - - Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color); - - Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color); - - Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color); -} +package com.sap.sailing.domain.base; + +import java.io.Serializable; + +import com.sap.sse.common.Color; + +/** + * Base interface for classes managing a set of {@link Boat} objects. + */ +public interface BoatFactory { + /** + * If a valid boat is returned and the caller has information available that could be used to update the boat, + * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Boat)}, and if true, + * must call {@link #getOrCreateBoat()} to cause an update of the boat's values. + */ + Boat getExistingBoatById(Serializable boatId); + + /** + * Checks if the boat shall be updated from the default provided by, e.g., a tracking infrastructure. + * Callers of {@link #getExistingBoatById(Serializable)} or {@link #getExistingBoatByIdAsString(String)} + * must call this method in case they retrieve a valid boat by ID and have data available that can be used to update + * the . + */ + boolean isBoatToUpdateDuringGetOrCreate(Boat result); + + Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color); + + Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color); + + Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorAndBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorAndBoat.java index 402b4d0d2ca..c84a8ef3517 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorAndBoat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorAndBoat.java @@ -1,13 +1,13 @@ -package com.sap.sailing.domain.base; - -import java.io.Serializable; - -/** - * A helper interface to combine a competitor and a boat - * @author fmittag - * - */ -public interface CompetitorAndBoat extends Serializable { - Competitor getCompetitor(); - Boat getBoat(); -} +package com.sap.sailing.domain.base; + +import java.io.Serializable; + +/** + * A helper interface to combine a competitor and a boat + * @author fmittag + * + */ +public interface CompetitorAndBoat extends Serializable { + Competitor getCompetitor(); + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 53a038bb847..4692c8f9145 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -1,144 +1,144 @@ -package com.sap.sailing.domain.base; - -import java.io.Serializable; -import java.net.URI; - -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; -import com.sap.sse.common.Color; -import com.sap.sse.common.Duration; - -/** - * Manages a set of {@link Competitor} and {@link Boat} objects. There may be a transient implementation based on a simple cache, - * and there may be persistent implementations. - * - * @author Axel Uhl (d043530) - * - */ -public interface CompetitorStore extends CompetitorFactory, BoatFactory { - public interface CompetitorUpdateListener { - void competitorUpdated(Competitor competitor); - } - - public interface BoatUpdateListener { - void boatUpdated(Boat boat); - } - - /** - * If a valid competitor is returned and the caller has information available that could be used to update the competitor, - * the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if true, - * must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the - * competitor's values. - */ - Competitor getExistingCompetitorByIdAsString(String idAsString); - - /** - * When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} - * , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team - * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This - * method can be used to reset a competitor object to what a tracking provider or an external system supplies to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the - * next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with - * competitor's {@link Competitor#getId() ID} will - * {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as - * the name, the sail ID and the nationality. - */ - void allowCompetitorResetToDefaults(Competitor competitor); - - int getCompetitorsCount(); - - /** - * Removes all competitors from this store. Use with due care. - */ - void clearCompetitors(); - - /** - * Obtains a non-live snapshot of the list of competitors managed by this store. - */ - Iterable getCompetitors(); - - void removeCompetitor(Competitor competitor); - - /** - * Updates the competitor with {@link Competitor#getId() ID} id by setting the name, sail ID and nationality to - * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. - * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will - * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

- * - * If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. - */ - Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, - Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, - Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); - - void addCompetitors(Iterable competitors); - - CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); - - CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); - - CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); - - /** - * Listeners added here are notified whenever {@link #updateCompetitor(String, String, Color, String, Nationality)} is called - * for any competitor in this store. - */ - void addCompetitorUpdateListener(CompetitorUpdateListener listener); - - void removeCompetitorUpdateListener(CompetitorUpdateListener listener); - - /** - * If a valid boat is returned and the caller has information available that could be used to update the boat, - * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, - * must call {@link #getOrCreateBoat(..)} to cause an update of the boat's values. - */ - Boat getExistingBoatByIdAsString(String idAsString); - - /** - * When a boat is queried using {@link #getOrCreateBoat(...)}, - * and the boat object for that ID already exists, it is generally returned unchanged, and the properties - * are not evaluated. This makes the data in this store generally "write-once." This - * method can be used to reset a boat object to what a tracking provider or an external system supplies to - * {@link #getOrCreateBoat(...)}. After calling this method, the - * next call to {@link #getOrCreateBoat(...)} with boat's {@link Boat#getId() ID} will - * {@link #updateBoat(...)} the boat in its updatable properties such as sail ID and the color. - */ - void allowBoatResetToDefaults(Boat boat); - - int getBoatsCount(); - - /** - * Removes all boats from this store. Use with due care. - */ - void clearBoats(); - - /** - * Obtains a non-live snapshot of the list of boats managed by this store. - */ - Iterable getBoats(); - - void removeBoat(Boat boat); - - /** - * Updates the boat with {@link Boat#getId() ID} id by setting the name, sail ID, etc. to - * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. - * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will - * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

- * - * If no boat with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. - */ - Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId); - - BoatDTO convertToBoatDTO(Boat boat); - - /** - * Listeners added here are notified whenever {@link #updateBoat(...)} is called - * for any boat in this store. - */ - void addBoatUpdateListener(BoatUpdateListener listener); - - void removeBoatUpdateListener(BoatUpdateListener listener); -} +package com.sap.sailing.domain.base; + +import java.io.Serializable; +import java.net.URI; + +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Manages a set of {@link Competitor} and {@link Boat} objects. There may be a transient implementation based on a simple cache, + * and there may be persistent implementations. + * + * @author Axel Uhl (d043530) + * + */ +public interface CompetitorStore extends CompetitorFactory, BoatFactory { + public interface CompetitorUpdateListener { + void competitorUpdated(Competitor competitor); + } + + public interface BoatUpdateListener { + void boatUpdated(Boat boat); + } + + /** + * If a valid competitor is returned and the caller has information available that could be used to update the competitor, + * the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if true, + * must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the + * competitor's values. + */ + Competitor getExistingCompetitorByIdAsString(String idAsString); + + /** + * When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} + * , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team + * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This + * method can be used to reset a competitor object to what a tracking provider or an external system supplies to + * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the + * next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with + * competitor's {@link Competitor#getId() ID} will + * {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as + * the name, the sail ID and the nationality. + */ + void allowCompetitorResetToDefaults(Competitor competitor); + + int getCompetitorsCount(); + + /** + * Removes all competitors from this store. Use with due care. + */ + void clearCompetitors(); + + /** + * Obtains a non-live snapshot of the list of competitors managed by this store. + */ + Iterable getCompetitors(); + + void removeCompetitor(Competitor competitor); + + /** + * Updates the competitor with {@link Competitor#getId() ID} id by setting the name, sail ID and nationality to + * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. + * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will + * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

+ * + * If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. + */ + Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); + + void addCompetitors(Iterable competitors); + + CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); + + CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); + + CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); + + /** + * Listeners added here are notified whenever {@link #updateCompetitor(String, String, Color, String, Nationality)} is called + * for any competitor in this store. + */ + void addCompetitorUpdateListener(CompetitorUpdateListener listener); + + void removeCompetitorUpdateListener(CompetitorUpdateListener listener); + + /** + * If a valid boat is returned and the caller has information available that could be used to update the boat, + * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, + * must call {@link #getOrCreateBoat(..)} to cause an update of the boat's values. + */ + Boat getExistingBoatByIdAsString(String idAsString); + + /** + * When a boat is queried using {@link #getOrCreateBoat(...)}, + * and the boat object for that ID already exists, it is generally returned unchanged, and the properties + * are not evaluated. This makes the data in this store generally "write-once." This + * method can be used to reset a boat object to what a tracking provider or an external system supplies to + * {@link #getOrCreateBoat(...)}. After calling this method, the + * next call to {@link #getOrCreateBoat(...)} with boat's {@link Boat#getId() ID} will + * {@link #updateBoat(...)} the boat in its updatable properties such as sail ID and the color. + */ + void allowBoatResetToDefaults(Boat boat); + + int getBoatsCount(); + + /** + * Removes all boats from this store. Use with due care. + */ + void clearBoats(); + + /** + * Obtains a non-live snapshot of the list of boats managed by this store. + */ + Iterable getBoats(); + + void removeBoat(Boat boat); + + /** + * Updates the boat with {@link Boat#getId() ID} id by setting the name, sail ID, etc. to + * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. + * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will + * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

+ * + * If no boat with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. + */ + Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId); + + BoatDTO convertToBoatDTO(Boat boat); + + /** + * Listeners added here are notified whenever {@link #updateBoat(...)} is called + * for any boat in this store. + */ + void addBoatUpdateListener(BoatUpdateListener listener); + + void removeBoatUpdateListener(BoatUpdateListener listener); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java index ba7e2563dc2..f8339fd5030 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java @@ -1,26 +1,26 @@ -package com.sap.sailing.domain.base.impl; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; - -public class CompetitorAndBoatImpl implements CompetitorAndBoat { - private static final long serialVersionUID = 6057339511208358777L; - private final Competitor competitor; - private final Boat boat; - - public CompetitorAndBoatImpl(Competitor competitor, Boat boat) { - this.competitor = competitor; - this.boat = boat; - } - - @Override - public Competitor getCompetitor() { - return competitor; - } - @Override - public Boat getBoat() { - return boat; - } - -} +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; + +public class CompetitorAndBoatImpl implements CompetitorAndBoat { + private static final long serialVersionUID = 6057339511208358777L; + private final Competitor competitor; + private final Boat boat; + + public CompetitorAndBoatImpl(Competitor competitor, Boat boat) { + this.competitor = competitor; + this.boat = boat; + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + @Override + public Boat getBoat() { + return boat; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java index cadf8a6d2c0..c96da025169 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicBoat.java @@ -1,12 +1,12 @@ -package com.sap.sailing.domain.base.impl; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sse.common.Color; - -public interface DynamicBoat extends Boat { - void setSailId(String sailId); - - void setName(String name); - - void setColor(Color color); -} +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sse.common.Color; + +public interface DynamicBoat extends Boat { + void setSailId(String sailId); + + void setName(String name); + + void setColor(Color color); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 146f573bb77..92d59e841d7 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -1,539 +1,539 @@ -package com.sap.sailing.domain.base.impl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.CompetitorWithBoat; -import com.sap.sailing.domain.base.LeaderboardGroupBase; -import com.sap.sailing.domain.base.Nationality; -import com.sap.sailing.domain.common.dto.BoatClassDTO; -import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTOImpl; -import com.sap.sse.common.Color; -import com.sap.sse.common.CountryCode; -import com.sap.sse.common.Duration; -import com.sap.sse.concurrent.LockUtil; -import com.sap.sse.concurrent.NamedReentrantReadWriteLock; - -public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable { - private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName()); - private static final long serialVersionUID = -4198298775476586931L; - private final Map competitorCache; - private final Map competitorsByIdAsString; - private transient Set competitorUpdateListeners; - private final Map boatCache; - private final Map boatsByIdAsString; - private transient Set boatUpdateListeners; - - /** - * The competitors contained in this map will have their changeable properties - * {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID. - */ - private final Set competitorsToUpdateDuringGetOrCreate; - - private transient WeakHashMap weakCompetitorDTOCache; - - private final Set boatsToUpdateDuringGetOrCreate; - - private transient WeakHashMap weakBoatDTOCache; - - private final NamedReentrantReadWriteLock lock; - - public TransientCompetitorStoreImpl() { - lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false); - competitorCache = new HashMap(); - competitorsByIdAsString = new HashMap(); - competitorsToUpdateDuringGetOrCreate = new HashSet(); - weakCompetitorDTOCache = new WeakHashMap(); - competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); - boatCache = new HashMap(); - boatsByIdAsString = new HashMap(); - boatsToUpdateDuringGetOrCreate = new HashSet(); - weakBoatDTOCache = new WeakHashMap(); - boatUpdateListeners = Collections.synchronizedSet(new HashSet()); - } - - private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - ois.defaultReadObject(); - weakCompetitorDTOCache = new WeakHashMap(); - competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); - weakBoatDTOCache = new WeakHashMap(); - boatUpdateListeners = Collections.synchronizedSet(new HashSet()); - } - - @Override - public void addCompetitorUpdateListener(CompetitorUpdateListener listener) { - competitorUpdateListeners.add(listener); - } - - @Override - public void removeCompetitorUpdateListener(CompetitorUpdateListener listener) { - competitorUpdateListeners.remove(listener); - } - - private Competitor createCompetitor(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, - DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = new CompetitorImpl(id, name, shortName, displayColor, email, flagImage, team, - timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); - addNewCompetitor(id, result); - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened")); - } - return result; - } - - /** - * Adds the competitor to this transient competitor collection so that it is available in - * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional - * measures such as durably storing the competitor. Overriding implementations must call this implementation. - */ - protected void addNewCompetitor(Serializable id, Competitor competitor) { - LockUtil.lockForWrite(lock); - try { - competitorCache.put(id, competitor); - competitorsByIdAsString.put(id.toString(), competitor); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, - URI flagImage, DynamicTeam team, Double timeOnTimeFactor, - Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { - Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access - if (result == null) { - LockUtil.lockForWrite(lock); - try { - result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock - if (result == null) { - result = createCompetitor(competitorId, name, shortName, displayColor, email, flagImage, team, - timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); - } - } finally { - LockUtil.unlockAfterWrite(lock); - } - } else if (isCompetitorToUpdateDuringGetOrCreate(result)) { - updateCompetitor(result.getId().toString(), name, shortName, displayColor, email, team.getNationality(), - team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); - competitorNoLongerToUpdateDuringGetOrCreate(result); - } - return result; - } - - private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor competitor) { - competitorsToUpdateDuringGetOrCreate.remove(competitor); - } - - @Override - public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { - return competitorsToUpdateDuringGetOrCreate.contains(competitor); - } - - @Override - public Competitor getExistingCompetitorById(Serializable competitorId) { - LockUtil.lockForRead(lock); - try { - return competitorCache.get(competitorId); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public Competitor getExistingCompetitorByIdAsString(String competitorIdAsString) { - LockUtil.lockForRead(lock); - try { - return competitorsByIdAsString.get(competitorIdAsString); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public int getCompetitorsCount() { - LockUtil.lockForRead(lock); - try { - return competitorCache.size(); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public void clearCompetitors() { - LockUtil.lockForWrite(lock); - try { - competitorCache.clear(); - competitorsByIdAsString.clear(); - competitorsToUpdateDuringGetOrCreate.clear(); - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Clearing competitor store "+this, new Exception("here is where it happened")); - } - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Iterable getCompetitors() { - LockUtil.lockForRead(lock); - try { - return new ArrayList(competitorCache.values()); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public void removeCompetitor(Competitor competitor) { - LockUtil.lockForWrite(lock); - try { - logger.fine("removing competitor "+competitor+" from competitor store "+this); - competitorCache.remove(competitor.getId()); - competitorsByIdAsString.remove(competitor.getId().toString()); - weakCompetitorDTOCache.remove(competitor); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, - Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, - Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { - DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString); - if (competitor != null) { - LockUtil.lockForWrite(lock); - try { - competitor.setName(newName); - competitor.setShortName(newShortName); - competitor.setColor(newDisplayColor); - competitor.setEmail(newEmail); - competitor.setFlagImage(newFlagImageUri); - competitor.getTeam().setNationality(newNationality); - competitor.getTeam().setImage(newTeamImageUri); - competitor.setTimeOnTimeFactor(timeOnTimeFactor); - competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile); - competitor.setSearchTag(newSearchTag); - weakCompetitorDTOCache.remove(competitor); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - synchronized (competitorUpdateListeners) { - for (CompetitorUpdateListener listener : competitorUpdateListeners) { - listener.competitorUpdated(competitor); - } - } - return competitor; - } - - @Override - public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { - LockUtil.lockForRead(lock); - boolean needToUnlockReadLock = true; - try { - CompetitorWithoutBoatDTO competitorDTO = weakCompetitorDTOCache.get(c); - if (competitorDTO == null) { - LockUtil.unlockAfterRead(lock); - needToUnlockReadLock = false; - LockUtil.lockForWrite(lock); - competitorDTO = weakCompetitorDTOCache.get(c); - if (competitorDTO == null) { - final Nationality nationality = c.getTeam().getNationality(); - CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); - competitorDTO = new CompetitorWithoutBoatDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" - : countryCode.getTwoLetterISOCode(), countryCode == null ? "" - : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), - c.getId().toString(), - c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), - c.getFlagImage() == null ? null : c.getFlagImage().toString(), - c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); - weakCompetitorDTOCache.put(c, competitorDTO); - } - } - return competitorDTO; - } finally { - if (needToUnlockReadLock) { - LockUtil.unlockAfterRead(lock); - } else { - LockUtil.unlockAfterWrite(lock); - } - } - } - - @Override - public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { - return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); - } - - @Override - public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { - CompetitorWithoutBoatDTO c = convertToCompetitorWithoutBoatDTO(competitor); - BoatClassDTO boatClassDTO = null; - BoatDTO boatDTO = null; - if (boat != null) { - boatClassDTO = new BoatClassDTO(boat.getBoatClass().getName(), boat.getBoatClass().getDisplayName(), - boat.getBoatClass().getHullLength(), boat.getBoatClass().getHullBeam()); - boatDTO = new BoatDTO(boat.getId().toString(), boat.getName(), boatClassDTO, boat.getSailID(), boat.getColor()); - } - CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getTwoLetterIsoCountryCode(), - c.getThreeLetterIocCountryCode(), - c.getCountryName(), - c.getIdAsString(), - c.getImageURL(), - c.getFlagImageURL(), - boatDTO, - boatClassDTO, - c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); - - return competitorDTO; - } - - @Override - public void allowCompetitorResetToDefaults(Competitor competitor) { - LockUtil.lockForWrite(lock); - try { - competitorsToUpdateDuringGetOrCreate.add(competitor); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public void addCompetitors(Iterable competitors) { - LockUtil.lockForWrite(lock); - try { - for (Competitor competitor: competitors) { - competitorCache.put(competitor.getId(), competitor); - competitorsByIdAsString.put(competitor.getId().toString(), competitor); - } - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - /** Boat stuff starts here */ - - @Override - public void addBoatUpdateListener(BoatUpdateListener listener) { - boatUpdateListeners.add(listener); - } - - @Override - public void removeBoatUpdateListener(BoatUpdateListener listener) { - boatUpdateListeners.remove(listener); - } - - private Boat createBoat(Serializable id, String name, BoatClass boatClass, String sailID, Color color) { - Boat result = new BoatImpl(id, name, boatClass, sailID, color); - addNewBoat(result.getId(), result); - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Created boat "+name+" with ID "+id, new Exception("Here is where it happened")); - } - return result; - } - - /** - * Adds the boat to this transient boat collection so that it is available in - * {@link #getExistingBoatById(Serializable)}. Subclasses may override in case they need to take additional - * measures such as durably storing the boat. Overriding implementations must call this implementation. - */ - protected void addNewBoat(Serializable id, Boat boat) { - LockUtil.lockForWrite(lock); - try { - boatCache.put(id, boat); - boatsByIdAsString.put(id.toString(), boat); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { - // create compound boat ID here? - Boat result = getExistingBoatById(id); // avoid synchronization for successful read access - if (result == null) { - LockUtil.lockForWrite(lock); - try { - result = getExistingBoatById(id); // try again, now while holding the write lock - if (result == null) { - result = createBoat(id, name, boatClass, sailId, color); - } - } finally { - LockUtil.unlockAfterWrite(lock); - } - } else if (isBoatToUpdateDuringGetOrCreate(result)) { - updateBoat(result.getId().toString(), name, color, sailId); - boatNoLongerToUpdateDuringGetOrCreate(result); - } - return result; - } - - @Override - public Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color) { - return getOrCreateBoat(leaderboardGroup.getId(), name, boatClass, sailId, color); - } - - @Override - public Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color) { - return getOrCreateBoat(competitor.getId(), name, boatClass, sailId, color); - } - - private void boatNoLongerToUpdateDuringGetOrCreate(Boat boat) { - boatsToUpdateDuringGetOrCreate.remove(boat); - } - - @Override - public boolean isBoatToUpdateDuringGetOrCreate(Boat boat) { - return boatsToUpdateDuringGetOrCreate.contains(boat); - } - - @Override - public Boat getExistingBoatById(Serializable boatId) { - LockUtil.lockForRead(lock); - try { - return boatCache.get(boatId); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public Boat getExistingBoatByIdAsString(String boatIdAsString) { - LockUtil.lockForRead(lock); - try { - return boatsByIdAsString.get(boatIdAsString); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public int getBoatsCount() { - LockUtil.lockForRead(lock); - try { - return boatCache.size(); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public void clearBoats() { - LockUtil.lockForWrite(lock); - try { - boatCache.clear(); - boatsByIdAsString.clear(); - boatsToUpdateDuringGetOrCreate.clear(); - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Clearing boat store "+this, new Exception("here is where it happened")); - } - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Iterable getBoats() { - LockUtil.lockForRead(lock); - try { - return new ArrayList(boatCache.values()); - } finally { - LockUtil.unlockAfterRead(lock); - } - } - - @Override - public void removeBoat(Boat boat) { - LockUtil.lockForWrite(lock); - try { - logger.fine("Removing boat "+boat+" from boat store "+this); - boatCache.remove(boat.getId()); - boatsByIdAsString.remove(boat.getId().toString()); - weakBoatDTOCache.remove(boat); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - - @Override - public Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId) { - DynamicBoat boat = (DynamicBoat) getExistingBoatByIdAsString(idAsString); - if (boat != null) { - LockUtil.lockForWrite(lock); - try { - boat.setName(newName); - boat.setSailId(newSailId); - boat.setColor(newColor); - weakBoatDTOCache.remove(boat); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } - synchronized (boatUpdateListeners) { - for (BoatUpdateListener listener : boatUpdateListeners) { - listener.boatUpdated(boat); - } - } - return boat; - } - - @Override - public BoatDTO convertToBoatDTO(Boat b) { - LockUtil.lockForRead(lock); - boolean needToUnlockReadLock = true; - try { - BoatDTO boatDTO = weakBoatDTOCache.get(b); - if (boatDTO == null) { - LockUtil.unlockAfterRead(lock); - needToUnlockReadLock = false; - LockUtil.lockForWrite(lock); - boatDTO = weakBoatDTOCache.get(b); - if (boatDTO == null) { - BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), - b.getBoatClass().getDisplayName(), b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam()); - boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); - weakBoatDTOCache.put(b, boatDTO); - } - } - return boatDTO; - } finally { - if (needToUnlockReadLock) { - LockUtil.unlockAfterRead(lock); - } else { - LockUtil.unlockAfterWrite(lock); - } - } - } - - @Override - public void allowBoatResetToDefaults(Boat boat) { - LockUtil.lockForWrite(lock); - try { - boatsToUpdateDuringGetOrCreate.add(boat); - } finally { - LockUtil.unlockAfterWrite(lock); - } - } -} +package com.sap.sailing.domain.base.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.LeaderboardGroupBase; +import com.sap.sailing.domain.base.Nationality; +import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTOImpl; +import com.sap.sse.common.Color; +import com.sap.sse.common.CountryCode; +import com.sap.sse.common.Duration; +import com.sap.sse.concurrent.LockUtil; +import com.sap.sse.concurrent.NamedReentrantReadWriteLock; + +public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable { + private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName()); + private static final long serialVersionUID = -4198298775476586931L; + private final Map competitorCache; + private final Map competitorsByIdAsString; + private transient Set competitorUpdateListeners; + private final Map boatCache; + private final Map boatsByIdAsString; + private transient Set boatUpdateListeners; + + /** + * The competitors contained in this map will have their changeable properties + * {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to + * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID. + */ + private final Set competitorsToUpdateDuringGetOrCreate; + + private transient WeakHashMap weakCompetitorDTOCache; + + private final Set boatsToUpdateDuringGetOrCreate; + + private transient WeakHashMap weakBoatDTOCache; + + private final NamedReentrantReadWriteLock lock; + + public TransientCompetitorStoreImpl() { + lock = new NamedReentrantReadWriteLock("CompetitorStore", /* fair */ false); + competitorCache = new HashMap(); + competitorsByIdAsString = new HashMap(); + competitorsToUpdateDuringGetOrCreate = new HashSet(); + weakCompetitorDTOCache = new WeakHashMap(); + competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + boatCache = new HashMap(); + boatsByIdAsString = new HashMap(); + boatsToUpdateDuringGetOrCreate = new HashSet(); + weakBoatDTOCache = new WeakHashMap(); + boatUpdateListeners = Collections.synchronizedSet(new HashSet()); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + weakCompetitorDTOCache = new WeakHashMap(); + competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + weakBoatDTOCache = new WeakHashMap(); + boatUpdateListeners = Collections.synchronizedSet(new HashSet()); + } + + @Override + public void addCompetitorUpdateListener(CompetitorUpdateListener listener) { + competitorUpdateListeners.add(listener); + } + + @Override + public void removeCompetitorUpdateListener(CompetitorUpdateListener listener) { + competitorUpdateListeners.remove(listener); + } + + private Competitor createCompetitor(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, + DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + Competitor result = new CompetitorImpl(id, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + addNewCompetitor(id, result); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened")); + } + return result; + } + + /** + * Adds the competitor to this transient competitor collection so that it is available in + * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional + * measures such as durably storing the competitor. Overriding implementations must call this implementation. + */ + protected void addNewCompetitor(Serializable id, Competitor competitor) { + LockUtil.lockForWrite(lock); + try { + competitorCache.put(id, competitor); + competitorsByIdAsString.put(id.toString(), competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Competitor getOrCreateCompetitor(Serializable competitorId, String name, String shortName, Color displayColor, String email, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, + Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + Competitor result = getExistingCompetitorById(competitorId); // avoid synchronization for successful read access + if (result == null) { + LockUtil.lockForWrite(lock); + try { + result = getExistingCompetitorById(competitorId); // try again, now while holding the write lock + if (result == null) { + result = createCompetitor(competitorId, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } else if (isCompetitorToUpdateDuringGetOrCreate(result)) { + updateCompetitor(result.getId().toString(), name, shortName, displayColor, email, team.getNationality(), + team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + competitorNoLongerToUpdateDuringGetOrCreate(result); + } + return result; + } + + private void competitorNoLongerToUpdateDuringGetOrCreate(Competitor competitor) { + competitorsToUpdateDuringGetOrCreate.remove(competitor); + } + + @Override + public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { + return competitorsToUpdateDuringGetOrCreate.contains(competitor); + } + + @Override + public Competitor getExistingCompetitorById(Serializable competitorId) { + LockUtil.lockForRead(lock); + try { + return competitorCache.get(competitorId); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public Competitor getExistingCompetitorByIdAsString(String competitorIdAsString) { + LockUtil.lockForRead(lock); + try { + return competitorsByIdAsString.get(competitorIdAsString); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public int getCompetitorsCount() { + LockUtil.lockForRead(lock); + try { + return competitorCache.size(); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void clearCompetitors() { + LockUtil.lockForWrite(lock); + try { + competitorCache.clear(); + competitorsByIdAsString.clear(); + competitorsToUpdateDuringGetOrCreate.clear(); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Clearing competitor store "+this, new Exception("here is where it happened")); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Iterable getCompetitors() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(competitorCache.values()); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void removeCompetitor(Competitor competitor) { + LockUtil.lockForWrite(lock); + try { + logger.fine("removing competitor "+competitor+" from competitor store "+this); + competitorCache.remove(competitor.getId()); + competitorsByIdAsString.remove(competitor.getId().toString()); + weakCompetitorDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Competitor updateCompetitor(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { + DynamicCompetitor competitor = (DynamicCompetitor) getExistingCompetitorByIdAsString(idAsString); + if (competitor != null) { + LockUtil.lockForWrite(lock); + try { + competitor.setName(newName); + competitor.setShortName(newShortName); + competitor.setColor(newDisplayColor); + competitor.setEmail(newEmail); + competitor.setFlagImage(newFlagImageUri); + competitor.getTeam().setNationality(newNationality); + competitor.getTeam().setImage(newTeamImageUri); + competitor.setTimeOnTimeFactor(timeOnTimeFactor); + competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile); + competitor.setSearchTag(newSearchTag); + weakCompetitorDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + synchronized (competitorUpdateListeners) { + for (CompetitorUpdateListener listener : competitorUpdateListeners) { + listener.competitorUpdated(competitor); + } + } + return competitor; + } + + @Override + public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { + LockUtil.lockForRead(lock); + boolean needToUnlockReadLock = true; + try { + CompetitorWithoutBoatDTO competitorDTO = weakCompetitorDTOCache.get(c); + if (competitorDTO == null) { + LockUtil.unlockAfterRead(lock); + needToUnlockReadLock = false; + LockUtil.lockForWrite(lock); + competitorDTO = weakCompetitorDTOCache.get(c); + if (competitorDTO == null) { + final Nationality nationality = c.getTeam().getNationality(); + CountryCode countryCode = nationality == null ? null : nationality.getCountryCode(); + competitorDTO = new CompetitorWithoutBoatDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), countryCode == null ? "" + : countryCode.getTwoLetterISOCode(), countryCode == null ? "" + : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), + c.getId().toString(), + c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), + c.getFlagImage() == null ? null : c.getFlagImage().toString(), + c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); + weakCompetitorDTOCache.put(c, competitorDTO); + } + } + return competitorDTO; + } finally { + if (needToUnlockReadLock) { + LockUtil.unlockAfterRead(lock); + } else { + LockUtil.unlockAfterWrite(lock); + } + } + } + + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { + return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { + CompetitorWithoutBoatDTO c = convertToCompetitorWithoutBoatDTO(competitor); + BoatClassDTO boatClassDTO = null; + BoatDTO boatDTO = null; + if (boat != null) { + boatClassDTO = new BoatClassDTO(boat.getBoatClass().getName(), boat.getBoatClass().getDisplayName(), + boat.getBoatClass().getHullLength(), boat.getBoatClass().getHullBeam()); + boatDTO = new BoatDTO(boat.getId().toString(), boat.getName(), boatClassDTO, boat.getSailID(), boat.getColor()); + } + CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getTwoLetterIsoCountryCode(), + c.getThreeLetterIocCountryCode(), + c.getCountryName(), + c.getIdAsString(), + c.getImageURL(), + c.getFlagImageURL(), + boatDTO, + boatClassDTO, + c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); + + return competitorDTO; + } + + @Override + public void allowCompetitorResetToDefaults(Competitor competitor) { + LockUtil.lockForWrite(lock); + try { + competitorsToUpdateDuringGetOrCreate.add(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public void addCompetitors(Iterable competitors) { + LockUtil.lockForWrite(lock); + try { + for (Competitor competitor: competitors) { + competitorCache.put(competitor.getId(), competitor); + competitorsByIdAsString.put(competitor.getId().toString(), competitor); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + /** Boat stuff starts here */ + + @Override + public void addBoatUpdateListener(BoatUpdateListener listener) { + boatUpdateListeners.add(listener); + } + + @Override + public void removeBoatUpdateListener(BoatUpdateListener listener) { + boatUpdateListeners.remove(listener); + } + + private Boat createBoat(Serializable id, String name, BoatClass boatClass, String sailID, Color color) { + Boat result = new BoatImpl(id, name, boatClass, sailID, color); + addNewBoat(result.getId(), result); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Created boat "+name+" with ID "+id, new Exception("Here is where it happened")); + } + return result; + } + + /** + * Adds the boat to this transient boat collection so that it is available in + * {@link #getExistingBoatById(Serializable)}. Subclasses may override in case they need to take additional + * measures such as durably storing the boat. Overriding implementations must call this implementation. + */ + protected void addNewBoat(Serializable id, Boat boat) { + LockUtil.lockForWrite(lock); + try { + boatCache.put(id, boat); + boatsByIdAsString.put(id.toString(), boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { + // create compound boat ID here? + Boat result = getExistingBoatById(id); // avoid synchronization for successful read access + if (result == null) { + LockUtil.lockForWrite(lock); + try { + result = getExistingBoatById(id); // try again, now while holding the write lock + if (result == null) { + result = createBoat(id, name, boatClass, sailId, color); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } else if (isBoatToUpdateDuringGetOrCreate(result)) { + updateBoat(result.getId().toString(), name, color, sailId); + boatNoLongerToUpdateDuringGetOrCreate(result); + } + return result; + } + + @Override + public Boat getOrCreateBoat(LeaderboardGroupBase leaderboardGroup, String name, BoatClass boatClass, String sailId, Color color) { + return getOrCreateBoat(leaderboardGroup.getId(), name, boatClass, sailId, color); + } + + @Override + public Boat getOrCreateBoat(Competitor competitor, String name, BoatClass boatClass, String sailId, Color color) { + return getOrCreateBoat(competitor.getId(), name, boatClass, sailId, color); + } + + private void boatNoLongerToUpdateDuringGetOrCreate(Boat boat) { + boatsToUpdateDuringGetOrCreate.remove(boat); + } + + @Override + public boolean isBoatToUpdateDuringGetOrCreate(Boat boat) { + return boatsToUpdateDuringGetOrCreate.contains(boat); + } + + @Override + public Boat getExistingBoatById(Serializable boatId) { + LockUtil.lockForRead(lock); + try { + return boatCache.get(boatId); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public Boat getExistingBoatByIdAsString(String boatIdAsString) { + LockUtil.lockForRead(lock); + try { + return boatsByIdAsString.get(boatIdAsString); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public int getBoatsCount() { + LockUtil.lockForRead(lock); + try { + return boatCache.size(); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void clearBoats() { + LockUtil.lockForWrite(lock); + try { + boatCache.clear(); + boatsByIdAsString.clear(); + boatsToUpdateDuringGetOrCreate.clear(); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Clearing boat store "+this, new Exception("here is where it happened")); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Iterable getBoats() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(boatCache.values()); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void removeBoat(Boat boat) { + LockUtil.lockForWrite(lock); + try { + logger.fine("Removing boat "+boat+" from boat store "+this); + boatCache.remove(boat.getId()); + boatsByIdAsString.remove(boat.getId().toString()); + weakBoatDTOCache.remove(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId) { + DynamicBoat boat = (DynamicBoat) getExistingBoatByIdAsString(idAsString); + if (boat != null) { + LockUtil.lockForWrite(lock); + try { + boat.setName(newName); + boat.setSailId(newSailId); + boat.setColor(newColor); + weakBoatDTOCache.remove(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + synchronized (boatUpdateListeners) { + for (BoatUpdateListener listener : boatUpdateListeners) { + listener.boatUpdated(boat); + } + } + return boat; + } + + @Override + public BoatDTO convertToBoatDTO(Boat b) { + LockUtil.lockForRead(lock); + boolean needToUnlockReadLock = true; + try { + BoatDTO boatDTO = weakBoatDTOCache.get(b); + if (boatDTO == null) { + LockUtil.unlockAfterRead(lock); + needToUnlockReadLock = false; + LockUtil.lockForWrite(lock); + boatDTO = weakBoatDTOCache.get(b); + if (boatDTO == null) { + BoatClassDTO boatClassDTO = new BoatClassDTO(b.getBoatClass().getName(), + b.getBoatClass().getDisplayName(), b.getBoatClass().getHullLength(), b.getBoatClass().getHullBeam()); + boatDTO = new BoatDTO(b.getId().toString(), b.getName(), boatClassDTO, b.getSailID(), b.getColor()); + weakBoatDTOCache.put(b, boatDTO); + } + } + return boatDTO; + } finally { + if (needToUnlockReadLock) { + LockUtil.unlockAfterRead(lock); + } else { + LockUtil.unlockAfterWrite(lock); + } + } + } + + @Override + public void allowBoatResetToDefaults(Boat boat) { + LockUtil.lockForWrite(lock); + try { + boatsToUpdateDuringGetOrCreate.add(boat); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java index 8ccd78f5069..470716492a7 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/FetchTracksAndStoreLocallyTest.java @@ -1,169 +1,169 @@ -package com.sap.sailing.domain.test; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Ignore; -import org.junit.Test; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; -import com.sap.sailing.domain.tracking.RaceChangeListener; -import com.sap.sailing.domain.tracking.RaceListener; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; -import com.sap.sailing.domain.tractracadapter.ReceiverType; -import com.tractrac.model.lib.api.event.CreateModelException; -import com.tractrac.subscription.lib.api.SubscriberInitializationException; - -/** - * Receives GPS tracks from a race. One test (if not ignored) stores these tracks in the resources/ - * folder for later (fast, off-line and reproducible) use by other tests. The other tests apply - * smoothening and ensure that smoothening filters out serious outliers but doesn't alter good - * tracks that don't have outliers. - * - * @author Axel Uhl (D043530) - * - */ -@Ignore("Un-ignore when you need to fetch new tracks") -public class FetchTracksAndStoreLocallyTest extends OnlineTracTracBasedTest { - private final Map> tracks; - private TrackedRace trackedRace; - - public FetchTracksAndStoreLocallyTest() throws URISyntaxException, MalformedURLException { - tracks = new HashMap>(); - } - - /** - * Sets up a single listener so that the rather time-consuming race setup is received only once, and all - * tests in this class share a single feed execution. The listener fills in the first event received - * into {@link #firstTracked} and {@link #firstData}. All events are converted into {@link GPSFixMovingImpl} - * objects and appended to the {@link DynamicTrackedRace}s. - * @throws SubscriberInitializationException - */ - private void setUp(String regattaName, String raceId) throws MalformedURLException, IOException, InterruptedException, URISyntaxException, SubscriberInitializationException, CreateModelException { - super.setUpWithoutLaunchingController(regattaName, raceId); - final RaceChangeListener positionListener = new AbstractRaceChangeListener() { - @Override - public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) { - DynamicGPSFixTrack track = tracks.get(competitor); - if (track == null) { - track = new DynamicGPSFixMovingTrackImpl(competitor, /* millisecondsOverWhichToAverage */ 40000); - tracks.put(competitor, track); - } - track.addGPSFix((GPSFixMoving) fix); - } - }; - DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(); - trackedRegatta.addRaceListener(new RaceListener() { - @Override - public void raceAdded(TrackedRace trackedRace) { - System.out.println("Subscribing raw position listener for race "+trackedRace); - FetchTracksAndStoreLocallyTest.this.trackedRace = trackedRace; - ((DynamicTrackedRace) trackedRace).addListener(positionListener); - } - @Override - public void raceRemoved(TrackedRace trackedRace) { - } - }); - super.completeSetupLaunchingControllerAndWaitForRaceDefinition(ReceiverType.RACECOURSE, - ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); - } - - @Test - public void storeEntireKielWeek() throws InterruptedException, FileNotFoundException, IOException, URISyntaxException, SubscriberInitializationException, CreateModelException { - for (String raceId : new String[] { - "7dce540a-98e4-11e0-85be-406186cbf87c", "6659efe8-98f1-11e0-85be-406186cbf87c", - "be1dc2fe-98fb-11e0-85be-406186cbf87c", "c3ec93e4-98fc-11e0-85be-406186cbf87c", - "bb214cfc-996d-11e0-85be-406186cbf87c", "648cf310-9930-11e0-85be-406186cbf87c", - "4074674e-9933-11e0-85be-406186cbf87c", "ba251890-9933-11e0-85be-406186cbf87c", - "5b08a9ee-9933-11e0-85be-406186cbf87c", "d6e18ba8-9933-11e0-85be-406186cbf87c", - "b9962c58-9932-11e0-85be-406186cbf87c", "d287c316-9932-11e0-85be-406186cbf87c", - "774b7942-9933-11e0-85be-406186cbf87c", "06c1e6d8-9934-11e0-85be-406186cbf87c", - "9cd8ce58-9933-11e0-85be-406186cbf87c", "1e68237e-9934-11e0-85be-406186cbf87c", - "047248b0-9933-11e0-85be-406186cbf87c", "1ecdea8e-9933-11e0-85be-406186cbf87c", - "367ae104-9934-11e0-85be-406186cbf87c", "5291b3ea-9934-11e0-85be-406186cbf87c", - "46b8c1c0-99ee-11e0-85be-406186cbf87c", "d0f23cdc-99ed-11e0-85be-406186cbf87c", - "65f5ea4a-99ee-11e0-85be-406186cbf87c", "a7405cce-99ee-11e0-85be-406186cbf87c", - "f5f531ec-99ed-11e0-85be-406186cbf87c", "bfe5f5cc-99ee-11e0-85be-406186cbf87c", - "7a4e6206-99ee-11e0-85be-406186cbf87c", "92abc794-99ee-11e0-85be-406186cbf87c", - "e9557aea-99ee-11e0-85be-406186cbf87c", "d5924a4c-99ee-11e0-85be-406186cbf87c", - "eaca658e-9a39-11e0-85be-406186cbf87c", "413b43f8-9a8e-11e0-85be-406186cbf87c", - "b3f37dee-9a8d-11e0-85be-406186cbf87c", "ca9e510e-9a8d-11e0-85be-406186cbf87c", - "0d21dc62-9a8e-11e0-85be-406186cbf87c", "2be15c2c-9a8e-11e0-85be-406186cbf87c", - "5b71b374-9a8e-11e0-85be-406186cbf87c", "a0679eda-9a8e-11e0-85be-406186cbf87c", - "7837359c-9a8e-11e0-85be-406186cbf87c", "8dc9feee-9a8e-11e0-85be-406186cbf87c", - "9690d0ee-9b69-11e0-85be-406186cbf87c", "77db2f88-9b7c-11e0-85be-406186cbf87c", - "65f746fa-9b7f-11e0-85be-406186cbf87c", "7d52a25e-9b7f-11e0-85be-406186cbf87c", - "962d13fe-9b7f-11e0-85be-406186cbf87c", "2aca1908-9c34-11e0-85be-406186cbf87c", - "8981ee52-9b7c-11e0-85be-406186cbf87c", "70acfbe2-9b81-11e0-85be-406186cbf87c", - "85c505d8-9b81-11e0-85be-406186cbf87c", "ffd33b76-9b7f-11e0-85be-406186cbf87c", - "2036421a-9a8f-11e0-85be-406186cbf87c", "2b0d3990-9b80-11e0-85be-406186cbf87c", - "49a95a00-9b80-11e0-85be-406186cbf87c", "9d686a32-9c48-11e0-85be-406186cbf87c", - "b0f20cf2-9c48-11e0-85be-406186cbf87c", "c489a63a-9c48-11e0-85be-406186cbf87c", - "d591d808-9c48-11e0-85be-406186cbf87c", "07a91aca-9cdc-11e0-85be-406186cbf87c", - "c5053bba-9c98-11e0-85be-406186cbf87c", "be3e0862-9d14-11e0-85be-406186cbf87c", - "357c700a-9d9a-11e0-85be-406186cbf87c", "71c9c288-9d9f-11e0-85be-406186cbf87c", - "5e11c318-9d76-11e0-85be-406186cbf87c", "16edbf04-9d77-11e0-85be-406186cbf87c", - "78991504-9da5-11e0-85be-406186cbf87c", "e876c3a0-9da8-11e0-85be-406186cbf87c", - "7b8423e4-9d91-11e0-85be-406186cbf87c", "b3e9082e-9d11-11e0-85be-406186cbf87c", - "fe8d9dc6-9dda-11e0-85be-406186cbf87c", "56a61922-9da7-11e0-85be-406186cbf87c", - "bf0f3188-9db1-11e0-85be-406186cbf87c", "68f793e6-9d91-11e0-85be-406186cbf87c", - "7c666e50-9dde-11e0-85be-406186cbf87c", "88152c2e-9ddd-11e0-85be-406186cbf87c", - "92d1755e-9dde-11e0-85be-406186cbf87c", "97eaedaa-9ddd-11e0-85be-406186cbf87c", - "a7893608-9dde-11e0-85be-406186cbf87c", "c31b099c-9ddd-11e0-85be-406186cbf87c", - "ee09d080-9e59-11e0-85be-406186cbf87c", "081307ee-9e5a-11e0-85be-406186cbf87c", - "20382b9c-9e5a-11e0-85be-406186cbf87c", "eb4ef344-9e67-11e0-85be-406186cbf87c", - "f54d922c-9ddd-11e0-85be-406186cbf87c", "04687b2a-9e68-11e0-85be-406186cbf87c", - "dffb64de-9e6a-11e0-85be-406186cbf87c", "797f28de-9e8e-11e0-85be-406186cbf87c", - "af33e03c-9e93-11e0-85be-406186cbf87c", "cb043bb4-9e92-11e0-85be-406186cbf87c", - "10a4757c-9e92-11e0-85be-406186cbf87c", "de822656-9e92-11e0-85be-406186cbf87c", - "c071401a-9e93-11e0-85be-406186cbf87c", "36ed21ca-9e92-11e0-85be-406186cbf87c", - "33851320-9e93-11e0-85be-406186cbf87c", "d9fd357a-9e93-11e0-85be-406186cbf87c", - "496a5458-9e92-11e0-85be-406186cbf87c", "a75dca04-9f55-11e0-85be-406186cbf87c", - "c9b627b4-9f54-11e0-85be-406186cbf87c", "829bd366-9f53-11e0-85be-406186cbf87c", - "bc78290c-9f55-11e0-85be-406186cbf87c", "d62d4288-9f55-11e0-85be-406186cbf87c", - "972c4d74-9f53-11e0-85be-406186cbf87c", "c3ab8bcc-a17d-11e0-aeec-406186cbf87c" }) { - System.out.println("Loading and storing race "+raceId); - storeRace("event_20110609_KielerWoch", raceId); - } - } - - @Ignore - public void store505Race2() throws InterruptedException, FileNotFoundException, IOException, URISyntaxException, SubscriberInitializationException, CreateModelException { - storeRace("event_20110609_KielerWoch", "357c700a-9d9a-11e0-85be-406186cbf87c"); - } - - private void storeRace(String regattaName, String raceId) throws MalformedURLException, IOException, InterruptedException, - URISyntaxException, FileNotFoundException, SubscriberInitializationException, CreateModelException { - setUp(regattaName, raceId); - storeTracks(); - } - - public static void main(String[] args) throws URISyntaxException, FileNotFoundException, IOException, InterruptedException, SubscriberInitializationException, CreateModelException { - FetchTracksAndStoreLocallyTest thiz = new FetchTracksAndStoreLocallyTest(); - for (int i=1; i> competitorAndTrack : tracks.entrySet()) { - Competitor competitor = competitorAndTrack.getKey(); - Boat boatOfCompetitor = trackedRace.getRace().getBoatOfCompetitorById(competitor); - DynamicGPSFixTrack track = competitorAndTrack.getValue(); - storeTrack(competitor, boatOfCompetitor, track, getTracTracEvent().getName()+"-"+trackedRace.getRace().getName()); - } - } - -} +package com.sap.sailing.domain.test; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Ignore; +import org.junit.Test; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.RaceChangeListener; +import com.sap.sailing.domain.tracking.RaceListener; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; +import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; +import com.sap.sailing.domain.tractracadapter.ReceiverType; +import com.tractrac.model.lib.api.event.CreateModelException; +import com.tractrac.subscription.lib.api.SubscriberInitializationException; + +/** + * Receives GPS tracks from a race. One test (if not ignored) stores these tracks in the resources/ + * folder for later (fast, off-line and reproducible) use by other tests. The other tests apply + * smoothening and ensure that smoothening filters out serious outliers but doesn't alter good + * tracks that don't have outliers. + * + * @author Axel Uhl (D043530) + * + */ +@Ignore("Un-ignore when you need to fetch new tracks") +public class FetchTracksAndStoreLocallyTest extends OnlineTracTracBasedTest { + private final Map> tracks; + private TrackedRace trackedRace; + + public FetchTracksAndStoreLocallyTest() throws URISyntaxException, MalformedURLException { + tracks = new HashMap>(); + } + + /** + * Sets up a single listener so that the rather time-consuming race setup is received only once, and all + * tests in this class share a single feed execution. The listener fills in the first event received + * into {@link #firstTracked} and {@link #firstData}. All events are converted into {@link GPSFixMovingImpl} + * objects and appended to the {@link DynamicTrackedRace}s. + * @throws SubscriberInitializationException + */ + private void setUp(String regattaName, String raceId) throws MalformedURLException, IOException, InterruptedException, URISyntaxException, SubscriberInitializationException, CreateModelException { + super.setUpWithoutLaunchingController(regattaName, raceId); + final RaceChangeListener positionListener = new AbstractRaceChangeListener() { + @Override + public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) { + DynamicGPSFixTrack track = tracks.get(competitor); + if (track == null) { + track = new DynamicGPSFixMovingTrackImpl(competitor, /* millisecondsOverWhichToAverage */ 40000); + tracks.put(competitor, track); + } + track.addGPSFix((GPSFixMoving) fix); + } + }; + DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(); + trackedRegatta.addRaceListener(new RaceListener() { + @Override + public void raceAdded(TrackedRace trackedRace) { + System.out.println("Subscribing raw position listener for race "+trackedRace); + FetchTracksAndStoreLocallyTest.this.trackedRace = trackedRace; + ((DynamicTrackedRace) trackedRace).addListener(positionListener); + } + @Override + public void raceRemoved(TrackedRace trackedRace) { + } + }); + super.completeSetupLaunchingControllerAndWaitForRaceDefinition(ReceiverType.RACECOURSE, + ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); + } + + @Test + public void storeEntireKielWeek() throws InterruptedException, FileNotFoundException, IOException, URISyntaxException, SubscriberInitializationException, CreateModelException { + for (String raceId : new String[] { + "7dce540a-98e4-11e0-85be-406186cbf87c", "6659efe8-98f1-11e0-85be-406186cbf87c", + "be1dc2fe-98fb-11e0-85be-406186cbf87c", "c3ec93e4-98fc-11e0-85be-406186cbf87c", + "bb214cfc-996d-11e0-85be-406186cbf87c", "648cf310-9930-11e0-85be-406186cbf87c", + "4074674e-9933-11e0-85be-406186cbf87c", "ba251890-9933-11e0-85be-406186cbf87c", + "5b08a9ee-9933-11e0-85be-406186cbf87c", "d6e18ba8-9933-11e0-85be-406186cbf87c", + "b9962c58-9932-11e0-85be-406186cbf87c", "d287c316-9932-11e0-85be-406186cbf87c", + "774b7942-9933-11e0-85be-406186cbf87c", "06c1e6d8-9934-11e0-85be-406186cbf87c", + "9cd8ce58-9933-11e0-85be-406186cbf87c", "1e68237e-9934-11e0-85be-406186cbf87c", + "047248b0-9933-11e0-85be-406186cbf87c", "1ecdea8e-9933-11e0-85be-406186cbf87c", + "367ae104-9934-11e0-85be-406186cbf87c", "5291b3ea-9934-11e0-85be-406186cbf87c", + "46b8c1c0-99ee-11e0-85be-406186cbf87c", "d0f23cdc-99ed-11e0-85be-406186cbf87c", + "65f5ea4a-99ee-11e0-85be-406186cbf87c", "a7405cce-99ee-11e0-85be-406186cbf87c", + "f5f531ec-99ed-11e0-85be-406186cbf87c", "bfe5f5cc-99ee-11e0-85be-406186cbf87c", + "7a4e6206-99ee-11e0-85be-406186cbf87c", "92abc794-99ee-11e0-85be-406186cbf87c", + "e9557aea-99ee-11e0-85be-406186cbf87c", "d5924a4c-99ee-11e0-85be-406186cbf87c", + "eaca658e-9a39-11e0-85be-406186cbf87c", "413b43f8-9a8e-11e0-85be-406186cbf87c", + "b3f37dee-9a8d-11e0-85be-406186cbf87c", "ca9e510e-9a8d-11e0-85be-406186cbf87c", + "0d21dc62-9a8e-11e0-85be-406186cbf87c", "2be15c2c-9a8e-11e0-85be-406186cbf87c", + "5b71b374-9a8e-11e0-85be-406186cbf87c", "a0679eda-9a8e-11e0-85be-406186cbf87c", + "7837359c-9a8e-11e0-85be-406186cbf87c", "8dc9feee-9a8e-11e0-85be-406186cbf87c", + "9690d0ee-9b69-11e0-85be-406186cbf87c", "77db2f88-9b7c-11e0-85be-406186cbf87c", + "65f746fa-9b7f-11e0-85be-406186cbf87c", "7d52a25e-9b7f-11e0-85be-406186cbf87c", + "962d13fe-9b7f-11e0-85be-406186cbf87c", "2aca1908-9c34-11e0-85be-406186cbf87c", + "8981ee52-9b7c-11e0-85be-406186cbf87c", "70acfbe2-9b81-11e0-85be-406186cbf87c", + "85c505d8-9b81-11e0-85be-406186cbf87c", "ffd33b76-9b7f-11e0-85be-406186cbf87c", + "2036421a-9a8f-11e0-85be-406186cbf87c", "2b0d3990-9b80-11e0-85be-406186cbf87c", + "49a95a00-9b80-11e0-85be-406186cbf87c", "9d686a32-9c48-11e0-85be-406186cbf87c", + "b0f20cf2-9c48-11e0-85be-406186cbf87c", "c489a63a-9c48-11e0-85be-406186cbf87c", + "d591d808-9c48-11e0-85be-406186cbf87c", "07a91aca-9cdc-11e0-85be-406186cbf87c", + "c5053bba-9c98-11e0-85be-406186cbf87c", "be3e0862-9d14-11e0-85be-406186cbf87c", + "357c700a-9d9a-11e0-85be-406186cbf87c", "71c9c288-9d9f-11e0-85be-406186cbf87c", + "5e11c318-9d76-11e0-85be-406186cbf87c", "16edbf04-9d77-11e0-85be-406186cbf87c", + "78991504-9da5-11e0-85be-406186cbf87c", "e876c3a0-9da8-11e0-85be-406186cbf87c", + "7b8423e4-9d91-11e0-85be-406186cbf87c", "b3e9082e-9d11-11e0-85be-406186cbf87c", + "fe8d9dc6-9dda-11e0-85be-406186cbf87c", "56a61922-9da7-11e0-85be-406186cbf87c", + "bf0f3188-9db1-11e0-85be-406186cbf87c", "68f793e6-9d91-11e0-85be-406186cbf87c", + "7c666e50-9dde-11e0-85be-406186cbf87c", "88152c2e-9ddd-11e0-85be-406186cbf87c", + "92d1755e-9dde-11e0-85be-406186cbf87c", "97eaedaa-9ddd-11e0-85be-406186cbf87c", + "a7893608-9dde-11e0-85be-406186cbf87c", "c31b099c-9ddd-11e0-85be-406186cbf87c", + "ee09d080-9e59-11e0-85be-406186cbf87c", "081307ee-9e5a-11e0-85be-406186cbf87c", + "20382b9c-9e5a-11e0-85be-406186cbf87c", "eb4ef344-9e67-11e0-85be-406186cbf87c", + "f54d922c-9ddd-11e0-85be-406186cbf87c", "04687b2a-9e68-11e0-85be-406186cbf87c", + "dffb64de-9e6a-11e0-85be-406186cbf87c", "797f28de-9e8e-11e0-85be-406186cbf87c", + "af33e03c-9e93-11e0-85be-406186cbf87c", "cb043bb4-9e92-11e0-85be-406186cbf87c", + "10a4757c-9e92-11e0-85be-406186cbf87c", "de822656-9e92-11e0-85be-406186cbf87c", + "c071401a-9e93-11e0-85be-406186cbf87c", "36ed21ca-9e92-11e0-85be-406186cbf87c", + "33851320-9e93-11e0-85be-406186cbf87c", "d9fd357a-9e93-11e0-85be-406186cbf87c", + "496a5458-9e92-11e0-85be-406186cbf87c", "a75dca04-9f55-11e0-85be-406186cbf87c", + "c9b627b4-9f54-11e0-85be-406186cbf87c", "829bd366-9f53-11e0-85be-406186cbf87c", + "bc78290c-9f55-11e0-85be-406186cbf87c", "d62d4288-9f55-11e0-85be-406186cbf87c", + "972c4d74-9f53-11e0-85be-406186cbf87c", "c3ab8bcc-a17d-11e0-aeec-406186cbf87c" }) { + System.out.println("Loading and storing race "+raceId); + storeRace("event_20110609_KielerWoch", raceId); + } + } + + @Ignore + public void store505Race2() throws InterruptedException, FileNotFoundException, IOException, URISyntaxException, SubscriberInitializationException, CreateModelException { + storeRace("event_20110609_KielerWoch", "357c700a-9d9a-11e0-85be-406186cbf87c"); + } + + private void storeRace(String regattaName, String raceId) throws MalformedURLException, IOException, InterruptedException, + URISyntaxException, FileNotFoundException, SubscriberInitializationException, CreateModelException { + setUp(regattaName, raceId); + storeTracks(); + } + + public static void main(String[] args) throws URISyntaxException, FileNotFoundException, IOException, InterruptedException, SubscriberInitializationException, CreateModelException { + FetchTracksAndStoreLocallyTest thiz = new FetchTracksAndStoreLocallyTest(); + for (int i=1; i> competitorAndTrack : tracks.entrySet()) { + Competitor competitor = competitorAndTrack.getKey(); + Boat boatOfCompetitor = trackedRace.getRace().getBoatOfCompetitorById(competitor); + DynamicGPSFixTrack track = competitorAndTrack.getValue(); + storeTrack(competitor, boatOfCompetitor, track, getTracTracEvent().getName()+"-"+trackedRace.getRace().getName()); + } + } + +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index ca505a6a1ba..dd54f5bf134 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -1,1299 +1,1299 @@ -package com.sap.sailing.domain.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.lang.reflect.Field; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.NavigableSet; -import java.util.Set; -import java.util.SortedSet; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.common.AbstractBearing; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.impl.DegreeBearingImpl; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.KnotSpeedImpl; -import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.MeterDistance; -import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedWithDegreeBearingImpl; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl; -import com.sap.sailing.domain.common.tracking.impl.CompactionNotPossibleException; -import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; -import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.impl.DistanceCache; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; -import com.sap.sailing.domain.tracking.impl.GPSFixTrackImpl; -import com.sap.sailing.domain.tracking.impl.MaxSpeedCache; -import com.sap.sailing.domain.tracking.impl.TrackImpl; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.TimeRange; -import com.sap.sse.common.Timed; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class TrackTest { - private static final int MILLIS_BETWEEN_FIXES = 3000000; - private DynamicGPSFixTrack track; - private GPSFixMovingImpl gpsFix1; - private GPSFixMovingImpl gpsFix2; - private GPSFixMovingImpl gpsFix3; - private GPSFixMovingImpl gpsFix4; - private GPSFixMovingImpl gpsFix5; - - @Before - public void setUp() throws InterruptedException { - track = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); - TimePoint now1 = MillisecondsTimePoint.now(); - TimePoint now2 = addMillisToTimepoint(now1, MILLIS_BETWEEN_FIXES); - DegreePosition position1 = new DegreePosition(1, 2); - DegreePosition position2 = new DegreePosition(1, 3); - gpsFix1 = new GPSFixMovingImpl( - position1, now1, new KnotSpeedWithBearingImpl(position1.getDistance(position2) - .inTime(now2.asMillis() - now1.asMillis()).getKnots(), - new DegreeBearingImpl(90))); - gpsFix2 = new GPSFixMovingImpl(position2, now2, new KnotSpeedWithBearingImpl(position1.getDistance(position2) - .inTime(now2.asMillis() - gpsFix1.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(90))); - TimePoint now3 = addMillisToTimepoint(now2, MILLIS_BETWEEN_FIXES); - Position position3 = new DegreePosition(1, 4); - gpsFix3 = new GPSFixMovingImpl( - position3, now3, new KnotSpeedWithBearingImpl(position2.getDistance(position3) - .inTime(now3.asMillis() - gpsFix2.getTimePoint().asMillis()).getKnots(), - new DegreeBearingImpl(0))); - TimePoint now4 = addMillisToTimepoint(now3, MILLIS_BETWEEN_FIXES); - Position position4 = new DegreePosition(3, 4); - gpsFix4 = new GPSFixMovingImpl( - position4, now4, new KnotSpeedWithBearingImpl(position3.getDistance(position4) - .inTime(now4.asMillis() - gpsFix3.getTimePoint().asMillis()).getKnots(), - new DegreeBearingImpl(0))); - TimePoint now5 = addMillisToTimepoint(now4, MILLIS_BETWEEN_FIXES); - Position position5 = new DegreePosition(5, 4); - gpsFix5 = new GPSFixMovingImpl(position5, now5, new KnotSpeedWithBearingImpl(position4.getDistance(position5) - .inTime(now5.asMillis() - gpsFix4.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(0))); - track.addGPSFix(gpsFix1); - track.addGPSFix(gpsFix2); - track.addGPSFix(gpsFix3); - track.addGPSFix(gpsFix4); - track.addGPSFix(gpsFix5); - } - - /** - * Tests for a incorrect method of estimating Positions - */ - @Test - public void positionEstimationTest() { - track = new DynamicGPSFixMovingTrackImpl( - new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", true), null), 5000, null); - DegreePosition p1 = new DegreePosition(0, 0); - DegreePosition p2 = new DegreePosition(90, 0); - TimePoint t1 = MillisecondsTimePoint.now(); - TimePoint t2 = t1.plus(30); - gpsFix1 = new GPSFixMovingImpl(p1, t1, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); - gpsFix2 = new GPSFixMovingImpl(p2, t2, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); - track.addGPSFix(gpsFix1); - track.addGPSFix(gpsFix2); - track.lockForRead(); - try { - assertEquals(0, track.getEstimatedPosition(t1, true).getLatDeg(), 0.00000001); - assertEquals(30, track.getEstimatedPosition(t1.plus(10), true).getLatDeg(), 0.00000001); - assertEquals(45, track.getEstimatedPosition(t1.plus(15), true).getLatDeg(), 0.00000001); - assertEquals(60, track.getEstimatedPosition(t1.plus(20), true).getLatDeg(), 0.00000001); - assertEquals(90, track.getEstimatedPosition(t1.plus(30), true).getLatDeg(), 0.00000001); - } finally { - track.unlockAfterRead(); - } - } - /** - * Introducing a new feature on {@link GPSFixTrack} that allows clients to find positions to a sequence of - * {@link Timed} objects in ascending order, this method compares those results to the ordinary explicit calls - * to {@link GPSFixTrack#getEstimatedPosition(TimePoint, boolean)}. - */ - @SuppressWarnings("serial") - @Test - public void testGetEstimatedPositionSingleVsIteratedWithSmallerSteps() { - TimePoint start = gpsFix1.getTimePoint().minus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); - TimePoint end = gpsFix5.getTimePoint().plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); - List timeds = new ArrayList<>(); - for (TimePoint t = start; !t.after(end); t = t.plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/10)) { - final TimePoint finalT = t; - timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }}); - } - assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true); - assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false); - } - - @SuppressWarnings("serial") - @Test - public void testGetEstimatedPositionSingleVsIteratedWithLargerSteps() { - TimePoint start = gpsFix1.getTimePoint().minus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); - TimePoint end = gpsFix5.getTimePoint().plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); - List timeds = new ArrayList<>(); - for (TimePoint t = start; !t.after(end); t = t.plus(gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())) { - final TimePoint finalT = t; - timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }}); - } - assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true); - assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false); - } - - private void assertEqualEstimatedPositionsSingleVsIterated(List timeds, boolean extrapolate) { - List positions1 = new ArrayList<>(); - for (Timed timed : timeds) { - positions1.add(track.getEstimatedPosition(timed.getTimePoint(), extrapolate)); - } - List positions2 = new ArrayList<>(); - track.lockForRead(); - try { - for (Iterator pIter = track.getEstimatedPositions(timeds, extrapolate); pIter.hasNext();) { - positions2.add(pIter.next()); - } - } finally { - track.unlockAfterRead(); - } - Iterator p1Iter = positions1.iterator(); - Iterator p2Iter = positions2.iterator(); - while (p1Iter.hasNext()) { - assertTrue(p2Iter.hasNext()); - Position p1 = p1Iter.next(); - Position p2 = p2Iter.next(); - assertEquals("Diff between "+p1+" and "+p2, p1.getLatDeg(), p2.getLatDeg(), 0.000000001); - assertEquals("Diff between "+p1+" and "+p2, p1.getLngDeg(), p2.getLngDeg(), 0.000000001); - } - } - - /** - * A test regarding bug 968. Three subsequent fixes at the same position with increasing time stamps each, then - * jumping to the next position for three seconds. Let's see what distance and SOG do... - *

- * - * TODO bug 1504 The challenge with this is that the equal fixes all have a wrong speed value compared to at least - * one of their neighbors. They are hence all considered outliers, and no fix remains. There is however a possible - * sub-sequence of fixes that constitutes a sequence of all-valid fixes when only valid fixes are checked for - * validity with their valid neighbors. But this, at first glance, sounds like an ugly NP-complete problem: find the - * longest possible sub-sequence such that all fixes in the sub-sequence are valid w.r.t. their neighbors. - */ - @Test - public void testJumpyFixes() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(new Object(), - /* millisecondsOverWhichToAverage */ 30000l); - TimePoint start = MillisecondsTimePoint.now(); - TimePoint now = start; - final DegreePosition startPos = new DegreePosition(0, 0); - Position pos = startPos; - SpeedWithBearing speed = new KnotSpeedWithBearingImpl(40, new DegreeBearingImpl(90)); - int NUMBER_OF_FIXES_AT_SAME_POSITION = 3; - int NUMBER_OF_REAL_FIXES = 10; - for (int i = 0; i < NUMBER_OF_REAL_FIXES; i++) { - addFixesWithSamePositionButProgressingTime(track, now, pos, speed, NUMBER_OF_FIXES_AT_SAME_POSITION); - track.getDistanceTraveled(start, now); // cause DistanceCache to cache a result - TimePoint nextNow = now.plus(NUMBER_OF_FIXES_AT_SAME_POSITION * 1000); - pos = pos.translateGreatCircle(speed.getBearing(), speed.travel(now, nextNow)); - now = nextNow; - } - assertEquals(speed.travel(start, now.minus(NUMBER_OF_FIXES_AT_SAME_POSITION * 1000)).getMeters(), - track.getDistanceTraveled(start, now).getMeters(), 0.01); - } - - private void addFixesWithSamePositionButProgressingTime(DynamicGPSFixTrack track, - TimePoint start, Position pos, SpeedWithBearing speed, int numberOfFixes) { - TimePoint now = start; - for (int i = 0; i < numberOfFixes; i++) { - GPSFixMoving fix1 = new GPSFixMovingImpl(pos, now, speed); - track.addGPSFix(fix1); - now = now.plus(1000); - } - } - - /** - * See bug 2626; this test tries to provoke a race condition by subclassing {@link MaxSpeedCache} and overriding - * {@link MaxSpeedCache#cache} so that it can synchronize fix additions to the track with a - * {@link MaxSpeedCache#getMaxSpeed(TimePoint, TimePoint)} call to the cache. - */ - @Test - public void testMaxSpeedCacheRaceCondition() throws InterruptedException, BrokenBarrierException, TimeoutException { - final CyclicBarrier cacheBarrier = new CyclicBarrier(2); - final CyclicBarrier cacheDone = new CyclicBarrier(2); - - DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { - private static final long serialVersionUID = 1L; - - @Override - protected MaxSpeedCache createMaxSpeedCache() { - return new MaxSpeedCache(this) { - private static final long serialVersionUID = 1L; - - @Override - protected Pair computeMaxSpeed(TimePoint from, TimePoint to) { - Pair result = super.computeMaxSpeed(from, to); - try { - Thread.sleep(1000); // just wait a bit; can't lock really because that would cause a deadlock - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - return result; - } - - @Override - protected void cache(TimePoint from, TimePoint to, Pair fixAtMaxSpeed) { - try { - cacheBarrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); - } - super.cache(from, to, fixAtMaxSpeed); - try { - cacheDone.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); - } - } - }; - } - }; - GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix1); - // The following getMaximumSpeedOverGround call will trigger a computeMaxSpeed(...) and a cache(...) call - new Thread(()-> - assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). - getB().getKnots(), 0.001)).start(); // produces a cache entry that ends - // now don't release the cacheBarrier as yet but add more fixes - new Thread(() -> { - GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), - new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(123))); - track.addGPSFix(fix2); - }).start(); - new Thread(() -> { - GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), - new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); - track.addGPSFix(fix3); - }).start(); - new Thread(() -> { - GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), - new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); - track.addGPSFix(fix4); - }).start(); - cacheBarrier.await(); // releasing the creation of the cache entry from way above; this would now add a stale entry - // that would have been invalidated by all the GPS fixes above - cacheDone.await(); // wait for the caching to have completed - final double maxSpeed[] = new double[1]; - final CyclicBarrier testDone = new CyclicBarrier(2); - new Thread(() -> { - maxSpeed[0] = track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). - getB().getKnots(); - try { - testDone.await(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }).start(); - cacheBarrier.await(20, TimeUnit.SECONDS); - cacheDone.await(20, TimeUnit.SECONDS); - testDone.await(); - assertEquals(2., maxSpeed[0], 0.1); - } - - @Test - public void testMaxSpeedForNonMovingTrackWithUpperTimeLimit() { - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - GPSFix fix1 = new GPSFixImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0)); - track.addGPSFix(fix1); - GPSFix fix2 = new GPSFixImpl(new DegreePosition(1./60., 0), new MillisecondsTimePoint(3600000)); // 1nm in one hour = 1kt - track.addGPSFix(fix2); - GPSFix fix3 = new GPSFixImpl(new DegreePosition(3./60., 0), new MillisecondsTimePoint(7200000)); // 2nm in one hour = 2kts - track.addGPSFix(fix3); - GPSFix fix4 = new GPSFixImpl(new DegreePosition(4./60., 0), new MillisecondsTimePoint(10800000)); // 1nm in one hour = 1kt - track.addGPSFix(fix4); - assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(3600000)). - getB().getKnots(), 0.001); - } - - @Test - public void testMaxSpeedForNonMovingTrack() { - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - GPSFix fix1 = new GPSFixImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0)); - track.addGPSFix(fix1); - GPSFix fix2 = new GPSFixImpl(new DegreePosition(1./60., 0), new MillisecondsTimePoint(3600000)); // 1nm in one hour = 1kt - track.addGPSFix(fix2); - GPSFix fix3 = new GPSFixImpl(new DegreePosition(3./60., 0), new MillisecondsTimePoint(7200000)); // 2nm in one hour = 2kts - track.addGPSFix(fix3); - GPSFix fix4 = new GPSFixImpl(new DegreePosition(4./60., 0), new MillisecondsTimePoint(10800000)); // 1nm in one hour = 1kt - track.addGPSFix(fix4); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). - getB().getKnots(), 0.001); - } - - @Test - public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundary() { - DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix1); - GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); - track.addGPSFix(fix2); - GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix3); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). - getB().getKnots(), 0.01); // produces a cache entry that ends - GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix4); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). - getB().getKnots(), 0.01); - } - - @Test - public void testMaxSpeedForFixOverwrittenWithLowerSpeed() { - DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - GPSFixMoving slow = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - GPSFixMoving fast = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); - track.addGPSFix(fast); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). - getB().getKnots(), 0.01); - track.addGPSFix(slow); - track.lockForRead(); - try { - assertEquals(1, track.getFixes().size()); - } finally { - track.unlockAfterRead(); - } - assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). - getB().getKnots(), 0.01); - } - - @Test - public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundaryAfterQuery() { - DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix1); - GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( - 2, new DegreeBearingImpl(123))); - track.addGPSFix(fix2); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). - getB().getKnots(), 0.01); // produces a cache entry that ends - GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix3); - GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( - 1, new DegreeBearingImpl(123))); - track.addGPSFix(fix4); - assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). - getB().getKnots(), 0.01); - } - - /** - * The DistanceCache must not contain any intervals pointing backwards because otherwise an endless recursion will - * result during the next cache look-up. This test performs a {@link GPSFixTrack#getDistanceTraveled(TimePoint, TimePoint)} with - * from later than to and ensures that no reversed entry is written to the cache. - */ - @Test - public void testDistanceTraveledBackwardsQuery() { - final Set> cacheEntries = new HashSet<>(); - final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { - @Override - public void cache(TimePoint from, TimePoint to, Distance distance) { - super.cache(from, to, distance); - cacheEntries.add(new com.sap.sse.common.Util.Triple<>(from, to, distance)); - } - - }; - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { - private static final long serialVersionUID = -7277196393160609503L; - @Override - protected DistanceCache getDistanceCache() { - return distanceCache; - } - }; - TimePoint now = MillisecondsTimePoint.now(); - TimePoint earlier = now.minus(10000); - TimePoint later = now.plus(10000); - Distance result = track.getDistanceTraveled(now, earlier); - assertEquals(Distance.NULL, result); - assertTrue(cacheEntries.isEmpty()); - Distance nextResult = track.getDistanceTraveled(now, later); - assertEquals(Distance.NULL, nextResult); - } - - @Test - public void testBearingAveragingAcrossZeroDegrees() { - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFix f1 = new GPSFixImpl(new DegreePosition(0, 0), t1); - GPSFix f2 = new GPSFixImpl(new DegreePosition(0.00001, 0.00001), t2); - GPSFix f3 = new GPSFixImpl(new DegreePosition(0.00002, 0), t3); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - SpeedWithBearing average = track.getEstimatedSpeed(t2); - PositionAssert.assertBearingEquals(new DegreeBearingImpl(0), average.getBearing(), 0.1); - } - - @Test - public void testFixValidEvenIfFixProvidedSpeedIsOutrageous() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - PositionAssert.assertGPSFixEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored - } - - @Test - public void testFixInvalidEvenIfPositionInferredSpeedIsOutrageous() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(150./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - PositionAssert.assertGPSFixEquals(f3, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored - } - - @Test - public void testFixInvalidBecauseProvidedSpeedIsTooDifferent() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - // expect the f2 fix to be invalid because provided speed is too different - assertEquals(0, f3.getPosition().getDistance(track.getFirstFixAtOrAfter(f2.getTimePoint()).getPosition()).getMeters(), 0.01); - } - - @Test - public void testIgnoringFixProvidedSpeedIfItIsOutrageous() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - PositionAssert.assertGPSFixEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored - SpeedWithBearing average = track.getEstimatedSpeed(t2); - assertEquals(1, average.getKnots(), 0.01); - } - - @Test - public void testBearingAveragingAcrossZeroDegreesWithGPSFixMoving() { - DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000); - TimePoint t1 = new MillisecondsTimePoint(1000); - TimePoint t2 = new MillisecondsTimePoint(2000); - TimePoint t3 = new MillisecondsTimePoint(3000); - GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(0, 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(45))); - GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(0.00001, 0.00001), t2, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); - GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(0.00002, 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(315))); - track.addGPSFix(f1); - track.addGPSFix(f2); - track.addGPSFix(f3); - SpeedWithBearing average = track.getRawEstimatedSpeed(t2); - PositionAssert.assertBearingEquals(new DegreeBearingImpl(0), average.getBearing(), /* deg delta */ 0.1); - } - - /** - * Bug #70: modify a track while iterating over a subset of it; ensure that this causes a - * {@link ConcurrentModificationException}. - */ - @Test - public void testAddingWhileIteratingOverSubset() throws InterruptedException, IllegalArgumentException, - IllegalAccessException, SecurityException, NoSuchFieldException { - Field fixesField = TrackImpl.class.getDeclaredField("fixes"); - fixesField.setAccessible(true); - @SuppressWarnings("unchecked") - NavigableSet fixes = (NavigableSet) fixesField.get(track); - SortedSet subset = fixes.subSet(gpsFix2, gpsFix5); - assertEquals(3, subset.size()); - Iterator subsetIter = subset.iterator(); - // start iteration - GPSFixMoving firstOfSubset = subsetIter.next(); - PositionAssert.assertGPSFixEquals(gpsFix2, firstOfSubset, /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); - // now add a fix: - TimePoint now6 = addMillisToTimepoint(gpsFix5.getTimePoint(), 3); - track.addGPSFix(new GPSFixMovingImpl( - new DegreePosition(6, 5), now6, new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)))); - try { - GPSFixMoving secondOfSubset = subsetIter.next(); - PositionAssert.assertGPSFixEquals(gpsFix3, secondOfSubset, /* pos deg delta */ 0.000001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); - fail("adding a fix interferes with iteration over subSet of track's fixes"); - } catch (ConcurrentModificationException e) { - // this is what we expected - } - } - - private TimePoint addMillisToTimepoint(TimePoint p, long millis) { - return p.plus(millis); - } - - @Test - public void testIterate() { - track.lockForRead(); - try { - Iterator i = track.getRawFixes().iterator(); - int count; - for (count = 0; i.hasNext(); count++) { - i.next(); - } - assertEquals(5, count); - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void testOrdering() { - long lastMillis = 0; - GPSFix lastFix = null; - boolean first = true; - track.lockForRead(); - try { - for (Iterator i = track.getRawFixes().iterator(); i.hasNext(); first = false) { - GPSFixMoving fix = i.next(); - long millis = fix.getTimePoint().asMillis(); - if (!first) { - assertTrue(millis > lastMillis); - TimePoint inBetweenTimePoint = new MillisecondsTimePoint((millis + lastMillis) / 2); - assertEquals(lastFix, track.getLastRawFixBefore(inBetweenTimePoint)); - assertEquals(lastFix, track.getLastRawFixAtOrBefore(inBetweenTimePoint)); - assertEquals(fix, track.getFirstRawFixAfter(inBetweenTimePoint)); - assertEquals(fix, track.getFirstRawFixAtOrAfter(inBetweenTimePoint)); - - assertEquals(lastFix, track.getLastRawFixAtOrBefore(lastFix.getTimePoint())); - assertEquals(fix, track.getFirstRawFixAtOrAfter(fix.getTimePoint())); - - assertEquals(lastFix, track.getLastRawFixBefore(fix.getTimePoint())); - assertEquals(fix, track.getLastRawFixAtOrBefore(fix.getTimePoint())); - assertEquals(fix, track.getFirstRawFixAfter(lastFix.getTimePoint())); - assertEquals(lastFix, track.getFirstRawFixAtOrAfter(lastFix.getTimePoint())); - } - lastMillis = millis; - lastFix = fix; - } - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void assertEstimatedPositionBeforeStartIsStart() { - track.lockForRead(); - try { - GPSFixMoving start = track.getRawFixes().iterator().next(); - TimePoint oneNanoBeforeStart = new MillisecondsTimePoint(start.getTimePoint().asMillis() - 1); - assertEquals(start.getPosition(), track.getEstimatedPosition(oneNanoBeforeStart, false)); - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void testSimpleInterpolation() { - long lastMillis = 0; - GPSFix lastFix = null; - boolean first = true; - track.lockForRead(); - try { - for (Iterator i = track.getRawFixes().iterator(); i.hasNext(); first = false) { - GPSFixMoving fix = i.next(); - long millis = fix.getTimePoint().asMillis(); - if (!first) { - TimePoint inBetweenTimePoint = new MillisecondsTimePoint((millis + lastMillis) / 2); - Position interpolatedPosition = track.getEstimatedRawPosition(inBetweenTimePoint, false); - Distance d1 = lastFix.getPosition().getDistance(interpolatedPosition); - Distance d2 = interpolatedPosition.getDistance(fix.getPosition()); - // the interpolated point should be on the great circle, not open a "triangle" - assertEquals(lastFix.getPosition().getDistance(fix.getPosition()).getMeters(), - d1.getMeters() + d2.getMeters(), 0.00001); - } - lastMillis = millis; - lastFix = fix; - } - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void testSimpleExtrapolation() { - GPSFix fix = track.getLastRawFix(); - long millis = fix.getTimePoint().asMillis(); - GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint()); - long lastMillis = lastFix.getTimePoint().asMillis(); - TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis)); - Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, true); - assertEquals(0.5, fix.getPosition().getDistance(extrapolatedPosition).getMeters() - / lastFix.getPosition().getDistance(extrapolatedPosition).getMeters(), 0.01); - } - - @Test - public void testExtrapolationDoesntHappenIfSuppressed() { - GPSFix fix = track.getLastRawFix(); - long millis = fix.getTimePoint().asMillis(); - GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint()); - long lastMillis = lastFix.getTimePoint().asMillis(); - TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis)); - Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, false); - assertEquals(extrapolatedPosition, fix.getPosition()); - } - - @Test - public void testDistanceTraveled() { - List distances = new ArrayList(); - List fixes = new ArrayList(); - boolean first = true; - GPSFixMoving oldFix = null; - track.lockForRead(); - try { - for (GPSFixMoving fix : track.getRawFixes()) { - fixes.add(fix); - if (first) { - first = false; - } else { - Distance d = oldFix.getPosition().getDistance(fix.getPosition()); - distances.add(d); - } - oldFix = fix; - } - for (int i = 0; i < fixes.size(); i++) { - for (int j = i; j < fixes.size(); j++) { - double distanceSumInNauticalMiles = 0; - for (int k = i; k < j; k++) { - distanceSumInNauticalMiles += distances.get(k).getNauticalMiles(); - } - // travel fully from fix #i to fix #j and require the segment distances to sum up equal - double nauticalMilesFromIToJ = track.getRawDistanceTraveled(fixes.get(i).getTimePoint(), - fixes.get(j).getTimePoint()).getNauticalMiles(); - assertEquals(distanceSumInNauticalMiles, nauticalMilesFromIToJ, 0.0000001); - if (j > i) { - // now skip half a segment at the beginning: - double nauticalMilesFromHalfAfterIToJ = track.getRawDistanceTraveled( - new MillisecondsTimePoint((fixes.get(i).getTimePoint().asMillis() + fixes.get(i + 1) - .getTimePoint().asMillis()) / 2), fixes.get(j).getTimePoint()) - .getNauticalMiles(); - assertTrue("for i=" + i + ", j=" + j + ": " + nauticalMilesFromHalfAfterIToJ + "<" - + distanceSumInNauticalMiles, - nauticalMilesFromHalfAfterIToJ < distanceSumInNauticalMiles); - if (i > 0) { - // now skip half a segment before the beginning: - double nauticalMilesFromHalfBeforeIToJ = track.getRawDistanceTraveled( - new MillisecondsTimePoint((fixes.get(i).getTimePoint().asMillis() + fixes - .get(i - 1).getTimePoint().asMillis()) / 2), fixes.get(j).getTimePoint()) - .getNauticalMiles(); - assertTrue(nauticalMilesFromHalfBeforeIToJ > distanceSumInNauticalMiles); - } - // now skip half a segment at the end: - double nauticalMilesFromIToHalfBeforeJ = track.getRawDistanceTraveled( - fixes.get(i).getTimePoint(), - new MillisecondsTimePoint((fixes.get(j).getTimePoint().asMillis() + fixes.get(j - 1) - .getTimePoint().asMillis()) / 2)).getNauticalMiles(); - assertTrue(nauticalMilesFromIToHalfBeforeJ < distanceSumInNauticalMiles); - if (j < fixes.size() - 1) { - // now skip half a segment before the beginning: - double nauticalMilesFromIToHalfAfterJ = track.getRawDistanceTraveled( - fixes.get(i).getTimePoint(), - new MillisecondsTimePoint((fixes.get(j).getTimePoint().asMillis() + fixes - .get(j + 1).getTimePoint().asMillis()) / 2)).getNauticalMiles(); - assertTrue("for i=" + i + ", j=" + j + ": " + nauticalMilesFromIToHalfAfterJ + ">" - + distanceSumInNauticalMiles, - nauticalMilesFromIToHalfAfterJ > distanceSumInNauticalMiles); - } - } - } - } - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void testDistanceTraveledOnSmoothenedTrackThenAddingOutlier() { - final Set invalidationCalls = new HashSet(); - final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { - @Override - public void invalidateAllAtOrLaterThan(TimePoint timePoint) { - super.invalidateAllAtOrLaterThan(timePoint); - invalidationCalls.add(timePoint); - } - }; - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { - private static final long serialVersionUID = -7277196393160609503L; - @Override - protected DistanceCache getDistanceCache() { - return distanceCache; - } - }; - final int timeBetweenFixesInMillis = 1000; - Bearing bearing = new DegreeBearingImpl(123); - Speed speed = new KnotSpeedImpl(7); - Position p = new DegreePosition(0, 0); - final TimePoint now = MillisecondsTimePoint.now(); - TimePoint start = now; - final int steps = 10; - TimePoint next = null; - for (int i=0; i> fullIntervalCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start); - assertNotNull(fullIntervalCacheEntry); // no more entry for "to"-value start in cache - assertEquals(start, fullIntervalCacheEntry.getA()); - assertEquals(now, fullIntervalCacheEntry.getB().getA()); - TimePoint timePointForOutlier = new MillisecondsTimePoint(now.asMillis() + ((int) steps/2) * timeBetweenFixesInMillis + timeBetweenFixesInMillis/2); - Position outlierPosition = new DegreePosition(90, 90); - GPSFix outlier = new GPSFixImpl(outlierPosition, timePointForOutlier); - track.addGPSFix(outlier); - assertEquals(1, invalidationCalls.size()); - TimePoint timePointOfLastFixBeforeOutlier = track.getLastFixBefore(timePointForOutlier).getTimePoint(); - assertTrue(invalidationCalls.iterator().next().after(timePointOfLastFixBeforeOutlier)); // outlier doesn't turn its preceding element into an outlier - assertNull(distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start)); // no more entry for "to"-value start in cache - invalidationCalls.clear(); - final TimePoint timePointOfLastOriginalFix = track.getLastRawFix().getTimePoint(); - assertEquals(speed.getMetersPerSecond() * (steps - 1), - track.getDistanceTraveled(now, timePointOfLastOriginalFix).getMeters(), 0.02); - final com.sap.sse.common.Util.Pair> newFullIntervalCacheEntry = distanceCache - .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); - assertNotNull(newFullIntervalCacheEntry); // no more entry for "to"-value start in cache - assertEquals(timePointOfLastOriginalFix, newFullIntervalCacheEntry.getA()); - assertEquals(now, newFullIntervalCacheEntry.getB().getA()); - TimePoint timePointForLateOutlier = new MillisecondsTimePoint(now.asMillis() + (steps-1)*timeBetweenFixesInMillis + timeBetweenFixesInMillis/2); - Position lateOutlierPosition = new DegreePosition(-90, 90); - GPSFix lateOutlier = new GPSFixImpl(lateOutlierPosition, timePointForLateOutlier); - // adding the outlier invalidates the fix just before the outlier because it now has a single successor that is in range but not reachable - track.addGPSFix(lateOutlier); - assertEquals(1, invalidationCalls.size()); - TimePoint timePointOfLastRawFixBeforeLateOutlier = track.getLastRawFixBefore(timePointForLateOutlier).getTimePoint(); - // assert that adding the outlier invalidated the distance cache starting from the raw fix before the late outlier - // because its validity changed from true to false - assertTrue(invalidationCalls.iterator().next().equals(timePointOfLastRawFixBeforeLateOutlier)); - invalidationCalls.clear(); - // expect the invalidation to have started after the single cache entry, so the cache entry still has to be there: - final com.sap.sse.common.Util.Pair> stillPresentFullIntervalCacheEntry = distanceCache - .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); - assertNull(stillPresentFullIntervalCacheEntry); // no more entry for "to"-value start in cache because new temporary outlier lies in previously cached interval - GPSFix polishedLastFix = track.getLastFixBefore(new MillisecondsTimePoint(Long.MAX_VALUE)); // get the last smoothened fix... - // ...which now is expected to be two fixes before lateOutlier because lateOutlier has previous fixes within the time range - // but none of them is reachable with max speed, and the raw fix right before lateOutlier is currently temporarily an outlier too - assertEquals(track.getLastRawFixBefore(timePointOfLastRawFixBeforeLateOutlier), polishedLastFix); - track.lockForRead(); - try { - assertEquals(steps-1, Util.size(track.getFixes())); // the lateOutlier and its predecessor are currently detected as outlier, so it's not steps+1 - // which would include the lateOutlier, but it's already only steps-1 valid fixes. - } finally { - track.unlockAfterRead(); - } - // now add another "normal" fix, making the lateOutlier really an outlier; invalidation starts 1ms after the last previously valid - // fix before the fix added, or at the earliest fix that changes its validity, whichever is earlier. In this case the earlier time point - // is 1ms after the last *valid* fix before the fix inserted because that's the fix two before the lateOutlier, and that fix and all other - // earlier fixes don't change their validity - GPSFix fix = new GPSFixImpl(p, start); // the "overshoot" from the previous loop can be used to generate the next "regular" fix - track.addGPSFix(fix); - assertEquals(1, invalidationCalls.size()); - // the lateOutlier's predecessor now is expected to have changed validity again, causing a distance cache invalidation at its time - assertEquals(track.getLastFixBefore(timePointOfLastRawFixBeforeLateOutlier).getTimePoint().plus(1), invalidationCalls.iterator().next()); - assertTrue(timePointForLateOutlier.compareTo(fix.getTimePoint()) < 0); - // expect the invalidation to have started at the fix before the outlier, leaving the previous result ending at the fix right before the outlier intact - final com.sap.sse.common.Util.Pair> stillStillPresentFullIntervalCacheEntry = distanceCache - .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); - assertNull(stillStillPresentFullIntervalCacheEntry); // still nothing in the cache - track.lockForRead(); - try { - assertEquals(steps+1, Util.size(track.getFixes())); // the one "normal" late fix is added on top of the fixes, but the two outliers should now be removed - } finally { - track.unlockAfterRead(); - } - GPSFix polishedLastFix2 = track.getLastFixBefore(new MillisecondsTimePoint(Long.MAX_VALUE)); // get the last smoothened fix... - PositionAssert.assertGPSFixEquals(fix, polishedLastFix2, /* pos deg delta */ 0.000001); - assertEquals(speed.getMetersPerSecond()*steps, track.getDistanceTraveled(now, start).getMeters(), 0.01); - } - - /** - * A test case for bug 968. If distances are requested for time intervals ending after the last GPS fix, the position - * is estimated to be at the last fix known. When another fix arrives, the positions for these time points can now be - * interpolated, leading to different results and hence to a cache inconsistency in case the cache isn't flushed for the - * interval between the last and the newest fix. This test case adds a few fixes, then asks a distance traveled for an - * interval ending after the last fix, then adds another fix at a later time point and asks the distance again. - */ - @Test - public void testMoreFrequentDistanceComputationThanGPSFixReception() { - DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); - final int timeBetweenFixesInMillis = 1000; - Bearing bearing = new DegreeBearingImpl(123); - SpeedWithBearing speed = new KnotSpeedWithBearingImpl(7, bearing); - Position p = new DegreePosition(0, 0); - final TimePoint now = MillisecondsTimePoint.now(); - TimePoint start = now; - final int steps = 10; - TimePoint next = null; - GPSFixMoving fix = null; - for (int i=0; i track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { - private static final long serialVersionUID = -7277196393160609503L; - @Override - protected DistanceCache getDistanceCache() { - return distanceCache; - } - }; - while (fixTime.before(start.plus(raceDuration))) { - for (int i=0; i= 0); - lastDistance = d; - queryTime = queryTime.plus(queryInterval); - } - } - assertTrue(distanceCache.size() <= DistanceCache.MAX_SIZE); - } - - @Test - public void testDistanceCacheAccessForPartialStrip() { - final Set invalidationCalls = new HashSet(); - final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { - @Override - public void invalidateAllAtOrLaterThan(TimePoint timePoint) { - super.invalidateAllAtOrLaterThan(timePoint); - invalidationCalls.add(timePoint); - } - }; - DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { - private static final long serialVersionUID = -7277196393160609503L; - @Override - protected DistanceCache getDistanceCache() { - return distanceCache; - } - }; - final int timeBetweenFixesInMillis = 1000; - Bearing bearing = new DegreeBearingImpl(123); - Speed speed = new KnotSpeedImpl(7); - Position p = new DegreePosition(0, 0); - final TimePoint now = MillisecondsTimePoint.now(); - TimePoint start = now; - final int steps = 10; - TimePoint next = null; - for (int i=0; i> stripCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(stripFrom, stripTo); - assertEquals(stripTo, stripCacheEntry.getA()); - assertEquals(stripFrom, stripCacheEntry.getB().getA()); - // expect a cache entry exactly for the full boundaries - com.sap.sse.common.Util.Pair> fullCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start); - assertEquals(start, fullCacheEntry.getA()); - assertEquals(now, fullCacheEntry.getB().getA()); - } - - @Test - public void testDistanceTraveledOnInBetweenSectionFromFixToFix() { - track.lockForRead(); - try { - // take second and third fix and compute distance between them - Iterator iter = track.getRawFixes().iterator(); - iter.next(); // skip first; - GPSFix second = iter.next(); - GPSFix third = iter.next(); - assertEquals(second.getPosition().getDistance(third.getPosition()), - track.getRawDistanceTraveled(second.getTimePoint(), third.getTimePoint())); - } finally { - track.unlockAfterRead(); - } - } - - @Test - public void testFarFutureFixNotUsedDuringEstimation() { - TimePoint normalFixesTime = null; - track.lockForRead(); - try { - Iterator iter = track.getRawFixes().iterator(); - for (int i = 0; i < 2; i++) { - normalFixesTime = iter.next().getTimePoint(); - } - assertNotNull(normalFixesTime); - } finally { - track.unlockAfterRead(); - } - SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(normalFixesTime); - GPSFixMovingImpl gpsFixFarInTheFuture = new GPSFixMovingImpl( - new DegreePosition(89, 180), new MillisecondsTimePoint( - System.currentTimeMillis()+10000000l), new KnotSpeedWithBearingImpl(200000, new DegreeBearingImpl(0))); - track.addGPSFix(gpsFixFarInTheFuture); - Position estimatedPosNew = track.getEstimatedPosition(normalFixesTime, /* extrapolate */ false); - // expecting to get the coordinates of gpsFix2's position - assertEquals(gpsFix2.getPosition().getLatDeg(), estimatedPosNew.getLatDeg(), 0.5); - assertEquals(gpsFix2.getPosition().getLngDeg(), estimatedPosNew.getLngDeg(), 0.5); - SpeedWithBearing estimatedSpeedNew = track.getEstimatedSpeed(normalFixesTime); - PositionAssert.assertSpeedEquals(estimatedSpeed, estimatedSpeedNew, /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); - } - - @Test - public void testValidCheckForFixThatSaysItsAsFastAsItWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); - TimePoint now1 = MillisecondsTimePoint.now(); - TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - AbstractBearing bearing = new DegreeBearingImpl(90); - Position position1 = new DegreePosition(1, 2); - Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); - GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(1, bearing)); - GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(1, bearing)); - myTrack.addGPSFix(myGpsFix1); - myTrack.addGPSFix(myGpsFix2); - myTrack.lockForRead(); - try { - assertEquals(2, myTrack.getFixes().size()); // expecting both fixes to be valid - } finally { - myTrack.unlockAfterRead(); - } - } - - @Test - public void testValidCheckForFixThatSaysItsFasterThanItActuallyWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); - TimePoint now1 = MillisecondsTimePoint.now(); - TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - AbstractBearing bearing = new DegreeBearingImpl(90); - Position position1 = new DegreePosition(1, 2); - Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); - GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(10, bearing)); - GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(10, bearing)); - myTrack.addGPSFix(myGpsFix1); - myTrack.addGPSFix(myGpsFix2); - myTrack.lockForRead(); - try { - assertTrue(myTrack.getFixes().size() < 2); // at least one fix must be classified as outlier - } finally { - myTrack.unlockAfterRead(); - } - } - - @Test - public void testValidCheckForFixThatSaysItsSlowerThanItActuallyWas() { - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ - true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); - TimePoint now1 = MillisecondsTimePoint.now(); - TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - AbstractBearing bearing = new DegreeBearingImpl(90); - Position position1 = new DegreePosition(1, 2); - Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); - GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(0.1, bearing)); - GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(0.1, bearing)); - myTrack.addGPSFix(myGpsFix1); - myTrack.addGPSFix(myGpsFix2); - myTrack.lockForRead(); - try { - assertTrue(myTrack.getFixes().size() < 2); // at least one fix must be classified as outlier - } finally { - myTrack.unlockAfterRead(); - } - } - - @Test - public void testInvalidationIntervalBeginningForPositionEstimation() { - track.lockForRead(); - final GPSFixMoving firstFixSoFar; - try { - firstFixSoFar = track.getFixes().iterator().next(); - } finally { - track.unlockAfterRead(); - } - assertNotNull(firstFixSoFar); - TimePoint beginningOfTime = new MillisecondsTimePoint(0); - Position positionAtBeginningOfTime = track.getEstimatedPosition(beginningOfTime, /* extrapolate */false); - long timespan = 2 /* hours */ * 3600 /* seconds/hour */ * 1000 /* millis/s */; - SpeedWithBearing speed = new KnotSpeedWithBearingImpl(45, new DegreeBearingImpl(123)); - TimePoint slightlyBeforeFirstFix = firstFixSoFar.getTimePoint().minus(timespan); - Position newPosition = firstFixSoFar.getPosition().translateGreatCircle(speed.getBearing().reverse(), - speed.travel(firstFixSoFar.getTimePoint(), firstFixSoFar.getTimePoint().plus(timespan))); - GPSFixMoving newFirstFix = new GPSFixMovingImpl(newPosition, slightlyBeforeFirstFix, speed); - track.addGPSFix(newFirstFix); - TimeRange intervalAffected = track.getEstimatedPositionTimePeriodAffectedBy(newFirstFix); - Position newPositionAtBeginningOfTime = track.getEstimatedPosition(beginningOfTime, /* extrapolate */false); - assertFalse(newPositionAtBeginningOfTime.equals(positionAtBeginningOfTime)); - assertTrue(!intervalAffected.from().after(beginningOfTime)); - } - - @Test - public void testInvalidationIntervalEndForPositionEstimation() { - TimePoint endOfTime = new MillisecondsTimePoint(Long.MAX_VALUE); - final GPSFixMoving lastFixSoFar = track.getLastFixBefore(endOfTime); - assertNotNull(lastFixSoFar); - Position positionAtEndOfTime = track.getEstimatedPosition(endOfTime, /* extrapolate */false); - long timespan = 2 /* hours */ * 3600 /* seconds/hour */ * 1000 /* millis/s */; - SpeedWithBearing speed = new KnotSpeedWithBearingImpl(45, new DegreeBearingImpl(123)); - TimePoint slightlyAfterLastFix = lastFixSoFar.getTimePoint().plus(timespan); - Position newPosition = lastFixSoFar.getPosition().translateGreatCircle(speed.getBearing(), - speed.travel(lastFixSoFar.getTimePoint(), lastFixSoFar.getTimePoint().plus(timespan))); - GPSFixMoving newLastFix = new GPSFixMovingImpl(newPosition, slightlyAfterLastFix, speed); - track.addGPSFix(newLastFix); - TimeRange intervalAffected = track.getEstimatedPositionTimePeriodAffectedBy(newLastFix); - Position newPositionAtEndOfTime = track.getEstimatedPosition(endOfTime, /* extrapolate */false); - assertFalse(newPositionAtEndOfTime.equals(positionAtEndOfTime)); - assertTrue(!intervalAffected.to().before(endOfTime)); - } - - @Test - public void testInvalidationIntervalForPositionEstimationForEmptyTrack() { - TimePoint now = MillisecondsTimePoint.now(); - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); - TimePoint beginningOfTime = new MillisecondsTimePoint(0); - Position positionAtBeginningOfTime = myTrack.getEstimatedPosition(beginningOfTime, /* extrapolate */false); - TimePoint endOfTime = new MillisecondsTimePoint(Long.MAX_VALUE); - Position positionAtEndOfTime = myTrack.getEstimatedPosition(endOfTime, /* extrapolate */false); - assertNull(positionAtBeginningOfTime); - assertNull(positionAtEndOfTime); - GPSFixMoving newFix = new GPSFixMovingImpl(new DegreePosition(12, 34), now, new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); - myTrack.addGPSFix(newFix); - TimeRange intervalAffected = myTrack.getEstimatedPositionTimePeriodAffectedBy(newFix); - Position newPositionAtBeginningOfTime = myTrack.getEstimatedPosition(beginningOfTime, /* extrapolate */false); - Position newPositionAtEndOfTime = myTrack.getEstimatedPosition(now, /* extrapolate */false); - assertFalse(newPositionAtBeginningOfTime.equals(positionAtBeginningOfTime)); - assertTrue(!intervalAffected.from().after(beginningOfTime)); - assertFalse(newPositionAtEndOfTime.equals(positionAtEndOfTime)); - assertTrue(!intervalAffected.to().before(endOfTime)); - } - - @Test - public void testSpeedEstimationForCourseChangeAtFix() throws ParseException { - /* - * See bug 1065, first test data set: [2011-06-23T16:08:27.000+0200: (54.49155,10.184947) with - * 5.399568034557236kn to 291.0�, 2011-06-23T16:08:31.000+0200: (54.491597,10.184808) with 5.939524838012959kn - * to 296.0�, 2011-06-23T16:08:37.000+0200: (54.491572999999995,10.184669999999999) with 3.7796976241900646kn - * to 210.0�, 2011-06-23T16:08:39.000+0200: (54.491523,10.184602) with 5.939524838012959kn to 219.0�, - * 2011-06-23T16:08:43.000+0200: (54.491457999999994,10.18451) with 4.859611231101512kn to 225.0�, - * 2011-06-23T16:08:45.000+0200: (54.491386999999996,10.184455) with 5.939524838012959kn to 196.0�] - * - * let the track estimate the speed at 16:08:37 at - * - * 5.469864974239993kn to 215.50791079454874� - */ - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); - GPSFixMoving fix1 = createFix("2011-06-23T16:08:27.000+0200", 54.49155, 10.184947, 5.399568034557236, 291.0); - myTrack.addGPSFix(fix1); - GPSFixMoving fix2 = createFix("2011-06-23T16:08:31.000+0200", 54.491597,10.184808, 5.939524838012959, 296.0); - myTrack.addGPSFix(fix2); - GPSFixMoving fix3 = createFix("2011-06-23T16:08:37.000+0200", 54.491572999999995,10.184669999999999, 3.7796976241900646, 210.0); - myTrack.addGPSFix(fix3); - GPSFixMoving fix4 = createFix("2011-06-23T16:08:39.000+0200", 54.491523, 10.184602, 5.939524838012959, 219.0); - myTrack.addGPSFix(fix4); - GPSFixMoving fix5 = createFix("2011-06-23T16:08:43.000+0200", 54.491457999999994, 10.18451, 4.859611231101512, 225.0); - myTrack.addGPSFix(fix5); - GPSFixMoving fix6 = createFix("2011-06-23T16:08:45.000+0200", 54.491386999999996, 10.184455, 5.939524838012959, 196.0); - myTrack.addGPSFix(fix6); - final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - SpeedWithBearing estimatedSpeedWithBearing = myTrack.getEstimatedSpeed(new MillisecondsTimePoint(dateFormatter.parse("2011-06-23T16:08:37.000+0200"))); - assertEquals(225., estimatedSpeedWithBearing.getBearing().getDegrees(), 5); - assertEquals(5.0, estimatedSpeedWithBearing.getKnots(), 0.2); - } - - @Test - public void testSpeedEstimationForCourseChangeBetweenFixes() throws ParseException { - /* - * See bug 1065, first test data set: [2012-10-21T15:00:32.000+0200: (43.692862999999996,7.267875) with - * 16.73866090712743kn to 294.0°, 2012-10-21T15:00:34.000+0200: (43.692937,7.267683) with 16.73866090712743kn - * to 299.0°, 2012-10-21T15:00:36.000+0200: (43.693017,7.267487999999999) with 16.73866090712743kn to 300.0°, - * 2012-10-21T15:00:38.000+0200: (43.693103,7.267297999999999) with 16.73866090712743kn to 300.0°, - * 2012-10-21T15:00:40.000+0200: (43.693191999999996,7.267112) with 16.73866090712743kn to 303.0°, - * 2012-10-21T15:00:43.000+0200: (43.693283,7.2669179999999995) with 18.898488120950326kn to 302.0°] - * 2012-10-21T15:00:51.000+0200: (43.693245,7.266183) with 11.339092872570195kn to 237.0° - */ - DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); - GPSFixMoving fix1 = createFix("2012-10-21T15:00:32.000+0200", 43.692862999999996,7.267875, 16.73866090712743, 294.0); - myTrack.addGPSFix(fix1); - GPSFixMoving fix2 = createFix("2012-10-21T15:00:34.000+0200", 43.692937, 7.267683, 16.73866090712743, 299.0); - myTrack.addGPSFix(fix2); - GPSFixMoving fix3 = createFix("2012-10-21T15:00:36.000+0200", 43.693017, 7.267487999999999, 16.73866090712743, 300.0); - myTrack.addGPSFix(fix3); - GPSFixMoving fix4 = createFix("2012-10-21T15:00:38.000+0200", 43.693103, 7.267297999999999, 16.73866090712743, 300.0); - myTrack.addGPSFix(fix4); - GPSFixMoving fix5 = createFix("2012-10-21T15:00:40.000+0200", 43.693191999999996, 7.267112, 16.73866090712743, 303.0); - myTrack.addGPSFix(fix5); - GPSFixMoving fix6 = createFix("2012-10-21T15:00:43.000+0200", 43.693283, 7.2669179999999995, 18.898488120950326, 302.0); - myTrack.addGPSFix(fix6); - GPSFixMoving fix7 = createFix("2012-10-21T15:00:51.000+0200", 43.693245, 7.266183, 11.339092872570195, 237.0); - myTrack.addGPSFix(fix7); - final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - SpeedWithBearing estimatedSpeedWithBearing = myTrack.getEstimatedSpeed(new MillisecondsTimePoint(dateFormatter.parse("2012-10-21T15:00:45.000+0200"))); - assertEquals(275., estimatedSpeedWithBearing.getBearing().getDegrees(), 5); - assertEquals(15.9, estimatedSpeedWithBearing.getKnots(), 0.2); - } - - private GPSFixMoving createFix(String isoDateTime, double lat, double lng, double knotSpeed, double bearingDeg) throws ParseException { - final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - TimePoint timePoint = new MillisecondsTimePoint(dateFormatter.parse(isoDateTime)); - Position position = new DegreePosition(lat, lng); - SpeedWithBearing speed = new KnotSpeedWithBearingImpl(knotSpeed, new DegreeBearingImpl(bearingDeg)); - GPSFixMoving fix = new GPSFixMovingImpl(position, timePoint, speed); - return fix; - } - - @Test - public void testFrequency() { - assertEquals(MILLIS_BETWEEN_FIXES, track.getAverageIntervalBetweenFixes().asMillis()); - assertEquals(MILLIS_BETWEEN_FIXES, track.getAverageIntervalBetweenRawFixes().asMillis()); - } - - @Test - public void testEstimatedSpeedCaching() throws CompactionNotPossibleException { - GPSFixMoving originalFix = new GPSFixMovingImpl(new DegreePosition(12, 34), MillisecondsTimePoint.now(), - new KnotSpeedWithBearingImpl(9, new DegreeBearingImpl(123))); - GPSFixMoving fix = new VeryCompactGPSFixMovingImpl(originalFix); - assertFalse(fix.isEstimatedSpeedCached()); - final KnotSpeedWithBearingImpl estimatedSpeed = new KnotSpeedWithBearingImpl(9.1, new DegreeBearingImpl(124)); - fix.cacheEstimatedSpeed(estimatedSpeed); - assertTrue(fix.isEstimatedSpeedCached()); - SpeedWithBearing cachedEstimatedSpeed = fix.getCachedEstimatedSpeed(); - PositionAssert.assertSpeedEquals(estimatedSpeed, cachedEstimatedSpeed, /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); - fix.invalidateEstimatedSpeedCache(); - assertFalse(fix.isEstimatedSpeedCached()); - } - - @Test - public void testEstimatedSpeedCachingOnTrack() { - GPSFixMoving compactFix3 = track.getFirstFixAtOrAfter(gpsFix3.getTimePoint()); - assertFalse(compactFix3.isEstimatedSpeedCached()); - SpeedWithBearing fix3EstimatedSpeed = track.getEstimatedSpeed(gpsFix3.getTimePoint()); - assertTrue(compactFix3.isEstimatedSpeedCached()); - PositionAssert.assertSpeedEquals(fix3EstimatedSpeed, compactFix3.getCachedEstimatedSpeed(), /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); - PositionAssert.assertSpeedEquals(fix3EstimatedSpeed, track.getEstimatedSpeed(gpsFix3.getTimePoint()), - /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); // fetch again from the cache - // assuming that all test fixes are within a few milliseconds and the averaging interval is much larger than that, - // adding a single fix in the middle should invalidate the cache - track.add(new GPSFixMovingImpl(gpsFix3.getPosition(), gpsFix3.getTimePoint().plus(1), gpsFix3.getSpeed())); - assertFalse(compactFix3.isEstimatedSpeedCached()); - } -} +package com.sap.sailing.domain.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.lang.reflect.Field; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.common.AbstractBearing; +import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.KnotSpeedImpl; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.MeterDistance; +import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedWithDegreeBearingImpl; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.impl.VeryCompactGPSFixMovingImpl; +import com.sap.sailing.domain.common.tracking.impl.CompactionNotPossibleException; +import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; +import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; +import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.impl.DistanceCache; +import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; +import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.GPSFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.MaxSpeedCache; +import com.sap.sailing.domain.tracking.impl.TrackImpl; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.TimeRange; +import com.sap.sse.common.Timed; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class TrackTest { + private static final int MILLIS_BETWEEN_FIXES = 3000000; + private DynamicGPSFixTrack track; + private GPSFixMovingImpl gpsFix1; + private GPSFixMovingImpl gpsFix2; + private GPSFixMovingImpl gpsFix3; + private GPSFixMovingImpl gpsFix4; + private GPSFixMovingImpl gpsFix5; + + @Before + public void setUp() throws InterruptedException { + track = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + TimePoint now1 = MillisecondsTimePoint.now(); + TimePoint now2 = addMillisToTimepoint(now1, MILLIS_BETWEEN_FIXES); + DegreePosition position1 = new DegreePosition(1, 2); + DegreePosition position2 = new DegreePosition(1, 3); + gpsFix1 = new GPSFixMovingImpl( + position1, now1, new KnotSpeedWithBearingImpl(position1.getDistance(position2) + .inTime(now2.asMillis() - now1.asMillis()).getKnots(), + new DegreeBearingImpl(90))); + gpsFix2 = new GPSFixMovingImpl(position2, now2, new KnotSpeedWithBearingImpl(position1.getDistance(position2) + .inTime(now2.asMillis() - gpsFix1.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(90))); + TimePoint now3 = addMillisToTimepoint(now2, MILLIS_BETWEEN_FIXES); + Position position3 = new DegreePosition(1, 4); + gpsFix3 = new GPSFixMovingImpl( + position3, now3, new KnotSpeedWithBearingImpl(position2.getDistance(position3) + .inTime(now3.asMillis() - gpsFix2.getTimePoint().asMillis()).getKnots(), + new DegreeBearingImpl(0))); + TimePoint now4 = addMillisToTimepoint(now3, MILLIS_BETWEEN_FIXES); + Position position4 = new DegreePosition(3, 4); + gpsFix4 = new GPSFixMovingImpl( + position4, now4, new KnotSpeedWithBearingImpl(position3.getDistance(position4) + .inTime(now4.asMillis() - gpsFix3.getTimePoint().asMillis()).getKnots(), + new DegreeBearingImpl(0))); + TimePoint now5 = addMillisToTimepoint(now4, MILLIS_BETWEEN_FIXES); + Position position5 = new DegreePosition(5, 4); + gpsFix5 = new GPSFixMovingImpl(position5, now5, new KnotSpeedWithBearingImpl(position4.getDistance(position5) + .inTime(now5.asMillis() - gpsFix4.getTimePoint().asMillis()).getKnots(), new DegreeBearingImpl(0))); + track.addGPSFix(gpsFix1); + track.addGPSFix(gpsFix2); + track.addGPSFix(gpsFix3); + track.addGPSFix(gpsFix4); + track.addGPSFix(gpsFix5); + } + + /** + * Tests for a incorrect method of estimating Positions + */ + @Test + public void positionEstimationTest() { + track = new DynamicGPSFixMovingTrackImpl( + new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", true), null), 5000, null); + DegreePosition p1 = new DegreePosition(0, 0); + DegreePosition p2 = new DegreePosition(90, 0); + TimePoint t1 = MillisecondsTimePoint.now(); + TimePoint t2 = t1.plus(30); + gpsFix1 = new GPSFixMovingImpl(p1, t1, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); + gpsFix2 = new GPSFixMovingImpl(p2, t2, new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0))); + track.addGPSFix(gpsFix1); + track.addGPSFix(gpsFix2); + track.lockForRead(); + try { + assertEquals(0, track.getEstimatedPosition(t1, true).getLatDeg(), 0.00000001); + assertEquals(30, track.getEstimatedPosition(t1.plus(10), true).getLatDeg(), 0.00000001); + assertEquals(45, track.getEstimatedPosition(t1.plus(15), true).getLatDeg(), 0.00000001); + assertEquals(60, track.getEstimatedPosition(t1.plus(20), true).getLatDeg(), 0.00000001); + assertEquals(90, track.getEstimatedPosition(t1.plus(30), true).getLatDeg(), 0.00000001); + } finally { + track.unlockAfterRead(); + } + } + /** + * Introducing a new feature on {@link GPSFixTrack} that allows clients to find positions to a sequence of + * {@link Timed} objects in ascending order, this method compares those results to the ordinary explicit calls + * to {@link GPSFixTrack#getEstimatedPosition(TimePoint, boolean)}. + */ + @SuppressWarnings("serial") + @Test + public void testGetEstimatedPositionSingleVsIteratedWithSmallerSteps() { + TimePoint start = gpsFix1.getTimePoint().minus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); + TimePoint end = gpsFix5.getTimePoint().plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); + List timeds = new ArrayList<>(); + for (TimePoint t = start; !t.after(end); t = t.plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/10)) { + final TimePoint finalT = t; + timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }}); + } + assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true); + assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false); + } + + @SuppressWarnings("serial") + @Test + public void testGetEstimatedPositionSingleVsIteratedWithLargerSteps() { + TimePoint start = gpsFix1.getTimePoint().minus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); + TimePoint end = gpsFix5.getTimePoint().plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/2); + List timeds = new ArrayList<>(); + for (TimePoint t = start; !t.after(end); t = t.plus(gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())) { + final TimePoint finalT = t; + timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }}); + } + assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true); + assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false); + } + + private void assertEqualEstimatedPositionsSingleVsIterated(List timeds, boolean extrapolate) { + List positions1 = new ArrayList<>(); + for (Timed timed : timeds) { + positions1.add(track.getEstimatedPosition(timed.getTimePoint(), extrapolate)); + } + List positions2 = new ArrayList<>(); + track.lockForRead(); + try { + for (Iterator pIter = track.getEstimatedPositions(timeds, extrapolate); pIter.hasNext();) { + positions2.add(pIter.next()); + } + } finally { + track.unlockAfterRead(); + } + Iterator p1Iter = positions1.iterator(); + Iterator p2Iter = positions2.iterator(); + while (p1Iter.hasNext()) { + assertTrue(p2Iter.hasNext()); + Position p1 = p1Iter.next(); + Position p2 = p2Iter.next(); + assertEquals("Diff between "+p1+" and "+p2, p1.getLatDeg(), p2.getLatDeg(), 0.000000001); + assertEquals("Diff between "+p1+" and "+p2, p1.getLngDeg(), p2.getLngDeg(), 0.000000001); + } + } + + /** + * A test regarding bug 968. Three subsequent fixes at the same position with increasing time stamps each, then + * jumping to the next position for three seconds. Let's see what distance and SOG do... + *

+ * + * TODO bug 1504 The challenge with this is that the equal fixes all have a wrong speed value compared to at least + * one of their neighbors. They are hence all considered outliers, and no fix remains. There is however a possible + * sub-sequence of fixes that constitutes a sequence of all-valid fixes when only valid fixes are checked for + * validity with their valid neighbors. But this, at first glance, sounds like an ugly NP-complete problem: find the + * longest possible sub-sequence such that all fixes in the sub-sequence are valid w.r.t. their neighbors. + */ + @Test + public void testJumpyFixes() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(new Object(), + /* millisecondsOverWhichToAverage */ 30000l); + TimePoint start = MillisecondsTimePoint.now(); + TimePoint now = start; + final DegreePosition startPos = new DegreePosition(0, 0); + Position pos = startPos; + SpeedWithBearing speed = new KnotSpeedWithBearingImpl(40, new DegreeBearingImpl(90)); + int NUMBER_OF_FIXES_AT_SAME_POSITION = 3; + int NUMBER_OF_REAL_FIXES = 10; + for (int i = 0; i < NUMBER_OF_REAL_FIXES; i++) { + addFixesWithSamePositionButProgressingTime(track, now, pos, speed, NUMBER_OF_FIXES_AT_SAME_POSITION); + track.getDistanceTraveled(start, now); // cause DistanceCache to cache a result + TimePoint nextNow = now.plus(NUMBER_OF_FIXES_AT_SAME_POSITION * 1000); + pos = pos.translateGreatCircle(speed.getBearing(), speed.travel(now, nextNow)); + now = nextNow; + } + assertEquals(speed.travel(start, now.minus(NUMBER_OF_FIXES_AT_SAME_POSITION * 1000)).getMeters(), + track.getDistanceTraveled(start, now).getMeters(), 0.01); + } + + private void addFixesWithSamePositionButProgressingTime(DynamicGPSFixTrack track, + TimePoint start, Position pos, SpeedWithBearing speed, int numberOfFixes) { + TimePoint now = start; + for (int i = 0; i < numberOfFixes; i++) { + GPSFixMoving fix1 = new GPSFixMovingImpl(pos, now, speed); + track.addGPSFix(fix1); + now = now.plus(1000); + } + } + + /** + * See bug 2626; this test tries to provoke a race condition by subclassing {@link MaxSpeedCache} and overriding + * {@link MaxSpeedCache#cache} so that it can synchronize fix additions to the track with a + * {@link MaxSpeedCache#getMaxSpeed(TimePoint, TimePoint)} call to the cache. + */ + @Test + public void testMaxSpeedCacheRaceCondition() throws InterruptedException, BrokenBarrierException, TimeoutException { + final CyclicBarrier cacheBarrier = new CyclicBarrier(2); + final CyclicBarrier cacheDone = new CyclicBarrier(2); + + DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { + private static final long serialVersionUID = 1L; + + @Override + protected MaxSpeedCache createMaxSpeedCache() { + return new MaxSpeedCache(this) { + private static final long serialVersionUID = 1L; + + @Override + protected Pair computeMaxSpeed(TimePoint from, TimePoint to) { + Pair result = super.computeMaxSpeed(from, to); + try { + Thread.sleep(1000); // just wait a bit; can't lock really because that would cause a deadlock + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return result; + } + + @Override + protected void cache(TimePoint from, TimePoint to, Pair fixAtMaxSpeed) { + try { + cacheBarrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + super.cache(from, to, fixAtMaxSpeed); + try { + cacheDone.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + } + }; + } + }; + GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix1); + // The following getMaximumSpeedOverGround call will trigger a computeMaxSpeed(...) and a cache(...) call + new Thread(()-> + assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). + getB().getKnots(), 0.001)).start(); // produces a cache entry that ends + // now don't release the cacheBarrier as yet but add more fixes + new Thread(() -> { + GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), + new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(123))); + track.addGPSFix(fix2); + }).start(); + new Thread(() -> { + GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), + new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); + track.addGPSFix(fix3); + }).start(); + new Thread(() -> { + GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), + new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(123))); + track.addGPSFix(fix4); + }).start(); + cacheBarrier.await(); // releasing the creation of the cache entry from way above; this would now add a stale entry + // that would have been invalidated by all the GPS fixes above + cacheDone.await(); // wait for the caching to have completed + final double maxSpeed[] = new double[1]; + final CyclicBarrier testDone = new CyclicBarrier(2); + new Thread(() -> { + maxSpeed[0] = track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). + getB().getKnots(); + try { + testDone.await(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }).start(); + cacheBarrier.await(20, TimeUnit.SECONDS); + cacheDone.await(20, TimeUnit.SECONDS); + testDone.await(); + assertEquals(2., maxSpeed[0], 0.1); + } + + @Test + public void testMaxSpeedForNonMovingTrackWithUpperTimeLimit() { + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + GPSFix fix1 = new GPSFixImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0)); + track.addGPSFix(fix1); + GPSFix fix2 = new GPSFixImpl(new DegreePosition(1./60., 0), new MillisecondsTimePoint(3600000)); // 1nm in one hour = 1kt + track.addGPSFix(fix2); + GPSFix fix3 = new GPSFixImpl(new DegreePosition(3./60., 0), new MillisecondsTimePoint(7200000)); // 2nm in one hour = 2kts + track.addGPSFix(fix3); + GPSFix fix4 = new GPSFixImpl(new DegreePosition(4./60., 0), new MillisecondsTimePoint(10800000)); // 1nm in one hour = 1kt + track.addGPSFix(fix4); + assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(3600000)). + getB().getKnots(), 0.001); + } + + @Test + public void testMaxSpeedForNonMovingTrack() { + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + GPSFix fix1 = new GPSFixImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0)); + track.addGPSFix(fix1); + GPSFix fix2 = new GPSFixImpl(new DegreePosition(1./60., 0), new MillisecondsTimePoint(3600000)); // 1nm in one hour = 1kt + track.addGPSFix(fix2); + GPSFix fix3 = new GPSFixImpl(new DegreePosition(3./60., 0), new MillisecondsTimePoint(7200000)); // 2nm in one hour = 2kts + track.addGPSFix(fix3); + GPSFix fix4 = new GPSFixImpl(new DegreePosition(4./60., 0), new MillisecondsTimePoint(10800000)); // 1nm in one hour = 1kt + track.addGPSFix(fix4); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). + getB().getKnots(), 0.001); + } + + @Test + public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundary() { + DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix1); + GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( + 2, new DegreeBearingImpl(123))); + track.addGPSFix(fix2); + GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix3); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). + getB().getKnots(), 0.01); // produces a cache entry that ends + GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix4); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). + getB().getKnots(), 0.01); + } + + @Test + public void testMaxSpeedForFixOverwrittenWithLowerSpeed() { + DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + GPSFixMoving slow = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + GPSFixMoving fast = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( + 2, new DegreeBearingImpl(123))); + track.addGPSFix(fast); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). + getB().getKnots(), 0.01); + track.addGPSFix(slow); + track.lockForRead(); + try { + assertEquals(1, track.getFixes().size()); + } finally { + track.unlockAfterRead(); + } + assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). + getB().getKnots(), 0.01); + } + + @Test + public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundaryAfterQuery() { + DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + GPSFixMoving fix1 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(0), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix1); + GPSFixMoving fix2 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl( + 2, new DegreeBearingImpl(123))); + track.addGPSFix(fix2); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(7200000)). + getB().getKnots(), 0.01); // produces a cache entry that ends + GPSFixMoving fix3 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(7200000), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix3); + GPSFixMoving fix4 = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(10800000), new KnotSpeedWithBearingImpl( + 1, new DegreeBearingImpl(123))); + track.addGPSFix(fix4); + assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)). + getB().getKnots(), 0.01); + } + + /** + * The DistanceCache must not contain any intervals pointing backwards because otherwise an endless recursion will + * result during the next cache look-up. This test performs a {@link GPSFixTrack#getDistanceTraveled(TimePoint, TimePoint)} with + * from later than to and ensures that no reversed entry is written to the cache. + */ + @Test + public void testDistanceTraveledBackwardsQuery() { + final Set> cacheEntries = new HashSet<>(); + final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { + @Override + public void cache(TimePoint from, TimePoint to, Distance distance) { + super.cache(from, to, distance); + cacheEntries.add(new com.sap.sse.common.Util.Triple<>(from, to, distance)); + } + + }; + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { + private static final long serialVersionUID = -7277196393160609503L; + @Override + protected DistanceCache getDistanceCache() { + return distanceCache; + } + }; + TimePoint now = MillisecondsTimePoint.now(); + TimePoint earlier = now.minus(10000); + TimePoint later = now.plus(10000); + Distance result = track.getDistanceTraveled(now, earlier); + assertEquals(Distance.NULL, result); + assertTrue(cacheEntries.isEmpty()); + Distance nextResult = track.getDistanceTraveled(now, later); + assertEquals(Distance.NULL, nextResult); + } + + @Test + public void testBearingAveragingAcrossZeroDegrees() { + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFix f1 = new GPSFixImpl(new DegreePosition(0, 0), t1); + GPSFix f2 = new GPSFixImpl(new DegreePosition(0.00001, 0.00001), t2); + GPSFix f3 = new GPSFixImpl(new DegreePosition(0.00002, 0), t3); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + SpeedWithBearing average = track.getEstimatedSpeed(t2); + PositionAssert.assertBearingEquals(new DegreeBearingImpl(0), average.getBearing(), 0.1); + } + + @Test + public void testFixValidEvenIfFixProvidedSpeedIsOutrageous() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + PositionAssert.assertGPSFixEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored + } + + @Test + public void testFixInvalidEvenIfPositionInferredSpeedIsOutrageous() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(150./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + PositionAssert.assertGPSFixEquals(f3, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored + } + + @Test + public void testFixInvalidBecauseProvidedSpeedIsTooDifferent() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + // expect the f2 fix to be invalid because provided speed is too different + assertEquals(0, f3.getPosition().getDistance(track.getFirstFixAtOrAfter(f2.getTimePoint()).getPosition()).getMeters(), 0.01); + } + + @Test + public void testIgnoringFixProvidedSpeedIfItIsOutrageous() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000l); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + PositionAssert.assertGPSFixEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint()), /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); // expect the fix to still be valid, but only its provided speed shall be ignored + SpeedWithBearing average = track.getEstimatedSpeed(t2); + assertEquals(1, average.getKnots(), 0.01); + } + + @Test + public void testBearingAveragingAcrossZeroDegreesWithGPSFixMoving() { + DynamicGPSFixMovingTrackImpl track = new DynamicGPSFixMovingTrackImpl(null, /* millisecondsOverWhichToAverage */ 5000); + TimePoint t1 = new MillisecondsTimePoint(1000); + TimePoint t2 = new MillisecondsTimePoint(2000); + TimePoint t3 = new MillisecondsTimePoint(3000); + GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(0, 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(45))); + GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(0.00001, 0.00001), t2, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0))); + GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(0.00002, 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(315))); + track.addGPSFix(f1); + track.addGPSFix(f2); + track.addGPSFix(f3); + SpeedWithBearing average = track.getRawEstimatedSpeed(t2); + PositionAssert.assertBearingEquals(new DegreeBearingImpl(0), average.getBearing(), /* deg delta */ 0.1); + } + + /** + * Bug #70: modify a track while iterating over a subset of it; ensure that this causes a + * {@link ConcurrentModificationException}. + */ + @Test + public void testAddingWhileIteratingOverSubset() throws InterruptedException, IllegalArgumentException, + IllegalAccessException, SecurityException, NoSuchFieldException { + Field fixesField = TrackImpl.class.getDeclaredField("fixes"); + fixesField.setAccessible(true); + @SuppressWarnings("unchecked") + NavigableSet fixes = (NavigableSet) fixesField.get(track); + SortedSet subset = fixes.subSet(gpsFix2, gpsFix5); + assertEquals(3, subset.size()); + Iterator subsetIter = subset.iterator(); + // start iteration + GPSFixMoving firstOfSubset = subsetIter.next(); + PositionAssert.assertGPSFixEquals(gpsFix2, firstOfSubset, /* pos deg delta */ 0.00001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); + // now add a fix: + TimePoint now6 = addMillisToTimepoint(gpsFix5.getTimePoint(), 3); + track.addGPSFix(new GPSFixMovingImpl( + new DegreePosition(6, 5), now6, new KnotSpeedWithBearingImpl(2, new DegreeBearingImpl(0)))); + try { + GPSFixMoving secondOfSubset = subsetIter.next(); + PositionAssert.assertGPSFixEquals(gpsFix3, secondOfSubset, /* pos deg delta */ 0.000001, /* bearing deg delta */ 0.01, /* knot delta */ 0.01); + fail("adding a fix interferes with iteration over subSet of track's fixes"); + } catch (ConcurrentModificationException e) { + // this is what we expected + } + } + + private TimePoint addMillisToTimepoint(TimePoint p, long millis) { + return p.plus(millis); + } + + @Test + public void testIterate() { + track.lockForRead(); + try { + Iterator i = track.getRawFixes().iterator(); + int count; + for (count = 0; i.hasNext(); count++) { + i.next(); + } + assertEquals(5, count); + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void testOrdering() { + long lastMillis = 0; + GPSFix lastFix = null; + boolean first = true; + track.lockForRead(); + try { + for (Iterator i = track.getRawFixes().iterator(); i.hasNext(); first = false) { + GPSFixMoving fix = i.next(); + long millis = fix.getTimePoint().asMillis(); + if (!first) { + assertTrue(millis > lastMillis); + TimePoint inBetweenTimePoint = new MillisecondsTimePoint((millis + lastMillis) / 2); + assertEquals(lastFix, track.getLastRawFixBefore(inBetweenTimePoint)); + assertEquals(lastFix, track.getLastRawFixAtOrBefore(inBetweenTimePoint)); + assertEquals(fix, track.getFirstRawFixAfter(inBetweenTimePoint)); + assertEquals(fix, track.getFirstRawFixAtOrAfter(inBetweenTimePoint)); + + assertEquals(lastFix, track.getLastRawFixAtOrBefore(lastFix.getTimePoint())); + assertEquals(fix, track.getFirstRawFixAtOrAfter(fix.getTimePoint())); + + assertEquals(lastFix, track.getLastRawFixBefore(fix.getTimePoint())); + assertEquals(fix, track.getLastRawFixAtOrBefore(fix.getTimePoint())); + assertEquals(fix, track.getFirstRawFixAfter(lastFix.getTimePoint())); + assertEquals(lastFix, track.getFirstRawFixAtOrAfter(lastFix.getTimePoint())); + } + lastMillis = millis; + lastFix = fix; + } + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void assertEstimatedPositionBeforeStartIsStart() { + track.lockForRead(); + try { + GPSFixMoving start = track.getRawFixes().iterator().next(); + TimePoint oneNanoBeforeStart = new MillisecondsTimePoint(start.getTimePoint().asMillis() - 1); + assertEquals(start.getPosition(), track.getEstimatedPosition(oneNanoBeforeStart, false)); + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void testSimpleInterpolation() { + long lastMillis = 0; + GPSFix lastFix = null; + boolean first = true; + track.lockForRead(); + try { + for (Iterator i = track.getRawFixes().iterator(); i.hasNext(); first = false) { + GPSFixMoving fix = i.next(); + long millis = fix.getTimePoint().asMillis(); + if (!first) { + TimePoint inBetweenTimePoint = new MillisecondsTimePoint((millis + lastMillis) / 2); + Position interpolatedPosition = track.getEstimatedRawPosition(inBetweenTimePoint, false); + Distance d1 = lastFix.getPosition().getDistance(interpolatedPosition); + Distance d2 = interpolatedPosition.getDistance(fix.getPosition()); + // the interpolated point should be on the great circle, not open a "triangle" + assertEquals(lastFix.getPosition().getDistance(fix.getPosition()).getMeters(), + d1.getMeters() + d2.getMeters(), 0.00001); + } + lastMillis = millis; + lastFix = fix; + } + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void testSimpleExtrapolation() { + GPSFix fix = track.getLastRawFix(); + long millis = fix.getTimePoint().asMillis(); + GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint()); + long lastMillis = lastFix.getTimePoint().asMillis(); + TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis)); + Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, true); + assertEquals(0.5, fix.getPosition().getDistance(extrapolatedPosition).getMeters() + / lastFix.getPosition().getDistance(extrapolatedPosition).getMeters(), 0.01); + } + + @Test + public void testExtrapolationDoesntHappenIfSuppressed() { + GPSFix fix = track.getLastRawFix(); + long millis = fix.getTimePoint().asMillis(); + GPSFix lastFix = track.getLastRawFixBefore(fix.getTimePoint()); + long lastMillis = lastFix.getTimePoint().asMillis(); + TimePoint afterTimePoint = new MillisecondsTimePoint(millis + (millis-lastMillis)); + Position extrapolatedPosition = track.getEstimatedPosition(afterTimePoint, false); + assertEquals(extrapolatedPosition, fix.getPosition()); + } + + @Test + public void testDistanceTraveled() { + List distances = new ArrayList(); + List fixes = new ArrayList(); + boolean first = true; + GPSFixMoving oldFix = null; + track.lockForRead(); + try { + for (GPSFixMoving fix : track.getRawFixes()) { + fixes.add(fix); + if (first) { + first = false; + } else { + Distance d = oldFix.getPosition().getDistance(fix.getPosition()); + distances.add(d); + } + oldFix = fix; + } + for (int i = 0; i < fixes.size(); i++) { + for (int j = i; j < fixes.size(); j++) { + double distanceSumInNauticalMiles = 0; + for (int k = i; k < j; k++) { + distanceSumInNauticalMiles += distances.get(k).getNauticalMiles(); + } + // travel fully from fix #i to fix #j and require the segment distances to sum up equal + double nauticalMilesFromIToJ = track.getRawDistanceTraveled(fixes.get(i).getTimePoint(), + fixes.get(j).getTimePoint()).getNauticalMiles(); + assertEquals(distanceSumInNauticalMiles, nauticalMilesFromIToJ, 0.0000001); + if (j > i) { + // now skip half a segment at the beginning: + double nauticalMilesFromHalfAfterIToJ = track.getRawDistanceTraveled( + new MillisecondsTimePoint((fixes.get(i).getTimePoint().asMillis() + fixes.get(i + 1) + .getTimePoint().asMillis()) / 2), fixes.get(j).getTimePoint()) + .getNauticalMiles(); + assertTrue("for i=" + i + ", j=" + j + ": " + nauticalMilesFromHalfAfterIToJ + "<" + + distanceSumInNauticalMiles, + nauticalMilesFromHalfAfterIToJ < distanceSumInNauticalMiles); + if (i > 0) { + // now skip half a segment before the beginning: + double nauticalMilesFromHalfBeforeIToJ = track.getRawDistanceTraveled( + new MillisecondsTimePoint((fixes.get(i).getTimePoint().asMillis() + fixes + .get(i - 1).getTimePoint().asMillis()) / 2), fixes.get(j).getTimePoint()) + .getNauticalMiles(); + assertTrue(nauticalMilesFromHalfBeforeIToJ > distanceSumInNauticalMiles); + } + // now skip half a segment at the end: + double nauticalMilesFromIToHalfBeforeJ = track.getRawDistanceTraveled( + fixes.get(i).getTimePoint(), + new MillisecondsTimePoint((fixes.get(j).getTimePoint().asMillis() + fixes.get(j - 1) + .getTimePoint().asMillis()) / 2)).getNauticalMiles(); + assertTrue(nauticalMilesFromIToHalfBeforeJ < distanceSumInNauticalMiles); + if (j < fixes.size() - 1) { + // now skip half a segment before the beginning: + double nauticalMilesFromIToHalfAfterJ = track.getRawDistanceTraveled( + fixes.get(i).getTimePoint(), + new MillisecondsTimePoint((fixes.get(j).getTimePoint().asMillis() + fixes + .get(j + 1).getTimePoint().asMillis()) / 2)).getNauticalMiles(); + assertTrue("for i=" + i + ", j=" + j + ": " + nauticalMilesFromIToHalfAfterJ + ">" + + distanceSumInNauticalMiles, + nauticalMilesFromIToHalfAfterJ > distanceSumInNauticalMiles); + } + } + } + } + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void testDistanceTraveledOnSmoothenedTrackThenAddingOutlier() { + final Set invalidationCalls = new HashSet(); + final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { + @Override + public void invalidateAllAtOrLaterThan(TimePoint timePoint) { + super.invalidateAllAtOrLaterThan(timePoint); + invalidationCalls.add(timePoint); + } + }; + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { + private static final long serialVersionUID = -7277196393160609503L; + @Override + protected DistanceCache getDistanceCache() { + return distanceCache; + } + }; + final int timeBetweenFixesInMillis = 1000; + Bearing bearing = new DegreeBearingImpl(123); + Speed speed = new KnotSpeedImpl(7); + Position p = new DegreePosition(0, 0); + final TimePoint now = MillisecondsTimePoint.now(); + TimePoint start = now; + final int steps = 10; + TimePoint next = null; + for (int i=0; i> fullIntervalCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start); + assertNotNull(fullIntervalCacheEntry); // no more entry for "to"-value start in cache + assertEquals(start, fullIntervalCacheEntry.getA()); + assertEquals(now, fullIntervalCacheEntry.getB().getA()); + TimePoint timePointForOutlier = new MillisecondsTimePoint(now.asMillis() + ((int) steps/2) * timeBetweenFixesInMillis + timeBetweenFixesInMillis/2); + Position outlierPosition = new DegreePosition(90, 90); + GPSFix outlier = new GPSFixImpl(outlierPosition, timePointForOutlier); + track.addGPSFix(outlier); + assertEquals(1, invalidationCalls.size()); + TimePoint timePointOfLastFixBeforeOutlier = track.getLastFixBefore(timePointForOutlier).getTimePoint(); + assertTrue(invalidationCalls.iterator().next().after(timePointOfLastFixBeforeOutlier)); // outlier doesn't turn its preceding element into an outlier + assertNull(distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start)); // no more entry for "to"-value start in cache + invalidationCalls.clear(); + final TimePoint timePointOfLastOriginalFix = track.getLastRawFix().getTimePoint(); + assertEquals(speed.getMetersPerSecond() * (steps - 1), + track.getDistanceTraveled(now, timePointOfLastOriginalFix).getMeters(), 0.02); + final com.sap.sse.common.Util.Pair> newFullIntervalCacheEntry = distanceCache + .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); + assertNotNull(newFullIntervalCacheEntry); // no more entry for "to"-value start in cache + assertEquals(timePointOfLastOriginalFix, newFullIntervalCacheEntry.getA()); + assertEquals(now, newFullIntervalCacheEntry.getB().getA()); + TimePoint timePointForLateOutlier = new MillisecondsTimePoint(now.asMillis() + (steps-1)*timeBetweenFixesInMillis + timeBetweenFixesInMillis/2); + Position lateOutlierPosition = new DegreePosition(-90, 90); + GPSFix lateOutlier = new GPSFixImpl(lateOutlierPosition, timePointForLateOutlier); + // adding the outlier invalidates the fix just before the outlier because it now has a single successor that is in range but not reachable + track.addGPSFix(lateOutlier); + assertEquals(1, invalidationCalls.size()); + TimePoint timePointOfLastRawFixBeforeLateOutlier = track.getLastRawFixBefore(timePointForLateOutlier).getTimePoint(); + // assert that adding the outlier invalidated the distance cache starting from the raw fix before the late outlier + // because its validity changed from true to false + assertTrue(invalidationCalls.iterator().next().equals(timePointOfLastRawFixBeforeLateOutlier)); + invalidationCalls.clear(); + // expect the invalidation to have started after the single cache entry, so the cache entry still has to be there: + final com.sap.sse.common.Util.Pair> stillPresentFullIntervalCacheEntry = distanceCache + .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); + assertNull(stillPresentFullIntervalCacheEntry); // no more entry for "to"-value start in cache because new temporary outlier lies in previously cached interval + GPSFix polishedLastFix = track.getLastFixBefore(new MillisecondsTimePoint(Long.MAX_VALUE)); // get the last smoothened fix... + // ...which now is expected to be two fixes before lateOutlier because lateOutlier has previous fixes within the time range + // but none of them is reachable with max speed, and the raw fix right before lateOutlier is currently temporarily an outlier too + assertEquals(track.getLastRawFixBefore(timePointOfLastRawFixBeforeLateOutlier), polishedLastFix); + track.lockForRead(); + try { + assertEquals(steps-1, Util.size(track.getFixes())); // the lateOutlier and its predecessor are currently detected as outlier, so it's not steps+1 + // which would include the lateOutlier, but it's already only steps-1 valid fixes. + } finally { + track.unlockAfterRead(); + } + // now add another "normal" fix, making the lateOutlier really an outlier; invalidation starts 1ms after the last previously valid + // fix before the fix added, or at the earliest fix that changes its validity, whichever is earlier. In this case the earlier time point + // is 1ms after the last *valid* fix before the fix inserted because that's the fix two before the lateOutlier, and that fix and all other + // earlier fixes don't change their validity + GPSFix fix = new GPSFixImpl(p, start); // the "overshoot" from the previous loop can be used to generate the next "regular" fix + track.addGPSFix(fix); + assertEquals(1, invalidationCalls.size()); + // the lateOutlier's predecessor now is expected to have changed validity again, causing a distance cache invalidation at its time + assertEquals(track.getLastFixBefore(timePointOfLastRawFixBeforeLateOutlier).getTimePoint().plus(1), invalidationCalls.iterator().next()); + assertTrue(timePointForLateOutlier.compareTo(fix.getTimePoint()) < 0); + // expect the invalidation to have started at the fix before the outlier, leaving the previous result ending at the fix right before the outlier intact + final com.sap.sse.common.Util.Pair> stillStillPresentFullIntervalCacheEntry = distanceCache + .getEarliestFromAndDistanceAtOrAfterFrom(now, timePointOfLastOriginalFix); + assertNull(stillStillPresentFullIntervalCacheEntry); // still nothing in the cache + track.lockForRead(); + try { + assertEquals(steps+1, Util.size(track.getFixes())); // the one "normal" late fix is added on top of the fixes, but the two outliers should now be removed + } finally { + track.unlockAfterRead(); + } + GPSFix polishedLastFix2 = track.getLastFixBefore(new MillisecondsTimePoint(Long.MAX_VALUE)); // get the last smoothened fix... + PositionAssert.assertGPSFixEquals(fix, polishedLastFix2, /* pos deg delta */ 0.000001); + assertEquals(speed.getMetersPerSecond()*steps, track.getDistanceTraveled(now, start).getMeters(), 0.01); + } + + /** + * A test case for bug 968. If distances are requested for time intervals ending after the last GPS fix, the position + * is estimated to be at the last fix known. When another fix arrives, the positions for these time points can now be + * interpolated, leading to different results and hence to a cache inconsistency in case the cache isn't flushed for the + * interval between the last and the newest fix. This test case adds a few fixes, then asks a distance traveled for an + * interval ending after the last fix, then adds another fix at a later time point and asks the distance again. + */ + @Test + public void testMoreFrequentDistanceComputationThanGPSFixReception() { + DynamicGPSFixTrack track = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l); + final int timeBetweenFixesInMillis = 1000; + Bearing bearing = new DegreeBearingImpl(123); + SpeedWithBearing speed = new KnotSpeedWithBearingImpl(7, bearing); + Position p = new DegreePosition(0, 0); + final TimePoint now = MillisecondsTimePoint.now(); + TimePoint start = now; + final int steps = 10; + TimePoint next = null; + GPSFixMoving fix = null; + for (int i=0; i track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { + private static final long serialVersionUID = -7277196393160609503L; + @Override + protected DistanceCache getDistanceCache() { + return distanceCache; + } + }; + while (fixTime.before(start.plus(raceDuration))) { + for (int i=0; i= 0); + lastDistance = d; + queryTime = queryTime.plus(queryInterval); + } + } + assertTrue(distanceCache.size() <= DistanceCache.MAX_SIZE); + } + + @Test + public void testDistanceCacheAccessForPartialStrip() { + final Set invalidationCalls = new HashSet(); + final DistanceCache distanceCache = new DistanceCache("test-DistanceCache") { + @Override + public void invalidateAllAtOrLaterThan(TimePoint timePoint) { + super.invalidateAllAtOrLaterThan(timePoint); + invalidationCalls.add(timePoint); + } + }; + DynamicGPSFixTrack track = new DynamicGPSFixTrackImpl(new Object(), /* millisecondsOverWhichToAverage */ 30000l) { + private static final long serialVersionUID = -7277196393160609503L; + @Override + protected DistanceCache getDistanceCache() { + return distanceCache; + } + }; + final int timeBetweenFixesInMillis = 1000; + Bearing bearing = new DegreeBearingImpl(123); + Speed speed = new KnotSpeedImpl(7); + Position p = new DegreePosition(0, 0); + final TimePoint now = MillisecondsTimePoint.now(); + TimePoint start = now; + final int steps = 10; + TimePoint next = null; + for (int i=0; i> stripCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(stripFrom, stripTo); + assertEquals(stripTo, stripCacheEntry.getA()); + assertEquals(stripFrom, stripCacheEntry.getB().getA()); + // expect a cache entry exactly for the full boundaries + com.sap.sse.common.Util.Pair> fullCacheEntry = distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start); + assertEquals(start, fullCacheEntry.getA()); + assertEquals(now, fullCacheEntry.getB().getA()); + } + + @Test + public void testDistanceTraveledOnInBetweenSectionFromFixToFix() { + track.lockForRead(); + try { + // take second and third fix and compute distance between them + Iterator iter = track.getRawFixes().iterator(); + iter.next(); // skip first; + GPSFix second = iter.next(); + GPSFix third = iter.next(); + assertEquals(second.getPosition().getDistance(third.getPosition()), + track.getRawDistanceTraveled(second.getTimePoint(), third.getTimePoint())); + } finally { + track.unlockAfterRead(); + } + } + + @Test + public void testFarFutureFixNotUsedDuringEstimation() { + TimePoint normalFixesTime = null; + track.lockForRead(); + try { + Iterator iter = track.getRawFixes().iterator(); + for (int i = 0; i < 2; i++) { + normalFixesTime = iter.next().getTimePoint(); + } + assertNotNull(normalFixesTime); + } finally { + track.unlockAfterRead(); + } + SpeedWithBearing estimatedSpeed = track.getEstimatedSpeed(normalFixesTime); + GPSFixMovingImpl gpsFixFarInTheFuture = new GPSFixMovingImpl( + new DegreePosition(89, 180), new MillisecondsTimePoint( + System.currentTimeMillis()+10000000l), new KnotSpeedWithBearingImpl(200000, new DegreeBearingImpl(0))); + track.addGPSFix(gpsFixFarInTheFuture); + Position estimatedPosNew = track.getEstimatedPosition(normalFixesTime, /* extrapolate */ false); + // expecting to get the coordinates of gpsFix2's position + assertEquals(gpsFix2.getPosition().getLatDeg(), estimatedPosNew.getLatDeg(), 0.5); + assertEquals(gpsFix2.getPosition().getLngDeg(), estimatedPosNew.getLngDeg(), 0.5); + SpeedWithBearing estimatedSpeedNew = track.getEstimatedSpeed(normalFixesTime); + PositionAssert.assertSpeedEquals(estimatedSpeed, estimatedSpeedNew, /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); + } + + @Test + public void testValidCheckForFixThatSaysItsAsFastAsItWas() { + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + TimePoint now1 = MillisecondsTimePoint.now(); + TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s + AbstractBearing bearing = new DegreeBearingImpl(90); + Position position1 = new DegreePosition(1, 2); + Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); + GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(1, bearing)); + GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(1, bearing)); + myTrack.addGPSFix(myGpsFix1); + myTrack.addGPSFix(myGpsFix2); + myTrack.lockForRead(); + try { + assertEquals(2, myTrack.getFixes().size()); // expecting both fixes to be valid + } finally { + myTrack.unlockAfterRead(); + } + } + + @Test + public void testValidCheckForFixThatSaysItsFasterThanItActuallyWas() { + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + TimePoint now1 = MillisecondsTimePoint.now(); + TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s + AbstractBearing bearing = new DegreeBearingImpl(90); + Position position1 = new DegreePosition(1, 2); + Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); + GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(10, bearing)); + GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(10, bearing)); + myTrack.addGPSFix(myGpsFix1); + myTrack.addGPSFix(myGpsFix2); + myTrack.lockForRead(); + try { + assertTrue(myTrack.getFixes().size() < 2); // at least one fix must be classified as outlier + } finally { + myTrack.unlockAfterRead(); + } + } + + @Test + public void testValidCheckForFixThatSaysItsSlowerThanItActuallyWas() { + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new BoatImpl("123", "MyFirstBoat", new BoatClassImpl("505", /* typicallyStartsUpwind */ + true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); + TimePoint now1 = MillisecondsTimePoint.now(); + TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s + AbstractBearing bearing = new DegreeBearingImpl(90); + Position position1 = new DegreePosition(1, 2); + Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); + GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(0.1, bearing)); + GPSFixMovingImpl myGpsFix2 = new GPSFixMovingImpl(position2, now2, new MeterPerSecondSpeedWithDegreeBearingImpl(0.1, bearing)); + myTrack.addGPSFix(myGpsFix1); + myTrack.addGPSFix(myGpsFix2); + myTrack.lockForRead(); + try { + assertTrue(myTrack.getFixes().size() < 2); // at least one fix must be classified as outlier + } finally { + myTrack.unlockAfterRead(); + } + } + + @Test + public void testInvalidationIntervalBeginningForPositionEstimation() { + track.lockForRead(); + final GPSFixMoving firstFixSoFar; + try { + firstFixSoFar = track.getFixes().iterator().next(); + } finally { + track.unlockAfterRead(); + } + assertNotNull(firstFixSoFar); + TimePoint beginningOfTime = new MillisecondsTimePoint(0); + Position positionAtBeginningOfTime = track.getEstimatedPosition(beginningOfTime, /* extrapolate */false); + long timespan = 2 /* hours */ * 3600 /* seconds/hour */ * 1000 /* millis/s */; + SpeedWithBearing speed = new KnotSpeedWithBearingImpl(45, new DegreeBearingImpl(123)); + TimePoint slightlyBeforeFirstFix = firstFixSoFar.getTimePoint().minus(timespan); + Position newPosition = firstFixSoFar.getPosition().translateGreatCircle(speed.getBearing().reverse(), + speed.travel(firstFixSoFar.getTimePoint(), firstFixSoFar.getTimePoint().plus(timespan))); + GPSFixMoving newFirstFix = new GPSFixMovingImpl(newPosition, slightlyBeforeFirstFix, speed); + track.addGPSFix(newFirstFix); + TimeRange intervalAffected = track.getEstimatedPositionTimePeriodAffectedBy(newFirstFix); + Position newPositionAtBeginningOfTime = track.getEstimatedPosition(beginningOfTime, /* extrapolate */false); + assertFalse(newPositionAtBeginningOfTime.equals(positionAtBeginningOfTime)); + assertTrue(!intervalAffected.from().after(beginningOfTime)); + } + + @Test + public void testInvalidationIntervalEndForPositionEstimation() { + TimePoint endOfTime = new MillisecondsTimePoint(Long.MAX_VALUE); + final GPSFixMoving lastFixSoFar = track.getLastFixBefore(endOfTime); + assertNotNull(lastFixSoFar); + Position positionAtEndOfTime = track.getEstimatedPosition(endOfTime, /* extrapolate */false); + long timespan = 2 /* hours */ * 3600 /* seconds/hour */ * 1000 /* millis/s */; + SpeedWithBearing speed = new KnotSpeedWithBearingImpl(45, new DegreeBearingImpl(123)); + TimePoint slightlyAfterLastFix = lastFixSoFar.getTimePoint().plus(timespan); + Position newPosition = lastFixSoFar.getPosition().translateGreatCircle(speed.getBearing(), + speed.travel(lastFixSoFar.getTimePoint(), lastFixSoFar.getTimePoint().plus(timespan))); + GPSFixMoving newLastFix = new GPSFixMovingImpl(newPosition, slightlyAfterLastFix, speed); + track.addGPSFix(newLastFix); + TimeRange intervalAffected = track.getEstimatedPositionTimePeriodAffectedBy(newLastFix); + Position newPositionAtEndOfTime = track.getEstimatedPosition(endOfTime, /* extrapolate */false); + assertFalse(newPositionAtEndOfTime.equals(positionAtEndOfTime)); + assertTrue(!intervalAffected.to().before(endOfTime)); + } + + @Test + public void testInvalidationIntervalForPositionEstimationForEmptyTrack() { + TimePoint now = MillisecondsTimePoint.now(); + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); + TimePoint beginningOfTime = new MillisecondsTimePoint(0); + Position positionAtBeginningOfTime = myTrack.getEstimatedPosition(beginningOfTime, /* extrapolate */false); + TimePoint endOfTime = new MillisecondsTimePoint(Long.MAX_VALUE); + Position positionAtEndOfTime = myTrack.getEstimatedPosition(endOfTime, /* extrapolate */false); + assertNull(positionAtBeginningOfTime); + assertNull(positionAtEndOfTime); + GPSFixMoving newFix = new GPSFixMovingImpl(new DegreePosition(12, 34), now, new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); + myTrack.addGPSFix(newFix); + TimeRange intervalAffected = myTrack.getEstimatedPositionTimePeriodAffectedBy(newFix); + Position newPositionAtBeginningOfTime = myTrack.getEstimatedPosition(beginningOfTime, /* extrapolate */false); + Position newPositionAtEndOfTime = myTrack.getEstimatedPosition(now, /* extrapolate */false); + assertFalse(newPositionAtBeginningOfTime.equals(positionAtBeginningOfTime)); + assertTrue(!intervalAffected.from().after(beginningOfTime)); + assertFalse(newPositionAtEndOfTime.equals(positionAtEndOfTime)); + assertTrue(!intervalAffected.to().before(endOfTime)); + } + + @Test + public void testSpeedEstimationForCourseChangeAtFix() throws ParseException { + /* + * See bug 1065, first test data set: [2011-06-23T16:08:27.000+0200: (54.49155,10.184947) with + * 5.399568034557236kn to 291.0�, 2011-06-23T16:08:31.000+0200: (54.491597,10.184808) with 5.939524838012959kn + * to 296.0�, 2011-06-23T16:08:37.000+0200: (54.491572999999995,10.184669999999999) with 3.7796976241900646kn + * to 210.0�, 2011-06-23T16:08:39.000+0200: (54.491523,10.184602) with 5.939524838012959kn to 219.0�, + * 2011-06-23T16:08:43.000+0200: (54.491457999999994,10.18451) with 4.859611231101512kn to 225.0�, + * 2011-06-23T16:08:45.000+0200: (54.491386999999996,10.184455) with 5.939524838012959kn to 196.0�] + * + * let the track estimate the speed at 16:08:37 at + * + * 5.469864974239993kn to 215.50791079454874� + */ + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); + GPSFixMoving fix1 = createFix("2011-06-23T16:08:27.000+0200", 54.49155, 10.184947, 5.399568034557236, 291.0); + myTrack.addGPSFix(fix1); + GPSFixMoving fix2 = createFix("2011-06-23T16:08:31.000+0200", 54.491597,10.184808, 5.939524838012959, 296.0); + myTrack.addGPSFix(fix2); + GPSFixMoving fix3 = createFix("2011-06-23T16:08:37.000+0200", 54.491572999999995,10.184669999999999, 3.7796976241900646, 210.0); + myTrack.addGPSFix(fix3); + GPSFixMoving fix4 = createFix("2011-06-23T16:08:39.000+0200", 54.491523, 10.184602, 5.939524838012959, 219.0); + myTrack.addGPSFix(fix4); + GPSFixMoving fix5 = createFix("2011-06-23T16:08:43.000+0200", 54.491457999999994, 10.18451, 4.859611231101512, 225.0); + myTrack.addGPSFix(fix5); + GPSFixMoving fix6 = createFix("2011-06-23T16:08:45.000+0200", 54.491386999999996, 10.184455, 5.939524838012959, 196.0); + myTrack.addGPSFix(fix6); + final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + SpeedWithBearing estimatedSpeedWithBearing = myTrack.getEstimatedSpeed(new MillisecondsTimePoint(dateFormatter.parse("2011-06-23T16:08:37.000+0200"))); + assertEquals(225., estimatedSpeedWithBearing.getBearing().getDegrees(), 5); + assertEquals(5.0, estimatedSpeedWithBearing.getKnots(), 0.2); + } + + @Test + public void testSpeedEstimationForCourseChangeBetweenFixes() throws ParseException { + /* + * See bug 1065, first test data set: [2012-10-21T15:00:32.000+0200: (43.692862999999996,7.267875) with + * 16.73866090712743kn to 294.0°, 2012-10-21T15:00:34.000+0200: (43.692937,7.267683) with 16.73866090712743kn + * to 299.0°, 2012-10-21T15:00:36.000+0200: (43.693017,7.267487999999999) with 16.73866090712743kn to 300.0°, + * 2012-10-21T15:00:38.000+0200: (43.693103,7.267297999999999) with 16.73866090712743kn to 300.0°, + * 2012-10-21T15:00:40.000+0200: (43.693191999999996,7.267112) with 16.73866090712743kn to 303.0°, + * 2012-10-21T15:00:43.000+0200: (43.693283,7.2669179999999995) with 18.898488120950326kn to 302.0°] + * 2012-10-21T15:00:51.000+0200: (43.693245,7.266183) with 11.339092872570195kn to 237.0° + */ + DynamicGPSFixMovingTrackImpl myTrack = new DynamicGPSFixMovingTrackImpl(new Object(), /* millisecondsOverWhichToAverage */5000); + GPSFixMoving fix1 = createFix("2012-10-21T15:00:32.000+0200", 43.692862999999996,7.267875, 16.73866090712743, 294.0); + myTrack.addGPSFix(fix1); + GPSFixMoving fix2 = createFix("2012-10-21T15:00:34.000+0200", 43.692937, 7.267683, 16.73866090712743, 299.0); + myTrack.addGPSFix(fix2); + GPSFixMoving fix3 = createFix("2012-10-21T15:00:36.000+0200", 43.693017, 7.267487999999999, 16.73866090712743, 300.0); + myTrack.addGPSFix(fix3); + GPSFixMoving fix4 = createFix("2012-10-21T15:00:38.000+0200", 43.693103, 7.267297999999999, 16.73866090712743, 300.0); + myTrack.addGPSFix(fix4); + GPSFixMoving fix5 = createFix("2012-10-21T15:00:40.000+0200", 43.693191999999996, 7.267112, 16.73866090712743, 303.0); + myTrack.addGPSFix(fix5); + GPSFixMoving fix6 = createFix("2012-10-21T15:00:43.000+0200", 43.693283, 7.2669179999999995, 18.898488120950326, 302.0); + myTrack.addGPSFix(fix6); + GPSFixMoving fix7 = createFix("2012-10-21T15:00:51.000+0200", 43.693245, 7.266183, 11.339092872570195, 237.0); + myTrack.addGPSFix(fix7); + final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + SpeedWithBearing estimatedSpeedWithBearing = myTrack.getEstimatedSpeed(new MillisecondsTimePoint(dateFormatter.parse("2012-10-21T15:00:45.000+0200"))); + assertEquals(275., estimatedSpeedWithBearing.getBearing().getDegrees(), 5); + assertEquals(15.9, estimatedSpeedWithBearing.getKnots(), 0.2); + } + + private GPSFixMoving createFix(String isoDateTime, double lat, double lng, double knotSpeed, double bearingDeg) throws ParseException { + final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + TimePoint timePoint = new MillisecondsTimePoint(dateFormatter.parse(isoDateTime)); + Position position = new DegreePosition(lat, lng); + SpeedWithBearing speed = new KnotSpeedWithBearingImpl(knotSpeed, new DegreeBearingImpl(bearingDeg)); + GPSFixMoving fix = new GPSFixMovingImpl(position, timePoint, speed); + return fix; + } + + @Test + public void testFrequency() { + assertEquals(MILLIS_BETWEEN_FIXES, track.getAverageIntervalBetweenFixes().asMillis()); + assertEquals(MILLIS_BETWEEN_FIXES, track.getAverageIntervalBetweenRawFixes().asMillis()); + } + + @Test + public void testEstimatedSpeedCaching() throws CompactionNotPossibleException { + GPSFixMoving originalFix = new GPSFixMovingImpl(new DegreePosition(12, 34), MillisecondsTimePoint.now(), + new KnotSpeedWithBearingImpl(9, new DegreeBearingImpl(123))); + GPSFixMoving fix = new VeryCompactGPSFixMovingImpl(originalFix); + assertFalse(fix.isEstimatedSpeedCached()); + final KnotSpeedWithBearingImpl estimatedSpeed = new KnotSpeedWithBearingImpl(9.1, new DegreeBearingImpl(124)); + fix.cacheEstimatedSpeed(estimatedSpeed); + assertTrue(fix.isEstimatedSpeedCached()); + SpeedWithBearing cachedEstimatedSpeed = fix.getCachedEstimatedSpeed(); + PositionAssert.assertSpeedEquals(estimatedSpeed, cachedEstimatedSpeed, /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); + fix.invalidateEstimatedSpeedCache(); + assertFalse(fix.isEstimatedSpeedCached()); + } + + @Test + public void testEstimatedSpeedCachingOnTrack() { + GPSFixMoving compactFix3 = track.getFirstFixAtOrAfter(gpsFix3.getTimePoint()); + assertFalse(compactFix3.isEstimatedSpeedCached()); + SpeedWithBearing fix3EstimatedSpeed = track.getEstimatedSpeed(gpsFix3.getTimePoint()); + assertTrue(compactFix3.isEstimatedSpeedCached()); + PositionAssert.assertSpeedEquals(fix3EstimatedSpeed, compactFix3.getCachedEstimatedSpeed(), /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); + PositionAssert.assertSpeedEquals(fix3EstimatedSpeed, track.getEstimatedSpeed(gpsFix3.getTimePoint()), + /* bearing deg delta */ 0.1, /* knot speed delta */ 0.1); // fetch again from the cache + // assuming that all test fixes are within a few milliseconds and the averaging interval is much larger than that, + // adding a single fix in the middle should invalidate the cache + track.add(new GPSFixMovingImpl(gpsFix3.getPosition(), gpsFix3.getTimePoint().plus(1), gpsFix3.getSpeed())); + assertFalse(compactFix3.isEstimatedSpeedCached()); + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java index 5608a0fd9a7..fb5ac0560dc 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java @@ -1,97 +1,97 @@ -package com.sap.sailing.domain.base; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; - -import com.sap.sailing.domain.base.impl.DomainFactoryImpl; -import com.sap.sailing.domain.common.Placemark; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.PlacemarkDTO; -import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.domain.common.dto.TrackedRaceDTO; -import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; -import com.sap.sailing.domain.common.media.MediaTrack; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sse.common.IsManagedByCache; -import com.sap.sse.common.TimePoint; -import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; - -public interface DomainFactory extends SharedDomainFactory { - /** - * A default domain factory for test purposes only. In a server environment, ensure NOT to use this. Use - * the RacingEventService.getBaseDomainFactory() instead which should be the single instance used - * by all other services linked to the RacingEventService. - */ - static DomainFactory INSTANCE = new DomainFactoryImpl((srlid)->null); - - MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor); - - /** - * When de-serializing objects of types whose instances that are managed and cached by this domain factory, - * de-serialized instances need to be replaced by / resolved to the counterparts already known by this factory. The - * stream returned by this method can be used to have objects implementing the {@link IsManagedByCache} interface - * {@link IsManagedByCache#resolve(Object) resolve} against this domain factory as their cache. - *

- * - * Note: In order to allow the deserialization process to find all the classes required, it is a good idea to - * {@link Thread#setContextClassLoader(ClassLoader) set the context class loader} on the - * {@link Thread#currentThread() current thread} to one that can see and resolve all the classes that have instances - * in the stream. Example:

-     *          ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
-     *          Thread.currentThread().setContextClassLoader(TopLevelMasterData.class.getClassLoader());
-     *          Object o = domainFactory.createObjectInputStreamResolvingAgainstThisFactory(inputStream).readObject();
-     *          Thread.currentThread().setContextClassLoader(oldContextClassLoader);
-     * 
- */ - ObjectInputStreamResolvingAgainstCache createObjectInputStreamResolvingAgainstThisFactory(InputStream inputStream) throws IOException; - - ScoringScheme createScoringScheme(ScoringSchemeType scoringSchemeType); - - CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); - - /** Temporary functions -> REMOVE later on */ - CompetitorDTO convertToCompetitorDTO(Competitor c); - - CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); - - CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); - - BoatDTO convertToBoatDTO(Boat boat); - - FleetDTO convertToFleetDTO(Fleet fleet); - - /** - * @param trackedRace must not be null - */ - RaceDTO createRaceDTO(TrackedRegattaRegistry trackedRegattaRegistry, boolean withGeoLocationData, RegattaAndRaceIdentifier raceIdentifier, TrackedRace trackedRace); - - PlacemarkDTO convertToPlacemarkDTO(Placemark placemark); - - List getCompetitorDTOList(List competitors); - - /** Temporary function -> REMOVE later on */ - List getCompetitorWithoutBoatDTOListTemp(List competitors); - - List getCompetitorDTOListTemp(List competitors); - - TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); - - TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn, - Fleet fleet, Iterable mediatracks); - - /** - * @param trackedRace must not be null - */ - void updateRaceDTOWithTrackedRaceData(TrackedRace trackedRace, RaceDTO raceDTO); - -} +package com.sap.sailing.domain.base; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.common.Placemark; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.PlacemarkDTO; +import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; +import com.sap.sse.common.IsManagedByCache; +import com.sap.sse.common.TimePoint; +import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; + +public interface DomainFactory extends SharedDomainFactory { + /** + * A default domain factory for test purposes only. In a server environment, ensure NOT to use this. Use + * the RacingEventService.getBaseDomainFactory() instead which should be the single instance used + * by all other services linked to the RacingEventService. + */ + static DomainFactory INSTANCE = new DomainFactoryImpl((srlid)->null); + + MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor); + + /** + * When de-serializing objects of types whose instances that are managed and cached by this domain factory, + * de-serialized instances need to be replaced by / resolved to the counterparts already known by this factory. The + * stream returned by this method can be used to have objects implementing the {@link IsManagedByCache} interface + * {@link IsManagedByCache#resolve(Object) resolve} against this domain factory as their cache. + *

+ * + * Note: In order to allow the deserialization process to find all the classes required, it is a good idea to + * {@link Thread#setContextClassLoader(ClassLoader) set the context class loader} on the + * {@link Thread#currentThread() current thread} to one that can see and resolve all the classes that have instances + * in the stream. Example:

+     *          ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
+     *          Thread.currentThread().setContextClassLoader(TopLevelMasterData.class.getClassLoader());
+     *          Object o = domainFactory.createObjectInputStreamResolvingAgainstThisFactory(inputStream).readObject();
+     *          Thread.currentThread().setContextClassLoader(oldContextClassLoader);
+     * 
+ */ + ObjectInputStreamResolvingAgainstCache createObjectInputStreamResolvingAgainstThisFactory(InputStream inputStream) throws IOException; + + ScoringScheme createScoringScheme(ScoringSchemeType scoringSchemeType); + + CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); + + /** Temporary functions -> REMOVE later on */ + CompetitorDTO convertToCompetitorDTO(Competitor c); + + CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); + + CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); + + BoatDTO convertToBoatDTO(Boat boat); + + FleetDTO convertToFleetDTO(Fleet fleet); + + /** + * @param trackedRace must not be null + */ + RaceDTO createRaceDTO(TrackedRegattaRegistry trackedRegattaRegistry, boolean withGeoLocationData, RegattaAndRaceIdentifier raceIdentifier, TrackedRace trackedRace); + + PlacemarkDTO convertToPlacemarkDTO(Placemark placemark); + + List getCompetitorDTOList(List competitors); + + /** Temporary function -> REMOVE later on */ + List getCompetitorWithoutBoatDTOListTemp(List competitors); + + List getCompetitorDTOListTemp(List competitors); + + TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); + + TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn, + Fleet fleet, Iterable mediatracks); + + /** + * @param trackedRace must not be null + */ + void updateRaceDTOWithTrackedRaceData(TrackedRace trackedRace, RaceDTO raceDTO); + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 2c38cc3e6a1..b35187d4fb5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -1,392 +1,392 @@ -package com.sap.sailing.domain.base.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.logging.Logger; - -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.CompetitorWithBoat; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Placemark; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.PlacemarkDTO; -import com.sap.sailing.domain.common.dto.PlacemarkOrderDTO; -import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.domain.common.dto.RaceStatusDTO; -import com.sap.sailing.domain.common.dto.TrackedRaceDTO; -import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.media.MediaTrack; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.impl.HighPoint; -import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; -import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall12PointsMax; -import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie; -import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10Or8AndLastBreaksTie; -import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBreaksTie; -import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBreaksTie2017; -import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie; -import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; -import com.sap.sailing.domain.leaderboard.impl.HighPointMatchRacing; -import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEight; -import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterpolation; -import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; -import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard; -import com.sap.sailing.domain.leaderboard.impl.LowPointTieBreakBasedOnLastSeriesOnly; -import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero; -import com.sap.sailing.domain.leaderboard.impl.LowPointWithEliminationsAndRoundsWinnerGets07; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; -import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; -import com.sap.sailing.geocoding.ReverseGeocoder; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; - -public class DomainFactoryImpl extends SharedDomainFactoryImpl implements DomainFactory { - private static Logger logger = Logger.getLogger(DomainFactoryImpl.class.getName()); - - /** - * Uses a transient competitor store - */ - public DomainFactoryImpl(RaceLogResolver raceLogResolver) { - super(new TransientCompetitorStoreImpl(), raceLogResolver); - } - - public DomainFactoryImpl(CompetitorStore competitorStore, RaceLogResolver raceLogResolver) { - super(competitorStore, raceLogResolver); - } - - @Override - public MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor) { - return new MarkPassingImpl(timePoint, waypoint, competitor); - } - - @Override - public ObjectInputStreamResolvingAgainstCache createObjectInputStreamResolvingAgainstThisFactory(InputStream inputStream) throws IOException { - return new ObjectInputStreamResolvingAgainstDomainFactoryImpl(inputStream, this); - } - - @Override - public ScoringScheme createScoringScheme(ScoringSchemeType scoringSchemeType) { - switch (scoringSchemeType) { - case LOW_POINT: - return new LowPoint(); - case HIGH_POINT: - return new HighPoint(); - case HIGH_POINT_ESS_OVERALL: - return new HighPointExtremeSailingSeriesOverall(); - case HIGH_POINT_ESS_OVERALL_12: - return new HighPointExtremeSailingSeriesOverall12PointsMax(); - case HIGH_POINT_LAST_BREAKS_TIE: - return new HighPointLastBreaksTie(); - case HIGH_POINT_FIRST_GETS_ONE: - return new HighPointFirstGets1LastBreaksTie(); - case HIGH_POINT_FIRST_GETS_TEN: - return new HighPointFirstGets10LastBreaksTie(); - case LOW_POINT_WINNER_GETS_ZERO: - return new LowPointWinnerGetsZero(); - case HIGH_POINT_WINNER_GETS_FIVE: - return new HighPointWinnerGetsFive(); - case HIGH_POINT_WINNER_GETS_SIX: - return new HighPointWinnerGetsSix(); - case HIGH_POINT_WINNER_GETS_EIGHT: - return new HighPointWinnerGetsEight(); - case HIGH_POINT_MATCH_RACING: - return new HighPointMatchRacing(); - case HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION: - return new HighPointWinnerGetsEightAndInterpolation(); - case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT: - return new HighPointFirstGets10Or8AndLastBreaksTie(); - case HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT: - return new HighPointFirstGets12Or8AndLastBreaksTie(); - case HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT_2017: - return new HighPointFirstGets12Or8AndLastBreaksTie2017(); - case LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07: - return new LowPointWithEliminationsAndRoundsWinnerGets07(); - case LOW_POINT_LEAGUE_OVERALL: - return new LowPointForLeagueOverallLeaderboard(); - case LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY: - return new LowPointTieBreakBasedOnLastSeriesOnly(); - } - throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name()); - } - - @Override - public CompetitorDTO convertToCompetitorDTO(Competitor competitor) { - return competitorAndBoatStore.convertToCompetitorDTO(competitor, null); - } - - @Override - public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { - return competitorAndBoatStore.convertToCompetitorDTO(competitor, boat); - } - - @Override - public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c) { - return competitorAndBoatStore.convertToCompetitorDTO(c); - } - - @Override - public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { - return competitorAndBoatStore.convertToCompetitorWithoutBoatDTO(c); - } - - @Override - public BoatDTO convertToBoatDTO(Boat boat) { - return competitorAndBoatStore.convertToBoatDTO(boat); - } - - @Override - public FleetDTO convertToFleetDTO(Fleet fleet) { - return new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); - } - - @Override - public RaceDTO createRaceDTO(TrackedRegattaRegistry trackedRegattaRegistry, boolean withGeoLocationData, RegattaAndRaceIdentifier raceIdentifier, TrackedRace trackedRace) { - assert trackedRace != null; - // Optional: Getting the places of the race - PlacemarkOrderDTO racePlaces = withGeoLocationData ? getRacePlaces(trackedRace) : null; - TrackedRaceDTO trackedRaceDTO = createTrackedRaceDTO(trackedRace); - RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked( - trackedRace.getTrackedRegatta().getRegatta(), trackedRace.getRace())); - raceDTO.places = racePlaces; - updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO); - return raceDTO; - } - - @Override - public void updateRaceDTOWithTrackedRaceData(TrackedRace trackedRace, RaceDTO raceDTO) { - assert trackedRace != null; - raceDTO.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate(); - raceDTO.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate(); - raceDTO.status = new RaceStatusDTO(); - raceDTO.status.status = trackedRace.getStatus() == null ? null : trackedRace.getStatus().getStatus(); - raceDTO.status.loadingProgress = trackedRace.getStatus() == null ? 0.0 : trackedRace.getStatus().getLoadingProgress(); - } - - @Override - public TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace) { - TrackedRaceDTO trackedRaceDTO = new TrackedRaceDTO(); - trackedRaceDTO.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate(); - trackedRaceDTO.endOfTracking = trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asDate(); - trackedRaceDTO.timePointOfNewestEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate(); - trackedRaceDTO.hasWindData = trackedRace.hasWindData(); - trackedRaceDTO.hasGPSData = trackedRace.hasGPSData(); - trackedRaceDTO.delayToLiveInMs = trackedRace.getDelayToLiveInMillis(); - return trackedRaceDTO; - } - - @Override - public TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, - RaceColumn raceColumn, Fleet fleet, Iterable mediaTracks) { - TrackedRaceStatisticsDTO statisticsDTO = new TrackedRaceStatisticsDTO(); - // GPS data - statisticsDTO.hasGPSData = trackedRace.hasGPSData(); - Competitor leaderOrWinner = null; - Boat leaderOrWinnerBoat = null; - TimePoint now = MillisecondsTimePoint.now(); - try { - if (trackedRace.isLive(now)) { - leaderOrWinner = trackedRace.getOverallLeader(now); - } else if (trackedRace.getEndOfRace() != null) { - for (Competitor competitor : leaderboard.getCompetitorsFromBestToWorst(raceColumn, now)) { - Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); - if (fleetOfCompetitor != null && fleetOfCompetitor.equals(fleet)) { - leaderOrWinner = competitor; - leaderOrWinnerBoat = trackedRace.getBoatOfCompetitor(leaderOrWinner); - break; - } - } - } - if (leaderOrWinner != null) { - statisticsDTO.hasLeaderOrWinnerData = true; - statisticsDTO.leaderOrWinner = convertToCompetitorDTO(leaderOrWinner, leaderOrWinnerBoat); - GPSFixTrack track = trackedRace.getTrack(leaderOrWinner); - if (track != null) { - statisticsDTO.averageGPSDataSampleInterval = track.getAverageIntervalBetweenRawFixes(); - } - } - } catch (NoWindException e) { - } - - // Measured wind sources data - statisticsDTO.measuredWindSourcesCount = Util.size(trackedRace.getWindSources(WindSourceType.EXPEDITION)); - statisticsDTO.hasMeasuredWindData = statisticsDTO.measuredWindSourcesCount > 0; - - // leg progress data - RaceDefinition race = trackedRace.getRace(); - if (race.getCourse() != null) { - statisticsDTO.hasLegProgressData = true; - statisticsDTO.totalLegsCount = race.getCourse().getLegs().size(); - statisticsDTO.currentLegNo = trackedRace.getLastLegStarted(MillisecondsTimePoint.now()); - } - - // media data - if (mediaTracks != null) { - for (MediaTrack track : mediaTracks) { - switch (track.mimeType.mediaType) { - case audio: - statisticsDTO.hasAudioData = true; - statisticsDTO.audioTracksCount = statisticsDTO.audioTracksCount == null ? 1 - : statisticsDTO.audioTracksCount++; - break; - case video: - statisticsDTO.hasVideoData = true; - statisticsDTO.videoTracksCount = statisticsDTO.videoTracksCount == null ? 1 - : statisticsDTO.videoTracksCount++; - break; - case image: // TODO should this add to an image count? - break; - case unknown: // TODO should this add to an "unknown media" count? Probably not - break; - default: - break; - } - } - } - - return statisticsDTO; - } - - private PlacemarkOrderDTO getRacePlaces(TrackedRace trackedRace) { - Util.Pair startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace); - PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO(); - if (startAndFinish.getA() != null) { - racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getA())); - } - if (startAndFinish.getB() != null) { - racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getB())); - } - if (racePlaces.isEmpty()) { - racePlaces = null; - } - return racePlaces; - } - - private Util.Pair getStartFinishPlacemarksForTrackedRace(TrackedRace race) { - double radiusCalculationFactor = 10.0; - Placemark startBest = null; - Placemark finishBest = null; - Position startPosition = null; - - // Get start postition - final Waypoint firstWaypoint = race.getRace().getCourse().getFirstWaypoint(); - if (firstWaypoint != null) { - Iterator startMarks = firstWaypoint.getMarks().iterator(); - GPSFix startMarkFix = startMarks.hasNext() ? race.getOrCreateTrack(startMarks.next()).getLastRawFix() : null; - startPosition = startMarkFix != null ? startMarkFix.getPosition() : null; - if (startPosition != null) { - try { - // Get distance to nearest placemark and calculate the search radius - Placemark startNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(startPosition); - if (startNearest != null) { - Distance startNearestDistance = startNearest.distanceFrom(startPosition); - double startRadius = startNearestDistance.getKilometers() * radiusCalculationFactor; - - // Get the estimated best start place - startBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(startPosition, startRadius, - new Placemark.ByPopulationDistanceRatio(startPosition)); - } - } catch (IOException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } catch (org.json.simple.parser.ParseException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } - } - } - - // Get finish position - final Waypoint lastWaypoint = race.getRace().getCourse().getLastWaypoint(); - if (lastWaypoint != null) { - Iterator finishMarks = firstWaypoint.getMarks().iterator(); - GPSFix finishMarkFix = finishMarks.hasNext() ? race.getOrCreateTrack(finishMarks.next()).getLastRawFix() : null; - Position finishPosition = finishMarkFix != null ? finishMarkFix.getPosition() : null; - if (startPosition != null && finishPosition != null) { - if (startPosition.getDistance(finishPosition).getKilometers() <= ReverseGeocoder.POSITION_CACHE_DISTANCE_LIMIT_IN_KM) { - finishBest = startBest; - } else { - try { - // Get distance to nearest placemark and calculate the search radius - Placemark finishNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(finishPosition); - Distance finishNearestDistance = finishNearest.distanceFrom(finishPosition); - double finishRadius = finishNearestDistance.getKilometers() * radiusCalculationFactor; - - // Get the estimated best finish place - finishBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(finishPosition, finishRadius, - new Placemark.ByPopulationDistanceRatio(finishPosition)); - } catch (IOException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } catch (org.json.simple.parser.ParseException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } - } - } - } - Util.Pair placemarks = new Util.Pair(startBest, finishBest); - return placemarks; - } - - @Override - public PlacemarkDTO convertToPlacemarkDTO(Placemark placemark) { - Position position = placemark.getPosition(); - return new PlacemarkDTO(placemark.getName(), placemark.getCountryCode(), new DegreePosition(position.getLatDeg(), - position.getLngDeg()), placemark.getPopulation()); - } - - @Override - public List getCompetitorDTOList(List competitors) { - List result = new ArrayList(); - for (CompetitorWithBoat competitor : competitors) { - result.add(convertToCompetitorDTO(competitor)); - } - return result; - } - - @Override - public List getCompetitorDTOListTemp(List competitors) { - List result = new ArrayList(); - for (Competitor competitor : competitors) { - result.add(convertToCompetitorDTO(competitor)); - } - return result; - } - - @Override - public List getCompetitorWithoutBoatDTOListTemp(List competitors) { - List result = new ArrayList(); - for (Competitor competitor : competitors) { - result.add(convertToCompetitorWithoutBoatDTO(competitor)); - } - return result; - } -} +package com.sap.sailing.domain.base.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.Placemark; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.PlacemarkDTO; +import com.sap.sailing.domain.common.dto.PlacemarkOrderDTO; +import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.dto.RaceStatusDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.impl.HighPoint; +import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; +import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall12PointsMax; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10Or8AndLastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets12Or8AndLastBreaksTie2017; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointMatchRacing; +import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEight; +import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterpolation; +import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; +import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard; +import com.sap.sailing.domain.leaderboard.impl.LowPointTieBreakBasedOnLastSeriesOnly; +import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero; +import com.sap.sailing.domain.leaderboard.impl.LowPointWithEliminationsAndRoundsWinnerGets07; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; +import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; +import com.sap.sailing.geocoding.ReverseGeocoder; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; + +public class DomainFactoryImpl extends SharedDomainFactoryImpl implements DomainFactory { + private static Logger logger = Logger.getLogger(DomainFactoryImpl.class.getName()); + + /** + * Uses a transient competitor store + */ + public DomainFactoryImpl(RaceLogResolver raceLogResolver) { + super(new TransientCompetitorStoreImpl(), raceLogResolver); + } + + public DomainFactoryImpl(CompetitorStore competitorStore, RaceLogResolver raceLogResolver) { + super(competitorStore, raceLogResolver); + } + + @Override + public MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor) { + return new MarkPassingImpl(timePoint, waypoint, competitor); + } + + @Override + public ObjectInputStreamResolvingAgainstCache createObjectInputStreamResolvingAgainstThisFactory(InputStream inputStream) throws IOException { + return new ObjectInputStreamResolvingAgainstDomainFactoryImpl(inputStream, this); + } + + @Override + public ScoringScheme createScoringScheme(ScoringSchemeType scoringSchemeType) { + switch (scoringSchemeType) { + case LOW_POINT: + return new LowPoint(); + case HIGH_POINT: + return new HighPoint(); + case HIGH_POINT_ESS_OVERALL: + return new HighPointExtremeSailingSeriesOverall(); + case HIGH_POINT_ESS_OVERALL_12: + return new HighPointExtremeSailingSeriesOverall12PointsMax(); + case HIGH_POINT_LAST_BREAKS_TIE: + return new HighPointLastBreaksTie(); + case HIGH_POINT_FIRST_GETS_ONE: + return new HighPointFirstGets1LastBreaksTie(); + case HIGH_POINT_FIRST_GETS_TEN: + return new HighPointFirstGets10LastBreaksTie(); + case LOW_POINT_WINNER_GETS_ZERO: + return new LowPointWinnerGetsZero(); + case HIGH_POINT_WINNER_GETS_FIVE: + return new HighPointWinnerGetsFive(); + case HIGH_POINT_WINNER_GETS_SIX: + return new HighPointWinnerGetsSix(); + case HIGH_POINT_WINNER_GETS_EIGHT: + return new HighPointWinnerGetsEight(); + case HIGH_POINT_MATCH_RACING: + return new HighPointMatchRacing(); + case HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION: + return new HighPointWinnerGetsEightAndInterpolation(); + case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT: + return new HighPointFirstGets10Or8AndLastBreaksTie(); + case HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT: + return new HighPointFirstGets12Or8AndLastBreaksTie(); + case HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT_2017: + return new HighPointFirstGets12Or8AndLastBreaksTie2017(); + case LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07: + return new LowPointWithEliminationsAndRoundsWinnerGets07(); + case LOW_POINT_LEAGUE_OVERALL: + return new LowPointForLeagueOverallLeaderboard(); + case LOW_POINT_TIE_BREAK_BASED_ON_LAST_SERIES_ONLY: + return new LowPointTieBreakBasedOnLastSeriesOnly(); + } + throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name()); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(Competitor competitor) { + return competitorAndBoatStore.convertToCompetitorDTO(competitor, null); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { + return competitorAndBoatStore.convertToCompetitorDTO(competitor, boat); + } + + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c) { + return competitorAndBoatStore.convertToCompetitorDTO(c); + } + + @Override + public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { + return competitorAndBoatStore.convertToCompetitorWithoutBoatDTO(c); + } + + @Override + public BoatDTO convertToBoatDTO(Boat boat) { + return competitorAndBoatStore.convertToBoatDTO(boat); + } + + @Override + public FleetDTO convertToFleetDTO(Fleet fleet) { + return new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); + } + + @Override + public RaceDTO createRaceDTO(TrackedRegattaRegistry trackedRegattaRegistry, boolean withGeoLocationData, RegattaAndRaceIdentifier raceIdentifier, TrackedRace trackedRace) { + assert trackedRace != null; + // Optional: Getting the places of the race + PlacemarkOrderDTO racePlaces = withGeoLocationData ? getRacePlaces(trackedRace) : null; + TrackedRaceDTO trackedRaceDTO = createTrackedRaceDTO(trackedRace); + RaceDTO raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, trackedRegattaRegistry.isRaceBeingTracked( + trackedRace.getTrackedRegatta().getRegatta(), trackedRace.getRace())); + raceDTO.places = racePlaces; + updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO); + return raceDTO; + } + + @Override + public void updateRaceDTOWithTrackedRaceData(TrackedRace trackedRace, RaceDTO raceDTO) { + assert trackedRace != null; + raceDTO.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate(); + raceDTO.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate(); + raceDTO.status = new RaceStatusDTO(); + raceDTO.status.status = trackedRace.getStatus() == null ? null : trackedRace.getStatus().getStatus(); + raceDTO.status.loadingProgress = trackedRace.getStatus() == null ? 0.0 : trackedRace.getStatus().getLoadingProgress(); + } + + @Override + public TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace) { + TrackedRaceDTO trackedRaceDTO = new TrackedRaceDTO(); + trackedRaceDTO.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate(); + trackedRaceDTO.endOfTracking = trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asDate(); + trackedRaceDTO.timePointOfNewestEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate(); + trackedRaceDTO.hasWindData = trackedRace.hasWindData(); + trackedRaceDTO.hasGPSData = trackedRace.hasGPSData(); + trackedRaceDTO.delayToLiveInMs = trackedRace.getDelayToLiveInMillis(); + return trackedRaceDTO; + } + + @Override + public TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, + RaceColumn raceColumn, Fleet fleet, Iterable mediaTracks) { + TrackedRaceStatisticsDTO statisticsDTO = new TrackedRaceStatisticsDTO(); + // GPS data + statisticsDTO.hasGPSData = trackedRace.hasGPSData(); + Competitor leaderOrWinner = null; + Boat leaderOrWinnerBoat = null; + TimePoint now = MillisecondsTimePoint.now(); + try { + if (trackedRace.isLive(now)) { + leaderOrWinner = trackedRace.getOverallLeader(now); + } else if (trackedRace.getEndOfRace() != null) { + for (Competitor competitor : leaderboard.getCompetitorsFromBestToWorst(raceColumn, now)) { + Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); + if (fleetOfCompetitor != null && fleetOfCompetitor.equals(fleet)) { + leaderOrWinner = competitor; + leaderOrWinnerBoat = trackedRace.getBoatOfCompetitor(leaderOrWinner); + break; + } + } + } + if (leaderOrWinner != null) { + statisticsDTO.hasLeaderOrWinnerData = true; + statisticsDTO.leaderOrWinner = convertToCompetitorDTO(leaderOrWinner, leaderOrWinnerBoat); + GPSFixTrack track = trackedRace.getTrack(leaderOrWinner); + if (track != null) { + statisticsDTO.averageGPSDataSampleInterval = track.getAverageIntervalBetweenRawFixes(); + } + } + } catch (NoWindException e) { + } + + // Measured wind sources data + statisticsDTO.measuredWindSourcesCount = Util.size(trackedRace.getWindSources(WindSourceType.EXPEDITION)); + statisticsDTO.hasMeasuredWindData = statisticsDTO.measuredWindSourcesCount > 0; + + // leg progress data + RaceDefinition race = trackedRace.getRace(); + if (race.getCourse() != null) { + statisticsDTO.hasLegProgressData = true; + statisticsDTO.totalLegsCount = race.getCourse().getLegs().size(); + statisticsDTO.currentLegNo = trackedRace.getLastLegStarted(MillisecondsTimePoint.now()); + } + + // media data + if (mediaTracks != null) { + for (MediaTrack track : mediaTracks) { + switch (track.mimeType.mediaType) { + case audio: + statisticsDTO.hasAudioData = true; + statisticsDTO.audioTracksCount = statisticsDTO.audioTracksCount == null ? 1 + : statisticsDTO.audioTracksCount++; + break; + case video: + statisticsDTO.hasVideoData = true; + statisticsDTO.videoTracksCount = statisticsDTO.videoTracksCount == null ? 1 + : statisticsDTO.videoTracksCount++; + break; + case image: // TODO should this add to an image count? + break; + case unknown: // TODO should this add to an "unknown media" count? Probably not + break; + default: + break; + } + } + } + + return statisticsDTO; + } + + private PlacemarkOrderDTO getRacePlaces(TrackedRace trackedRace) { + Util.Pair startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace); + PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO(); + if (startAndFinish.getA() != null) { + racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getA())); + } + if (startAndFinish.getB() != null) { + racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getB())); + } + if (racePlaces.isEmpty()) { + racePlaces = null; + } + return racePlaces; + } + + private Util.Pair getStartFinishPlacemarksForTrackedRace(TrackedRace race) { + double radiusCalculationFactor = 10.0; + Placemark startBest = null; + Placemark finishBest = null; + Position startPosition = null; + + // Get start postition + final Waypoint firstWaypoint = race.getRace().getCourse().getFirstWaypoint(); + if (firstWaypoint != null) { + Iterator startMarks = firstWaypoint.getMarks().iterator(); + GPSFix startMarkFix = startMarks.hasNext() ? race.getOrCreateTrack(startMarks.next()).getLastRawFix() : null; + startPosition = startMarkFix != null ? startMarkFix.getPosition() : null; + if (startPosition != null) { + try { + // Get distance to nearest placemark and calculate the search radius + Placemark startNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(startPosition); + if (startNearest != null) { + Distance startNearestDistance = startNearest.distanceFrom(startPosition); + double startRadius = startNearestDistance.getKilometers() * radiusCalculationFactor; + + // Get the estimated best start place + startBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(startPosition, startRadius, + new Placemark.ByPopulationDistanceRatio(startPosition)); + } + } catch (IOException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } catch (org.json.simple.parser.ParseException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } + } + } + + // Get finish position + final Waypoint lastWaypoint = race.getRace().getCourse().getLastWaypoint(); + if (lastWaypoint != null) { + Iterator finishMarks = firstWaypoint.getMarks().iterator(); + GPSFix finishMarkFix = finishMarks.hasNext() ? race.getOrCreateTrack(finishMarks.next()).getLastRawFix() : null; + Position finishPosition = finishMarkFix != null ? finishMarkFix.getPosition() : null; + if (startPosition != null && finishPosition != null) { + if (startPosition.getDistance(finishPosition).getKilometers() <= ReverseGeocoder.POSITION_CACHE_DISTANCE_LIMIT_IN_KM) { + finishBest = startBest; + } else { + try { + // Get distance to nearest placemark and calculate the search radius + Placemark finishNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(finishPosition); + Distance finishNearestDistance = finishNearest.distanceFrom(finishPosition); + double finishRadius = finishNearestDistance.getKilometers() * radiusCalculationFactor; + + // Get the estimated best finish place + finishBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(finishPosition, finishRadius, + new Placemark.ByPopulationDistanceRatio(finishPosition)); + } catch (IOException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } catch (org.json.simple.parser.ParseException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } + } + } + } + Util.Pair placemarks = new Util.Pair(startBest, finishBest); + return placemarks; + } + + @Override + public PlacemarkDTO convertToPlacemarkDTO(Placemark placemark) { + Position position = placemark.getPosition(); + return new PlacemarkDTO(placemark.getName(), placemark.getCountryCode(), new DegreePosition(position.getLatDeg(), + position.getLngDeg()), placemark.getPopulation()); + } + + @Override + public List getCompetitorDTOList(List competitors) { + List result = new ArrayList(); + for (CompetitorWithBoat competitor : competitors) { + result.add(convertToCompetitorDTO(competitor)); + } + return result; + } + + @Override + public List getCompetitorDTOListTemp(List competitors) { + List result = new ArrayList(); + for (Competitor competitor : competitors) { + result.add(convertToCompetitorDTO(competitor)); + } + return result; + } + + @Override + public List getCompetitorWithoutBoatDTOListTemp(List competitors) { + List result = new ArrayList(); + for (Competitor competitor : competitors) { + result.add(convertToCompetitorWithoutBoatDTO(competitor)); + } + return result; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java index 811a3b17436..ff3d2e86e7c 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java @@ -1,177 +1,177 @@ -package com.sap.sailing.domain.base.impl; - -import java.io.Serializable; - -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.racelog.RaceLogIdentifier; - -public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Serializable { - private static final long serialVersionUID = 4752330236765192592L; - - private final RaceColumn raceColumn; - private final RaceLogIdentifier identifier; - - public RaceColumnRaceLogReplicator(RaceColumn raceColumn, RaceLogIdentifier identifier) { - this.raceColumn = raceColumn; - this.identifier = identifier; - } - - private void notifyOnAdd(RaceLogEvent event) { - raceColumn.getRaceColumnListeners().notifyListenersAboutRaceLogEventAdded( - raceColumn, - identifier, - event); - } - - @Override - public void visit(RaceLogCourseAreaChangedEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogStartTimeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogRaceStatusEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogPassChangeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogFlagEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogCourseDesignChangedEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogFinishPositioningListChangedEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogFinishPositioningConfirmedEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogPathfinderEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogGateLineOpeningTimeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogStartProcedureChangedEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogProtestStartTimeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogWindFixEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogDenoteForTrackingEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogStartTrackingEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogRevokeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogRegisterCompetitorEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogFixedMarkPassingEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogSuppressedMarkPassingsEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { - notifyOnAdd(additionalScoringInformation); - } - - @Override - public void visit(RaceLogDependentStartTimeEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogStartOfTrackingEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogEndOfTrackingEvent event) { - notifyOnAdd(event); - } - - @Override - public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { - notifyOnAdd(event); - } -} +package com.sap.sailing.domain.base.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; + +public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Serializable { + private static final long serialVersionUID = 4752330236765192592L; + + private final RaceColumn raceColumn; + private final RaceLogIdentifier identifier; + + public RaceColumnRaceLogReplicator(RaceColumn raceColumn, RaceLogIdentifier identifier) { + this.raceColumn = raceColumn; + this.identifier = identifier; + } + + private void notifyOnAdd(RaceLogEvent event) { + raceColumn.getRaceColumnListeners().notifyListenersAboutRaceLogEventAdded( + raceColumn, + identifier, + event); + } + + @Override + public void visit(RaceLogCourseAreaChangedEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogStartTimeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogRaceStatusEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogPassChangeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogFlagEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogCourseDesignChangedEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogFinishPositioningListChangedEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogFinishPositioningConfirmedEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogPathfinderEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogGateLineOpeningTimeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogStartProcedureChangedEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogWindFixEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogDenoteForTrackingEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogStartTrackingEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogRevokeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogRegisterCompetitorEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogFixedMarkPassingEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogSuppressedMarkPassingsEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { + notifyOnAdd(additionalScoringInformation); + } + + @Override + public void visit(RaceLogDependentStartTimeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogStartOfTrackingEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogEndOfTrackingEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { + notifyOnAdd(event); + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index 7f5888970ae..2f0b3695a8e 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -1,558 +1,558 @@ -package com.sap.sailing.domain.leaderboard; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.LeaderboardBase; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.LegType; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.dto.LeaderboardDTO; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCache; -import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; - -/** - * A leaderboard is used to display the results of one or more {@link TrackedRace races}. It manages the competitors' - * scores and can aggregate them, e.g., to show the overall regatta standings. In addition to the races, a "carry" - * column may be used to carry results of races not displayed in the leaderboard into the calculations. - *

- * - * While a single {@link TrackedRace} can tell about the ranks in which according to the tracking information the - * competitors crossed the finish line, the leaderboard may overlay this information with disqualifications, changes in - * results because the finish-line tracking was inaccurate, jury penalties and discarded results (depending on the - * regatta rules, the worst zero, one or more races of each competitor are discarded from the aggregated points). - *

- * - * @author Axel Uhl (d043530) - * - */ -public interface Leaderboard extends LeaderboardBase, HasRaceColumns { - /** - * If the leaderboard is a "matrix" with the cells being defined by a competitor / race "coordinate," - * then this interface defines the structure of the "cells." - * - * @author Axel Uhl (d043530) - * - */ - public interface Entry { - int getTrackedRank(); - Double getTotalPoints(); - Double getTotalPointsUncorrected(); - Double getNetPoints(); - MaxPointsReason getMaxPointsReason(); - boolean isDiscarded(); - /** - * Tells if the total points have been corrected by a {@link ScoreCorrection} - */ - boolean isTotalPointsCorrected(); - - /** - * @return null, if the competitor's fleet in the race column cannot be determined, the - * {@link Fleet} otherwise - */ - Fleet getFleet(); - } - - LeaderboardDTO computeDTO(final TimePoint timePoint, - final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, - final boolean waitForLatestAnalyses, TrackedRegattaRegistry trackedRegattaRegistry, - DomainFactory baseDomainFactory, boolean fillTotalPointsUncorrected) throws NoWindException; - - /** - * Obtains the unique set of {@link Competitor} objects from all {@link TrackedRace}s currently linked to this - * leaderboard, with suppressed competitors removed. See also {@link #getAllCompetitors()} which also returns - * the suppressed competitors. - */ - Iterable getCompetitors(); - - /** - * A leaderboard may suppress particular competitors which are then not assigned a score and shall not be displayed - * in a regular view of the leaderboard. Editors for leaderboards shall, though, also display the suppressed competitors - * together with a visual indication showing which competitors are currently suppressed. The "suppressed-state" of a - * competitor can change over the life cycle of a leaderboard. A typical use case for suppressing a competitor is - * removing one-time entries from a series (meta-)leaderboard or suppressing a camera boat in scoring.

- * - * @return all competitors in this leaderboard, including the suppressed ones. - */ - Iterable getAllCompetitors(); - - /** - * Retrieves all competitors expected to race in the fleet and column specified. - * When a {@link TrackedRace} is {@link RaceColumn#getTrackedRace(Fleet) attached} to the race - * column for the fleet specified, its competitor set is returned. Otherwise, - * the competitors are collected from any other information, such as a regatta log and/or the - * race log for the combination of race column and fleet or, in case of a meta-leaderboard, - * from the leaderboard represented by the race column. - */ - Iterable getAllCompetitors(RaceColumn raceColumn, Fleet fleet); - - /** - * Same as {@link #getAllCompetitors(RaceColumn, Fleet)} with competitors from {@link #getSuppressedCompetitors()} - * removed - */ - Iterable getCompetitors(RaceColumn raceColumn, Fleet fleet); - - /** - * Convenience method which returns the difference between {@link #getAllCompetitors()} and {@link #getCompetitors()}. - */ - Iterable getSuppressedCompetitors(); - - /** - * Tells whether {@code competitor} is among those {@link #getSuppressedCompetitors() suppressed} - */ - boolean isSuppressed(Competitor competitor); - - /** - * Can be used to exclude competitor from regular views of this leaderboard as well as from the scoring process. - * As a result of suppressing a competitor, it will no longer result from calls to {@link #getCompetitors} nor to - * {@link #getCompetitorsFromBestToWorst(TimePoint)} nor {@link #getCompetitorsFromBestToWorst(RaceColumn, TimePoint)}. - * It will, however, continue to be returned from {@link #getAllCompetitors()}. - */ - void setSuppressed(Competitor competitor, boolean suppressed); - - /** - * Retrieves the boat of a given competitor for the specified raceColumn and fleet. - */ - Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet); - - /** - * Returns the first fleet found in the sequence of this leaderboard's {@link #getRaceColumns() race columns}' - * {@link RaceColumn#getFleets() fleets} whose name equals fleetName. If no such fleet is found, - * null is returned. If fleetName is null, the leaderboard may return - * a default fleet if it has one, or null otherwise. - */ - Fleet getFleet(String fleetName); - - Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException; - - /** - * Same as {@link #getEntry}, but the discards for the competitor across the leaderboard can be provided for better performance - * in case the entries for several columns shall be computed by multiple calls to this method. - * - * @param discardedRaceColumns - * expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}. - * {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint) - * getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}. - */ - Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint, Set discardedRaceColumns) throws NoWindException; - - /** - * Computes the competitor's ranks as they were or would have been after each race column (from left to right) - * was completed.

- * - * A leaderboard fills up over time, usually "from left to right" with one race after another finishing. - * For split fleets things can vary slightly. There, one fleet may complete a few races before the another fleet - * starts with those races. In this case there isn't even any point in time at which all fleets have finished - * exactly n races. Still, this method pretends such a time point would have existed, actually ignoring - * the times at which a race took place but only looking at the resulting scores and discards.

- * - * When computing the ranks after all columns up to and including the race column that is the key of the resulting - * map, the method applies the discarding and tie breaking rules as they would have had to be applied had the races - * in the respective column just completed. - * - * @return The resulting map is guaranteed to have the same iteration order regarding the race columns - * as {@link #getRaceColumns()}. - */ - Map> getRankedCompetitorsFromBestToWorstAfterEachRaceColumn(TimePoint timePoint) throws NoWindException; - - /** - * Computes the competitor's net points sum as they were or would have been after each race column (from left to right) - * was completed.

- * - * A leaderboard fills up over time, usually "from left to right" with one race after another finishing. - * For split fleets things can vary slightly. There, one fleet may complete a few races before the another fleet - * starts with those races. In this case there isn't even any point in time at which all fleets have finished - * exactly n races. Still, this method pretends such a time point would have existed, actually ignoring - * the times at which a race took place but only looking at the resulting scores and discards.

- * - * When computing the net points sum after all columns up to and including the race column that is the key of the resulting - * map, the method applies the discarding and tie breaking rules as they would have had to be applied had the races - * in the respective column just completed. - * - * @return The resulting map is guaranteed to have the same iteration order regarding the race columns - * as {@link #getRaceColumns()}. - */ - Map> getNetPointsSumAfterRaceColumn(TimePoint timePoint) throws NoWindException; - - /** - * Tells the number of points carried over from previous races not tracked by this leaderboard for - * the competitor. Returns 0 if there is no carried points definition for - * competitor. - */ - double getCarriedPoints(Competitor competitor); - - /** - * - * @return an unmodifiable map of competitors and their carried points. The key set can be a true super set of what - * {@link #getAllCompetitors()} returns. - */ - Map getCompetitorsForWhichThereAreCarriedPoints(); - - /** - * Shorthand for {@link TrackedRace#getRank(Competitor, com.sap.sse.common.TimePoint)} with the - * additional logic that in case the race hasn't {@link TrackedRace#hasStarted(TimePoint) started} yet - * or no {@link TrackedRace} exists for race, 0 will be returned for all those competitors. The tracked - * race for the correct {@link Fleet} is determined using {@link RaceColumn#getTrackedRace(Competitor)}.

- * - * For each competitor tracking-wise ranking better than competitor but with - * a {@link #getMaxPointsReason(Competitor, RaceColumn, TimePoint) disqualification reason} given, competitor's - * rank is improved by one. - * - * @param competitor - * a competitor contained in the {@link #getCompetitors()} result - * @param race - * a race that is contained in the {@link #getRaceColumns()} result - */ - int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint); - - /** - * A possibly corrected number of points for the race specified. Defaults to the result of calling - * {@link #getTrackedRank(Competitor, TrackedRace, TimePoint)} but may be corrected by disqualifications or calls by - * the jury for the particular race that differ from the tracking results. - * - * @param competitor - * a competitor contained in the {@link #getCompetitors()} result - * @param raceColumn - * a race that is contained in the {@link #getRaceColumns()} result - * @return null if the competitor didn't participate in the race or the race hasn't started yet at - * timePoint - */ - Double getTotalPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); - - /** - * Tells if and why a competitor received "penalty" points for a race (however the scoring rules define the - * points for such a penalty; usually, it would be a high score defined by the number of competitors plus one) - */ - MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn race, TimePoint timePoint); - - /** - * A possibly corrected number of points for the race specified. Defaults to the result of calling - * {@link #getTotalPoints(Competitor, TrackedRace, TimePoint)} but may be corrected by the regatta rules for - * discarding results. If {@link #isDiscarded(Competitor, RaceColumn, TimePoint) discarded}, the points returned - * will be 0. - * - * @param competitor - * a competitor contained in the {@link #getCompetitors()} result - * @param race - * a race that is contained in the {@link #getRaceColumns()} result - * @return null if the competitor obtained no score (yet?) in race. This may - * happen if the competitor has no score correction for race in this leaderboard and there is - * no tracked rank available for the competitor (e.g., because the race hasn't started yet) or the - * competitor doesn't appear in any of the race column's attached tracked races. A 0.0 score is returned - * if the competitor's result for race is discarded. - */ - Double getNetPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException; - - /** - * Tells whether the contribution of raceColumn is discarded in the current leaderboard's standings for - * competitor. A column representing a {@link RaceColumn#isMedalRace() medal race} cannot be discarded. - * Neither can be a race where the competitor received a non-{@link MaxPointsReason#isDiscardable() discardable} - * penalty or disqualification. - */ - boolean isDiscarded(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); - - /** - * Sums up the {@link #getNetPoints(Competitor, TrackedRace, TimePoint) net points} of competitor - * across all races tracked by this leaderboard, respecting the {@link RaceColumn#isStartsWithZeroScore()} property. - */ - Double getNetPoints(Competitor competitor, TimePoint timePoint); - - /** - * Sums up the {@link #getNetPoints(Competitor, RaceColumn, TimePoint) net points} of competitor - * across all race columns listed in raceColumnsToconsider, respecting the - * {@link RaceColumn#isStartsWithZeroScore()} property. - */ - Double getNetPoints(Competitor competitor, Iterable raceColumnsToConsider, TimePoint timePoint) - throws NoWindException; - - /** - * Sorts the competitors according to their ranking in the race column specified. Only competitors who have a score - * are added to the result list. This excludes competitors whose fleet hasn't raced for the raceColumn - * yet, and those where no tracked rank is known and no manual score correction was performed. - *

- * - * The sorting order considers this leaderboard's scoring scheme including the semantics of - * {@link Fleet#compareTo(Fleet) ordered fleets} and {@link RaceColumn#isMedalRace() medal races}. The ordering - * does not consider result discarding because when sorting for a race column it is of interest how the competitor - * performed in that race and not how the score affected the overall regatta score. Therefore, it is based on - * {@link #getTotalPoints(Competitor, RaceColumn, TimePoint)} and not on - * {@link #getNetPoints(Competitor, RaceColumn, TimePoint)}. - */ - List getCompetitorsFromBestToWorst(RaceColumn raceColumn, TimePoint timePoint) throws NoWindException; - - /** - * Sorts the competitors according to the overall regatta standings, considering the sorting rules for - * {@link Series}, {@link Fleet}s, medal races, discarding rules and score corrections. A new list is - * created per call, so the caller may freely manipulate the result. - * @throws NoWindException - */ - List getCompetitorsFromBestToWorst(TimePoint timePoint); - - /** - * Returns the total rank of the given competitor. - */ - int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint) throws NoWindException; - - /** - * Fetches all entries for all competitors of all races tracked by this leaderboard in one sweep. This saves some - * computational effort compared to fetching all entries separately, particularly because all - * {@link #isDiscarded(Competitor, RaceColumn, TimePoint) discarded races} of a competitor are computed in one - * sweep using {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)} only once. - * Note that in order to get the {@link #getNetPoints(Competitor, TimePoint) total points} for a competitor - * for the entire leaderboard, the {@link #getCarriedPoints(Competitor) carried-over points} need to be added. - */ - Map, Entry> getContent(TimePoint timePoint) throws NoWindException; - - /** - * Retrieves all race columns that were added, either by {@link #addRace(TrackedRace, String, boolean)} or - * {@link #addRaceColumn(String, boolean)}. - */ - Iterable getRaceColumns(); - - /** - * Retrieves a {@link RaceColumn race column} by the name used in calls to either {@link #addRaceColumn} or - * {@link #addRace}. If no race column by the requested name exists, null is returned. - */ - RaceColumn getRaceColumnByName(String name); - - /** - * A leaderboard can carry over points from races that are not tracked by this leaderboard in detail, - * so for which no {@link RaceColumn} column is present in this leaderboard. These scores are - * simply added to the scores tracked by this leaderboard in the {@link #getNetPoints(Competitor, TimePoint)} - * method. - */ - void setCarriedPoints(Competitor competitor, double carriedPoints); - - /** - * Reverses the effect of {@link #setCarriedPoints(Competitor, int)}, i.e., afterwards, asking {@link #getCarriedPoints(Competitor)} - * will return 0. Furthermore, other than invoking {@link #setCarriedPoints(Competitor, int) setCarriedPoints(c, 0)}, - * this will, when executed for all competitors of this leaderboard, have {@link #hasCarriedPoints} return false. - */ - void unsetCarriedPoints(Competitor competitor); - - /** - * Tells if a carry-column shall be displayed. If the result is false, then no - * {@link #setCarriedPoints(Competitor, int) scores are carried} into this leaderboard, and - * only the race columns will be accumulated by the board. - */ - boolean hasCarriedPoints(); - - boolean hasCarriedPoints(Competitor competitor); - - SettableScoreCorrection getScoreCorrection(); - - Competitor getCompetitorByName(String competitorName); - - void setDisplayName(Competitor competitor, String displayName); - - void setDisplayName(String displayName); - - /** - * If a display name different from the competitor's {@link Competitor#getName() name} has been defined, - * this method returns it; otherwise, null is returned. - */ - String getDisplayName(Competitor competitor); - - /** - * Tells if the column represented by raceColumn shall be considered when counting the number of "races - * so far" for discarding. Although medal races are never discarded themselves, they still count in determining the - * number of "races so far" which is then the basis for deciding how many races may be discarded. If a leaderboard - * has corrections for a column for the competitor that are already to be applied at - * timePoint (e.g., because the race can be proven to have finished at timePoint), then - * that column shall be considered for discarding and counts for determining the number of races so far. Also, if a - * tracked race is connected to the column and has started already, the column is to be considered for discarding - * unless the column has several unordered fleets and not all fleets have started their race yet (see - * {@link ScoringScheme#isValidInNetScore(Leaderboard, RaceColumn, Competitor, TimePoint)}). - */ - boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); - - /** - * Returns the result discarding rule for this leaderboard. This may be an explicit rule set for the entire leaderboard, - * or it may be an implicit rule that relies on other data such as a regatta's series-specific result discarding rules. - */ - ResultDiscardingRule getResultDiscardingRule(); - - /** - * Trying to set a cross-leaderboard result discarding rule may fail with an exception if the leaderboard obtains - * its result discarding rule in another way. For example, if the leaderboard is a {@link RegattaLeaderboard} and the - * regatta's series define their own result discarding rules, the regatta leaderboard will use a composite - * result discarding rule that considers all series-specific result discarding rules. - */ - public void setCrossLeaderboardResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule); - - Competitor getCompetitorByIdAsString(String idAsString); - - void addRaceColumnListener(RaceColumnListener listener); - - void removeRaceColumnListener(RaceColumnListener listener); - - /** - * For this leaderboard computes the delay to live of the {@link TrackedRace} linked to any of the leaderboard's - * columns that has the latest start date. If no tracked race is linked to the leaderboard, null is returned. - */ - Long getDelayToLiveInMillis(); - - /** - * Obtains all {@link TrackedRace}s currently attached to any of the columns of this leaderboard - */ - Iterable getTrackedRaces(); - - ScoringScheme getScoringScheme(); - - /** - * Finds out the time point when any of the {@link Leaderboard#getTrackedRaces() tracked races currently attached to - * the leaderboard} and the {@link Leaderboard#getScoreCorrection() score corrections} have last been - * modified. If no tracked race is attached and no time-stamped score corrections have been applied to the leaderboard, - * null is returned. - */ - TimePoint getTimePointOfLatestModification(); - - /** - * @return null if no tracked race is available for competitor in this leaderboard - * or the competitor hasn't started sailing a single race at timePoint for any of the tracked - * races attached to this leaderboard; the fix where the maximum speed was achieved, and the speed value - */ - Util.Pair getMaximumSpeedOverGround(Competitor competitor, TimePoint timePoint); - - /** - * @return null if no tracked race is available in this leaderboard, the competitor hasn't started - * a single race at timePoint or if the competitor has not finished one of the races. This method - * computes the average speed starting with the first mark passing until timePoint or if earlier then - * the timePoint of the last mark passing. - */ - Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint); - - /** - * @param legType the leg type for which to add up the times sailed - * @return null if no tracked race is available for competitor in this leaderboard - * or the competitor hasn't started sailing a single downwind leg at timePoint for any of the tracked - * races attached to this leaderboard - */ - Duration getTotalTimeSailedInLegType(Competitor competitor, LegType legType, TimePoint timePoint) throws NoWindException; - - /** - * Starts counting when the gun goes off, not when the competitor passed the line. - * - * @return null if no tracked race is available for competitor in this leaderboard - * or the competitor hasn't started sailing a single race at timePoint for any of the tracked - * races attached to this leaderboard - */ - Duration getTotalTimeSailed(Competitor competitor, TimePoint timePoint); - - /** - * Computes the distance the competitor has sailed in the tracked races in this leaderboard, starting - * to count in each race when the competitor passes the start line, aggregating up to timePoint or the - * end of the last race, whichever is first. - * - * @return null if the competitor hasn't sailed any distance in any tracked race in this - * leaderboard - */ - Distance getTotalDistanceTraveled(Competitor competitor, TimePoint timePoint); - - /** - * Same as {@link #getNetPoints(Competitor, RaceColumn, TimePoint)}, only that for determining the discarded - * results only raceColumnsToConsider are considered. - */ - Double getNetPoints(Competitor competitor, RaceColumn raceColumn, Iterable raceColumnsToConsider, - TimePoint timePoint) throws NoWindException; - - /** - * Same as {@link #getNetPoints(Competitor, RaceColumn, Iterable, TimePoint)}, only that the set of discarded race columns can - * be specified which is useful when total points are to be computed for more than one column for the same - * competitor because then the calculation of discards (which requires looking at all columns) only needs to be done - * once and not again for each column (which would lead to quadratic effort). - * - * @param discardedRaceColumns - * expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}. - * {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint) - * getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}. - */ - Double getNetPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint, - Set discardedRaceColumns); - - TimePoint getNowMinusDelay(); - - /** - * Get the default {@link CourseArea} of this leaderboard. - * @return the default {@link CourseArea} for all races of this leaderboard. - */ - CourseArea getDefaultCourseArea(); - - /** - * Must be called when the leaderboard is removed from its server, becoming in accessible. This will give the leaderboard - * a chance to release all its resources that won't be collected or freed automatically. In particular, a leaderboard may - * hold on to listeners which in turn are registered with {@link TrackedRace}s and therefore won't be released to the garbage - * collector unless the tracked race becomes unreferenced. This may take long because the tracked race can generally - * be referenced by more than one leaderboard. For example, a test leaderboard may additionally reference a tracked - * race already referenced by an "official" leaderboard. When the test leaderboard is removed, its listeners would not - * be released and avoid garbage-collecting the test leaderboard. When calling this method, the leaderboard will cleanly - * unregister its listeners from the tracked races and therefore become eligible for garbage collection. - */ - void destroy(); - - /** - * Returns a data transfer object (DTO) that has the leaderboard's data for the race columns with basic information - * for all columns, and with detailed information for those columns whose names are provided in - * namesOfRaceColumnsForWhichToLoadLegDetails. The leaderboard is evaluated at timePoint, - * or, if timePoint is null, for the "live" time point (now - delay). - *

- * - * The implementation uses different approaches for caching the results. For "live" requests, a - * {@link LiveLeaderboardUpdater} is used to keep refreshing the cached results. Other queries are managed by a - * {@link LeaderboardDTOCache} which remembers a number of results before it starts evicting the least frequently - * used ones. - * - * @param timePoint - * null for "live" results for the time point "now" - delay; otherwise, the explicit time - * point at which to evaluate the leaderboard status - * @param namesOfRaceColumnsForWhichToLoadLegDetails - * the names of the race columns of which to expand the details in the result - * @param trackedRegattaRegistry - * used to determine which of the races are still being tracked and which ones are not - * @param baseDomainFactory - * required as factory and cache for various DTO types - */ - LeaderboardDTO getLeaderboardDTO(TimePoint timePoint, - Collection namesOfRaceColumnsForWhichToLoadLegDetails, - boolean addOverallDetails, TrackedRegattaRegistry trackedRegattaRegistry, DomainFactory baseDomainFactory, boolean fillTotalPointsUncorrected) throws NoWindException, - InterruptedException, ExecutionException; - - NumberOfCompetitorsInLeaderboardFetcher getNumberOfCompetitorsInLeaderboardFetcher(); - - /** - * Looks through all {@link #getRaceColumns() race columns} and their {@link RaceColumn#getFleets() fleets} and checks - * if {@code trackedRace} is {@link RaceColumn#getTrackedRace(Fleet) linked} to that combination. If such a slot is found - * that "slot" is returned by a pair specifying the non-{@code null} {@link RaceColumn} and {@code Fleet} pair. Otherwise, - * {@code null} is returned. - */ - Pair getRaceColumnAndFleet(TrackedRace trackedRace); - - /** - * Gets the ("dominant") boat class for this leaderboard. For a {@link RegattaLeaderboard} this is the {@link Regatta}'s boat class. - * For a {@link FlexibleLeaderboard} the implementation is more complex because no fixed boat class is set for the leaderboard. There, - * the boat class will be determined based on the most frequently occurring boat class when iterating across the competitors. - */ - BoatClass getBoatClass(); -} +package com.sap.sailing.domain.leaderboard; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.LeaderboardBase; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.LegType; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.dto.LeaderboardDTO; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCache; +import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; + +/** + * A leaderboard is used to display the results of one or more {@link TrackedRace races}. It manages the competitors' + * scores and can aggregate them, e.g., to show the overall regatta standings. In addition to the races, a "carry" + * column may be used to carry results of races not displayed in the leaderboard into the calculations. + *

+ * + * While a single {@link TrackedRace} can tell about the ranks in which according to the tracking information the + * competitors crossed the finish line, the leaderboard may overlay this information with disqualifications, changes in + * results because the finish-line tracking was inaccurate, jury penalties and discarded results (depending on the + * regatta rules, the worst zero, one or more races of each competitor are discarded from the aggregated points). + *

+ * + * @author Axel Uhl (d043530) + * + */ +public interface Leaderboard extends LeaderboardBase, HasRaceColumns { + /** + * If the leaderboard is a "matrix" with the cells being defined by a competitor / race "coordinate," + * then this interface defines the structure of the "cells." + * + * @author Axel Uhl (d043530) + * + */ + public interface Entry { + int getTrackedRank(); + Double getTotalPoints(); + Double getTotalPointsUncorrected(); + Double getNetPoints(); + MaxPointsReason getMaxPointsReason(); + boolean isDiscarded(); + /** + * Tells if the total points have been corrected by a {@link ScoreCorrection} + */ + boolean isTotalPointsCorrected(); + + /** + * @return null, if the competitor's fleet in the race column cannot be determined, the + * {@link Fleet} otherwise + */ + Fleet getFleet(); + } + + LeaderboardDTO computeDTO(final TimePoint timePoint, + final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, + final boolean waitForLatestAnalyses, TrackedRegattaRegistry trackedRegattaRegistry, + DomainFactory baseDomainFactory, boolean fillTotalPointsUncorrected) throws NoWindException; + + /** + * Obtains the unique set of {@link Competitor} objects from all {@link TrackedRace}s currently linked to this + * leaderboard, with suppressed competitors removed. See also {@link #getAllCompetitors()} which also returns + * the suppressed competitors. + */ + Iterable getCompetitors(); + + /** + * A leaderboard may suppress particular competitors which are then not assigned a score and shall not be displayed + * in a regular view of the leaderboard. Editors for leaderboards shall, though, also display the suppressed competitors + * together with a visual indication showing which competitors are currently suppressed. The "suppressed-state" of a + * competitor can change over the life cycle of a leaderboard. A typical use case for suppressing a competitor is + * removing one-time entries from a series (meta-)leaderboard or suppressing a camera boat in scoring.

+ * + * @return all competitors in this leaderboard, including the suppressed ones. + */ + Iterable getAllCompetitors(); + + /** + * Retrieves all competitors expected to race in the fleet and column specified. + * When a {@link TrackedRace} is {@link RaceColumn#getTrackedRace(Fleet) attached} to the race + * column for the fleet specified, its competitor set is returned. Otherwise, + * the competitors are collected from any other information, such as a regatta log and/or the + * race log for the combination of race column and fleet or, in case of a meta-leaderboard, + * from the leaderboard represented by the race column. + */ + Iterable getAllCompetitors(RaceColumn raceColumn, Fleet fleet); + + /** + * Same as {@link #getAllCompetitors(RaceColumn, Fleet)} with competitors from {@link #getSuppressedCompetitors()} + * removed + */ + Iterable getCompetitors(RaceColumn raceColumn, Fleet fleet); + + /** + * Convenience method which returns the difference between {@link #getAllCompetitors()} and {@link #getCompetitors()}. + */ + Iterable getSuppressedCompetitors(); + + /** + * Tells whether {@code competitor} is among those {@link #getSuppressedCompetitors() suppressed} + */ + boolean isSuppressed(Competitor competitor); + + /** + * Can be used to exclude competitor from regular views of this leaderboard as well as from the scoring process. + * As a result of suppressing a competitor, it will no longer result from calls to {@link #getCompetitors} nor to + * {@link #getCompetitorsFromBestToWorst(TimePoint)} nor {@link #getCompetitorsFromBestToWorst(RaceColumn, TimePoint)}. + * It will, however, continue to be returned from {@link #getAllCompetitors()}. + */ + void setSuppressed(Competitor competitor, boolean suppressed); + + /** + * Retrieves the boat of a given competitor for the specified raceColumn and fleet. + */ + Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet); + + /** + * Returns the first fleet found in the sequence of this leaderboard's {@link #getRaceColumns() race columns}' + * {@link RaceColumn#getFleets() fleets} whose name equals fleetName. If no such fleet is found, + * null is returned. If fleetName is null, the leaderboard may return + * a default fleet if it has one, or null otherwise. + */ + Fleet getFleet(String fleetName); + + Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException; + + /** + * Same as {@link #getEntry}, but the discards for the competitor across the leaderboard can be provided for better performance + * in case the entries for several columns shall be computed by multiple calls to this method. + * + * @param discardedRaceColumns + * expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}. + * {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint) + * getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}. + */ + Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint, Set discardedRaceColumns) throws NoWindException; + + /** + * Computes the competitor's ranks as they were or would have been after each race column (from left to right) + * was completed.

+ * + * A leaderboard fills up over time, usually "from left to right" with one race after another finishing. + * For split fleets things can vary slightly. There, one fleet may complete a few races before the another fleet + * starts with those races. In this case there isn't even any point in time at which all fleets have finished + * exactly n races. Still, this method pretends such a time point would have existed, actually ignoring + * the times at which a race took place but only looking at the resulting scores and discards.

+ * + * When computing the ranks after all columns up to and including the race column that is the key of the resulting + * map, the method applies the discarding and tie breaking rules as they would have had to be applied had the races + * in the respective column just completed. + * + * @return The resulting map is guaranteed to have the same iteration order regarding the race columns + * as {@link #getRaceColumns()}. + */ + Map> getRankedCompetitorsFromBestToWorstAfterEachRaceColumn(TimePoint timePoint) throws NoWindException; + + /** + * Computes the competitor's net points sum as they were or would have been after each race column (from left to right) + * was completed.

+ * + * A leaderboard fills up over time, usually "from left to right" with one race after another finishing. + * For split fleets things can vary slightly. There, one fleet may complete a few races before the another fleet + * starts with those races. In this case there isn't even any point in time at which all fleets have finished + * exactly n races. Still, this method pretends such a time point would have existed, actually ignoring + * the times at which a race took place but only looking at the resulting scores and discards.

+ * + * When computing the net points sum after all columns up to and including the race column that is the key of the resulting + * map, the method applies the discarding and tie breaking rules as they would have had to be applied had the races + * in the respective column just completed. + * + * @return The resulting map is guaranteed to have the same iteration order regarding the race columns + * as {@link #getRaceColumns()}. + */ + Map> getNetPointsSumAfterRaceColumn(TimePoint timePoint) throws NoWindException; + + /** + * Tells the number of points carried over from previous races not tracked by this leaderboard for + * the competitor. Returns 0 if there is no carried points definition for + * competitor. + */ + double getCarriedPoints(Competitor competitor); + + /** + * + * @return an unmodifiable map of competitors and their carried points. The key set can be a true super set of what + * {@link #getAllCompetitors()} returns. + */ + Map getCompetitorsForWhichThereAreCarriedPoints(); + + /** + * Shorthand for {@link TrackedRace#getRank(Competitor, com.sap.sse.common.TimePoint)} with the + * additional logic that in case the race hasn't {@link TrackedRace#hasStarted(TimePoint) started} yet + * or no {@link TrackedRace} exists for race, 0 will be returned for all those competitors. The tracked + * race for the correct {@link Fleet} is determined using {@link RaceColumn#getTrackedRace(Competitor)}.

+ * + * For each competitor tracking-wise ranking better than competitor but with + * a {@link #getMaxPointsReason(Competitor, RaceColumn, TimePoint) disqualification reason} given, competitor's + * rank is improved by one. + * + * @param competitor + * a competitor contained in the {@link #getCompetitors()} result + * @param race + * a race that is contained in the {@link #getRaceColumns()} result + */ + int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint); + + /** + * A possibly corrected number of points for the race specified. Defaults to the result of calling + * {@link #getTrackedRank(Competitor, TrackedRace, TimePoint)} but may be corrected by disqualifications or calls by + * the jury for the particular race that differ from the tracking results. + * + * @param competitor + * a competitor contained in the {@link #getCompetitors()} result + * @param raceColumn + * a race that is contained in the {@link #getRaceColumns()} result + * @return null if the competitor didn't participate in the race or the race hasn't started yet at + * timePoint + */ + Double getTotalPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); + + /** + * Tells if and why a competitor received "penalty" points for a race (however the scoring rules define the + * points for such a penalty; usually, it would be a high score defined by the number of competitors plus one) + */ + MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn race, TimePoint timePoint); + + /** + * A possibly corrected number of points for the race specified. Defaults to the result of calling + * {@link #getTotalPoints(Competitor, TrackedRace, TimePoint)} but may be corrected by the regatta rules for + * discarding results. If {@link #isDiscarded(Competitor, RaceColumn, TimePoint) discarded}, the points returned + * will be 0. + * + * @param competitor + * a competitor contained in the {@link #getCompetitors()} result + * @param race + * a race that is contained in the {@link #getRaceColumns()} result + * @return null if the competitor obtained no score (yet?) in race. This may + * happen if the competitor has no score correction for race in this leaderboard and there is + * no tracked rank available for the competitor (e.g., because the race hasn't started yet) or the + * competitor doesn't appear in any of the race column's attached tracked races. A 0.0 score is returned + * if the competitor's result for race is discarded. + */ + Double getNetPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException; + + /** + * Tells whether the contribution of raceColumn is discarded in the current leaderboard's standings for + * competitor. A column representing a {@link RaceColumn#isMedalRace() medal race} cannot be discarded. + * Neither can be a race where the competitor received a non-{@link MaxPointsReason#isDiscardable() discardable} + * penalty or disqualification. + */ + boolean isDiscarded(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); + + /** + * Sums up the {@link #getNetPoints(Competitor, TrackedRace, TimePoint) net points} of competitor + * across all races tracked by this leaderboard, respecting the {@link RaceColumn#isStartsWithZeroScore()} property. + */ + Double getNetPoints(Competitor competitor, TimePoint timePoint); + + /** + * Sums up the {@link #getNetPoints(Competitor, RaceColumn, TimePoint) net points} of competitor + * across all race columns listed in raceColumnsToconsider, respecting the + * {@link RaceColumn#isStartsWithZeroScore()} property. + */ + Double getNetPoints(Competitor competitor, Iterable raceColumnsToConsider, TimePoint timePoint) + throws NoWindException; + + /** + * Sorts the competitors according to their ranking in the race column specified. Only competitors who have a score + * are added to the result list. This excludes competitors whose fleet hasn't raced for the raceColumn + * yet, and those where no tracked rank is known and no manual score correction was performed. + *

+ * + * The sorting order considers this leaderboard's scoring scheme including the semantics of + * {@link Fleet#compareTo(Fleet) ordered fleets} and {@link RaceColumn#isMedalRace() medal races}. The ordering + * does not consider result discarding because when sorting for a race column it is of interest how the competitor + * performed in that race and not how the score affected the overall regatta score. Therefore, it is based on + * {@link #getTotalPoints(Competitor, RaceColumn, TimePoint)} and not on + * {@link #getNetPoints(Competitor, RaceColumn, TimePoint)}. + */ + List getCompetitorsFromBestToWorst(RaceColumn raceColumn, TimePoint timePoint) throws NoWindException; + + /** + * Sorts the competitors according to the overall regatta standings, considering the sorting rules for + * {@link Series}, {@link Fleet}s, medal races, discarding rules and score corrections. A new list is + * created per call, so the caller may freely manipulate the result. + * @throws NoWindException + */ + List getCompetitorsFromBestToWorst(TimePoint timePoint); + + /** + * Returns the total rank of the given competitor. + */ + int getTotalRankOfCompetitor(Competitor competitor, TimePoint timePoint) throws NoWindException; + + /** + * Fetches all entries for all competitors of all races tracked by this leaderboard in one sweep. This saves some + * computational effort compared to fetching all entries separately, particularly because all + * {@link #isDiscarded(Competitor, RaceColumn, TimePoint) discarded races} of a competitor are computed in one + * sweep using {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint)} only once. + * Note that in order to get the {@link #getNetPoints(Competitor, TimePoint) total points} for a competitor + * for the entire leaderboard, the {@link #getCarriedPoints(Competitor) carried-over points} need to be added. + */ + Map, Entry> getContent(TimePoint timePoint) throws NoWindException; + + /** + * Retrieves all race columns that were added, either by {@link #addRace(TrackedRace, String, boolean)} or + * {@link #addRaceColumn(String, boolean)}. + */ + Iterable getRaceColumns(); + + /** + * Retrieves a {@link RaceColumn race column} by the name used in calls to either {@link #addRaceColumn} or + * {@link #addRace}. If no race column by the requested name exists, null is returned. + */ + RaceColumn getRaceColumnByName(String name); + + /** + * A leaderboard can carry over points from races that are not tracked by this leaderboard in detail, + * so for which no {@link RaceColumn} column is present in this leaderboard. These scores are + * simply added to the scores tracked by this leaderboard in the {@link #getNetPoints(Competitor, TimePoint)} + * method. + */ + void setCarriedPoints(Competitor competitor, double carriedPoints); + + /** + * Reverses the effect of {@link #setCarriedPoints(Competitor, int)}, i.e., afterwards, asking {@link #getCarriedPoints(Competitor)} + * will return 0. Furthermore, other than invoking {@link #setCarriedPoints(Competitor, int) setCarriedPoints(c, 0)}, + * this will, when executed for all competitors of this leaderboard, have {@link #hasCarriedPoints} return false. + */ + void unsetCarriedPoints(Competitor competitor); + + /** + * Tells if a carry-column shall be displayed. If the result is false, then no + * {@link #setCarriedPoints(Competitor, int) scores are carried} into this leaderboard, and + * only the race columns will be accumulated by the board. + */ + boolean hasCarriedPoints(); + + boolean hasCarriedPoints(Competitor competitor); + + SettableScoreCorrection getScoreCorrection(); + + Competitor getCompetitorByName(String competitorName); + + void setDisplayName(Competitor competitor, String displayName); + + void setDisplayName(String displayName); + + /** + * If a display name different from the competitor's {@link Competitor#getName() name} has been defined, + * this method returns it; otherwise, null is returned. + */ + String getDisplayName(Competitor competitor); + + /** + * Tells if the column represented by raceColumn shall be considered when counting the number of "races + * so far" for discarding. Although medal races are never discarded themselves, they still count in determining the + * number of "races so far" which is then the basis for deciding how many races may be discarded. If a leaderboard + * has corrections for a column for the competitor that are already to be applied at + * timePoint (e.g., because the race can be proven to have finished at timePoint), then + * that column shall be considered for discarding and counts for determining the number of races so far. Also, if a + * tracked race is connected to the column and has started already, the column is to be considered for discarding + * unless the column has several unordered fleets and not all fleets have started their race yet (see + * {@link ScoringScheme#isValidInNetScore(Leaderboard, RaceColumn, Competitor, TimePoint)}). + */ + boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); + + /** + * Returns the result discarding rule for this leaderboard. This may be an explicit rule set for the entire leaderboard, + * or it may be an implicit rule that relies on other data such as a regatta's series-specific result discarding rules. + */ + ResultDiscardingRule getResultDiscardingRule(); + + /** + * Trying to set a cross-leaderboard result discarding rule may fail with an exception if the leaderboard obtains + * its result discarding rule in another way. For example, if the leaderboard is a {@link RegattaLeaderboard} and the + * regatta's series define their own result discarding rules, the regatta leaderboard will use a composite + * result discarding rule that considers all series-specific result discarding rules. + */ + public void setCrossLeaderboardResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule); + + Competitor getCompetitorByIdAsString(String idAsString); + + void addRaceColumnListener(RaceColumnListener listener); + + void removeRaceColumnListener(RaceColumnListener listener); + + /** + * For this leaderboard computes the delay to live of the {@link TrackedRace} linked to any of the leaderboard's + * columns that has the latest start date. If no tracked race is linked to the leaderboard, null is returned. + */ + Long getDelayToLiveInMillis(); + + /** + * Obtains all {@link TrackedRace}s currently attached to any of the columns of this leaderboard + */ + Iterable getTrackedRaces(); + + ScoringScheme getScoringScheme(); + + /** + * Finds out the time point when any of the {@link Leaderboard#getTrackedRaces() tracked races currently attached to + * the leaderboard} and the {@link Leaderboard#getScoreCorrection() score corrections} have last been + * modified. If no tracked race is attached and no time-stamped score corrections have been applied to the leaderboard, + * null is returned. + */ + TimePoint getTimePointOfLatestModification(); + + /** + * @return null if no tracked race is available for competitor in this leaderboard + * or the competitor hasn't started sailing a single race at timePoint for any of the tracked + * races attached to this leaderboard; the fix where the maximum speed was achieved, and the speed value + */ + Util.Pair getMaximumSpeedOverGround(Competitor competitor, TimePoint timePoint); + + /** + * @return null if no tracked race is available in this leaderboard, the competitor hasn't started + * a single race at timePoint or if the competitor has not finished one of the races. This method + * computes the average speed starting with the first mark passing until timePoint or if earlier then + * the timePoint of the last mark passing. + */ + Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint); + + /** + * @param legType the leg type for which to add up the times sailed + * @return null if no tracked race is available for competitor in this leaderboard + * or the competitor hasn't started sailing a single downwind leg at timePoint for any of the tracked + * races attached to this leaderboard + */ + Duration getTotalTimeSailedInLegType(Competitor competitor, LegType legType, TimePoint timePoint) throws NoWindException; + + /** + * Starts counting when the gun goes off, not when the competitor passed the line. + * + * @return null if no tracked race is available for competitor in this leaderboard + * or the competitor hasn't started sailing a single race at timePoint for any of the tracked + * races attached to this leaderboard + */ + Duration getTotalTimeSailed(Competitor competitor, TimePoint timePoint); + + /** + * Computes the distance the competitor has sailed in the tracked races in this leaderboard, starting + * to count in each race when the competitor passes the start line, aggregating up to timePoint or the + * end of the last race, whichever is first. + * + * @return null if the competitor hasn't sailed any distance in any tracked race in this + * leaderboard + */ + Distance getTotalDistanceTraveled(Competitor competitor, TimePoint timePoint); + + /** + * Same as {@link #getNetPoints(Competitor, RaceColumn, TimePoint)}, only that for determining the discarded + * results only raceColumnsToConsider are considered. + */ + Double getNetPoints(Competitor competitor, RaceColumn raceColumn, Iterable raceColumnsToConsider, + TimePoint timePoint) throws NoWindException; + + /** + * Same as {@link #getNetPoints(Competitor, RaceColumn, Iterable, TimePoint)}, only that the set of discarded race columns can + * be specified which is useful when total points are to be computed for more than one column for the same + * competitor because then the calculation of discards (which requires looking at all columns) only needs to be done + * once and not again for each column (which would lead to quadratic effort). + * + * @param discardedRaceColumns + * expected to be the result of what we would get if we called {@link #getResultDiscardingRule()}. + * {@link ResultDiscardingRule#getDiscardedRaceColumns(Competitor, Leaderboard, Iterable, TimePoint) + * getDiscardedRaceColumns(competitor, this, raceColumnsToConsider, timePoint)}. + */ + Double getNetPoints(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint, + Set discardedRaceColumns); + + TimePoint getNowMinusDelay(); + + /** + * Get the default {@link CourseArea} of this leaderboard. + * @return the default {@link CourseArea} for all races of this leaderboard. + */ + CourseArea getDefaultCourseArea(); + + /** + * Must be called when the leaderboard is removed from its server, becoming in accessible. This will give the leaderboard + * a chance to release all its resources that won't be collected or freed automatically. In particular, a leaderboard may + * hold on to listeners which in turn are registered with {@link TrackedRace}s and therefore won't be released to the garbage + * collector unless the tracked race becomes unreferenced. This may take long because the tracked race can generally + * be referenced by more than one leaderboard. For example, a test leaderboard may additionally reference a tracked + * race already referenced by an "official" leaderboard. When the test leaderboard is removed, its listeners would not + * be released and avoid garbage-collecting the test leaderboard. When calling this method, the leaderboard will cleanly + * unregister its listeners from the tracked races and therefore become eligible for garbage collection. + */ + void destroy(); + + /** + * Returns a data transfer object (DTO) that has the leaderboard's data for the race columns with basic information + * for all columns, and with detailed information for those columns whose names are provided in + * namesOfRaceColumnsForWhichToLoadLegDetails. The leaderboard is evaluated at timePoint, + * or, if timePoint is null, for the "live" time point (now - delay). + *

+ * + * The implementation uses different approaches for caching the results. For "live" requests, a + * {@link LiveLeaderboardUpdater} is used to keep refreshing the cached results. Other queries are managed by a + * {@link LeaderboardDTOCache} which remembers a number of results before it starts evicting the least frequently + * used ones. + * + * @param timePoint + * null for "live" results for the time point "now" - delay; otherwise, the explicit time + * point at which to evaluate the leaderboard status + * @param namesOfRaceColumnsForWhichToLoadLegDetails + * the names of the race columns of which to expand the details in the result + * @param trackedRegattaRegistry + * used to determine which of the races are still being tracked and which ones are not + * @param baseDomainFactory + * required as factory and cache for various DTO types + */ + LeaderboardDTO getLeaderboardDTO(TimePoint timePoint, + Collection namesOfRaceColumnsForWhichToLoadLegDetails, + boolean addOverallDetails, TrackedRegattaRegistry trackedRegattaRegistry, DomainFactory baseDomainFactory, boolean fillTotalPointsUncorrected) throws NoWindException, + InterruptedException, ExecutionException; + + NumberOfCompetitorsInLeaderboardFetcher getNumberOfCompetitorsInLeaderboardFetcher(); + + /** + * Looks through all {@link #getRaceColumns() race columns} and their {@link RaceColumn#getFleets() fleets} and checks + * if {@code trackedRace} is {@link RaceColumn#getTrackedRace(Fleet) linked} to that combination. If such a slot is found + * that "slot" is returned by a pair specifying the non-{@code null} {@link RaceColumn} and {@code Fleet} pair. Otherwise, + * {@code null} is returned. + */ + Pair getRaceColumnAndFleet(TrackedRace trackedRace); + + /** + * Gets the ("dominant") boat class for this leaderboard. For a {@link RegattaLeaderboard} this is the {@link Regatta}'s boat class. + * For a {@link FlexibleLeaderboard} the implementation is more complex because no fixed boat class is set for the leaderboard. There, + * the boat class will be determined based on the most frequently occurring boat class when iterating across the competitors. + */ + BoatClass getBoatClass(); +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 46ca0ff849a..9454eeac508 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -1,301 +1,301 @@ -package com.sap.sailing.domain.leaderboard.meta; - -import java.util.Collections; -import java.util.Map; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Fleet; -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.impl.SimpleAbstractRaceColumn; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; -import com.sap.sailing.domain.racelog.RaceLogIdentifier; -import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; -import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider; -import com.sap.sailing.domain.tracking.TrackedRace; - -/** - * All {@link RaceColumnListener} events received from the underlying leaderboard's race columns - * are forwarded to this object's {@link RaceColumnListener}s. - * - * @author Axel Uhl - * - */ -public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements RaceColumn, RaceColumnListener { - private static final long serialVersionUID = 3092096133388262955L; - private final Leaderboard leaderboard; - private final Fleet metaFleet; - - public MetaLeaderboardColumn(Leaderboard leaderboard, Fleet metaFleet) { - super(); - this.leaderboard = leaderboard; - this.metaFleet = metaFleet; - leaderboard.addRaceColumnListener(this); - } - - @Override - public RaceLog getRaceLog(Fleet fleet) { - return null; - } - - public Leaderboard getLeaderboard() { - return leaderboard; - } - - @Override - public String getName() { - return leaderboard.getDisplayName() != null ? leaderboard.getDisplayName() : leaderboard.getName(); - } - - @Override - public Iterable getFleets() { - return Collections.singleton(metaFleet); - } - - @Override - public Fleet getFleetByName(String fleetName) { - return fleetName.equals(metaFleet.getName()) ? metaFleet : null; - } - - @Override - public Fleet getFleetOfCompetitor(Competitor competitor) { - return metaFleet; - } - - @Override - public void setTrackedRace(Fleet fleet, TrackedRace race) { - } - - @Override - public boolean hasTrackedRaces() { - return false; - } - - @Override - public TrackedRace getTrackedRace(Fleet fleet) { - return null; - } - - @Override - public TrackedRace getTrackedRace(Competitor competitor) { - return null; - } - - @Override - public RaceIdentifier getRaceIdentifier(Fleet fleet) { - return null; - } - - @Override - public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) { - } - - @Override - public boolean isMedalRace() { - return false; - } - - @Override - public void releaseTrackedRace(Fleet fleet) { - } - - @Override - public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(raceColumn, fleet, trackedRace); - } - - @Override - public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(raceColumn, fleet, trackedRace); - } - - @Override - public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) { - getRaceColumnListeners().notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace); - } - - @Override - public void isFleetsCanRunInParallelChanged(RaceColumn raceColumn, boolean newIsFleetsCanRunInParallel) { - getRaceColumnListeners().notifyListenersAboutIsFleetsCanRunInParallelChanged(raceColumn, newIsFleetsCanRunInParallel); - } - - @Override - public void isStartsWithZeroScoreChanged(RaceColumn raceColumn, boolean newIsStartsWithZeroScore) { - getRaceColumnListeners().notifyListenersAboutIsStartsWithZeroScoreChanged(raceColumn, newIsStartsWithZeroScore); - } - - @Override - public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn, boolean firstColumnIsNonDiscardableCarryForward) { - getRaceColumnListeners().notifyListenersAboutIsFirstColumnIsNonDiscardableCarryForwardChanged(raceColumn, firstColumnIsNonDiscardableCarryForward); - } - - @Override - public void hasSplitFleetContiguousScoringChanged(RaceColumn raceColumn, boolean hasSplitFleetContiguousScoring) { - getRaceColumnListeners().notifyListenersAboutHasSplitFleetContiguousScoringChanged(raceColumn, hasSplitFleetContiguousScoring); - } - - @Override - public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) { - return getRaceColumnListeners().canAddRaceColumnToContainer(raceColumn); - } - - @Override - public void raceColumnAddedToContainer(RaceColumn raceColumn) { - getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(raceColumn); - } - - @Override - public void raceColumnRemovedFromContainer(RaceColumn raceColumn) { - getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn); - } - - @Override - public void raceColumnMoved(RaceColumn raceColumn, int newIndex) { - getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(raceColumn, newIndex); - } - - @Override - public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { - getRaceColumnListeners().notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor); - } - - @Override - public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) { - getRaceColumnListeners().notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName); - } - - @Override - public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { - getRaceColumnListeners().notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); - } - - @Override - public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) { - getRaceColumnListeners().notifyListenersAboutRaceLogEventAdded(raceColumn, raceLogIdentifier, event); - } - - @Override - public boolean isTransient() { - return false; - } - - @Override - public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) { - return null; - } - - @Override - public void removeRaceIdentifier(Fleet fleet) { - } - - @Override - public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { - } - - @Override - public void setRaceLogInformation(RaceLogStore raceLogStore, RegattaLikeIdentifier regattaLikeParent) { - } - - @Override - public void reloadRaceLog(Fleet fleet) { - } - - @Override - public RaceExecutionOrderProvider getRaceExecutionOrderProvider() { - return null; - } - - @Override - public Iterable getAllCompetitors() { - return leaderboard.getAllCompetitors(); - } - - @Override - public Iterable getAllCompetitors(Fleet fleet) { - final Iterable result; - if (fleet == metaFleet) { - result = leaderboard.getAllCompetitors(); - } else { - result = Collections.emptySet(); - } - return result; - } - - @Override - public RegattaLog getRegattaLog() { - return null; - } - - @Override - public Iterable getCourseMarks() { - return Collections.emptySet(); - } - - @Override - public Iterable getCourseMarks(Fleet fleet) { - return Collections.emptySet(); - } - - @Override - public Iterable getAvailableMarks() { - return Collections.emptySet(); - } - - @Override - public Iterable getAvailableMarks(Fleet fleet) { - return Collections.emptySet(); - } - - @Override - public void registerCompetitor(Competitor competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void registerCompetitors(Iterable competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void deregisterCompetitor(Competitor competitors, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void deregisterCompetitors(Iterable competitors, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void enableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - - @Override - public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - - @Override - public Map getAllCompetitorsAndTheirBoats() { - // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } - - @Override - public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { - // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } -} +package com.sap.sailing.domain.leaderboard.meta; + +import java.util.Collections; +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Fleet; +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.impl.SimpleAbstractRaceColumn; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; +import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; +import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider; +import com.sap.sailing.domain.tracking.TrackedRace; + +/** + * All {@link RaceColumnListener} events received from the underlying leaderboard's race columns + * are forwarded to this object's {@link RaceColumnListener}s. + * + * @author Axel Uhl + * + */ +public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements RaceColumn, RaceColumnListener { + private static final long serialVersionUID = 3092096133388262955L; + private final Leaderboard leaderboard; + private final Fleet metaFleet; + + public MetaLeaderboardColumn(Leaderboard leaderboard, Fleet metaFleet) { + super(); + this.leaderboard = leaderboard; + this.metaFleet = metaFleet; + leaderboard.addRaceColumnListener(this); + } + + @Override + public RaceLog getRaceLog(Fleet fleet) { + return null; + } + + public Leaderboard getLeaderboard() { + return leaderboard; + } + + @Override + public String getName() { + return leaderboard.getDisplayName() != null ? leaderboard.getDisplayName() : leaderboard.getName(); + } + + @Override + public Iterable getFleets() { + return Collections.singleton(metaFleet); + } + + @Override + public Fleet getFleetByName(String fleetName) { + return fleetName.equals(metaFleet.getName()) ? metaFleet : null; + } + + @Override + public Fleet getFleetOfCompetitor(Competitor competitor) { + return metaFleet; + } + + @Override + public void setTrackedRace(Fleet fleet, TrackedRace race) { + } + + @Override + public boolean hasTrackedRaces() { + return false; + } + + @Override + public TrackedRace getTrackedRace(Fleet fleet) { + return null; + } + + @Override + public TrackedRace getTrackedRace(Competitor competitor) { + return null; + } + + @Override + public RaceIdentifier getRaceIdentifier(Fleet fleet) { + return null; + } + + @Override + public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) { + } + + @Override + public boolean isMedalRace() { + return false; + } + + @Override + public void releaseTrackedRace(Fleet fleet) { + } + + @Override + public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(raceColumn, fleet, trackedRace); + } + + @Override + public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(raceColumn, fleet, trackedRace); + } + + @Override + public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) { + getRaceColumnListeners().notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace); + } + + @Override + public void isFleetsCanRunInParallelChanged(RaceColumn raceColumn, boolean newIsFleetsCanRunInParallel) { + getRaceColumnListeners().notifyListenersAboutIsFleetsCanRunInParallelChanged(raceColumn, newIsFleetsCanRunInParallel); + } + + @Override + public void isStartsWithZeroScoreChanged(RaceColumn raceColumn, boolean newIsStartsWithZeroScore) { + getRaceColumnListeners().notifyListenersAboutIsStartsWithZeroScoreChanged(raceColumn, newIsStartsWithZeroScore); + } + + @Override + public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn, boolean firstColumnIsNonDiscardableCarryForward) { + getRaceColumnListeners().notifyListenersAboutIsFirstColumnIsNonDiscardableCarryForwardChanged(raceColumn, firstColumnIsNonDiscardableCarryForward); + } + + @Override + public void hasSplitFleetContiguousScoringChanged(RaceColumn raceColumn, boolean hasSplitFleetContiguousScoring) { + getRaceColumnListeners().notifyListenersAboutHasSplitFleetContiguousScoringChanged(raceColumn, hasSplitFleetContiguousScoring); + } + + @Override + public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) { + return getRaceColumnListeners().canAddRaceColumnToContainer(raceColumn); + } + + @Override + public void raceColumnAddedToContainer(RaceColumn raceColumn) { + getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(raceColumn); + } + + @Override + public void raceColumnRemovedFromContainer(RaceColumn raceColumn) { + getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn); + } + + @Override + public void raceColumnMoved(RaceColumn raceColumn, int newIndex) { + getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(raceColumn, newIndex); + } + + @Override + public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { + getRaceColumnListeners().notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor); + } + + @Override + public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) { + getRaceColumnListeners().notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName); + } + + @Override + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { + getRaceColumnListeners().notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); + } + + @Override + public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) { + getRaceColumnListeners().notifyListenersAboutRaceLogEventAdded(raceColumn, raceLogIdentifier, event); + } + + @Override + public boolean isTransient() { + return false; + } + + @Override + public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) { + return null; + } + + @Override + public void removeRaceIdentifier(Fleet fleet) { + } + + @Override + public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { + } + + @Override + public void setRaceLogInformation(RaceLogStore raceLogStore, RegattaLikeIdentifier regattaLikeParent) { + } + + @Override + public void reloadRaceLog(Fleet fleet) { + } + + @Override + public RaceExecutionOrderProvider getRaceExecutionOrderProvider() { + return null; + } + + @Override + public Iterable getAllCompetitors() { + return leaderboard.getAllCompetitors(); + } + + @Override + public Iterable getAllCompetitors(Fleet fleet) { + final Iterable result; + if (fleet == metaFleet) { + result = leaderboard.getAllCompetitors(); + } else { + result = Collections.emptySet(); + } + return result; + } + + @Override + public RegattaLog getRegattaLog() { + return null; + } + + @Override + public Iterable getCourseMarks() { + return Collections.emptySet(); + } + + @Override + public Iterable getCourseMarks(Fleet fleet) { + return Collections.emptySet(); + } + + @Override + public Iterable getAvailableMarks() { + return Collections.emptySet(); + } + + @Override + public Iterable getAvailableMarks(Fleet fleet) { + return Collections.emptySet(); + } + + @Override + public void registerCompetitor(Competitor competitor, Fleet fleet) + throws CompetitorRegistrationOnRaceLogDisabledException { + throw new CompetitorRegistrationOnRaceLogDisabledException(); + } + + @Override + public void registerCompetitors(Iterable competitor, Fleet fleet) + throws CompetitorRegistrationOnRaceLogDisabledException { + throw new CompetitorRegistrationOnRaceLogDisabledException(); + } + + @Override + public void deregisterCompetitor(Competitor competitors, Fleet fleet) + throws CompetitorRegistrationOnRaceLogDisabledException { + throw new CompetitorRegistrationOnRaceLogDisabledException(); + } + + @Override + public void deregisterCompetitors(Iterable competitors, Fleet fleet) + throws CompetitorRegistrationOnRaceLogDisabledException { + throw new CompetitorRegistrationOnRaceLogDisabledException(); + } + + @Override + public void enableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { + } + + @Override + public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { + } + + @Override + public Map getAllCompetitorsAndTheirBoats() { + // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + + @Override + public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { + // TODO: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } +} 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 36052458019..5795c5bf69e 100644 --- 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 @@ -1,745 +1,745 @@ -package com.sap.sailing.domain.tracking; - -import java.io.Serializable; -import java.util.List; -import java.util.NavigableSet; -import java.util.Set; -import java.util.SortedSet; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -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.regatta.events.RegattaLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -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.SharedDomainFactory; -import com.sap.sailing.domain.base.Sideline; -import com.sap.sailing.domain.base.SpeedWithConfidence; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.DouglasPeucker; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.LegType; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Tack; -import com.sap.sailing.domain.common.TargetTimeInfo; -import com.sap.sailing.domain.common.TimingConstants; -import com.sap.sailing.domain.common.TrackedRaceStatusEnum; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; -import com.sap.sailing.domain.common.dto.TrackedRaceDTO; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.SensorFix; -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.tracking.GPSFixStore; -import com.sap.sailing.domain.ranking.RankingMetric; -import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; -import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache; -import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; -import com.sap.sse.common.Duration; -import com.sap.sse.common.IsManagedByCache; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; - -/** - * Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The - * course may change over time as the race committee decides to change it. Therefore, a {@link TrackedRace} instance - * {@link Course#addCourseListener(com.sap.sailing.domain.base.CourseListener) observes} the race {@link Course} for - * such changes. The tracking information of a leg can be requested either for all competitors (see - * {@link #getTrackedLegs()} and {@link #getTrackedLeg(Leg)}) or for a single competitor (see - * {@link #getTrackedLeg(Competitor, Leg)}). - *

- * - * The overall race standings can be requested in terms of a competitor's ranking. More detailed information about what - * happens / happened within a leg is available from {@link TrackedLeg} and {@link TrackedLegOfCompetitor}. - * - * @author Axel Uhl (d043530) - * - */ -public interface TrackedRace extends Serializable, IsManagedByCache { - final Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5); - final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_MINUTE.times(2); - - final long MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS = 30000; - - final long DEFAULT_LIVE_DELAY_IN_MILLISECONDS = 5000; - - RaceDefinition getRace(); - - RegattaAndRaceIdentifier getRaceIdentifier(); - - /** - * Tells how ranks are to be assigned to the competitors at any time during the race. For one-design boat classes - * this will usually happen by projecting the competitors to the wind direction for upwind and downwind legs or to - * the leg's rhumb line for reaching legs, then comparing positions. For handicap races using a time-on-time, - * time-on-distance, combination thereof or a more complicated scheme such as ORC Performance Curve, the ranking - * process needs to take into account the competitor-specific correction factors defined in the measurement - * certificate. - */ - RankingMetric getRankingMetric(); - - /** - * Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time - * point which is expected to be before the race start time). The highest precedence take the - * {@link #attachedRaceLogs race logs} and their start time events, followed by the field {@link #startTimeReceived} - * which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. When there are no {@link MarkPassing}s - * for the first mark, null is returned. If there are mark passings for the first mark and the start - * time is less than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} before the first mark - * passing for the first mark. Otherwise, the first mark passing for the first mark minus - * {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} is returned as the race start time. - *

- * - * If no start time can be determined this way, null is returned. - */ - TimePoint getStartOfRace(); - - /** - * Like {@link #getStartOfRace()}, but ignoring any inference from start mark passings in case {@code inferred} is - * {@code false}. In this case, if no official start time was set, e.g., in the {@link RaceLog} or explicitly using - * {@link #getStartTimeReceived()}, {@code null} will be returned by this method even if start mark passings are - * present. - */ - TimePoint getStartOfRace(boolean inferred); - - /** - * @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race - * into status {@link RaceLogRaceStatus#FINISHED} from any of the {@link RaceLog}s attached to this race, - * or {@code null} if no such event is found. - * - * @see {@link RaceChangeListener#finishedTimeChanged(TimePoint, TimePoint)} - */ - TimePoint getFinishedTime(); - - /** - * Determine the race end time is tricky. Boats may sink, stop, not finish, although they started the race. We - * therefore cannot wait for all boats to reach the finish line. The following rules are used to calculate the - * endOfRace: - *

    - *
  1. Returns null if no boat passed the finish line
  2. - *
  3. Returns time of the last mark passing recorded for the finish line
  4. - *
  5. TODO: Returns the time of the first passing of the finish line + the target window (defined in the - * competition rules) if a target window has been defined for the race
  6. - */ - TimePoint getEndOfRace(); - - /** - * Returns a list of the first and last mark passing times of all course waypoints. Callers wanting to iterate over - * the result must synchronize on the result. - */ - Iterable>> getMarkPassingsTimes(); - - /** - * Shorthand for {@link #getStart()}.{@link TimePoint#compareTo(TimePoint) compareTo(at)} <= 0 - */ - boolean hasStarted(TimePoint at); - - /** - * A race is considered "live" if it - * {@link TrackedRaceDTO#hasGPSData has GPS data} and {@link TrackedRaceDTO#hasWindData wind data} and if the - * at time point is between the start and the end of the race. - *

    - * - * The pre-start phase of a race is interesting also in live mode. Therefore, if a {@link TrackedRace#getStartOfRace start - * time} is available for the race, the {@link TimingConstants#PRE_START_PHASE_DURATION_IN_MILLIS} is subtracted - * from the actual start time so that the pre-start phase also counts as live. If no start time is known for the - * race, but a {@link TrackedRace#getStartOfTracking start of tracking time} is known, it is used as the start of - * the "live" interval. - *

    - * - * If an {@link TrackedRace#getEndOfRace end time} is already known for the race, - * {@link TimingConstants#IS_LIVE_GRACE_PERIOD_IN_MILLIS} is added to that and the result is taken to be the end of - * the "live" period. If no end time is known but a {@link TrackedRace#getTimePointOfNewestEvent} is set, again the - * {@link TimingConstants#IS_LIVE_GRACE_PERIOD_IN_MILLIS} is added to that to mark the end of the "live" interval. - *

    - * - * @param at - * the time point at which to determine whether the race for fleet - * is/was live. A null value will use the start time of the race. - * @return - */ - boolean isLive(TimePoint at); - - /** - * Clients can safely iterate over the iterable returned because it's a non-live copy of the tracked legs of this - * tracked race. This implies that should an update to the underlying list of waypoints in this race's - * {@link Course} take place after this method has returned, then this won't be reflected in the result returned. - * Callers should obtain the {@link Course#lockForRead() course's read lock} while using the result of this call if - * they want to ensure that no course update is applied concurrently. - */ - Iterable getTrackedLegs(); - - TrackedLeg getTrackedLeg(Leg leg); - - /** - * Tracking information about the leg competitor is on at timePoint, or null - * if the competitor hasn't started any leg yet at timePoint or has already finished the race. - */ - TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint); - - /** - * Tells which leg the leader at timePoint is on - */ - TrackedLeg getCurrentLeg(TimePoint timePoint); - - /** - * Tells the number of the last started leg at timePoint - * The leg number is 0 before the start, the number of the current leg during the race - * and the number of the last leg at the end of the race even if the race has finished. - */ - int getLastLegStarted(TimePoint timePoint); - - /** - * Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}. - */ - TrackedLeg getTrackedLegFinishingAt(Waypoint endOfLeg); - - /** - * Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}. - */ - TrackedLeg getTrackedLegStartingAt(Waypoint startOfLeg); - - /** - * The raw, updating feed of a single competitor participating in this race - */ - GPSFixTrack getTrack(Competitor competitor); - - /** - * {@link SensorFixTrack}s provide timed sensor data in addition to GPSFixes that are hold in {@link GPSFixTrack}s. - * In contrast to {@link GPSFixTrack}s there is a 1:n relation of competitors to tracks by introducing track names. - * So every type of track has an associated name. With this construct you can have track implementations that - * provide specific functionality based on the contained fix type. - * - * @param competitor the competitor to get the track for - * @param trackName the name of the track to get - * @return the track associated to the given Competitor and name or null if there is none. - */ - > TrackT getSensorTrack(Competitor competitor, String trackName); - - /** - * Tells the leg on which the competitor was at time at. If the competitor hasn't passed - * the start waypoint yet, null is returned because the competitor was not yet on any leg at that point - * in time. If the time point happens to be after the last fix received from that competitor, the last known leg for - * that competitor is returned. If the time point is after the competitor's mark passing for the finish line, - * null is returned. For all legs except the last, if the time point equals a mark passing time point - * of the leg's starting waypoint, that leg is returned. For the time point of the mark passing for the finish line, - * the last leg is returned. - */ - TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, TimePoint at); - - TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, Leg leg); - - /** - * @return a sequential number counting the updates that occurred to this tracked race. Callers may use this to ask - * for updates newer than such a sequence number. - */ - long getUpdateCount(); - - int getRankDifference(Competitor competitor, Leg leg, TimePoint timePoint); - - /** - * Computes the rank of the competitor in this race for the current time. - */ - int getRank(Competitor competitor) throws NoWindException; - - /** - * Computes the rank of competitor in this race. A competitor is ahead of all competitors that are one - * or more legs behind. Within the same leg, the rank is determined by the windward distance to go and therefore - * depends on the assumptions of the wind direction for the given timePoint. If the race hasn't - * {@link #hasStarted(TimePoint) started} yet, the result is undefined. - * - * @return 0 in case the competitor hasn't participated in the race; a rank starting with - * 1 where rank 1 identifies the leader otherwise - */ - int getRank(Competitor competitor, TimePoint timePoint); - - /** - * For the given waypoint lists the {@link MarkPassing} events that describe which competitor passed the waypoint at - * which point in time. This can, e.g., be used to sort those competitors who already finished a leg within the leg - * that ends with waypoint. The remaining competitors need to be ordered by the advantage line-related - * distance to the waypoint. - * - * @return the iterable sequence of {@link MarkPassing}s as described above. If the caller wants to iterate on the - * resulting collection, the caller needs to invoke {@link #lockForRead(Iterable)} with the collection - * returned as parameter because insertions into the competitor's mark passing collection will obtain the - * corresponding write lock. - */ - Iterable getMarkPassingsInOrder(Waypoint waypoint); - - /** - * Obtains the {@link MarkPassing} for competitor passing waypoint. If no such mark - * passing has been reported (yet), null is returned. - */ - MarkPassing getMarkPassing(Competitor competitor, Waypoint waypoint); - - /** - * Yields the track describing mark's movement over time; never null because a new track - * will be created in case no track was present for mark so far. - * - * @see #getTrack(Mark) - */ - GPSFixTrack getOrCreateTrack(Mark mark); - - /** - * Yields the track describing mark's movement over time; null if no track exists for - * mark so far. - * - * @see #getOrCreateTrack(Mark) - */ - GPSFixTrack getTrack(Mark mark); - - /** - * Retrieves all marks assigned to the race. They are not necessarily part of the race course. - */ - Iterable getMarks(); - - /** - * Retrieves all course side lines assigned to the race. - */ - Iterable getCourseSidelines(); - - /** - * If the waypoint only has one {@link #getMarks() mark}, its position at time timePoint - * is returned. Otherwise, the center of gravity between the mark positions is computed and returned. - */ - default Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) { - return getApproximatePosition(waypoint, timePoint, new NonCachingMarkPositionAtTimePointCache(this, timePoint)); - } - - /** - * Same as {@link #getApproximatePosition(Waypoint, TimePoint)}, but giving the caller the possibility to pass a - * cache of mark positions and related information that can help speed up compound operations requiring frequent - * access to the same marks in the same race for the same time point. - * - * @param markPositionCache - * a cache for this {@link MarkPositionAtTimePointCache#getTrackedRace() race} and the - * {@link MarkPositionAtTimePointCache#getTimePoint() timePoint} passed - */ - Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, - MarkPositionAtTimePointCache markPositionCache); - - /** - * Checks whether the {@link Wind#getTimePoint()} is in range of start and end {@link TimePoint}s plus extra time - * for wind recording. If, based on a {@link RaceExecutionOrderProvider}, there is no previous race that takes the - * wind fix, an extended time range lead (see - * {@link TrackedRaceImpl#EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS}) is used to record wind even a long - * time before the race start. - *

    - * - * A race does not record wind when both, {@link #getStartOfTracking()} and {@link #getStartOfRace()} are - * null. Wind is not recorded when it is after the later of {@link #getEndOfRace()} and - * {@link #getEndOfTracking()} and one of the two is not null. - *

    - * - * This default implementation returns true which may be useful for tests and mocked implementations; however, real - * implementations shall override this and provide a meaningful implementation according to the specification given - * above. - */ - default boolean takesWindFixWithTimePoint(TimePoint timePoint) { - return true; - } - - default boolean takesWindFixWithTimePointRecursively(TimePoint windFixTimePoint, Set visited) { - return true; - } - - /** - * Same as {@link #getWind(Position, TimePoint, Set) getWind(p, at, Collections.emptyList())} - */ - Wind getWind(Position p, TimePoint at); - - /** - * Obtains estimated interpolated wind information for a given position and time point. The information is taken - * from all wind sources available except for those listed in windSourcesToExclude, using the - * confidences of the wind values provided by the various sources during averaging. - */ - Wind getWind(Position p, TimePoint at, Set windSourcesToExclude); - - /** - * Retrieves the wind sources used so far by this race that have the specified type as their - * {@link WindSource#getType() type}. Always returns a non-null iterable which may be empty in case the - * race does not use any wind source of the specified type (yet).

    - * - * It is possible to ask for the {@link WindSourceType#COMBINED} and {@link WindSourceType#LEG_MIDDLE} types and - * get a non-empty result although those sources are never returned by {@link #getWindSources()}. - */ - Set getWindSources(WindSourceType type); - - /** - * Retrieves all wind sources known to this race, including those {@link #getWindSourcesToExclude() to exclude}. - * Callers can freely iterate because a copied collection is returned. The {@link WindSourceType#COMBINED} wind source - * as well as the {@link WindSourceType#LEG_MIDDLE} sources are never part of the result. - */ - Set getWindSources(); - - /** - * Same as {@link #getOrCreateWindTrack(WindSource, long) getOrCreateWindTrack(windSource, - * getMillisecondsOverWhichToAverageWind())}. - */ - WindTrack getOrCreateWindTrack(WindSource windSource); - - WindTrack getOrCreateWindTrack(WindSource windSource, long delayForWindEstimationCacheInvalidation); - - /** - * Waits until {@link #getUpdateCount()} is after sinceUpdate. - */ - void waitForNextUpdate(int sinceUpdate) throws InterruptedException; - - /** - * Time stamp of the start of the actual tracking. The value can be null (e.g. if we have not received any signal - * from the tracking infrastructure) - */ - TimePoint getStartOfTracking(); - - /** - * Time stamp of the end of the actual tracking. The value can be null (e.g. if we have not received any signal from - * the tracking infrastructure) - */ - TimePoint getEndOfTracking(); - - /** - * Regardless of the order in which events were received, this method returns the latest time point contained by any - * of the events received and processed. - */ - TimePoint getTimePointOfNewestEvent(); - - /** - * Regardless of the order in which events were received, this method returns the oldest time point contained by any - * of the events received and processed. - */ - TimePoint getTimePointOfOldestEvent(); - - /** - * @return the mark passings for competitor in this race received so far; the mark passing objects are - * returned such that their {@link MarkPassing#getWaypoint() waypoints} are ordered in the same way they are - * ordered in the race's {@link Course}. Note, that this doesn't necessarily guarantee ascending time - * points, particularly if premature mark passings have been detected accidentally as can be the case with - * some tracking providers such as TracTrac. If the caller wants to iterate on the resulting collection or - * construct a {@link SortedSet#headSet(Object)} or {@link SortedSet#tailSet(Object)} and then iterate over - * that, the caller needs to invoke {@link #lockForRead(Iterable)} with the collection returned as parameter - * because insertions into the competitor's mark passing collection will obtain the corresponding write - * lock. - */ - NavigableSet getMarkPassings(Competitor competitor); - - /** - * Returns competitor's mark passings. - * - * @param waitForLatestUpdates - * if any mark passing updates are pending because some calculations are currently going on and updates - * haven't all been processed yet then the call will block until these updates have been processed in - * case this parameter is set to {@code true}. For this the method uses a lock on the - * {@link MarkPassingCalculator }to block the thread until all calculations will be finished. - */ - NavigableSet getMarkPassings(Competitor competitor, boolean waitForLatestUpdates); - - /** - * This obtains the course's read lock before asking for the read lock for the markPassings structure. - * See also bug 1370 (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1370). This is necessary because the - * code that executes a course update will first ask the course's write lock and then relay execution to the - * course change listeners among which there is a {@link TrackedRace} which will then update the mark passings - * for all competitors and therefore will need to ask the write lock for those. If the thread calling this method - * first obtains the mark passings read lock and later, while holding on to that lock, asks for the course's read - * lock, a deadlock may result.

    - * - * Furthermore, when trying to acquire both, a lock for the {@link #getMarkPassings(Competitor) mark passings for a competitor} - * and a lock for the {@link #getMarkPassingsInOrder(Waypoint) mark passings for a waypoint, this needs to happen in exactly - * this order, or a deadlock may result.

    - * - * The {@link #unlockAfterRead(Iterable)} method will symmetrically unlock the course's read lock after releasing the - * read lock for the mark passings. - */ - void lockForRead(Iterable markPassings); - - /** - * Releases the read lock for the mark passings and then the read lock for the course. - * - * @see #lockForRead(Iterable) - */ - void unlockAfterRead(Iterable markPassings); - - /** - * Time stamp that the event received last from the underlying push service carried on it. Note that these times may - * not increase monotonically. - */ - TimePoint getTimePointOfLastEvent(); - - long getMillisecondsOverWhichToAverageSpeed(); - - long getMillisecondsOverWhichToAverageWind(); - - /** - * Gets the current delay of incoming events to the real time of the events in milliseconds - */ - long getDelayToLiveInMillis(); - - /** - * Estimates the wind direction based on the observed boat courses at the time given for the position provided. The - * estimate is based on the assumption that the boats which are on an upwind or a downwind leg sail with very - * similar angles on the starboard and the port side. There should be clusters of courses which are close to each - * other (within a threshold of, say, +/- 5 degrees), whereas for the upwind group there should be two clusters with - * angles about 90 degrees apart; similarly, for the downwind leg there should be two clusters, only that the - * general jibing angle may vary more, based on the wind speed and the boat class. - *

    - * - * Boats {@link GPSFixTrack#hasDirectionChange(TimePoint, double) currently maneuvering} are not considered for this - * analysis. - *

    - * - * This wind direction should not be used directly to compute the leg's wind direction and hence the {@link LegType - * leg type} because an endless recursion may result: an implementation of this method signature will need to know - * whether a leg is an upwind or downwind leg for which it has to know where the wind is coming from. - * - * @return null if no sufficient boat track information is available or leg type identification (upwind - * vs. downwind) is not possible; a valid {@link Wind} fix otherwise whose bearing is inferred from the boat - * courses and whose speed in knots is currently a rough indication of how many boats' courses contributed - * to determining the bearing. If in the future we have data about polar diagrams specific to boat classes, - * we may be able to also infer the wind speed from the boat tracks. - */ - Wind getEstimatedWindDirection(TimePoint timePoint); - - /** - * Determines whether the competitor is sailing on port or starboard tack at the timePoint - * requested. Note that this will have to retrieve information about the wind. This, in turn, can lead to the - * current thread obtaining the monitor of the various wind tracks, and, if the - * {@link WindSource#TRACK_BASED_ESTIMATION} source is used, also the monitors of the competitors' GPS tracks. - */ - Tack getTack(Competitor competitor, TimePoint timePoint) throws NoWindException; - - /** - * Determines whether the competitor is sailing on port or starboard tack at the timePoint - * requested. - *

    - * This method outperforms {@link #getTack(Competitor, TimePoint)}, based on being passed an already calculated wind - * for the given time and competitor position as well as the competitors speed and course over ground. - *

    - * This method will acquire the read lock for the competitor's track. - */ - Tack getTack(SpeedWithBearing speedWithBearing, Wind wind, TimePoint timePoint); - - TrackedRegatta getTrackedRegatta(); - - /** - * Computes a default wind direction based on the direction of the first leg at time at, with a default - * speed of zero knots. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()} returns - * true. - * - * @param at - * usually the {@link #getStart() start time} should be used; if no valid start time is provided, the - * current time point may serve as a default - * @return null in case the first leg's direction cannot be determined, e.g., because the necessary - * mark positions are not known (yet) - */ - Wind getDirectionFromStartToNextMark(TimePoint at); - - /** - * Uses a {@link DouglasPeucker Douglas-Peucker} algorithm to approximate this track's fixes starting at time - * from until time point to such that the maximum distance between the track's fixes and - * the approximation is at most maxDistance. The approximation's fixes are original fixes from - * the competitor's {@link GPSFixTrack track}. - */ - Iterable approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to); - - /** - * @return a non-null but perhaps empty list of the maneuvers that competitor performed in - * this race between from and to. Depending on waitForLatest the - * result is taken from the cache straight away (waitForLatest==false) or, if a re-calculation - * for the key is still ongoing, the result of that ongoing re-calculation is returned. - */ - Iterable getManeuvers(Competitor competitor, TimePoint from, TimePoint to, boolean waitForLatest); - - /** - * @return true if this race is known to start with an {@link LegType#UPWIND upwind} leg. If this is - * the case, the wind estimation may default to using the first leg's direction at race start time as the - * direction the wind comes from. - */ - boolean raceIsKnownToStartUpwind(); - - /** - * Many calculations require valid wind data. In order to prevent NoWindException's to be handled by those - * calculation this method can be used to check whether the tracked race has sufficient wind information available. - * - * @return true if {@link #getWind(Position, TimePoint)} delivers a (not null) wind fix. - */ - boolean hasWindData(); - - /** - * - * @return true if at least one GPS fix for one of the competitors is available for this race. - */ - boolean hasGPSData(); - - /** - * Adds a race change listener to the set of listeners that will be notified about changes to this race. The - * listener won't be serialized together with this object. - */ - void addListener(RaceChangeListener listener); - - /** - * Like {@link #addListener(RaceChangeListener)}, but notifies the listener about the wind fixes known so far by the - * tracked race. This runs synchronized with the otherwise asynchronous loading of wind tracks, triggered by the - * constructor of the {@link TrackedRace} implementation classes. This procedure guarantees that eventually the - * listener will have received a notification for all wind fixes, regardless of whether they were already loaded at - * the time the listener is registered or they are loaded after the registration has completed.

    - * - * The same is true for the GPS fixes for marks and competitors. - */ - void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded, - boolean notifyAboutGPSFixesAlreadyLoaded); - - void removeListener(RaceChangeListener listener); - - /** - * @return null if there are no mark passings for the competitor in this race - * or if the competitor has not finished one of the legs in the race. - */ - Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint); - - /** - * See {@link TrackedLegOfCompetitor#getDistanceTraveledConsideringGateStart(TimePoint)} - */ - Distance getDistanceTraveledIncludingGateStart(Competitor competitor, TimePoint timePoint); - - /** - * See {@link TrackedLegOfCompetitor#getWindwardDistanceToCompetitorFarthestAhead(TimePoint, WindPositionMode, RankingInfo)} - */ - Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode); - - /** - * Same as {@link #getWindwardDistanceToCompetitorFarthestAhead(Competitor, TimePoint, WindPositionMode)}, only with an - * additional cache to speed up wind and leg type and leg bearing calculations in case of multiple similar look-ups - * for the same time point. - * - * @param rankingInfo - * materialized ranking information that is expensive to calculate, avoiding redundant calculations - */ - Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); - - /** - * Calls {@link #getWindWithConfidence(Position, TimePoint, Iterable)} and excludes those wind sources listed in - * {@link #getWindSourcesToExclude}. - */ - WindWithConfidence> getWindWithConfidence(Position p, TimePoint at); - - /** - * Lists those wind sources which by default are not considered in {@link #getWind(Position, TimePoint)} and - * {@link #getWindWithConfidence(Position, TimePoint)}. - */ - Set getWindSourcesToExclude(); - - /** - * Loops over this tracked race's wind sources and from each asks its averaged wind for the position p - * and time point at, using the particular wind source's averaging interval. The confidences delivered - * by each wind source are used during computing the averaged result across the wind sources. The result has the - * averaged confidence attached. - */ - WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, - Set windSourcesToExclude); - - /** - * Same as {@link #getEstimatedWindDirection(TimePoint)}, but propagates the confidence of the wind - * estimation, relative to the timePoint for which the request is made, in the result. The - * {@link Wind#getPosition() position} of all {@link Wind} fixes returned is null. - */ - WindWithConfidence getEstimatedWindDirectionWithConfidence(TimePoint timePoint); - - /** - * After the call returns, {@link #getWindSourcesToExclude()} returns an iterable that equals - * windSourcesToExclude - */ - void setWindSourcesToExclude(Iterable windSourcesToExclude); - - /** - * Computes the average cross-track error for the legs with type {@link LegType#UPWIND}. - * - * @param waitForLatestAnalysis - * if true and any cache update is currently going on, wait for the update to complete and - * then fetch the updated value; otherwise, serve this requests from whatever is currently in the cache - */ - Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis) - throws NoWindException; - - /** - * Same as {@link #getAverageAbsoluteCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg type, - * wind on leg and leg bearing is provided. - */ - Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, - WindLegTypeAndLegBearingCache cache) throws NoWindException; - - Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, - boolean waitForLatestAnalyses) throws NoWindException; - - Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis) - throws NoWindException; - - /** - * Same as {@link #getAverageSignedCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg type, - * wind direction and leg bearing is provided. - */ - Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, - WindLegTypeAndLegBearingCache cache) throws NoWindException; - - Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, - boolean waitForLatestAnalysis) throws NoWindException; - - public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint); - - WindStore getWindStore(); - - Competitor getOverallLeader(TimePoint timePoint); - - Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); - - Boat getBoatOfCompetitor(Serializable competitorId); - - /** - * Returns the competitors of this tracked race, according to their ranking. Competitors whose - * {@link #getRank(Competitor)} is 0 will be sorted "worst". - */ - List getCompetitorsFromBestToWorst(TimePoint timePoint); - - /** - * Same as {@link #getCompetitorsFromBestToWorst(TimePoint)}, using a cache for wind, leg type and leg - * bearing values. - */ - List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); - - /** - * When provided with a {@link WindStore} during construction, the tracked race will - * asynchronously load the wind data for this tracked race from the wind store and the GPS store in a - * background thread and update this tracked race with the results. Clients that want to wait for the wind - * loading process to complete can do so by calling this method which will block until the wind loading has - * completed. - */ - void waitUntilLoadingFromWindStoreComplete() throws InterruptedException; - - /** - * Whenever a {@link RegattaLog} is attached, fixes are loaded from the {@link GPSFixStore} for all mappings - * found in the {@code RegattaLog} in a separate thread. This method blocks if there is such a thread loading - * fixes, until that thread is finished. - */ - void waitForLoadingToFinish() throws InterruptedException; - +package com.sap.sailing.domain.tracking; + +import java.io.Serializable; +import java.util.List; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedSet; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +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.regatta.events.RegattaLogDefineMarkEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +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.SharedDomainFactory; +import com.sap.sailing.domain.base.Sideline; +import com.sap.sailing.domain.base.SpeedWithConfidence; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.DouglasPeucker; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.LegType; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Tack; +import com.sap.sailing.domain.common.TargetTimeInfo; +import com.sap.sailing.domain.common.TimingConstants; +import com.sap.sailing.domain.common.TrackedRaceStatusEnum; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; +import com.sap.sailing.domain.common.dto.TrackedRaceDTO; +import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.common.tracking.SensorFix; +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.tracking.GPSFixStore; +import com.sap.sailing.domain.ranking.RankingMetric; +import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; +import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; +import com.sap.sse.common.Duration; +import com.sap.sse.common.IsManagedByCache; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; + +/** + * Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The + * course may change over time as the race committee decides to change it. Therefore, a {@link TrackedRace} instance + * {@link Course#addCourseListener(com.sap.sailing.domain.base.CourseListener) observes} the race {@link Course} for + * such changes. The tracking information of a leg can be requested either for all competitors (see + * {@link #getTrackedLegs()} and {@link #getTrackedLeg(Leg)}) or for a single competitor (see + * {@link #getTrackedLeg(Competitor, Leg)}). + *

    + * + * The overall race standings can be requested in terms of a competitor's ranking. More detailed information about what + * happens / happened within a leg is available from {@link TrackedLeg} and {@link TrackedLegOfCompetitor}. + * + * @author Axel Uhl (d043530) + * + */ +public interface TrackedRace extends Serializable, IsManagedByCache { + final Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5); + final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_MINUTE.times(2); + + final long MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS = 30000; + + final long DEFAULT_LIVE_DELAY_IN_MILLISECONDS = 5000; + + RaceDefinition getRace(); + + RegattaAndRaceIdentifier getRaceIdentifier(); + + /** + * Tells how ranks are to be assigned to the competitors at any time during the race. For one-design boat classes + * this will usually happen by projecting the competitors to the wind direction for upwind and downwind legs or to + * the leg's rhumb line for reaching legs, then comparing positions. For handicap races using a time-on-time, + * time-on-distance, combination thereof or a more complicated scheme such as ORC Performance Curve, the ranking + * process needs to take into account the competitor-specific correction factors defined in the measurement + * certificate. + */ + RankingMetric getRankingMetric(); + + /** + * Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time + * point which is expected to be before the race start time). The highest precedence take the + * {@link #attachedRaceLogs race logs} and their start time events, followed by the field {@link #startTimeReceived} + * which can explicitly be set using {@link #setStartTimeReceived(TimePoint)}. When there are no {@link MarkPassing}s + * for the first mark, null is returned. If there are mark passings for the first mark and the start + * time is less than {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} before the first mark + * passing for the first mark. Otherwise, the first mark passing for the first mark minus + * {@link #MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS} is returned as the race start time. + *

    + * + * If no start time can be determined this way, null is returned. + */ + TimePoint getStartOfRace(); + + /** + * Like {@link #getStartOfRace()}, but ignoring any inference from start mark passings in case {@code inferred} is + * {@code false}. In this case, if no official start time was set, e.g., in the {@link RaceLog} or explicitly using + * {@link #getStartTimeReceived()}, {@code null} will be returned by this method even if start mark passings are + * present. + */ + TimePoint getStartOfRace(boolean inferred); + + /** + * @return the time point taken from a valid, non-revoked {@link RaceLogRaceStatusEvent} that transfers the race + * into status {@link RaceLogRaceStatus#FINISHED} from any of the {@link RaceLog}s attached to this race, + * or {@code null} if no such event is found. + * + * @see {@link RaceChangeListener#finishedTimeChanged(TimePoint, TimePoint)} + */ + TimePoint getFinishedTime(); + + /** + * Determine the race end time is tricky. Boats may sink, stop, not finish, although they started the race. We + * therefore cannot wait for all boats to reach the finish line. The following rules are used to calculate the + * endOfRace: + *

      + *
    1. Returns null if no boat passed the finish line
    2. + *
    3. Returns time of the last mark passing recorded for the finish line
    4. + *
    5. TODO: Returns the time of the first passing of the finish line + the target window (defined in the + * competition rules) if a target window has been defined for the race
    6. + */ + TimePoint getEndOfRace(); + + /** + * Returns a list of the first and last mark passing times of all course waypoints. Callers wanting to iterate over + * the result must synchronize on the result. + */ + Iterable>> getMarkPassingsTimes(); + + /** + * Shorthand for {@link #getStart()}.{@link TimePoint#compareTo(TimePoint) compareTo(at)} <= 0 + */ + boolean hasStarted(TimePoint at); + + /** + * A race is considered "live" if it + * {@link TrackedRaceDTO#hasGPSData has GPS data} and {@link TrackedRaceDTO#hasWindData wind data} and if the + * at time point is between the start and the end of the race. + *

      + * + * The pre-start phase of a race is interesting also in live mode. Therefore, if a {@link TrackedRace#getStartOfRace start + * time} is available for the race, the {@link TimingConstants#PRE_START_PHASE_DURATION_IN_MILLIS} is subtracted + * from the actual start time so that the pre-start phase also counts as live. If no start time is known for the + * race, but a {@link TrackedRace#getStartOfTracking start of tracking time} is known, it is used as the start of + * the "live" interval. + *

      + * + * If an {@link TrackedRace#getEndOfRace end time} is already known for the race, + * {@link TimingConstants#IS_LIVE_GRACE_PERIOD_IN_MILLIS} is added to that and the result is taken to be the end of + * the "live" period. If no end time is known but a {@link TrackedRace#getTimePointOfNewestEvent} is set, again the + * {@link TimingConstants#IS_LIVE_GRACE_PERIOD_IN_MILLIS} is added to that to mark the end of the "live" interval. + *

      + * + * @param at + * the time point at which to determine whether the race for fleet + * is/was live. A null value will use the start time of the race. + * @return + */ + boolean isLive(TimePoint at); + + /** + * Clients can safely iterate over the iterable returned because it's a non-live copy of the tracked legs of this + * tracked race. This implies that should an update to the underlying list of waypoints in this race's + * {@link Course} take place after this method has returned, then this won't be reflected in the result returned. + * Callers should obtain the {@link Course#lockForRead() course's read lock} while using the result of this call if + * they want to ensure that no course update is applied concurrently. + */ + Iterable getTrackedLegs(); + + TrackedLeg getTrackedLeg(Leg leg); + + /** + * Tracking information about the leg competitor is on at timePoint, or null + * if the competitor hasn't started any leg yet at timePoint or has already finished the race. + */ + TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint); + + /** + * Tells which leg the leader at timePoint is on + */ + TrackedLeg getCurrentLeg(TimePoint timePoint); + + /** + * Tells the number of the last started leg at timePoint + * The leg number is 0 before the start, the number of the current leg during the race + * and the number of the last leg at the end of the race even if the race has finished. + */ + int getLastLegStarted(TimePoint timePoint); + + /** + * Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}. + */ + TrackedLeg getTrackedLegFinishingAt(Waypoint endOfLeg); + + /** + * Precondition: waypoint must still be part of {@link #getRace()}.{@link RaceDefinition#getCourse() getCourse()}. + */ + TrackedLeg getTrackedLegStartingAt(Waypoint startOfLeg); + + /** + * The raw, updating feed of a single competitor participating in this race + */ + GPSFixTrack getTrack(Competitor competitor); + + /** + * {@link SensorFixTrack}s provide timed sensor data in addition to GPSFixes that are hold in {@link GPSFixTrack}s. + * In contrast to {@link GPSFixTrack}s there is a 1:n relation of competitors to tracks by introducing track names. + * So every type of track has an associated name. With this construct you can have track implementations that + * provide specific functionality based on the contained fix type. + * + * @param competitor the competitor to get the track for + * @param trackName the name of the track to get + * @return the track associated to the given Competitor and name or null if there is none. + */ + > TrackT getSensorTrack(Competitor competitor, String trackName); + + /** + * Tells the leg on which the competitor was at time at. If the competitor hasn't passed + * the start waypoint yet, null is returned because the competitor was not yet on any leg at that point + * in time. If the time point happens to be after the last fix received from that competitor, the last known leg for + * that competitor is returned. If the time point is after the competitor's mark passing for the finish line, + * null is returned. For all legs except the last, if the time point equals a mark passing time point + * of the leg's starting waypoint, that leg is returned. For the time point of the mark passing for the finish line, + * the last leg is returned. + */ + TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, TimePoint at); + + TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, Leg leg); + + /** + * @return a sequential number counting the updates that occurred to this tracked race. Callers may use this to ask + * for updates newer than such a sequence number. + */ + long getUpdateCount(); + + int getRankDifference(Competitor competitor, Leg leg, TimePoint timePoint); + + /** + * Computes the rank of the competitor in this race for the current time. + */ + int getRank(Competitor competitor) throws NoWindException; + + /** + * Computes the rank of competitor in this race. A competitor is ahead of all competitors that are one + * or more legs behind. Within the same leg, the rank is determined by the windward distance to go and therefore + * depends on the assumptions of the wind direction for the given timePoint. If the race hasn't + * {@link #hasStarted(TimePoint) started} yet, the result is undefined. + * + * @return 0 in case the competitor hasn't participated in the race; a rank starting with + * 1 where rank 1 identifies the leader otherwise + */ + int getRank(Competitor competitor, TimePoint timePoint); + + /** + * For the given waypoint lists the {@link MarkPassing} events that describe which competitor passed the waypoint at + * which point in time. This can, e.g., be used to sort those competitors who already finished a leg within the leg + * that ends with waypoint. The remaining competitors need to be ordered by the advantage line-related + * distance to the waypoint. + * + * @return the iterable sequence of {@link MarkPassing}s as described above. If the caller wants to iterate on the + * resulting collection, the caller needs to invoke {@link #lockForRead(Iterable)} with the collection + * returned as parameter because insertions into the competitor's mark passing collection will obtain the + * corresponding write lock. + */ + Iterable getMarkPassingsInOrder(Waypoint waypoint); + + /** + * Obtains the {@link MarkPassing} for competitor passing waypoint. If no such mark + * passing has been reported (yet), null is returned. + */ + MarkPassing getMarkPassing(Competitor competitor, Waypoint waypoint); + + /** + * Yields the track describing mark's movement over time; never null because a new track + * will be created in case no track was present for mark so far. + * + * @see #getTrack(Mark) + */ + GPSFixTrack getOrCreateTrack(Mark mark); + + /** + * Yields the track describing mark's movement over time; null if no track exists for + * mark so far. + * + * @see #getOrCreateTrack(Mark) + */ + GPSFixTrack getTrack(Mark mark); + + /** + * Retrieves all marks assigned to the race. They are not necessarily part of the race course. + */ + Iterable getMarks(); + + /** + * Retrieves all course side lines assigned to the race. + */ + Iterable getCourseSidelines(); + + /** + * If the waypoint only has one {@link #getMarks() mark}, its position at time timePoint + * is returned. Otherwise, the center of gravity between the mark positions is computed and returned. + */ + default Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) { + return getApproximatePosition(waypoint, timePoint, new NonCachingMarkPositionAtTimePointCache(this, timePoint)); + } + + /** + * Same as {@link #getApproximatePosition(Waypoint, TimePoint)}, but giving the caller the possibility to pass a + * cache of mark positions and related information that can help speed up compound operations requiring frequent + * access to the same marks in the same race for the same time point. + * + * @param markPositionCache + * a cache for this {@link MarkPositionAtTimePointCache#getTrackedRace() race} and the + * {@link MarkPositionAtTimePointCache#getTimePoint() timePoint} passed + */ + Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, + MarkPositionAtTimePointCache markPositionCache); + + /** + * Checks whether the {@link Wind#getTimePoint()} is in range of start and end {@link TimePoint}s plus extra time + * for wind recording. If, based on a {@link RaceExecutionOrderProvider}, there is no previous race that takes the + * wind fix, an extended time range lead (see + * {@link TrackedRaceImpl#EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS}) is used to record wind even a long + * time before the race start. + *

      + * + * A race does not record wind when both, {@link #getStartOfTracking()} and {@link #getStartOfRace()} are + * null. Wind is not recorded when it is after the later of {@link #getEndOfRace()} and + * {@link #getEndOfTracking()} and one of the two is not null. + *

      + * + * This default implementation returns true which may be useful for tests and mocked implementations; however, real + * implementations shall override this and provide a meaningful implementation according to the specification given + * above. + */ + default boolean takesWindFixWithTimePoint(TimePoint timePoint) { + return true; + } + + default boolean takesWindFixWithTimePointRecursively(TimePoint windFixTimePoint, Set visited) { + return true; + } + + /** + * Same as {@link #getWind(Position, TimePoint, Set) getWind(p, at, Collections.emptyList())} + */ + Wind getWind(Position p, TimePoint at); + + /** + * Obtains estimated interpolated wind information for a given position and time point. The information is taken + * from all wind sources available except for those listed in windSourcesToExclude, using the + * confidences of the wind values provided by the various sources during averaging. + */ + Wind getWind(Position p, TimePoint at, Set windSourcesToExclude); + + /** + * Retrieves the wind sources used so far by this race that have the specified type as their + * {@link WindSource#getType() type}. Always returns a non-null iterable which may be empty in case the + * race does not use any wind source of the specified type (yet).

      + * + * It is possible to ask for the {@link WindSourceType#COMBINED} and {@link WindSourceType#LEG_MIDDLE} types and + * get a non-empty result although those sources are never returned by {@link #getWindSources()}. + */ + Set getWindSources(WindSourceType type); + + /** + * Retrieves all wind sources known to this race, including those {@link #getWindSourcesToExclude() to exclude}. + * Callers can freely iterate because a copied collection is returned. The {@link WindSourceType#COMBINED} wind source + * as well as the {@link WindSourceType#LEG_MIDDLE} sources are never part of the result. + */ + Set getWindSources(); + + /** + * Same as {@link #getOrCreateWindTrack(WindSource, long) getOrCreateWindTrack(windSource, + * getMillisecondsOverWhichToAverageWind())}. + */ + WindTrack getOrCreateWindTrack(WindSource windSource); + + WindTrack getOrCreateWindTrack(WindSource windSource, long delayForWindEstimationCacheInvalidation); + + /** + * Waits until {@link #getUpdateCount()} is after sinceUpdate. + */ + void waitForNextUpdate(int sinceUpdate) throws InterruptedException; + + /** + * Time stamp of the start of the actual tracking. The value can be null (e.g. if we have not received any signal + * from the tracking infrastructure) + */ + TimePoint getStartOfTracking(); + + /** + * Time stamp of the end of the actual tracking. The value can be null (e.g. if we have not received any signal from + * the tracking infrastructure) + */ + TimePoint getEndOfTracking(); + + /** + * Regardless of the order in which events were received, this method returns the latest time point contained by any + * of the events received and processed. + */ + TimePoint getTimePointOfNewestEvent(); + + /** + * Regardless of the order in which events were received, this method returns the oldest time point contained by any + * of the events received and processed. + */ + TimePoint getTimePointOfOldestEvent(); + + /** + * @return the mark passings for competitor in this race received so far; the mark passing objects are + * returned such that their {@link MarkPassing#getWaypoint() waypoints} are ordered in the same way they are + * ordered in the race's {@link Course}. Note, that this doesn't necessarily guarantee ascending time + * points, particularly if premature mark passings have been detected accidentally as can be the case with + * some tracking providers such as TracTrac. If the caller wants to iterate on the resulting collection or + * construct a {@link SortedSet#headSet(Object)} or {@link SortedSet#tailSet(Object)} and then iterate over + * that, the caller needs to invoke {@link #lockForRead(Iterable)} with the collection returned as parameter + * because insertions into the competitor's mark passing collection will obtain the corresponding write + * lock. + */ + NavigableSet getMarkPassings(Competitor competitor); + + /** + * Returns competitor's mark passings. + * + * @param waitForLatestUpdates + * if any mark passing updates are pending because some calculations are currently going on and updates + * haven't all been processed yet then the call will block until these updates have been processed in + * case this parameter is set to {@code true}. For this the method uses a lock on the + * {@link MarkPassingCalculator }to block the thread until all calculations will be finished. + */ + NavigableSet getMarkPassings(Competitor competitor, boolean waitForLatestUpdates); + + /** + * This obtains the course's read lock before asking for the read lock for the markPassings structure. + * See also bug 1370 (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1370). This is necessary because the + * code that executes a course update will first ask the course's write lock and then relay execution to the + * course change listeners among which there is a {@link TrackedRace} which will then update the mark passings + * for all competitors and therefore will need to ask the write lock for those. If the thread calling this method + * first obtains the mark passings read lock and later, while holding on to that lock, asks for the course's read + * lock, a deadlock may result.

      + * + * Furthermore, when trying to acquire both, a lock for the {@link #getMarkPassings(Competitor) mark passings for a competitor} + * and a lock for the {@link #getMarkPassingsInOrder(Waypoint) mark passings for a waypoint, this needs to happen in exactly + * this order, or a deadlock may result.

      + * + * The {@link #unlockAfterRead(Iterable)} method will symmetrically unlock the course's read lock after releasing the + * read lock for the mark passings. + */ + void lockForRead(Iterable markPassings); + + /** + * Releases the read lock for the mark passings and then the read lock for the course. + * + * @see #lockForRead(Iterable) + */ + void unlockAfterRead(Iterable markPassings); + + /** + * Time stamp that the event received last from the underlying push service carried on it. Note that these times may + * not increase monotonically. + */ + TimePoint getTimePointOfLastEvent(); + + long getMillisecondsOverWhichToAverageSpeed(); + + long getMillisecondsOverWhichToAverageWind(); + + /** + * Gets the current delay of incoming events to the real time of the events in milliseconds + */ + long getDelayToLiveInMillis(); + + /** + * Estimates the wind direction based on the observed boat courses at the time given for the position provided. The + * estimate is based on the assumption that the boats which are on an upwind or a downwind leg sail with very + * similar angles on the starboard and the port side. There should be clusters of courses which are close to each + * other (within a threshold of, say, +/- 5 degrees), whereas for the upwind group there should be two clusters with + * angles about 90 degrees apart; similarly, for the downwind leg there should be two clusters, only that the + * general jibing angle may vary more, based on the wind speed and the boat class. + *

      + * + * Boats {@link GPSFixTrack#hasDirectionChange(TimePoint, double) currently maneuvering} are not considered for this + * analysis. + *

      + * + * This wind direction should not be used directly to compute the leg's wind direction and hence the {@link LegType + * leg type} because an endless recursion may result: an implementation of this method signature will need to know + * whether a leg is an upwind or downwind leg for which it has to know where the wind is coming from. + * + * @return null if no sufficient boat track information is available or leg type identification (upwind + * vs. downwind) is not possible; a valid {@link Wind} fix otherwise whose bearing is inferred from the boat + * courses and whose speed in knots is currently a rough indication of how many boats' courses contributed + * to determining the bearing. If in the future we have data about polar diagrams specific to boat classes, + * we may be able to also infer the wind speed from the boat tracks. + */ + Wind getEstimatedWindDirection(TimePoint timePoint); + + /** + * Determines whether the competitor is sailing on port or starboard tack at the timePoint + * requested. Note that this will have to retrieve information about the wind. This, in turn, can lead to the + * current thread obtaining the monitor of the various wind tracks, and, if the + * {@link WindSource#TRACK_BASED_ESTIMATION} source is used, also the monitors of the competitors' GPS tracks. + */ + Tack getTack(Competitor competitor, TimePoint timePoint) throws NoWindException; + + /** + * Determines whether the competitor is sailing on port or starboard tack at the timePoint + * requested. + *

      + * This method outperforms {@link #getTack(Competitor, TimePoint)}, based on being passed an already calculated wind + * for the given time and competitor position as well as the competitors speed and course over ground. + *

      + * This method will acquire the read lock for the competitor's track. + */ + Tack getTack(SpeedWithBearing speedWithBearing, Wind wind, TimePoint timePoint); + + TrackedRegatta getTrackedRegatta(); + + /** + * Computes a default wind direction based on the direction of the first leg at time at, with a default + * speed of zero knots. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()} returns + * true. + * + * @param at + * usually the {@link #getStart() start time} should be used; if no valid start time is provided, the + * current time point may serve as a default + * @return null in case the first leg's direction cannot be determined, e.g., because the necessary + * mark positions are not known (yet) + */ + Wind getDirectionFromStartToNextMark(TimePoint at); + + /** + * Uses a {@link DouglasPeucker Douglas-Peucker} algorithm to approximate this track's fixes starting at time + * from until time point to such that the maximum distance between the track's fixes and + * the approximation is at most maxDistance. The approximation's fixes are original fixes from + * the competitor's {@link GPSFixTrack track}. + */ + Iterable approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to); + + /** + * @return a non-null but perhaps empty list of the maneuvers that competitor performed in + * this race between from and to. Depending on waitForLatest the + * result is taken from the cache straight away (waitForLatest==false) or, if a re-calculation + * for the key is still ongoing, the result of that ongoing re-calculation is returned. + */ + Iterable getManeuvers(Competitor competitor, TimePoint from, TimePoint to, boolean waitForLatest); + + /** + * @return true if this race is known to start with an {@link LegType#UPWIND upwind} leg. If this is + * the case, the wind estimation may default to using the first leg's direction at race start time as the + * direction the wind comes from. + */ + boolean raceIsKnownToStartUpwind(); + + /** + * Many calculations require valid wind data. In order to prevent NoWindException's to be handled by those + * calculation this method can be used to check whether the tracked race has sufficient wind information available. + * + * @return true if {@link #getWind(Position, TimePoint)} delivers a (not null) wind fix. + */ + boolean hasWindData(); + + /** + * + * @return true if at least one GPS fix for one of the competitors is available for this race. + */ + boolean hasGPSData(); + + /** + * Adds a race change listener to the set of listeners that will be notified about changes to this race. The + * listener won't be serialized together with this object. + */ + void addListener(RaceChangeListener listener); + + /** + * Like {@link #addListener(RaceChangeListener)}, but notifies the listener about the wind fixes known so far by the + * tracked race. This runs synchronized with the otherwise asynchronous loading of wind tracks, triggered by the + * constructor of the {@link TrackedRace} implementation classes. This procedure guarantees that eventually the + * listener will have received a notification for all wind fixes, regardless of whether they were already loaded at + * the time the listener is registered or they are loaded after the registration has completed.

      + * + * The same is true for the GPS fixes for marks and competitors. + */ + void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded, + boolean notifyAboutGPSFixesAlreadyLoaded); + + void removeListener(RaceChangeListener listener); + + /** + * @return null if there are no mark passings for the competitor in this race + * or if the competitor has not finished one of the legs in the race. + */ + Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint); + + /** + * See {@link TrackedLegOfCompetitor#getDistanceTraveledConsideringGateStart(TimePoint)} + */ + Distance getDistanceTraveledIncludingGateStart(Competitor competitor, TimePoint timePoint); + + /** + * See {@link TrackedLegOfCompetitor#getWindwardDistanceToCompetitorFarthestAhead(TimePoint, WindPositionMode, RankingInfo)} + */ + Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode); + + /** + * Same as {@link #getWindwardDistanceToCompetitorFarthestAhead(Competitor, TimePoint, WindPositionMode)}, only with an + * additional cache to speed up wind and leg type and leg bearing calculations in case of multiple similar look-ups + * for the same time point. + * + * @param rankingInfo + * materialized ranking information that is expensive to calculate, avoiding redundant calculations + */ + Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + + /** + * Calls {@link #getWindWithConfidence(Position, TimePoint, Iterable)} and excludes those wind sources listed in + * {@link #getWindSourcesToExclude}. + */ + WindWithConfidence> getWindWithConfidence(Position p, TimePoint at); + + /** + * Lists those wind sources which by default are not considered in {@link #getWind(Position, TimePoint)} and + * {@link #getWindWithConfidence(Position, TimePoint)}. + */ + Set getWindSourcesToExclude(); + + /** + * Loops over this tracked race's wind sources and from each asks its averaged wind for the position p + * and time point at, using the particular wind source's averaging interval. The confidences delivered + * by each wind source are used during computing the averaged result across the wind sources. The result has the + * averaged confidence attached. + */ + WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, + Set windSourcesToExclude); + + /** + * Same as {@link #getEstimatedWindDirection(TimePoint)}, but propagates the confidence of the wind + * estimation, relative to the timePoint for which the request is made, in the result. The + * {@link Wind#getPosition() position} of all {@link Wind} fixes returned is null. + */ + WindWithConfidence getEstimatedWindDirectionWithConfidence(TimePoint timePoint); + + /** + * After the call returns, {@link #getWindSourcesToExclude()} returns an iterable that equals + * windSourcesToExclude + */ + void setWindSourcesToExclude(Iterable windSourcesToExclude); + + /** + * Computes the average cross-track error for the legs with type {@link LegType#UPWIND}. + * + * @param waitForLatestAnalysis + * if true and any cache update is currently going on, wait for the update to complete and + * then fetch the updated value; otherwise, serve this requests from whatever is currently in the cache + */ + Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis) + throws NoWindException; + + /** + * Same as {@link #getAverageAbsoluteCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg type, + * wind on leg and leg bearing is provided. + */ + Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, + WindLegTypeAndLegBearingCache cache) throws NoWindException; + + Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, + boolean waitForLatestAnalyses) throws NoWindException; + + Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis) + throws NoWindException; + + /** + * Same as {@link #getAverageSignedCrossTrackError(Competitor, TimePoint, boolean)}, only that a cache for leg type, + * wind direction and leg bearing is provided. + */ + Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, + WindLegTypeAndLegBearingCache cache) throws NoWindException; + + Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, + boolean waitForLatestAnalysis) throws NoWindException; + + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint); + + WindStore getWindStore(); + + Competitor getOverallLeader(TimePoint timePoint); + + Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + + Boat getBoatOfCompetitor(Serializable competitorId); + + /** + * Returns the competitors of this tracked race, according to their ranking. Competitors whose + * {@link #getRank(Competitor)} is 0 will be sorted "worst". + */ + List getCompetitorsFromBestToWorst(TimePoint timePoint); + + /** + * Same as {@link #getCompetitorsFromBestToWorst(TimePoint)}, using a cache for wind, leg type and leg + * bearing values. + */ + List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + + /** + * When provided with a {@link WindStore} during construction, the tracked race will + * asynchronously load the wind data for this tracked race from the wind store and the GPS store in a + * background thread and update this tracked race with the results. Clients that want to wait for the wind + * loading process to complete can do so by calling this method which will block until the wind loading has + * completed. + */ + void waitUntilLoadingFromWindStoreComplete() throws InterruptedException; + + /** + * Whenever a {@link RegattaLog} is attached, fixes are loaded from the {@link GPSFixStore} for all mappings + * found in the {@code RegattaLog} in a separate thread. This method blocks if there is such a thread loading + * fixes, until that thread is finished. + */ + void waitForLoadingToFinish() throws InterruptedException; + /** * Returns the current status of the {@link TrackedRace}. This consists of one of the {@link TrackedRaceStatusEnum} * values plus a progress for LOADING state.
      @@ -751,247 +751,247 @@ public interface TrackedRace extends Serializable, IsManagedByCache getAttachedRegattaLogs(); - - /** - * Attaches a {@link RaceExecutionOrderProvider} to make a {@link TrackedRace} aware - * which races are scheduled around it in the execution order of a {@link Regatta}. - * */ - void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider); - - /** - * Returns the attached race log event track for this race if any. - * Otherwise null. - */ - RaceLog getRaceLog(Serializable identifier); - - /** - * A setter for the listener on course design changes suggested by one of the {@link RaceLog}s attached to this - * race. The listener is mostly part of the tracking provider adapter. - * - * @param listener - * the listener to operate with. - */ - void addCourseDesignChangedListener(CourseDesignChangedListener listener); - - void addStartTimeChangedListener(StartTimeChangedListener listener); - - void removeStartTimeChangedListener(StartTimeChangedListener listener); - - void addRaceAbortedListener(RaceAbortedListener listener); - - /** - * Tells how far the given competitor was from the start line at the time point of the given seconds before the start. - *

      - * - * The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and - * computing the distance of the projected position and the competitor's position. - *

      - * - * Should the course be empty, null is returned. If the course's first waypoint is not a line or gate, - * the geometric distance between the first waypoint and the competitor's position at timePoint is - * returned. If the competitor's position cannot be determined, null is returned. - */ - Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart); - - /** - * Tells how far the given competitor was from the start line at the given timePoint. - * Using the {@link #getStartOfRace() race start time} for timePoint, this tells the competitor's - * distance to the line when the race was started. - *

      - * - * The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and - * computing the distance of the projected position and the competitor's position. - *

      - * - * Should the course be empty, null is returned. If the course's first waypoint is not a line or gate, - * the geometric distance between the first waypoint and the competitor's position at timePoint is - * returned. If the competitor's position cannot be determined, null is returned. - */ - Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint); - - /** - * When the competitor has started, this method returns the distance to the starboard end of the start line - * or---if the start waypoint was a single mark---the distance to the single start mark at the time the competitor started. - * If the competitor hasn't started yet, null is returned. - */ - Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor); - - /** - * At the given timepoint and for the competitor, this method returns the distance to the starboard end of the start line - * or---if the start waypoint was a single mark---the distance to the single start mark at the timepoint. - * If the competitor hasn't started yet, null is returned. - * - */ - Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint); - - /** - * The estimated speed of the competitor at the time point of the given seconds before the start of race. - */ - Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart); - - /** - * The speed of the competitor when crossing the start line. It will return null if there are no recorded - * mark passings for this competitor (competitor did not yet or never pass the start line). - */ - Speed getSpeedWhenCrossingStartLine(Competitor competitor); - - /** - * Start time received by the tracking infrastructure. To determine real start time use {@link #getStartOfRace()}. - */ - TimePoint getStartTimeReceived(); - - /** - * @return null if the start waypoint does not have two marks or the course - * is empty or the start waypoint is the only waypoint - */ - LineDetails getStartLine(TimePoint at); - - /** - * @return null if the finish waypoint does not have two marks or the course - * is empty or the finish waypoint is the only waypoint - */ - LineDetails getFinishLine(TimePoint at); - - /** - * Length of course if there are mark passings for competitors. - */ - Distance getCourseLength(); - - /** - * The average wind speed with confidence for this race. It uses the timepoint of the race end as - * a reference point. - */ - SpeedWithConfidence getAverageWindSpeedWithConfidence(long resolutionInMillis); - - /** - * Computes the center point of the course's marks at the given time point. - */ - Position getCenterOfCourse(TimePoint at); - - /** - * If the {@link RacingProcedure} defined by any of the {@link #attachedRaceLogs attached} {@link RaceLog}s - * has type {@link RacingProcedureType#GateStart}, this method returns true, false for - * any other type found. If no type is found, e.g., because no race log is currently attached to this tracked race, - * null is returned, meaning that the type is not known. - */ - Boolean isGateStart(); - - /** - * Returns the time in milliseconds when the line was closed with lowering flag {@link Flags#GOLF} if {@link #isGateStart()} is true. - * If flag was not raised or {@link #isGateStart()} is false it returns null. - */ - long getGateStartGolfDownTime(); - - /** - * If the race was started with a gate start (see {@link #isGateStart()}, this method returns the distance between - * the competitor's starting position and the port side of the start line (pin end); otherwise, returns a zero - * distance. - */ - Distance getAdditionalGateStartDistance(Competitor competitor, TimePoint timePoint); - - boolean isUsingMarkPassingCalculator(); - - /** - * Calculates the estimated time it takes a competitor to sail the race, from start to finish. - * - * @param timepoint - * Used for positions of marks and wind information; note that sometimes the marks are not in place yet - * when the race starts and that a windward mark may be collected already before the race finishes. - * - * @return estimated time it takes to complete the race, plus more useful information about how this result came about - * - * @throws NotEnoughDataHasBeenAddedException - * thrown if not enough polar data has been added or polar data service is not available - * @throws NoWindException - */ - TargetTimeInfo getEstimatedTimeToComplete(TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, NoWindException; - - void setPolarDataService(PolarDataService polarDataService); - - default RaceLogResolver getRaceLogResolver() { - return null; - } - - default Pair getTrackingTimesFromRaceLogs() { - return null; - } - - default Pair getStartAndFinishedTimeFromRaceLogs() { - return null; - } - - /** - * Returns all marks found in the {@link #markTracks} map and the mark device mappings and mark - * definition events in all attached race and regatta logs. Note that usually a device mapping should - * exist for a mark only if that mark is also defined by a {@link RegattaLogDefineMarkEvent}, so for - * this standard case, adding the marks from the device mark mappings would be redundant. - */ - default Iterable getMarksFromRegattaLogs() { - return getMarks(); - } - - /** - * Updates the start and end of tracking in the following precedence order: - * - *

        - *
      1. start/end of tracking in Racelog
      2. - *
      3. manually set start/end of tracking via {@link #setStartOfTrackingReceived(TimePoint, boolean)} and {@link #setEndOfTrackingReceived(TimePoint, boolean)}
      4. - *
      5. start/end of race in Racelog -/+ {@link #START_TRACKING_THIS_MUCH_BEFORE_RACE_START}/{@link #STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH}
      6. - *
      - */ - public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad); - - default void lockForSerializationRead() { - } - - default void unlockAfterSerializationRead() { - } - - /** - * @return all currently attached {@link RaceLog}s or an empty Iterable if there aren't any - */ - Iterable getAttachedRaceLogs(); - -} + TrackedRaceStatus getStatus(); + + /** + * If the {@link #getStatus() status} is currently {@link TrackedRaceStatusEnum#LOADING}, blocks until the status changes to any + * other status. + */ + void waitUntilNotLoading(); + + /** + * Detaches the race log associated with this {@link TrackedRace}. + * + * @return the race log detached or {@code null} if no race log can be found by the {@code identifier} + */ + RaceLog detachRaceLog(Serializable identifier); + + /** + * Detaches the link {@link RaceExecutionOrderProvider} + */ + void detachRaceExecutionOrderProvider(RaceExecutionOrderProvider raceExecutionOrderProvider); + + /** + * Attaches the passed race log with this {@link TrackedRace}. + * This causes fixes from the {@link GPSFixStore} to be loaded for such {@link RegattaLogDeviceMappingEvent}s + * that are present in the raceLog. This loading is offloaded into a separate thread, that blocks + * serialization until it is finished. If multiple race logs are attached, the loading process is + * forced to be serialized. + * To garuantee that a the fixes for a race log have been fully loaded before continuing, + * {@link #waitForLoadingFromGPSFixStoreToFinishRunning} can be used. + * @param raceLog to be attached. + */ + void attachRaceLog(RaceLog raceLog); + + /** + * Attaches the passed regatta log with this {@link TrackedRace}. + * This also causes fixes from the {@link GPSFixStore} to be loaded (see {@link #attachRaceLog} for details). + */ + void attachRegattaLog(RegattaLog regattaLog); + + /** + * @return all currently attached {@link RegattaLog}s or an empty Iterable if there aren't any + */ + Iterable getAttachedRegattaLogs(); + + /** + * Attaches a {@link RaceExecutionOrderProvider} to make a {@link TrackedRace} aware + * which races are scheduled around it in the execution order of a {@link Regatta}. + * */ + void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider); + + /** + * Returns the attached race log event track for this race if any. + * Otherwise null. + */ + RaceLog getRaceLog(Serializable identifier); + + /** + * A setter for the listener on course design changes suggested by one of the {@link RaceLog}s attached to this + * race. The listener is mostly part of the tracking provider adapter. + * + * @param listener + * the listener to operate with. + */ + void addCourseDesignChangedListener(CourseDesignChangedListener listener); + + void addStartTimeChangedListener(StartTimeChangedListener listener); + + void removeStartTimeChangedListener(StartTimeChangedListener listener); + + void addRaceAbortedListener(RaceAbortedListener listener); + + /** + * Tells how far the given competitor was from the start line at the time point of the given seconds before the start. + *

      + * + * The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and + * computing the distance of the projected position and the competitor's position. + *

      + * + * Should the course be empty, null is returned. If the course's first waypoint is not a line or gate, + * the geometric distance between the first waypoint and the competitor's position at timePoint is + * returned. If the competitor's position cannot be determined, null is returned. + */ + Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart); + + /** + * Tells how far the given competitor was from the start line at the given timePoint. + * Using the {@link #getStartOfRace() race start time} for timePoint, this tells the competitor's + * distance to the line when the race was started. + *

      + * + * The distance to the line is calculated by projecting the competitor's position onto the line orthogonally and + * computing the distance of the projected position and the competitor's position. + *

      + * + * Should the course be empty, null is returned. If the course's first waypoint is not a line or gate, + * the geometric distance between the first waypoint and the competitor's position at timePoint is + * returned. If the competitor's position cannot be determined, null is returned. + */ + Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint); + + /** + * When the competitor has started, this method returns the distance to the starboard end of the start line + * or---if the start waypoint was a single mark---the distance to the single start mark at the time the competitor started. + * If the competitor hasn't started yet, null is returned. + */ + Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor); + + /** + * At the given timepoint and for the competitor, this method returns the distance to the starboard end of the start line + * or---if the start waypoint was a single mark---the distance to the single start mark at the timepoint. + * If the competitor hasn't started yet, null is returned. + * + */ + Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint); + + /** + * The estimated speed of the competitor at the time point of the given seconds before the start of race. + */ + Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart); + + /** + * The speed of the competitor when crossing the start line. It will return null if there are no recorded + * mark passings for this competitor (competitor did not yet or never pass the start line). + */ + Speed getSpeedWhenCrossingStartLine(Competitor competitor); + + /** + * Start time received by the tracking infrastructure. To determine real start time use {@link #getStartOfRace()}. + */ + TimePoint getStartTimeReceived(); + + /** + * @return null if the start waypoint does not have two marks or the course + * is empty or the start waypoint is the only waypoint + */ + LineDetails getStartLine(TimePoint at); + + /** + * @return null if the finish waypoint does not have two marks or the course + * is empty or the finish waypoint is the only waypoint + */ + LineDetails getFinishLine(TimePoint at); + + /** + * Length of course if there are mark passings for competitors. + */ + Distance getCourseLength(); + + /** + * The average wind speed with confidence for this race. It uses the timepoint of the race end as + * a reference point. + */ + SpeedWithConfidence getAverageWindSpeedWithConfidence(long resolutionInMillis); + + /** + * Computes the center point of the course's marks at the given time point. + */ + Position getCenterOfCourse(TimePoint at); + + /** + * If the {@link RacingProcedure} defined by any of the {@link #attachedRaceLogs attached} {@link RaceLog}s + * has type {@link RacingProcedureType#GateStart}, this method returns true, false for + * any other type found. If no type is found, e.g., because no race log is currently attached to this tracked race, + * null is returned, meaning that the type is not known. + */ + Boolean isGateStart(); + + /** + * Returns the time in milliseconds when the line was closed with lowering flag {@link Flags#GOLF} if {@link #isGateStart()} is true. + * If flag was not raised or {@link #isGateStart()} is false it returns null. + */ + long getGateStartGolfDownTime(); + + /** + * If the race was started with a gate start (see {@link #isGateStart()}, this method returns the distance between + * the competitor's starting position and the port side of the start line (pin end); otherwise, returns a zero + * distance. + */ + Distance getAdditionalGateStartDistance(Competitor competitor, TimePoint timePoint); + + boolean isUsingMarkPassingCalculator(); + + /** + * Calculates the estimated time it takes a competitor to sail the race, from start to finish. + * + * @param timepoint + * Used for positions of marks and wind information; note that sometimes the marks are not in place yet + * when the race starts and that a windward mark may be collected already before the race finishes. + * + * @return estimated time it takes to complete the race, plus more useful information about how this result came about + * + * @throws NotEnoughDataHasBeenAddedException + * thrown if not enough polar data has been added or polar data service is not available + * @throws NoWindException + */ + TargetTimeInfo getEstimatedTimeToComplete(TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, NoWindException; + + void setPolarDataService(PolarDataService polarDataService); + + default RaceLogResolver getRaceLogResolver() { + return null; + } + + default Pair getTrackingTimesFromRaceLogs() { + return null; + } + + default Pair getStartAndFinishedTimeFromRaceLogs() { + return null; + } + + /** + * Returns all marks found in the {@link #markTracks} map and the mark device mappings and mark + * definition events in all attached race and regatta logs. Note that usually a device mapping should + * exist for a mark only if that mark is also defined by a {@link RegattaLogDefineMarkEvent}, so for + * this standard case, adding the marks from the device mark mappings would be redundant. + */ + default Iterable getMarksFromRegattaLogs() { + return getMarks(); + } + + /** + * Updates the start and end of tracking in the following precedence order: + * + *

        + *
      1. start/end of tracking in Racelog
      2. + *
      3. manually set start/end of tracking via {@link #setStartOfTrackingReceived(TimePoint, boolean)} and {@link #setEndOfTrackingReceived(TimePoint, boolean)}
      4. + *
      5. start/end of race in Racelog -/+ {@link #START_TRACKING_THIS_MUCH_BEFORE_RACE_START}/{@link #STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH}
      6. + *
      + */ + public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad); + + default void lockForSerializationRead() { + } + + default void unlockAfterSerializationRead() { + } + + /** + * @return all currently attached {@link RaceLog}s or an empty Iterable if there aren't any + */ + Iterable getAttachedRaceLogs(); + +} diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java index 3033c42e8d5..3c337b181a6 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogConnectivityParamsLoadAndStoreTest.java @@ -1,90 +1,90 @@ -package com.sap.sailing.mongodb.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import org.junit.Test; - -import com.mongodb.MongoException; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.SeriesImpl; -import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory; -import com.sap.sailing.domain.racelogtracking.impl.RaceLogConnectivityParams; -import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; -import com.sap.sse.common.Duration; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class RaceLogConnectivityParamsLoadAndStoreTest extends AbstractConnectivityParamsLoadAndStoreTest { - public RaceLogConnectivityParamsLoadAndStoreTest() throws UnknownHostException, MongoException { - super(); - } - - @Test - public void testStoreAndLoadRaceLogTrackingParams() throws MalformedURLException, URISyntaxException, NotDenotableForRaceLogTrackingException, InterruptedException, ExecutionException { - // set up - final long delayToLiveInMillis = 3000; - final boolean trackWind = true; - final boolean correctWindDirectionByMagneticDeclination = true; - final FleetImpl fleet = new FleetImpl("Default"); - final SeriesImpl theSeries = new SeriesImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, - Arrays.asList(fleet), Collections.emptyList(), racingEventService); - final Iterable series = Arrays.asList(theSeries); - final Regatta regatta = racingEventService.createRegatta("My Regatta", "12mR", true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus(Duration.ONE_DAY), - UUID.randomUUID(), series, /* persistent */ true, new LowPoint(), new CourseAreaImpl("Default", UUID.randomUUID()), +package com.sap.sailing.mongodb.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import org.junit.Test; + +import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.impl.CourseAreaImpl; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory; +import com.sap.sailing.domain.racelogtracking.impl.RaceLogConnectivityParams; +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; +import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; +import com.sap.sse.common.Duration; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class RaceLogConnectivityParamsLoadAndStoreTest extends AbstractConnectivityParamsLoadAndStoreTest { + public RaceLogConnectivityParamsLoadAndStoreTest() throws UnknownHostException, MongoException { + super(); + } + + @Test + public void testStoreAndLoadRaceLogTrackingParams() throws MalformedURLException, URISyntaxException, NotDenotableForRaceLogTrackingException, InterruptedException, ExecutionException { + // set up + final long delayToLiveInMillis = 3000; + final boolean trackWind = true; + final boolean correctWindDirectionByMagneticDeclination = true; + final FleetImpl fleet = new FleetImpl("Default"); + final SeriesImpl theSeries = new SeriesImpl("Default", /* isMedal */ false, /* isFleetsCanRunInParallel */ true, + Arrays.asList(fleet), Collections.emptyList(), racingEventService); + final Iterable series = Arrays.asList(theSeries); + final Regatta regatta = racingEventService.createRegatta("My Regatta", "12mR", true, MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus(Duration.ONE_DAY), + UUID.randomUUID(), series, /* persistent */ true, new LowPoint(), new CourseAreaImpl("Default", UUID.randomUUID()), /* buoyZoneRadiusInHullLengths */ 2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, - OneDesignRankingMetric::new); - theSeries.addRaceColumn("R1", racingEventService); - theSeries.addRaceColumn("R2", racingEventService); - theSeries.addRaceColumn("R3", racingEventService); - final RegattaLeaderboard leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), /* leaderboardDisplayName */ null, new int[] { 5, 9 }); - RaceLogTrackingAdapterFactory.INSTANCE.getAdapter(domainObjectFactory.getBaseDomainFactory()).denoteAllRacesForRaceLogTracking(racingEventService, leaderboard); - final RaceLogConnectivityParams rlParams = new RaceLogConnectivityParams( - racingEventService, regatta, leaderboard.getRaceColumnByName("R2"), fleet, leaderboard, - delayToLiveInMillis, domainObjectFactory.getBaseDomainFactory(), trackWind, - correctWindDirectionByMagneticDeclination); - // store - mongoObjectFactory.addConnectivityParametersForRaceToRestore(rlParams); - // load - final Set connectivityParametersForRacesToRestore = new HashSet<>(); - domainObjectFactory.loadConnectivityParametersForRacesToRestore(params -> connectivityParametersForRacesToRestore.add(params)) - .waitForCompletionOfCallbacksForAllParameters(); - // compare - assertEquals(1, Util.size(connectivityParametersForRacesToRestore)); - final RaceTrackingConnectivityParameters paramsReadFromDB = connectivityParametersForRacesToRestore.iterator().next(); - assertTrue(paramsReadFromDB instanceof RaceLogConnectivityParams); - RaceLogConnectivityParams raceLogParamsReadFromDB = (RaceLogConnectivityParams) paramsReadFromDB; - assertEquals(delayToLiveInMillis, raceLogParamsReadFromDB.getDelayToLiveInMillis()); - assertSame(leaderboard, raceLogParamsReadFromDB.getLeaderboard()); - assertSame(theSeries.getRaceColumnByName("R2"), raceLogParamsReadFromDB.getRaceColumn()); - assertSame(fleet, raceLogParamsReadFromDB.getFleet()); - assertEquals(rlParams.getTrackerID(), raceLogParamsReadFromDB.getTrackerID()); - assertEquals(rlParams.isTrackWind(), raceLogParamsReadFromDB.isTrackWind()); - assertEquals(rlParams.isCorrectWindDirectionByMagneticDeclination(), raceLogParamsReadFromDB.isCorrectWindDirectionByMagneticDeclination()); - // remove again - mongoObjectFactory.removeConnectivityParametersForRaceToRestore(rlParams); - final Set connectivityParametersForRacesToRestore2 = new HashSet<>(); - domainObjectFactory.loadConnectivityParametersForRacesToRestore(params->connectivityParametersForRacesToRestore2.add(params)) - .waitForCompletionOfCallbacksForAllParameters(); - assertTrue(connectivityParametersForRacesToRestore2.isEmpty()); - } -} + OneDesignRankingMetric::new); + theSeries.addRaceColumn("R1", racingEventService); + theSeries.addRaceColumn("R2", racingEventService); + theSeries.addRaceColumn("R3", racingEventService); + final RegattaLeaderboard leaderboard = racingEventService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), /* leaderboardDisplayName */ null, new int[] { 5, 9 }); + RaceLogTrackingAdapterFactory.INSTANCE.getAdapter(domainObjectFactory.getBaseDomainFactory()).denoteAllRacesForRaceLogTracking(racingEventService, leaderboard); + final RaceLogConnectivityParams rlParams = new RaceLogConnectivityParams( + racingEventService, regatta, leaderboard.getRaceColumnByName("R2"), fleet, leaderboard, + delayToLiveInMillis, domainObjectFactory.getBaseDomainFactory(), trackWind, + correctWindDirectionByMagneticDeclination); + // store + mongoObjectFactory.addConnectivityParametersForRaceToRestore(rlParams); + // load + final Set connectivityParametersForRacesToRestore = new HashSet<>(); + domainObjectFactory.loadConnectivityParametersForRacesToRestore(params -> connectivityParametersForRacesToRestore.add(params)) + .waitForCompletionOfCallbacksForAllParameters(); + // compare + assertEquals(1, Util.size(connectivityParametersForRacesToRestore)); + final RaceTrackingConnectivityParameters paramsReadFromDB = connectivityParametersForRacesToRestore.iterator().next(); + assertTrue(paramsReadFromDB instanceof RaceLogConnectivityParams); + RaceLogConnectivityParams raceLogParamsReadFromDB = (RaceLogConnectivityParams) paramsReadFromDB; + assertEquals(delayToLiveInMillis, raceLogParamsReadFromDB.getDelayToLiveInMillis()); + assertSame(leaderboard, raceLogParamsReadFromDB.getLeaderboard()); + assertSame(theSeries.getRaceColumnByName("R2"), raceLogParamsReadFromDB.getRaceColumn()); + assertSame(fleet, raceLogParamsReadFromDB.getFleet()); + assertEquals(rlParams.getTrackerID(), raceLogParamsReadFromDB.getTrackerID()); + assertEquals(rlParams.isTrackWind(), raceLogParamsReadFromDB.isTrackWind()); + assertEquals(rlParams.isCorrectWindDirectionByMagneticDeclination(), raceLogParamsReadFromDB.isCorrectWindDirectionByMagneticDeclination()); + // remove again + mongoObjectFactory.removeConnectivityParametersForRaceToRestore(rlParams); + final Set connectivityParametersForRacesToRestore2 = new HashSet<>(); + domainObjectFactory.loadConnectivityParametersForRacesToRestore(params->connectivityParametersForRacesToRestore2.add(params)) + .waitForCompletionOfCallbacksForAllParameters(); + assertTrue(connectivityParametersForRacesToRestore2.isEmpty()); + } +} diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 9ac3ed86858..bcb1740c287 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -1,484 +1,484 @@ -package com.sap.sailing.mongodb.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.mongodb.MongoException; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.NationalityImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; -import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; -import com.sap.sailing.domain.persistence.DomainObjectFactory; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; -import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; -import com.sap.sailing.domain.persistence.media.MediaDBFactory; -import com.sap.sailing.domain.racelog.tracking.EmptySensorFixStore; -import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrection; -import com.sap.sse.common.Color; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.mongodb.MongoDBService; - -public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTest { - private MongoObjectFactory mongoObjectFactory = null; - private DomainObjectFactory domainObjectFactory = null; - - - public TestStoringAndRetrievingLeaderboardGroups() throws UnknownHostException, MongoException { - super(); - } - - @Before - public void setUp() { - DomainFactory.INSTANCE.getCompetitorStore().clearCompetitors(); - mongoObjectFactory = new MongoObjectFactoryImpl(db); - domainObjectFactory = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE); - } - - @Test - public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboard() { - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final ArrayList leaderboards = new ArrayList<>(); - - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); - final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, - new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); - leaderboardGroup.setOverallLeaderboard(overallLeaderboard); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - - final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, - /* leaderboardRegistry */ null); - assertNotNull(loadedLeaderboardGroup.getOverallLeaderboard()); - assertEquals(leaderboardGroup.getId(), loadedLeaderboardGroup.getId()); - assertNotSame(leaderboardGroup.getOverallLeaderboard(), loadedLeaderboardGroup.getOverallLeaderboard()); - assertSame(ScoringSchemeType.HIGH_POINT_ESS_OVERALL, loadedLeaderboardGroup.getOverallLeaderboard().getScoringScheme().getType()); - } - - @Test - public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboardWithScoreCorrection() throws NoWindException { - RacingEventService racingEventService = new RacingEventServiceImpl(); - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, - new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); - - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - racingEventService.addLeaderboard(leaderboard); - leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - racingEventService.addLeaderboard(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - racingEventService.addLeaderboard(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - racingEventService.addLeaderboard(leaderboard); - - LeaderboardGroup leaderboardGroup = racingEventService.addLeaderboardGroup(UUID.randomUUID(), groupName, groupDescription, - "The LG Display Name", false, - Arrays.asList(leaderboardNames), new int[0], ScoringSchemeType.HIGH_POINT_ESS_OVERALL); - final Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - racingEventService.apply(new UpdateLeaderboardScoreCorrection(overallLeaderboard.getName(), "Leaderboard 3", - wolfgang.getId().toString(), 99.9, MillisecondsTimePoint.now())); - - final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, - /* leaderboardRegistry */ null); - loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( - loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); - Leaderboard loadedOverallLeaderboard = loadedLeaderboardGroup.getOverallLeaderboard(); - final RaceColumn leaderboard3Column = loadedOverallLeaderboard.getRaceColumnByName("Leaderboard 3"); - assertTrue(loadedOverallLeaderboard.getScoreCorrection().hasCorrectionFor(leaderboard3Column)); - final Double netPoints = loadedOverallLeaderboard.getNetPoints(wolfgang, leaderboard3Column, - MillisecondsTimePoint.now()); - assertNotNull(netPoints); - assertEquals(99.9, netPoints, 0.00000000001); - } - - @Test - public void testStoringAndRetrievingLeaderboardGroupWithSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, - new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); - - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final ArrayList leaderboards = new ArrayList<>(); - - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); - final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, - new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); - leaderboardGroup.setOverallLeaderboard(overallLeaderboard); - overallLeaderboard.setSuppressed(wolfgang, true); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - - final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, - /* leaderboardRegistry */ null); - // ensure that with no tracked races associated, suppressed competitors are not yet resolved: - assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); - assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); - // now add tracked race to one of the group's leaderboards: - loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( - loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); - // ensure that with no tracked races associated, suppressed competitors are not yet resolved: - assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); - assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); - } - - @Test - public void testStoringAndRetrievingLeaderboardGroupWithTwoSuppressedCompetitorsInOverallLeaderboard() { - Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( - new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, - new TeamImpl("STG", Collections.singleton( - new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); - final String raceColumnName1 = "My First Race 1"; - MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( - new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); - raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); - - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final ArrayList leaderboards = new ArrayList<>(); - - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); - final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, - new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); - leaderboardGroup.setOverallLeaderboard(overallLeaderboard); - overallLeaderboard.setSuppressed(wolfgang, true); - overallLeaderboard.setSuppressed(hasso, true); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - - final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, - /* leaderboardRegistry */ null); - // ensure that with no tracked races associated, suppressed competitors are not yet resolved: - assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); - assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); - // now add tracked race to one of the group's leaderboards: - loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( - loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); - // ensure that with no tracked races associated, suppressed competitors are not yet resolved: - assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); - assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); - } - - /** - * Bug 908: asserting that after loading two leaderboard groups referencing the same leaderbard the leaderboard is - * loaded only once - */ - @Test - public void testStoringAndRetrievingTwoLeaderboardGroupsReferencingTheSameLeaderboard() { - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName1 = "Leaderboard Group 1"; - final String groupDescription1 = "A leaderboard group 1"; - final ArrayList leaderboards1 = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards1.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards1.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards1.add(leaderboard); - final LeaderboardGroup leaderboardGroup1 = new LeaderboardGroupImpl(groupName1, groupDescription1, /* displayName */ null, false, leaderboards1); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup1); - - final String groupName2 = "Leaderboard Group 2"; - final String groupDescription2= "A leaderboard group 2"; - final ArrayList leaderboards2 = new ArrayList<>(); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards2.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards2.add(leaderboard); - final LeaderboardGroup leaderboardGroup2 = new LeaderboardGroupImpl(groupName2, groupDescription2, /* displayName */ null, false, leaderboards2); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup2); - - // the leaderboard named leaderboardNames[2] occurs in both groups - RacingEventService racingEventService = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(MongoDBService.INSTANCE), MediaDBFactory.INSTANCE.getMediaDB(MongoDBService.INSTANCE), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE, /* restoreTrackedRaces */ false); // expected to load leaderboard groups - final LeaderboardGroup loadedLeaderboardGroup1 = racingEventService.getLeaderboardGroupByName(groupName1); - final LeaderboardGroup loadedLeaderboardGroup2 = racingEventService.getLeaderboardGroupByName(groupName2); - - assertEquals(groupName1, loadedLeaderboardGroup1.getName()); - assertEquals(groupDescription1, loadedLeaderboardGroup1.getDescription()); - assertEquals(groupName2, loadedLeaderboardGroup2.getName()); - assertEquals(groupDescription2, loadedLeaderboardGroup2.getDescription()); - assertSame(Util.get(loadedLeaderboardGroup1.getLeaderboards(), 2), Util.get(loadedLeaderboardGroup2.getLeaderboards(), 0)); - } - - @Test - public void testStoringAndRetrievingSimpleLeaderboardGroup() { - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final String groupDisplayName = "Some short name"; - final ArrayList leaderboards = new ArrayList<>(); - - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, groupDisplayName, false, leaderboards); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - - final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, - /* leaderboardRegistry */ null); - - Assert.assertEquals(groupName, loadedLeaderboardGroup.getName()); - Assert.assertEquals(groupDescription, loadedLeaderboardGroup.getDescription()); - Assert.assertEquals(groupDisplayName, loadedLeaderboardGroup.getDisplayName()); - - int c = 0; - for (Leaderboard board : leaderboardGroup.getLeaderboards()) { - Assert.assertEquals(leaderboardNames[c], board.getName()); - c++; - } - } - - @Test - public void testGetLeaderboardsNotInGroup() { - final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1"}; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final ArrayList leaderboards = new ArrayList<>(); - - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null); - leaderboards.add(leaderboard); - - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - - final String[] ungroupedLeaderboardNames = {"Ungrouped Leaderboard 0", "Ungrouped Leaderboard 1", "Ungrouped Leaderboard 2"}; - - final FlexibleLeaderboard[] ungroupedLeaderboards = { - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null), - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null), - new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), - new LowPoint(), null) }; - mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]); - mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]); - mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[2]); - - Iterable loadedUngroupedLeaderboards = domainObjectFactory.getLeaderboardsNotInGroup(/* regattaRegistry */ null, - /* leaderboardRegistry */ null); - - Assert.assertTrue(loadedUngroupedLeaderboards.iterator().hasNext()); - - int c = 0; - for (int i = 0; i < ungroupedLeaderboardNames.length; i++) { - boolean loadedBoardsContainsName = false; - for (Leaderboard board : loadedUngroupedLeaderboards) { - if (ungroupedLeaderboardNames[i].equals(board.getName())) { - loadedBoardsContainsName = true; - c++; - break; - } - } - Assert.assertTrue(loadedBoardsContainsName); - } - - Assert.assertTrue(c == ungroupedLeaderboards.length); - } - - @Test - public void testLeaderboardReferenceBreak() { - //Set up - final String leaderboardName = "Leaderboard 0"; - final String columnName = "Column"; - final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - - final String groupName = "Leaderboard Group"; - final String groupDescription = "A leaderboard group"; - final ArrayList leaderboards = new ArrayList<>(); - - final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); - final Fleet fleet = leaderboard.getFleet(null); - final RaceColumn race = leaderboard.addRaceColumn(columnName, false); - leaderboards.add(leaderboard); - - final LeaderboardGroup group = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); - mongoObjectFactory.storeLeaderboardGroup(group); - - //Name change test - final String newLeaderboardName = "Leaderboard ChangedName"; - mongoObjectFactory.renameLeaderboard(leaderboardName, newLeaderboardName); - leaderboard.setName(newLeaderboardName); - - LeaderboardGroup loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); - String loadedLeaderboardName = loadedGroup.getLeaderboards().iterator().next().getName(); - Assert.assertEquals(newLeaderboardName, loadedLeaderboardName); - - //RaceIdentifier change test - final String regattaName = "Event"; - final String raceName = "Race"; - leaderboard.getRaceColumnByName(columnName).setRaceIdentifier(fleet, new RegattaNameAndRaceName(regattaName, raceName)); - mongoObjectFactory.storeLeaderboard(leaderboard); - - //Check if the leaderboard updated correctly - final Leaderboard loadedLeaderboard = domainObjectFactory.loadLeaderboard(leaderboard.getName(), /* regattaRegistry */ null); - final RaceColumn loadedRaceColumnByName = loadedLeaderboard.getRaceColumnByName(columnName); - Fleet loadedFleet = loadedRaceColumnByName.getFleetByName(fleet.getName()); - Assert.assertEquals(race.getRaceIdentifier(fleet), loadedRaceColumnByName.getRaceIdentifier(loadedFleet)); - - // Check if the group received the changes - loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); - final RaceColumn loadedRaceColumnFromGroupByName = loadedGroup.getLeaderboards().iterator().next().getRaceColumnByName(columnName); - Fleet loadedGroupFleet = loadedRaceColumnFromGroupByName.getFleetByName(fleet.getName()); - RaceIdentifier loadedIdentifier = loadedRaceColumnFromGroupByName.getRaceIdentifier(loadedGroupFleet); - Assert.assertEquals(race.getRaceIdentifier(fleet), loadedIdentifier); - } - -} +package com.sap.sailing.mongodb.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.MongoException; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; +import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; +import com.sap.sailing.domain.persistence.media.MediaDBFactory; +import com.sap.sailing.domain.racelog.tracking.EmptySensorFixStore; +import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrection; +import com.sap.sse.common.Color; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.mongodb.MongoDBService; + +public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTest { + private MongoObjectFactory mongoObjectFactory = null; + private DomainObjectFactory domainObjectFactory = null; + + + public TestStoringAndRetrievingLeaderboardGroups() throws UnknownHostException, MongoException { + super(); + } + + @Before + public void setUp() { + DomainFactory.INSTANCE.getCompetitorStore().clearCompetitors(); + mongoObjectFactory = new MongoObjectFactoryImpl(db); + domainObjectFactory = new DomainObjectFactoryImpl(db, DomainFactory.INSTANCE); + } + + @Test + public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboard() { + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final ArrayList leaderboards = new ArrayList<>(); + + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + + final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); + final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, + new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); + leaderboardGroup.setOverallLeaderboard(overallLeaderboard); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + + final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, + /* leaderboardRegistry */ null); + assertNotNull(loadedLeaderboardGroup.getOverallLeaderboard()); + assertEquals(leaderboardGroup.getId(), loadedLeaderboardGroup.getId()); + assertNotSame(leaderboardGroup.getOverallLeaderboard(), loadedLeaderboardGroup.getOverallLeaderboard()); + assertSame(ScoringSchemeType.HIGH_POINT_ESS_OVERALL, loadedLeaderboardGroup.getOverallLeaderboard().getScoringScheme().getType()); + } + + @Test + public void testStoringAndRetrievingLeaderboardGroupWithOverallLeaderboardWithScoreCorrection() throws NoWindException { + RacingEventService racingEventService = new RacingEventServiceImpl(); + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + final String raceColumnName1 = "My First Race 1"; + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); + + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + racingEventService.addLeaderboard(leaderboard); + leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + racingEventService.addLeaderboard(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + racingEventService.addLeaderboard(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + racingEventService.addLeaderboard(leaderboard); + + LeaderboardGroup leaderboardGroup = racingEventService.addLeaderboardGroup(UUID.randomUUID(), groupName, groupDescription, + "The LG Display Name", false, + Arrays.asList(leaderboardNames), new int[0], ScoringSchemeType.HIGH_POINT_ESS_OVERALL); + final Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + racingEventService.apply(new UpdateLeaderboardScoreCorrection(overallLeaderboard.getName(), "Leaderboard 3", + wolfgang.getId().toString(), 99.9, MillisecondsTimePoint.now())); + + final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, + /* leaderboardRegistry */ null); + loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( + loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); + Leaderboard loadedOverallLeaderboard = loadedLeaderboardGroup.getOverallLeaderboard(); + final RaceColumn leaderboard3Column = loadedOverallLeaderboard.getRaceColumnByName("Leaderboard 3"); + assertTrue(loadedOverallLeaderboard.getScoreCorrection().hasCorrectionFor(leaderboard3Column)); + final Double netPoints = loadedOverallLeaderboard.getNetPoints(wolfgang, leaderboard3Column, + MillisecondsTimePoint.now()); + assertNotNull(netPoints); + assertEquals(99.9, netPoints, 0.00000000001); + } + + @Test + public void testStoringAndRetrievingLeaderboardGroupWithSuppressedCompetitorsInOverallLeaderboard() { + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null, null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + final String raceColumnName1 = "My First Race 1"; + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); + + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final ArrayList leaderboards = new ArrayList<>(); + + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + + final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); + final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, + new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); + leaderboardGroup.setOverallLeaderboard(overallLeaderboard); + overallLeaderboard.setSuppressed(wolfgang, true); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + + final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, + /* leaderboardRegistry */ null); + // ensure that with no tracked races associated, suppressed competitors are not yet resolved: + assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); + assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); + // now add tracked race to one of the group's leaderboards: + loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( + loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); + // ensure that with no tracked races associated, suppressed competitors are not yet resolved: + assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); + assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); + } + + @Test + public void testStoringAndRetrievingLeaderboardGroupWithTwoSuppressedCompetitorsInOverallLeaderboard() { + Competitor wolfgang = new CompetitorImpl(123, "$$$Dr. Wolfgang+Hunger$$$", "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl("$$$Dr. Wolfgang+Hunger$$$", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Wolfgang Hunger")), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */ null, "This is Rigo, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat wolfgangsBoat = new BoatImpl("123", "Dr. Wolfgang Hunger's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + Competitor hasso = new CompetitorImpl(234, "Hasso Plattner", "KYC", Color.RED, null,null, + new TeamImpl("STG", Collections.singleton( + new PersonImpl("Hasso Plattner", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous Dr. Hasso Plattner")), new PersonImpl("Lutz Patrunky", new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is Patty, the coach")), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + Boat hassosBoat = new BoatImpl("456", "Dr. Hasso Plattner's boat", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null); + final String raceColumnName1 = "My First Race 1"; + MockedTrackedRaceWithFixedRankAndManyCompetitors raceWithTwoCompetitors = new MockedTrackedRaceWithFixedRankAndManyCompetitors( + new CompetitorAndBoatImpl(wolfgang,wolfgangsBoat), /* rank */ 1, /* started */ true); + raceWithTwoCompetitors.addCompetitorAndBoat(new CompetitorAndBoatImpl(hasso,hassosBoat)); + + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final ArrayList leaderboards = new ArrayList<>(); + + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard.addRace(raceWithTwoCompetitors, raceColumnName1, /* medalRace */false); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + + final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); + final Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, + new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); + leaderboardGroup.setOverallLeaderboard(overallLeaderboard); + overallLeaderboard.setSuppressed(wolfgang, true); + overallLeaderboard.setSuppressed(hasso, true); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + + final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, + /* leaderboardRegistry */ null); + // ensure that with no tracked races associated, suppressed competitors are not yet resolved: + assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); + assertFalse(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); + // now add tracked race to one of the group's leaderboards: + loadedLeaderboardGroup.getLeaderboards().iterator().next().getRaceColumnByName(raceColumnName1).setTrackedRace( + loadedLeaderboardGroup.getLeaderboards().iterator().next().getFleet(null), raceWithTwoCompetitors); + // ensure that with no tracked races associated, suppressed competitors are not yet resolved: + assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), wolfgang)); + assertTrue(Util.contains(loadedLeaderboardGroup.getOverallLeaderboard().getSuppressedCompetitors(), hasso)); + } + + /** + * Bug 908: asserting that after loading two leaderboard groups referencing the same leaderbard the leaderboard is + * loaded only once + */ + @Test + public void testStoringAndRetrievingTwoLeaderboardGroupsReferencingTheSameLeaderboard() { + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName1 = "Leaderboard Group 1"; + final String groupDescription1 = "A leaderboard group 1"; + final ArrayList leaderboards1 = new ArrayList<>(); + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards1.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards1.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards1.add(leaderboard); + final LeaderboardGroup leaderboardGroup1 = new LeaderboardGroupImpl(groupName1, groupDescription1, /* displayName */ null, false, leaderboards1); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup1); + + final String groupName2 = "Leaderboard Group 2"; + final String groupDescription2= "A leaderboard group 2"; + final ArrayList leaderboards2 = new ArrayList<>(); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards2.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards2.add(leaderboard); + final LeaderboardGroup leaderboardGroup2 = new LeaderboardGroupImpl(groupName2, groupDescription2, /* displayName */ null, false, leaderboards2); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup2); + + // the leaderboard named leaderboardNames[2] occurs in both groups + RacingEventService racingEventService = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(MongoDBService.INSTANCE), MediaDBFactory.INSTANCE.getMediaDB(MongoDBService.INSTANCE), EmptyWindStore.INSTANCE, EmptySensorFixStore.INSTANCE, /* restoreTrackedRaces */ false); // expected to load leaderboard groups + final LeaderboardGroup loadedLeaderboardGroup1 = racingEventService.getLeaderboardGroupByName(groupName1); + final LeaderboardGroup loadedLeaderboardGroup2 = racingEventService.getLeaderboardGroupByName(groupName2); + + assertEquals(groupName1, loadedLeaderboardGroup1.getName()); + assertEquals(groupDescription1, loadedLeaderboardGroup1.getDescription()); + assertEquals(groupName2, loadedLeaderboardGroup2.getName()); + assertEquals(groupDescription2, loadedLeaderboardGroup2.getDescription()); + assertSame(Util.get(loadedLeaderboardGroup1.getLeaderboards(), 2), Util.get(loadedLeaderboardGroup2.getLeaderboards(), 0)); + } + + @Test + public void testStoringAndRetrievingSimpleLeaderboardGroup() { + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1", "Leaderboard 2", "Leaderboard 3"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final String groupDisplayName = "Some short name"; + final ArrayList leaderboards = new ArrayList<>(); + + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + + final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, groupDisplayName, false, leaderboards); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + + final LeaderboardGroup loadedLeaderboardGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, + /* leaderboardRegistry */ null); + + Assert.assertEquals(groupName, loadedLeaderboardGroup.getName()); + Assert.assertEquals(groupDescription, loadedLeaderboardGroup.getDescription()); + Assert.assertEquals(groupDisplayName, loadedLeaderboardGroup.getDisplayName()); + + int c = 0; + for (Leaderboard board : leaderboardGroup.getLeaderboards()) { + Assert.assertEquals(leaderboardNames[c], board.getName()); + c++; + } + } + + @Test + public void testGetLeaderboardsNotInGroup() { + final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1"}; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final ArrayList leaderboards = new ArrayList<>(); + + Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null); + leaderboards.add(leaderboard); + + final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + + final String[] ungroupedLeaderboardNames = {"Ungrouped Leaderboard 0", "Ungrouped Leaderboard 1", "Ungrouped Leaderboard 2"}; + + final FlexibleLeaderboard[] ungroupedLeaderboards = { + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null), + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null), + new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), + new LowPoint(), null) }; + mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]); + mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]); + mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[2]); + + Iterable loadedUngroupedLeaderboards = domainObjectFactory.getLeaderboardsNotInGroup(/* regattaRegistry */ null, + /* leaderboardRegistry */ null); + + Assert.assertTrue(loadedUngroupedLeaderboards.iterator().hasNext()); + + int c = 0; + for (int i = 0; i < ungroupedLeaderboardNames.length; i++) { + boolean loadedBoardsContainsName = false; + for (Leaderboard board : loadedUngroupedLeaderboards) { + if (ungroupedLeaderboardNames[i].equals(board.getName())) { + loadedBoardsContainsName = true; + c++; + break; + } + } + Assert.assertTrue(loadedBoardsContainsName); + } + + Assert.assertTrue(c == ungroupedLeaderboards.length); + } + + @Test + public void testLeaderboardReferenceBreak() { + //Set up + final String leaderboardName = "Leaderboard 0"; + final String columnName = "Column"; + final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; + + final String groupName = "Leaderboard Group"; + final String groupDescription = "A leaderboard group"; + final ArrayList leaderboards = new ArrayList<>(); + + final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); + final Fleet fleet = leaderboard.getFleet(null); + final RaceColumn race = leaderboard.addRaceColumn(columnName, false); + leaderboards.add(leaderboard); + + final LeaderboardGroup group = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); + mongoObjectFactory.storeLeaderboardGroup(group); + + //Name change test + final String newLeaderboardName = "Leaderboard ChangedName"; + mongoObjectFactory.renameLeaderboard(leaderboardName, newLeaderboardName); + leaderboard.setName(newLeaderboardName); + + LeaderboardGroup loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); + String loadedLeaderboardName = loadedGroup.getLeaderboards().iterator().next().getName(); + Assert.assertEquals(newLeaderboardName, loadedLeaderboardName); + + //RaceIdentifier change test + final String regattaName = "Event"; + final String raceName = "Race"; + leaderboard.getRaceColumnByName(columnName).setRaceIdentifier(fleet, new RegattaNameAndRaceName(regattaName, raceName)); + mongoObjectFactory.storeLeaderboard(leaderboard); + + //Check if the leaderboard updated correctly + final Leaderboard loadedLeaderboard = domainObjectFactory.loadLeaderboard(leaderboard.getName(), /* regattaRegistry */ null); + final RaceColumn loadedRaceColumnByName = loadedLeaderboard.getRaceColumnByName(columnName); + Fleet loadedFleet = loadedRaceColumnByName.getFleetByName(fleet.getName()); + Assert.assertEquals(race.getRaceIdentifier(fleet), loadedRaceColumnByName.getRaceIdentifier(loadedFleet)); + + // Check if the group received the changes + loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); + final RaceColumn loadedRaceColumnFromGroupByName = loadedGroup.getLeaderboards().iterator().next().getRaceColumnByName(columnName); + Fleet loadedGroupFleet = loadedRaceColumnFromGroupByName.getFleetByName(fleet.getName()); + RaceIdentifier loadedIdentifier = loadedRaceColumnFromGroupByName.getRaceIdentifier(loadedGroupFleet); + Assert.assertEquals(race.getRaceIdentifier(fleet), loadedIdentifier); + } + +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java index d100ef1c056..ad4fb610c34 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesBoatsPanelPO.java @@ -1,42 +1,42 @@ -package com.sap.sailing.selenium.pages.adminconsole.tracking; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import com.sap.sailing.selenium.core.BySeleniumId; -import com.sap.sailing.selenium.core.FindBy; -import com.sap.sailing.selenium.pages.PageArea; - -public class TrackedRacesBoatsPanelPO extends PageArea { - @FindBy(how = BySeleniumId.class, using = "RefreshButton") - private WebElement refreshButton; - - @FindBy(how = BySeleniumId.class, using = "AddBoatButton") - private WebElement addButton; - - @FindBy(how = BySeleniumId.class, using = "BoatsTable") - private WebElement boatsTable; - - public final WebDriver driver; - - public TrackedRacesBoatsPanelPO(WebDriver driver, WebElement element) { - super(driver, element); - this.driver = driver; - } - - public TrackedRacesBoatEditDialogPO pushAddButton() { - this.addButton.click(); - waitForAjaxRequests(); - WebElement dialog = findElementBySeleniumId(this.driver, "BoatEditDialog"); - return new TrackedRacesBoatEditDialogPO(this.driver, dialog); - } - - public void pushRefreshButton() { - this.refreshButton.click(); - waitForAjaxRequests(); - } - - public TrackedRacesBoatTablePO getBoatsTable() { - return new TrackedRacesBoatTablePO(this.driver, this.boatsTable); - } -} +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.PageArea; + +public class TrackedRacesBoatsPanelPO extends PageArea { + @FindBy(how = BySeleniumId.class, using = "RefreshButton") + private WebElement refreshButton; + + @FindBy(how = BySeleniumId.class, using = "AddBoatButton") + private WebElement addButton; + + @FindBy(how = BySeleniumId.class, using = "BoatsTable") + private WebElement boatsTable; + + public final WebDriver driver; + + public TrackedRacesBoatsPanelPO(WebDriver driver, WebElement element) { + super(driver, element); + this.driver = driver; + } + + public TrackedRacesBoatEditDialogPO pushAddButton() { + this.addButton.click(); + waitForAjaxRequests(); + WebElement dialog = findElementBySeleniumId(this.driver, "BoatEditDialog"); + return new TrackedRacesBoatEditDialogPO(this.driver, dialog); + } + + public void pushRefreshButton() { + this.refreshButton.click(); + waitForAjaxRequests(); + } + + public TrackedRacesBoatTablePO getBoatsTable() { + return new TrackedRacesBoatTablePO(this.driver, this.boatsTable); + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java index 1b11391733e..7051156dde1 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java @@ -1,105 +1,105 @@ -package com.sap.sailing.server.gateway.deserialization.impl; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.util.UUID; -import java.util.logging.Logger; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; -import com.sap.sailing.domain.base.CompetitorFactory; -import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sse.common.Color; -import com.sap.sse.common.impl.MillisecondsDurationImpl; -import com.sap.sse.common.impl.RGBColor; - -public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { - protected final CompetitorFactory competitorFactory; - protected final JsonDeserializer teamJsonDeserializer; - protected final JsonDeserializer boatJsonDeserializer; - private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); - - public static CompetitorWithBoatJsonDeserializer create(SharedDomainFactory baseDomainFactory) { - return new CompetitorWithBoatJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( - new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); - } - - public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory) { - this(competitorFactory, null, /* boatDeserializer */ null); - } - - public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorFactory = competitorFactory; - this.teamJsonDeserializer = teamJsonDeserializer; - this.boatJsonDeserializer = boatDeserializer; - } - - @Override - public CompetitorAndBoat deserialize(JSONObject object) throws JsonDeserializationException { - Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); - try { - Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); - if (Number.class.isAssignableFrom(idClass)) { - Constructor constructorFromString = idClass.getConstructor(String.class); - competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); - } else if (UUID.class.isAssignableFrom(idClass)) { - competitorId = Helpers.tryUuidConversion(competitorId); - } - String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); - String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); - String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); - String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); - String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); - - URI flagImageURI = null; - String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); - if (flagImageURIAsString != null) { - try { - flagImageURI = URI.create(flagImageURIAsString); - } catch (IllegalArgumentException e) { - logger.warning("Illegal flag image URI " + e.getMessage()); - } - } - - final Color displayColor; - if (displayColorAsString == null || displayColorAsString.isEmpty()) { - displayColor = null; - } else { - displayColor = new RGBColor(displayColorAsString); - } - DynamicTeam team = null; - DynamicBoat boat = null; - if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { - team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_TEAM)); - } - if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { - boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_BOAT)); - String sailID = (String) object.get(CompetitorJsonConstants.FIELD_SAIL_ID); - boat.setSailId(sailID); - } - final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); - final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object - .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, - flagImageURI, team, timeOnTimeFactor, - timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); - - return new CompetitorAndBoatImpl(competitor, boat); - } catch (Exception e) { - throw new JsonDeserializationException(e); - } - } -} +package com.sap.sailing.server.gateway.deserialization.impl; + +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.util.UUID; +import java.util.logging.Logger; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sse.common.Color; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.RGBColor; + +public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { + protected final CompetitorFactory competitorFactory; + protected final JsonDeserializer teamJsonDeserializer; + protected final JsonDeserializer boatJsonDeserializer; + private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); + + public static CompetitorWithBoatJsonDeserializer create(SharedDomainFactory baseDomainFactory) { + return new CompetitorWithBoatJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( + new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); + } + + public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory) { + this(competitorFactory, null, /* boatDeserializer */ null); + } + + public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorFactory = competitorFactory; + this.teamJsonDeserializer = teamJsonDeserializer; + this.boatJsonDeserializer = boatDeserializer; + } + + @Override + public CompetitorAndBoat deserialize(JSONObject object) throws JsonDeserializationException { + Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); + try { + Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); + if (Number.class.isAssignableFrom(idClass)) { + Constructor constructorFromString = idClass.getConstructor(String.class); + competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); + } else if (UUID.class.isAssignableFrom(idClass)) { + competitorId = Helpers.tryUuidConversion(competitorId); + } + String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); + String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); + String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); + String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); + String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); + + URI flagImageURI = null; + String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); + if (flagImageURIAsString != null) { + try { + flagImageURI = URI.create(flagImageURIAsString); + } catch (IllegalArgumentException e) { + logger.warning("Illegal flag image URI " + e.getMessage()); + } + } + + final Color displayColor; + if (displayColorAsString == null || displayColorAsString.isEmpty()) { + displayColor = null; + } else { + displayColor = new RGBColor(displayColorAsString); + } + DynamicTeam team = null; + DynamicBoat boat = null; + if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { + team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_TEAM)); + } + if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { + boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_BOAT)); + String sailID = (String) object.get(CompetitorJsonConstants.FIELD_SAIL_ID); + boat.setSailId(sailID); + } + final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); + final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object + .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); + Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, + flagImageURI, team, timeOnTimeFactor, + timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); + + return new CompetitorAndBoatImpl(competitor, boat); + } catch (Exception e) { + throw new JsonDeserializationException(e); + } + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java index 9a2ba017748..7738db556c5 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java @@ -1,39 +1,39 @@ -package com.sap.sailing.server.gateway.serialization.impl; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; -import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; - -public class CompetitorWithBoatJsonSerializer implements JsonSerializer { - private final JsonSerializer boatJsonSerializer; - private final JsonSerializer competitorJsonSerializer; - - public static CompetitorWithBoatJsonSerializer create() { - return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); - } - - public CompetitorWithBoatJsonSerializer() { - this(null, null); - } - - public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { - this.competitorJsonSerializer = competitorJsonSerializer; - this.boatJsonSerializer = boatJsonSerializer; - } - - @Override - public JSONObject serialize(CompetitorAndBoat competitorAndBoat) { - JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getCompetitor()); - - serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitorAndBoat.getBoat() == null ? "" : competitorAndBoat.getBoat().getSailID()); - - if (boatJsonSerializer != null) { - serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitorAndBoat.getBoat())); - } - return serializedCompetitor; - } -} +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class CompetitorWithBoatJsonSerializer implements JsonSerializer { + private final JsonSerializer boatJsonSerializer; + private final JsonSerializer competitorJsonSerializer; + + public static CompetitorWithBoatJsonSerializer create() { + return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); + } + + public CompetitorWithBoatJsonSerializer() { + this(null, null); + } + + public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { + this.competitorJsonSerializer = competitorJsonSerializer; + this.boatJsonSerializer = boatJsonSerializer; + } + + @Override + public JSONObject serialize(CompetitorAndBoat competitorAndBoat) { + JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getCompetitor()); + + serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitorAndBoat.getBoat() == null ? "" : competitorAndBoat.getBoat().getSailID()); + + if (boatJsonSerializer != null) { + serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitorAndBoat.getBoat())); + } + return serializedCompetitor; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index 33cd593911b..c543199f77f 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -1,307 +1,307 @@ -package com.sap.sailing.server.gateway.serialization.racelog.impl; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.server.gateway.serialization.coursedata.impl.ControlPointJsonSerializer; -import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseBaseJsonSerializer; -import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer; -import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; -import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.DeviceIdentifierJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; -import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.SmartphoneUUIDJsonHandler; - -public class RaceLogEventSerializer implements JsonSerializer, RaceLogEventVisitor { - public static JsonSerializer create(JsonSerializer competitorSerializer) { - return create(competitorSerializer, DeviceIdentifierJsonSerializer.create( - new SmartphoneUUIDJsonHandler(), SmartphoneUUIDIdentifier.TYPE)); - } - - public static JsonSerializer create(JsonSerializer competitorSerializer, - JsonSerializer deviceSerializer) { - return new RaceLogEventSerializer( - new RaceLogFlagEventSerializer(competitorSerializer), - new RaceLogStartTimeEventSerializer(competitorSerializer), - new RaceLogRaceStatusEventSerializer(competitorSerializer), - new RaceLogCourseAreaChangedEventSerializer(competitorSerializer), - new RaceLogPassChangeEventSerializer(competitorSerializer), - new RaceLogCourseDesignChangedEventSerializer(competitorSerializer, - new CourseBaseJsonSerializer( - new WaypointJsonSerializer( - new ControlPointJsonSerializer( - new MarkJsonSerializer(), - new GateJsonSerializer(new MarkJsonSerializer()))))), - new RaceLogFinishPositioningListChangedEventSerializer(competitorSerializer), - new RaceLogFinishPositioningConfirmedEventSerializer(competitorSerializer), - new RaceLogPathfinderEventSerializer(competitorSerializer), - new RaceLogGateLineOpeningTimeEventSerializer(competitorSerializer), - new RaceLogStartProcedureChangedEventSerializer(competitorSerializer), - new RaceLogProtestStartTimeEventSerializer(competitorSerializer), - new RaceLogWindFixEventSerializer(competitorSerializer, - new WindJsonSerializer( - new PositionJsonSerializer())), - new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), - new RaceLogStartTrackingEventSerializer(competitorSerializer), - new RaceLogRevokeEventSerializer(competitorSerializer), - new RaceLogRegisterCompetitorEventSerializer(competitorSerializer), - new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), - new RaceLogFixedMarkPassingEventSerializer(competitorSerializer), - new RaceLogSuppressedMarkPassingsEventSerializer(competitorSerializer), - new RaceLogDependentStartTimeEventSerializer(competitorSerializer), - new RaceLogStartOfTrackingEventSerializer(competitorSerializer), - new RaceLogUseCompetitorsFromRaceLogEventSerializer(competitorSerializer), - new RaceLogEndOfTrackingEventSerializer(competitorSerializer)); - } - - private final JsonSerializer flagEventSerializer; - private final JsonSerializer startTimeSerializer; - private final JsonSerializer raceStatusSerializer; - private final JsonSerializer courseAreaChangedEventSerializer; - private final JsonSerializer passChangedEventSerializer; - private final JsonSerializer courseDesignChangedEventSerializer; - private final JsonSerializer finishPositioningListChangedEventSerializer; - private final JsonSerializer finishPositioningConfirmedEventSerializer; - private final JsonSerializer pathfinderEventSerializer; - private final JsonSerializer gateLineOpeningTimeEventSerializer; - private final JsonSerializer startProcedureChangedEventSerializer; - private final JsonSerializer protestStartTimeEventSerializer; - private final JsonSerializer windFixEventSerializer; - private final JsonSerializer denoteForTrackingSerializer; - private final JsonSerializer startTrackingSerializer; - private final JsonSerializer revokeSerializer; - private final JsonSerializer registerCompetitorSerializer; - private final JsonSerializer additionalScoringInformationSerializer; - private final JsonSerializer fixedMarkPassingEventSerializer; - private final JsonSerializer suppressedMarkPassingsEventSerializer; - private final JsonSerializer dependentStartTimeEventSerializer; - private final JsonSerializer startOfTrackingEventSerializer; - private final JsonSerializer endOfTrackingEventSerializer; - private final JsonSerializer useCompetitorsFromRaceLogEventSerializer; - - private JsonSerializer chosenSerializer; - - - public RaceLogEventSerializer( - JsonSerializer flagEventSerializer, - JsonSerializer startTimeSerializer, - JsonSerializer raceStatusSerializer, - JsonSerializer courseAreaChangedEventSerializer, - JsonSerializer passChangedEventSerializer, - JsonSerializer courseDesignChangedEventSerializer, - JsonSerializer finishPositioningListChangedEventSerializer, - JsonSerializer finishPositioningConfirmedEventSerializer, - JsonSerializer pathfinderEventSerializer, - JsonSerializer gateLineOpeningTimeEventSerializer, - JsonSerializer startProcedureChangedEventSerializer, - JsonSerializer protestStartTimeEventSerializer, - JsonSerializer windFixEventSerializer, - JsonSerializer denoteForTrackingSerializer, - JsonSerializer createRaceSerializer, - JsonSerializer revokeSerializer, - JsonSerializer registerCompetitorSerializer, - JsonSerializer additionalScoringInformationSerializer, - JsonSerializer fixedMarkPassingEventSerializer, - JsonSerializer suppressedMarkPassingsSerializer, - JsonSerializer dependentStartTimeEventSerializer, - JsonSerializer startOfTrackingEventSerializer, - JsonSerializer endOfTrackingEventSerializer, - JsonSerializer useCompetitorsFromRaceLogEventSerializer) { - this.flagEventSerializer = flagEventSerializer; - this.startTimeSerializer = startTimeSerializer; - this.raceStatusSerializer = raceStatusSerializer; - this.courseAreaChangedEventSerializer = courseAreaChangedEventSerializer; - this.passChangedEventSerializer = passChangedEventSerializer; - this.courseDesignChangedEventSerializer = courseDesignChangedEventSerializer; - this.finishPositioningListChangedEventSerializer = finishPositioningListChangedEventSerializer; - this.finishPositioningConfirmedEventSerializer = finishPositioningConfirmedEventSerializer; - this.pathfinderEventSerializer = pathfinderEventSerializer; - this.gateLineOpeningTimeEventSerializer = gateLineOpeningTimeEventSerializer; - this.startProcedureChangedEventSerializer = startProcedureChangedEventSerializer; - this.protestStartTimeEventSerializer = protestStartTimeEventSerializer; - this.windFixEventSerializer = windFixEventSerializer; - this.denoteForTrackingSerializer = denoteForTrackingSerializer; - this.startTrackingSerializer = createRaceSerializer; - this.revokeSerializer = revokeSerializer; - this.registerCompetitorSerializer = registerCompetitorSerializer; - this.additionalScoringInformationSerializer = additionalScoringInformationSerializer; - this.fixedMarkPassingEventSerializer = fixedMarkPassingEventSerializer; - this.suppressedMarkPassingsEventSerializer = suppressedMarkPassingsSerializer; - this.dependentStartTimeEventSerializer = dependentStartTimeEventSerializer; - this.startOfTrackingEventSerializer = startOfTrackingEventSerializer; - this.endOfTrackingEventSerializer = endOfTrackingEventSerializer; - this.useCompetitorsFromRaceLogEventSerializer = useCompetitorsFromRaceLogEventSerializer; - - this.chosenSerializer = null; - } - - protected JsonSerializer getSerializer(RaceLogEvent event) { - chosenSerializer = null; - event.accept(this); - if (chosenSerializer == null) { - throw new UnsupportedOperationException( - String.format("There is no serializer for event type %s", - event.getClass().getName())); - } - return chosenSerializer; - } - - @Override - public JSONObject serialize(RaceLogEvent object) { - return getSerializer(object).serialize(object); - } - - @Override - public void visit(RaceLogFlagEvent event) { - chosenSerializer = flagEventSerializer; - } - - @Override - public void visit(RaceLogPassChangeEvent event) { - chosenSerializer = passChangedEventSerializer; - } - - @Override - public void visit(RaceLogRaceStatusEvent event) { - chosenSerializer = raceStatusSerializer; - } - - @Override - public void visit(RaceLogStartTimeEvent event) { - chosenSerializer = startTimeSerializer; - } - - @Override - public void visit(RaceLogCourseAreaChangedEvent event) { - chosenSerializer = courseAreaChangedEventSerializer; - } - - @Override - public void visit(RaceLogCourseDesignChangedEvent event) { - chosenSerializer = courseDesignChangedEventSerializer; - } - - @Override - public void visit(RaceLogFinishPositioningListChangedEvent event) { - chosenSerializer = finishPositioningListChangedEventSerializer; - } - - @Override - public void visit(RaceLogFinishPositioningConfirmedEvent event) { - chosenSerializer = finishPositioningConfirmedEventSerializer; - } - - @Override - public void visit(RaceLogPathfinderEvent event) { - chosenSerializer = pathfinderEventSerializer; - } - - @Override - public void visit(RaceLogGateLineOpeningTimeEvent event) { - chosenSerializer = gateLineOpeningTimeEventSerializer; - } - - @Override - public void visit(RaceLogStartProcedureChangedEvent event) { - chosenSerializer = startProcedureChangedEventSerializer; - } - - @Override - public void visit(RaceLogProtestStartTimeEvent event) { - chosenSerializer = protestStartTimeEventSerializer; - } - - @Override - public void visit(RaceLogWindFixEvent event) { - chosenSerializer = windFixEventSerializer; - } - - @Override - public void visit(RaceLogDenoteForTrackingEvent event) { - chosenSerializer = denoteForTrackingSerializer; - } - @Override - public void visit(RaceLogStartTrackingEvent event) { - chosenSerializer = startTrackingSerializer; - } - @Override - public void visit(RaceLogRevokeEvent event) { - chosenSerializer = revokeSerializer; - } - - @Override - public void visit(RaceLogRegisterCompetitorEvent event) { - chosenSerializer = registerCompetitorSerializer; - } - - @Override - public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { - chosenSerializer = registerCompetitorSerializer; - } - - @Override - public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { - chosenSerializer = additionalScoringInformationSerializer; - } - - @Override - public void visit(RaceLogFixedMarkPassingEvent event) { - chosenSerializer = fixedMarkPassingEventSerializer; - } - - @Override - public void visit(RaceLogSuppressedMarkPassingsEvent event) { - chosenSerializer = suppressedMarkPassingsEventSerializer; - } - - @Override - public void visit(RaceLogDependentStartTimeEvent event) { - chosenSerializer = dependentStartTimeEventSerializer; - } - - @Override - public void visit(RaceLogStartOfTrackingEvent event) { - chosenSerializer = startOfTrackingEventSerializer; - } - - @Override - public void visit(RaceLogEndOfTrackingEvent event) { - chosenSerializer = endOfTrackingEventSerializer; - } - - @Override - public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { - chosenSerializer = useCompetitorsFromRaceLogEventSerializer; - } -} +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.ControlPointJsonSerializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseBaseJsonSerializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.DeviceIdentifierJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.SmartphoneUUIDJsonHandler; + +public class RaceLogEventSerializer implements JsonSerializer, RaceLogEventVisitor { + public static JsonSerializer create(JsonSerializer competitorSerializer) { + return create(competitorSerializer, DeviceIdentifierJsonSerializer.create( + new SmartphoneUUIDJsonHandler(), SmartphoneUUIDIdentifier.TYPE)); + } + + public static JsonSerializer create(JsonSerializer competitorSerializer, + JsonSerializer deviceSerializer) { + return new RaceLogEventSerializer( + new RaceLogFlagEventSerializer(competitorSerializer), + new RaceLogStartTimeEventSerializer(competitorSerializer), + new RaceLogRaceStatusEventSerializer(competitorSerializer), + new RaceLogCourseAreaChangedEventSerializer(competitorSerializer), + new RaceLogPassChangeEventSerializer(competitorSerializer), + new RaceLogCourseDesignChangedEventSerializer(competitorSerializer, + new CourseBaseJsonSerializer( + new WaypointJsonSerializer( + new ControlPointJsonSerializer( + new MarkJsonSerializer(), + new GateJsonSerializer(new MarkJsonSerializer()))))), + new RaceLogFinishPositioningListChangedEventSerializer(competitorSerializer), + new RaceLogFinishPositioningConfirmedEventSerializer(competitorSerializer), + new RaceLogPathfinderEventSerializer(competitorSerializer), + new RaceLogGateLineOpeningTimeEventSerializer(competitorSerializer), + new RaceLogStartProcedureChangedEventSerializer(competitorSerializer), + new RaceLogProtestStartTimeEventSerializer(competitorSerializer), + new RaceLogWindFixEventSerializer(competitorSerializer, + new WindJsonSerializer( + new PositionJsonSerializer())), + new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), + new RaceLogStartTrackingEventSerializer(competitorSerializer), + new RaceLogRevokeEventSerializer(competitorSerializer), + new RaceLogRegisterCompetitorEventSerializer(competitorSerializer), + new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), + new RaceLogFixedMarkPassingEventSerializer(competitorSerializer), + new RaceLogSuppressedMarkPassingsEventSerializer(competitorSerializer), + new RaceLogDependentStartTimeEventSerializer(competitorSerializer), + new RaceLogStartOfTrackingEventSerializer(competitorSerializer), + new RaceLogUseCompetitorsFromRaceLogEventSerializer(competitorSerializer), + new RaceLogEndOfTrackingEventSerializer(competitorSerializer)); + } + + private final JsonSerializer flagEventSerializer; + private final JsonSerializer startTimeSerializer; + private final JsonSerializer raceStatusSerializer; + private final JsonSerializer courseAreaChangedEventSerializer; + private final JsonSerializer passChangedEventSerializer; + private final JsonSerializer courseDesignChangedEventSerializer; + private final JsonSerializer finishPositioningListChangedEventSerializer; + private final JsonSerializer finishPositioningConfirmedEventSerializer; + private final JsonSerializer pathfinderEventSerializer; + private final JsonSerializer gateLineOpeningTimeEventSerializer; + private final JsonSerializer startProcedureChangedEventSerializer; + private final JsonSerializer protestStartTimeEventSerializer; + private final JsonSerializer windFixEventSerializer; + private final JsonSerializer denoteForTrackingSerializer; + private final JsonSerializer startTrackingSerializer; + private final JsonSerializer revokeSerializer; + private final JsonSerializer registerCompetitorSerializer; + private final JsonSerializer additionalScoringInformationSerializer; + private final JsonSerializer fixedMarkPassingEventSerializer; + private final JsonSerializer suppressedMarkPassingsEventSerializer; + private final JsonSerializer dependentStartTimeEventSerializer; + private final JsonSerializer startOfTrackingEventSerializer; + private final JsonSerializer endOfTrackingEventSerializer; + private final JsonSerializer useCompetitorsFromRaceLogEventSerializer; + + private JsonSerializer chosenSerializer; + + + public RaceLogEventSerializer( + JsonSerializer flagEventSerializer, + JsonSerializer startTimeSerializer, + JsonSerializer raceStatusSerializer, + JsonSerializer courseAreaChangedEventSerializer, + JsonSerializer passChangedEventSerializer, + JsonSerializer courseDesignChangedEventSerializer, + JsonSerializer finishPositioningListChangedEventSerializer, + JsonSerializer finishPositioningConfirmedEventSerializer, + JsonSerializer pathfinderEventSerializer, + JsonSerializer gateLineOpeningTimeEventSerializer, + JsonSerializer startProcedureChangedEventSerializer, + JsonSerializer protestStartTimeEventSerializer, + JsonSerializer windFixEventSerializer, + JsonSerializer denoteForTrackingSerializer, + JsonSerializer createRaceSerializer, + JsonSerializer revokeSerializer, + JsonSerializer registerCompetitorSerializer, + JsonSerializer additionalScoringInformationSerializer, + JsonSerializer fixedMarkPassingEventSerializer, + JsonSerializer suppressedMarkPassingsSerializer, + JsonSerializer dependentStartTimeEventSerializer, + JsonSerializer startOfTrackingEventSerializer, + JsonSerializer endOfTrackingEventSerializer, + JsonSerializer useCompetitorsFromRaceLogEventSerializer) { + this.flagEventSerializer = flagEventSerializer; + this.startTimeSerializer = startTimeSerializer; + this.raceStatusSerializer = raceStatusSerializer; + this.courseAreaChangedEventSerializer = courseAreaChangedEventSerializer; + this.passChangedEventSerializer = passChangedEventSerializer; + this.courseDesignChangedEventSerializer = courseDesignChangedEventSerializer; + this.finishPositioningListChangedEventSerializer = finishPositioningListChangedEventSerializer; + this.finishPositioningConfirmedEventSerializer = finishPositioningConfirmedEventSerializer; + this.pathfinderEventSerializer = pathfinderEventSerializer; + this.gateLineOpeningTimeEventSerializer = gateLineOpeningTimeEventSerializer; + this.startProcedureChangedEventSerializer = startProcedureChangedEventSerializer; + this.protestStartTimeEventSerializer = protestStartTimeEventSerializer; + this.windFixEventSerializer = windFixEventSerializer; + this.denoteForTrackingSerializer = denoteForTrackingSerializer; + this.startTrackingSerializer = createRaceSerializer; + this.revokeSerializer = revokeSerializer; + this.registerCompetitorSerializer = registerCompetitorSerializer; + this.additionalScoringInformationSerializer = additionalScoringInformationSerializer; + this.fixedMarkPassingEventSerializer = fixedMarkPassingEventSerializer; + this.suppressedMarkPassingsEventSerializer = suppressedMarkPassingsSerializer; + this.dependentStartTimeEventSerializer = dependentStartTimeEventSerializer; + this.startOfTrackingEventSerializer = startOfTrackingEventSerializer; + this.endOfTrackingEventSerializer = endOfTrackingEventSerializer; + this.useCompetitorsFromRaceLogEventSerializer = useCompetitorsFromRaceLogEventSerializer; + + this.chosenSerializer = null; + } + + protected JsonSerializer getSerializer(RaceLogEvent event) { + chosenSerializer = null; + event.accept(this); + if (chosenSerializer == null) { + throw new UnsupportedOperationException( + String.format("There is no serializer for event type %s", + event.getClass().getName())); + } + return chosenSerializer; + } + + @Override + public JSONObject serialize(RaceLogEvent object) { + return getSerializer(object).serialize(object); + } + + @Override + public void visit(RaceLogFlagEvent event) { + chosenSerializer = flagEventSerializer; + } + + @Override + public void visit(RaceLogPassChangeEvent event) { + chosenSerializer = passChangedEventSerializer; + } + + @Override + public void visit(RaceLogRaceStatusEvent event) { + chosenSerializer = raceStatusSerializer; + } + + @Override + public void visit(RaceLogStartTimeEvent event) { + chosenSerializer = startTimeSerializer; + } + + @Override + public void visit(RaceLogCourseAreaChangedEvent event) { + chosenSerializer = courseAreaChangedEventSerializer; + } + + @Override + public void visit(RaceLogCourseDesignChangedEvent event) { + chosenSerializer = courseDesignChangedEventSerializer; + } + + @Override + public void visit(RaceLogFinishPositioningListChangedEvent event) { + chosenSerializer = finishPositioningListChangedEventSerializer; + } + + @Override + public void visit(RaceLogFinishPositioningConfirmedEvent event) { + chosenSerializer = finishPositioningConfirmedEventSerializer; + } + + @Override + public void visit(RaceLogPathfinderEvent event) { + chosenSerializer = pathfinderEventSerializer; + } + + @Override + public void visit(RaceLogGateLineOpeningTimeEvent event) { + chosenSerializer = gateLineOpeningTimeEventSerializer; + } + + @Override + public void visit(RaceLogStartProcedureChangedEvent event) { + chosenSerializer = startProcedureChangedEventSerializer; + } + + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + chosenSerializer = protestStartTimeEventSerializer; + } + + @Override + public void visit(RaceLogWindFixEvent event) { + chosenSerializer = windFixEventSerializer; + } + + @Override + public void visit(RaceLogDenoteForTrackingEvent event) { + chosenSerializer = denoteForTrackingSerializer; + } + @Override + public void visit(RaceLogStartTrackingEvent event) { + chosenSerializer = startTrackingSerializer; + } + @Override + public void visit(RaceLogRevokeEvent event) { + chosenSerializer = revokeSerializer; + } + + @Override + public void visit(RaceLogRegisterCompetitorEvent event) { + chosenSerializer = registerCompetitorSerializer; + } + + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + chosenSerializer = registerCompetitorSerializer; + } + + @Override + public void visit(RaceLogAdditionalScoringInformationEvent additionalScoringInformation) { + chosenSerializer = additionalScoringInformationSerializer; + } + + @Override + public void visit(RaceLogFixedMarkPassingEvent event) { + chosenSerializer = fixedMarkPassingEventSerializer; + } + + @Override + public void visit(RaceLogSuppressedMarkPassingsEvent event) { + chosenSerializer = suppressedMarkPassingsEventSerializer; + } + + @Override + public void visit(RaceLogDependentStartTimeEvent event) { + chosenSerializer = dependentStartTimeEventSerializer; + } + + @Override + public void visit(RaceLogStartOfTrackingEvent event) { + chosenSerializer = startOfTrackingEventSerializer; + } + + @Override + public void visit(RaceLogEndOfTrackingEvent event) { + chosenSerializer = endOfTrackingEventSerializer; + } + + @Override + public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { + chosenSerializer = useCompetitorsFromRaceLogEventSerializer; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java index a1e66936cbe..4fe254c74e1 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java @@ -1,65 +1,65 @@ -package com.sap.sailing.server.gateway.serialization.impl; - -import java.util.Map.Entry; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; -import com.sap.sailing.domain.tracking.Maneuver; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { - public final static String MANEUVERS = "maneuvers"; - - private final CompetitorWithBoatJsonSerializer competitorSerializer; - private final ManeuverJsonSerializer maneuverSerializer; - - public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { - super(); - this.competitorSerializer = competitorSerializer; - this.maneuverSerializer = maneuverSerializer; - } - - @Override - public JSONObject serialize(TrackedRace trackedRace) { - final JSONObject result = new JSONObject(); - JSONArray byCompetitorJson = new JSONArray(); - result.put(BYCOMPETITOR, byCompetitorJson); - for (Entry competitorAndBoatEntry : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { - Competitor competitor = competitorAndBoatEntry.getKey(); - Boat boat = competitorAndBoatEntry.getValue(); - final JSONObject forCompetitorJson = new JSONObject(); - byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); - final JSONArray maneuvers = new JSONArray(); - forCompetitorJson.put(MANEUVERS, maneuvers); - for (final Maneuver maneuver : getManeuversDuringRace(trackedRace, competitor)) { - maneuvers.add(maneuverSerializer.serialize(maneuver)); - } - } - return result; - } - - private Iterable getManeuversDuringRace(TrackedRace trackedRace, Competitor competitor) { - final TimePoint startTime = trackedRace.getStartOfRace(); - final TimePoint endOfRace = trackedRace.getEndOfRace(); - final TimePoint endTime; - if (endOfRace != null) { - endTime = endOfRace; - } else { - final TimePoint endOfTracking = trackedRace.getEndOfTracking(); - if (endOfTracking == null || endOfTracking.after(MillisecondsTimePoint.now())) { - endTime = MillisecondsTimePoint.now(); - } else { - endTime = endOfTracking; - } - } +package com.sap.sailing.server.gateway.serialization.impl; + +import java.util.Map.Entry; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.tracking.Maneuver; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { + public final static String MANEUVERS = "maneuvers"; + + private final CompetitorWithBoatJsonSerializer competitorSerializer; + private final ManeuverJsonSerializer maneuverSerializer; + + public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + super(); + this.competitorSerializer = competitorSerializer; + this.maneuverSerializer = maneuverSerializer; + } + + @Override + public JSONObject serialize(TrackedRace trackedRace) { + final JSONObject result = new JSONObject(); + JSONArray byCompetitorJson = new JSONArray(); + result.put(BYCOMPETITOR, byCompetitorJson); + for (Entry competitorAndBoatEntry : trackedRace.getRace().getCompetitorsAndTheirBoats().entrySet()) { + Competitor competitor = competitorAndBoatEntry.getKey(); + Boat boat = competitorAndBoatEntry.getValue(); + final JSONObject forCompetitorJson = new JSONObject(); + byCompetitorJson.add(forCompetitorJson); + forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); + final JSONArray maneuvers = new JSONArray(); + forCompetitorJson.put(MANEUVERS, maneuvers); + for (final Maneuver maneuver : getManeuversDuringRace(trackedRace, competitor)) { + maneuvers.add(maneuverSerializer.serialize(maneuver)); + } + } + return result; + } + + private Iterable getManeuversDuringRace(TrackedRace trackedRace, Competitor competitor) { + final TimePoint startTime = trackedRace.getStartOfRace(); + final TimePoint endOfRace = trackedRace.getEndOfRace(); + final TimePoint endTime; + if (endOfRace != null) { + endTime = endOfRace; + } else { + final TimePoint endOfTracking = trackedRace.getEndOfTracking(); + if (endOfTracking == null || endOfTracking.after(MillisecondsTimePoint.now())) { + endTime = MillisecondsTimePoint.now(); + } else { + endTime = endOfTracking; + } + } return trackedRace.getManeuvers(competitor, startTime, endTime, /* waitForLatest */ false); - } - -} + } + +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java index 207b07033ce..fe4306be13d 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/CompetitorStoreTest.java @@ -1,121 +1,121 @@ -package com.sap.sailing.server.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicCompetitor; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.test.AbstractLeaderboardTest; -import com.sap.sailing.server.impl.PersistentCompetitorStore; -import com.sap.sse.common.Duration; -import com.sap.sse.common.impl.RGBColor; - -public class CompetitorStoreTest { - @Test - public void testAddingCompetitorsToTransientStore() { - CompetitorStore transientStore = new TransientCompetitorStoreImpl(); - DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); - Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); - assertTrue(competitor != template); - Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - /* timeOnTimeFactor */ 1.345, - /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); - assertSame(competitor, competitor2); - assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); - DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); - differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); - assertSame(competitor, competitor3); // use existing competitor despite the different team - assertSame(competitor.getTeam(), competitor3.getTeam()); - - // now mark the competitor as to update from defaults - transientStore.allowCompetitorResetToDefaults(competitor); - Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); - assertSame(competitor, competitor4); // expecting an in-place update - assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); - } - - @Test - public void testPersistentCompetitorStore() { - CompetitorStore persistentStore1 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); - DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); - Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), - /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); - - CompetitorStore persistentStore2 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); - Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId()); - assertNotSame(competitor2, template); // the new store loads new instances from the database - assertEquals(template.getId(), competitor2.getId()); - assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); - assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); - assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); - - DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); - differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana - Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); - assertSame(competitor2, competitor3); // use existing competitor despite the different team - assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged - assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality - // expected to remain unchanged - // now mark the competitor as to update from defaults - persistentStore2.allowCompetitorResetToDefaults(competitor2); - Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), - template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ - null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); - assertSame(competitor2, competitor4); // expecting an in-place update - assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); - } - - @Test - public void testPersistentBoatStore() { - CompetitorStore persistentStore1 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); - DynamicBoat template = new BoatImpl("id-12345", "Morning Glory", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), - "GER 1234", new RGBColor(255, 0, 0)); - persistentStore1.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), - template.getSailID(), template.getColor()); - - CompetitorStore persistentStore2 = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); - Boat boat2 = persistentStore2.getExistingBoatById(template.getId()); - assertNotSame(boat2, template); // the new store loads new instances from the database - assertEquals(template.getId(), boat2.getId()); - - String differentSailId = "USA 1234"; - Boat boat3 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), - differentSailId, template.getColor()); - assertSame(boat2, boat3); // use existing boat despite the different sailID - assertNotSame(differentSailId, boat2.getSailID()); // sailID expected to remain unchanged - - // now mark the boat as to update from defaults - persistentStore2.allowBoatResetToDefaults(boat2); - Boat boat4 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), - differentSailId, template.getColor()); - assertSame(boat2, boat4); // expecting an in-place update - assertEquals(differentSailId, boat4.getSailID()); - } -} +package com.sap.sailing.server.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.test.AbstractLeaderboardTest; +import com.sap.sailing.server.impl.PersistentCompetitorStore; +import com.sap.sse.common.Duration; +import com.sap.sse.common.impl.RGBColor; + +public class CompetitorStoreTest { + @Test + public void testAddingCompetitorsToTransientStore() { + CompetitorStore transientStore = new TransientCompetitorStoreImpl(); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); + Competitor competitor = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); + assertTrue(competitor != template); + Competitor competitor2 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + /* timeOnTimeFactor */ 1.345, + /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(750.2), null); + assertSame(competitor, competitor2); + assertEquals(DomainFactory.INSTANCE.getOrCreateNationality("GER"), competitor.getTeam().getNationality()); + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + Competitor competitor3 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor, competitor3); // use existing competitor despite the different team + assertSame(competitor.getTeam(), competitor3.getTeam()); + + // now mark the competitor as to update from defaults + transientStore.allowCompetitorResetToDefaults(competitor); + Competitor competitor4 = transientStore.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } + + @Test + public void testPersistentCompetitorStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); + Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + Competitor competitor2 = persistentStore2.getExistingCompetitorById(template.getId()); + assertNotSame(competitor2, template); // the new store loads new instances from the database + assertEquals(template.getId(), competitor2.getId()); + assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); + assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); + assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); + + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor2, competitor3); // use existing competitor despite the different team + assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged + assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality + // expected to remain unchanged + // now mark the competitor as to update from defaults + persistentStore2.allowCompetitorResetToDefaults(competitor2); + Competitor competitor4 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null); + assertSame(competitor2, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } + + @Test + public void testPersistentBoatStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicBoat template = new BoatImpl("id-12345", "Morning Glory", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), + "GER 1234", new RGBColor(255, 0, 0)); + persistentStore1.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + template.getSailID(), template.getColor()); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + Boat boat2 = persistentStore2.getExistingBoatById(template.getId()); + assertNotSame(boat2, template); // the new store loads new instances from the database + assertEquals(template.getId(), boat2.getId()); + + String differentSailId = "USA 1234"; + Boat boat3 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + differentSailId, template.getColor()); + assertSame(boat2, boat3); // use existing boat despite the different sailID + assertNotSame(differentSailId, boat2.getSailID()); // sailID expected to remain unchanged + + // now mark the boat as to update from defaults + persistentStore2.allowBoatResetToDefaults(boat2); + Boat boat4 = persistentStore2.getOrCreateBoat(template.getId(), template.getName(), template.getBoatClass(), + differentSailId, template.getColor()); + assertSame(boat2, boat4); // expecting an in-place update + assertEquals(differentSailId, boat4.getSailID()); + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java index dc15cac3232..7fdc49bc60e 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/AllowBoatResetToDefaults.java @@ -1,46 +1,46 @@ -package com.sap.sailing.server.operationaltransformation; - -import java.util.ArrayList; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.RacingEventServiceOperation; -import com.sap.sse.common.Util; - -public class AllowBoatResetToDefaults extends AbstractRacingEventServiceOperation { - private static final long serialVersionUID = -3698113910122095903L; - private final Iterable boatIdsAsStrings; - - public AllowBoatResetToDefaults(Iterable boatIdsAsStrings) { - super(); - final ArrayList arrayList = new ArrayList<>(); // to guarantee serializability, even if an unmodifiable or singleton is passed - this.boatIdsAsStrings = arrayList; - Util.addAll(boatIdsAsStrings, arrayList); - } - - @Override - public Void internalApplyTo(RacingEventService toState) throws Exception { - final CompetitorStore competitorAndBoatStore = toState.getBaseDomainFactory().getCompetitorStore(); - for (String boatIdAsString : boatIdsAsStrings) { - Boat boat = competitorAndBoatStore.getExistingBoatByIdAsString(boatIdAsString); - if (boat != null) { - competitorAndBoatStore.allowBoatResetToDefaults(boat); - } - } - return null; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} +package com.sap.sailing.server.operationaltransformation; + +import java.util.ArrayList; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.Util; + +public class AllowBoatResetToDefaults extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = -3698113910122095903L; + private final Iterable boatIdsAsStrings; + + public AllowBoatResetToDefaults(Iterable boatIdsAsStrings) { + super(); + final ArrayList arrayList = new ArrayList<>(); // to guarantee serializability, even if an unmodifiable or singleton is passed + this.boatIdsAsStrings = arrayList; + Util.addAll(boatIdsAsStrings, arrayList); + } + + @Override + public Void internalApplyTo(RacingEventService toState) throws Exception { + final CompetitorStore competitorAndBoatStore = toState.getBaseDomainFactory().getCompetitorStore(); + for (String boatIdAsString : boatIdsAsStrings) { + Boat boat = competitorAndBoatStore.getExistingBoatByIdAsString(boatIdAsString); + if (boat != null) { + competitorAndBoatStore.allowBoatResetToDefaults(boat); + } + } + return null; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java index bbcde670d36..9a57cf809bf 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateBoat.java @@ -1,53 +1,53 @@ -package com.sap.sailing.server.operationaltransformation; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.RacingEventServiceOperation; -import com.sap.sse.common.Color; - -public class UpdateBoat extends AbstractRacingEventServiceOperation { - private static final long serialVersionUID = 1341635844670894476L; - private final String idAsString; - private final String newName; - private final Color newColor; - private final String newSailId; - - /** - * @param idAsString - * Identifies the boat to update - */ - public UpdateBoat(String idAsString, String newName, Color newColor, String newSailId) { - super(); - this.idAsString = idAsString; - this.newName = newName; - this.newColor = newColor; - this.newSailId = newSailId; - } - - /** - * {@link #internalApplyTo(RacingEventService)} already replicates the effects - */ - @Override - public boolean isRequiresExplicitTransitiveReplication() { - return false; - } - - @Override - public Boat internalApplyTo(RacingEventService toState) throws Exception { - Boat result = toState.getBaseDomainFactory().getCompetitorStore().updateBoat(idAsString, newName, newColor, newSailId); - return result; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} +package com.sap.sailing.server.operationaltransformation; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.Color; + +public class UpdateBoat extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = 1341635844670894476L; + private final String idAsString; + private final String newName; + private final Color newColor; + private final String newSailId; + + /** + * @param idAsString + * Identifies the boat to update + */ + public UpdateBoat(String idAsString, String newName, Color newColor, String newSailId) { + super(); + this.idAsString = idAsString; + this.newName = newName; + this.newColor = newColor; + this.newSailId = newSailId; + } + + /** + * {@link #internalApplyTo(RacingEventService)} already replicates the effects + */ + @Override + public boolean isRequiresExplicitTransitiveReplication() { + return false; + } + + @Override + public Boat internalApplyTo(RacingEventService toState) throws Exception { + Boat result = toState.getBaseDomainFactory().getCompetitorStore().updateBoat(idAsString, newName, newColor, newSailId); + return result; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java index 46fcd6cfac1..a4f4ce71d39 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/LeaderboardData.java @@ -1,1076 +1,1076 @@ -package com.sap.sailing.xmlexport; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Vector; -import java.util.logging.Logger; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.jdom.Element; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Fleet; -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.SpeedWithConfidence; -import com.sap.sailing.domain.base.impl.SpeedWithConfidenceImpl; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.NauticalSide; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.Tack; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.impl.KnotSpeedImpl; -import com.sap.sailing.domain.common.impl.MeterDistance; -import com.sap.sailing.domain.common.impl.WindSourceImpl; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.LineDetails; -import com.sap.sailing.domain.tracking.Maneuver; -import com.sap.sailing.domain.tracking.TrackedLeg; -import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindPositionMode; -import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.server.RacingEventService; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.impl.MillisecondsDurationImpl; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -/** - * Exports all data from a leaderboard into XML format. - * - * @author Simon Marcel Pamies - */ -public class LeaderboardData extends ExportAction { - - private static final int MAX_EARLY_START_DIFFERENCE = 10*1000; // 10 seconds - - private final Logger log = Logger.getLogger(LeaderboardData.class.getName()); - - private static final String VERY_LIGHT_WIND_DESCRIPTION = "Very Light"; - private static final String LIGHT_WIND_DESCRIPTION = "Light"; - private static final String MEDIUM_WIND_DESCRIPTION = "Medium"; - private static final String MEDIUM_STRONG_WIND_DESCRIPTION = "Medium Strong"; - private static final String STRONG_WIND_DESCRIPTION = "Strong"; - private static final String VERY_STRONG_WIND_DESCRIPTION = "Very Strong"; - - private final Map> raceColumnToCompetitors; - - public LeaderboardData(HttpServletRequest req, HttpServletResponse res, RacingEventService service) { - super(req, res, service); - this.raceColumnToCompetitors = new HashMap<>(); - } - - public LeaderboardData(Leaderboard leaderboard) { - super(leaderboard); - this.raceColumnToCompetitors = new HashMap<>(); - } - - /** - * Creates XML for a leaderboard. Expects a list of generated competitors and races XML elements that are associated with the leaderboard. - *
      -     *  
      -     *     ESS 2014 Qingdao (Extreme40)
      -     *     Qingdao
      -     *     8000
      -     *     HIGH_POINT_FIRST_GETS_TEN
      -     *     Extreme40
      -     *       
      -     *       1.0
      -     *       
      -     *     
      -     *     
      -     *     
      -     *  
      - */ - private Element createLeaderboardXML(Leaderboard leaderboard, List windData, List competitors, List races, Util.Pair> leaderboardConfidenceAndErrorMessages) { - Element leaderboardElement = new Element("leaderboard"); - addNamedElementWithValue(leaderboardElement, "name", leaderboard.getName()); - addNamedElementWithValue(leaderboardElement, "display_name", leaderboard.getDisplayName()); - addNamedElementWithValue(leaderboardElement, "delay_to_live_in_millis", leaderboard.getDelayToLiveInMillis()); - addNamedElementWithValue(leaderboardElement, "scoring_scheme", leaderboard.getScoringScheme().getType().name()); - addNamedElementWithValue(leaderboardElement, "boat_class", getBoatClassName(leaderboard)); - leaderboardElement.addContent(createTimedXML("last_modification_", leaderboard.getTimePointOfLatestModification())); - leaderboardElement.addContent(createDataConfidenceXML(leaderboardConfidenceAndErrorMessages)); - Element windContainer = new Element("wind"); - windContainer.addContent(windData); - leaderboardElement.addContent(windContainer); - leaderboardElement.addContent(competitors); - leaderboardElement.addContent(races); - return leaderboardElement; - } - - /** - * For the given {@link TimePoint} creates elements with several representations - * of that {@link TimePoint}. - *
      -     *   2014
      -     *   4
      -     *   4
      -     *   9
      -     *   3
      -     *   45
      -     *   04.05.2014 09:03:45
      -     *   1399194225000
      -     * 
      - */ - private List createTimedXML(String prefix, TimePoint timepoint) { - List timedElements = new ArrayList(); - Calendar timedDate = Calendar.getInstance(); - if (timepoint != null) { - timedDate.setTime(timepoint.asDate()); - - timedElements.add(createNamedElementWithValue(prefix+"year", timedDate.get(Calendar.YEAR))); - timedElements.add(createNamedElementWithValue(prefix+"month", timedDate.get(Calendar.MONTH))); - timedElements.add(createNamedElementWithValue(prefix+"day", timedDate.get(Calendar.DAY_OF_MONTH))); - timedElements.add(createNamedElementWithValue(prefix+"hour", timedDate.get(Calendar.HOUR_OF_DAY))); - timedElements.add(createNamedElementWithValue(prefix+"minute", timedDate.get(Calendar.MINUTE))); - timedElements.add(createNamedElementWithValue(prefix+"second", timedDate.get(Calendar.SECOND))); - - SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); - timedElements.add(createNamedElementWithValue(prefix+"formatted", dateFormatter.format(timedDate.getTime()))); - timedElements.add(createNamedElementWithValue(prefix+"millis_since_epoch", timepoint.asMillis())); - } else { - timedElements.add(createNamedElementWithValue(prefix+"year", "")); - timedElements.add(createNamedElementWithValue(prefix+"month", "")); - timedElements.add(createNamedElementWithValue(prefix+"day", "")); - timedElements.add(createNamedElementWithValue(prefix+"hour", "")); - timedElements.add(createNamedElementWithValue(prefix+"minute", "")); - timedElements.add(createNamedElementWithValue(prefix+"second", "")); - timedElements.add(createNamedElementWithValue(prefix+"formatted", "")); - timedElements.add(createNamedElementWithValue(prefix+"millis_since_epoch", "")); - } - return timedElements; - } - - /** - * Creates elements related to the given speed fix. Implies that this is related to wind. - *
      -     *       10.985139054212647
      -     *       5.652159186143912
      -     *       4.0
      -     *       0.24242981000649663
      -     *       Medium
      -     *       8-12kn
      -     * 
      - */ - public List createWindXML(String prefix, SpeedWithConfidence speedWithConfidence) { - List windElements = new ArrayList(); - if (speedWithConfidence == null) { - speedWithConfidence = new SpeedWithConfidenceImpl(new KnotSpeedImpl(0.0), 0, MillisecondsTimePoint.now()); - } - windElements.add(createNamedElementWithValue(prefix+"speed_in_knots", speedWithConfidence.getObject().getKnots())); - windElements.add(createNamedElementWithValue(prefix+"speed_in_meters_per_second", speedWithConfidence.getObject().getMetersPerSecond())); - windElements.add(createNamedElementWithValue(prefix+"speed_in_beaufort", Math.rint(speedWithConfidence.getObject().getBeaufort()))); - windElements.add(createNamedElementWithValue(prefix+"confidence", speedWithConfidence.getConfidence())); - - double speedInKnots = speedWithConfidence.getObject().getKnots(); - String windSpeedAsHumanReadableString = ""; - String windSpeedAsInterval = ""; - if (speedInKnots <= 4) { - windSpeedAsHumanReadableString = VERY_LIGHT_WIND_DESCRIPTION; - windSpeedAsInterval = "0-4kn"; - } else if (speedInKnots > 4 && speedInKnots <= 8) { - windSpeedAsHumanReadableString = LIGHT_WIND_DESCRIPTION; - windSpeedAsInterval = "4-8kn"; - } else if (speedInKnots > 8 && speedInKnots <= 12) { - windSpeedAsHumanReadableString = MEDIUM_WIND_DESCRIPTION; - windSpeedAsInterval = "8-12kn"; - } else if (speedInKnots > 12 && speedInKnots <= 16) { - windSpeedAsHumanReadableString = MEDIUM_STRONG_WIND_DESCRIPTION; - windSpeedAsInterval = "12-16kn"; - } else if (speedInKnots > 16 && speedInKnots <= 20) { - windSpeedAsHumanReadableString = STRONG_WIND_DESCRIPTION; - windSpeedAsInterval = "16-20kn"; - } else if (speedInKnots > 20) { - windSpeedAsHumanReadableString = VERY_STRONG_WIND_DESCRIPTION; - windSpeedAsInterval = "20-80kn"; - } - windElements.add(createNamedElementWithValue(prefix+"human_readable", windSpeedAsHumanReadableString)); - windElements.add(createNamedElementWithValue(prefix+"knots_interval", windSpeedAsInterval)); - return windElements; - } - - private Element createRaceXMLWithoutRaceData(final Fleet fleet, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Util.Pair> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { - Element raceElement = new Element("race"); - addNamedElementWithValue(raceElement, "name", column.getName()+'-'+fleet.getName()); - addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter); - addNamedElementWithValue(raceElement, "fleet_name", fleet.getName()); - addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex); - addNamedElementWithValue(raceElement, "is_live", "false"); - TimePoint timepointToBeUsed = MillisecondsTimePoint.now(); - List competitorsForColumn = this.raceColumnToCompetitors.get(column); - if (competitorsForColumn == null) { - competitorsForColumn = new ArrayList<>(); - } - List competitors = leaderboard.getCompetitorsFromBestToWorst(column, timepointToBeUsed); - for (Competitor competitorInLeaderboard : competitors) { - // we must keep track of competitors that we are associated to fleets - // in order to not export the score correction twice. This is needed - // because the score correction does not know about fleets and we do not - // know to which fleet the competitor belongs because no races are linked - if (!competitorsForColumn.contains(competitorInLeaderboard)) { - MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); - if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { - // add this competitor to the list to have him evaluated - Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? - Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); - Element competitorRaceDataElement = new Element("competitor_race_data"); - MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); - addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); - boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitorInLeaderboard, column, timepointToBeUsed); - addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); - Double finalRaceScore = leaderboard.getNetPoints(competitorInLeaderboard, column, timepointToBeUsed); - addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); - competitorElement.addContent(competitorRaceDataElement); - raceElement.addContent(competitorElement); - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitorInLeaderboard.getName() + " has no valid data for this race!", 0.2, raceConfidenceAndErrorMessages); - competitorsForColumn.add(competitorInLeaderboard); - } - } - } - this.raceColumnToCompetitors.put(column, competitorsForColumn); - return raceElement; - } - - /** - * Creates elements containing information about a race - */ - private Element createRaceXML(final TrackedRace race, final Fleet fleet, final List legs, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Util.Pair> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { - Element raceElement = new Element("race"); - addNamedElementWithValue(raceElement, "name", cleanRaceName(race.getRace().getName())); - addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter); - addNamedElementWithValue(raceElement, "fleet_name", fleet.getName()); - addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex); - addNamedElementWithValue(raceElement, "is_live", race.isLive(MillisecondsTimePoint.now()) ? "true" : "false"); - - addNamedElementWithValue(raceElement, "start_type", race.getTrackedLeg(race.getRace().getCourse().getFirstLeg()).getLegType(race.getStartOfRace()).name()); - addNamedElementWithValue(raceElement, "delay_to_live_in_millis", race.getDelayToLiveInMillis()); - addNamedElementWithValue(raceElement, "multiplication_factor", column.getExplicitFactor() == null ? 1.0d : column.getExplicitFactor()); - - addNamedElementWithValue(raceElement, "timepoint_of_last_event_as_millis", handleValue(race.getTimePointOfLastEvent())); - addNamedElementWithValue(raceElement, "timepoint_of_newest_event_as_millis", handleValue(race.getTimePointOfNewestEvent())); - addNamedElementWithValue(raceElement, "timepoint_of_oldest_event_as_millis", handleValue(race.getTimePointOfOldestEvent())); - - if (race.isLive(MillisecondsTimePoint.now())) { - // we can't tell meaningful values about live races - raceElement.addContent(createDataConfidenceXML(raceConfidenceAndErrorMessages)); - raceElement.addContent(legs); - return raceElement; - } - - raceElement.addContent(createTimedXML("start_time_", race.getStartOfRace())); - raceElement.addContent(createTimedXML("end_time_", race.getEndOfRace())); - addNamedElementWithValue(raceElement, "start_of_tracking_time_as_millis", handleValue(race.getStartOfTracking())); - addNamedElementWithValue(raceElement, "end_of_tracking_time_as_millis", handleValue(race.getEndOfTracking())); - - LineDetails start = race.getStartLine(race.getStartOfRace()); - if (start != null) { - if (start.getLength() != null) { - addNamedElementWithValue(raceElement, "start_line_length_in_meters", start.getLength().getMeters()); - } else { - addNamedElementWithValue(raceElement, "start_line_length_in_meters", 0); - } - Distance advantage = start.getAdvantage(); - addNamedElementWithValue(raceElement, "start_advantage_in_meters", advantage != null ? advantage.getMeters() : 0); - NauticalSide nauticalSideWhileApproaching = start.getAdvantageousSideWhileApproachingLine(); - addNamedElementWithValue(raceElement, "advantageous_side_while_approaching_start_line", nauticalSideWhileApproaching != null ? nauticalSideWhileApproaching.name() : "UNKNOWN"); - } else { - addNamedElementWithValue(raceElement, "start_line_length_in_meters", 0); - addNamedElementWithValue(raceElement, "start_advantage_in_meters", 0); - addNamedElementWithValue(raceElement, "advantageous_side_while_approaching_start_line", "UNKNOWN"); - } - - Distance raceCourseLength = race.getCourseLength(); - if (raceCourseLength == null) { - raceConfidenceAndErrorMessages = updateConfidence("Race " + race.getRace().getName() + " has no course length.", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(raceElement, "course_length_in_meters", raceCourseLength != null ? raceCourseLength.getMeters() : 0); - raceElement.addContent(createWindXML("wind_", race.getAverageWindSpeedWithConfidence(/*resolutionInMillis*/ 5*60*1000))); - - final List allCompetitors = race.getCompetitorsFromBestToWorst(/*timePoint*/ race.getEndOfRace()); - addNamedElementWithValue(raceElement, "race_participant_count", allCompetitors.size()); - - boolean isDiscarded = leaderboard.isDiscarded(allCompetitors.get(0), column, race.getEndOfRace()); - addNamedElementWithValue(raceElement, "is_discarded_by_looking_at_first_competitor", isDiscarded == true ? "true" : "false"); - - long numberOfGPSFixes = 0, numberOfWindFixes = 0; - for (Competitor competitor : race.getRace().getCompetitors()) { - GPSFixTrack competitorTrack = race.getTrack(competitor); - competitorTrack.lockForRead(); - try { - numberOfGPSFixes += Util.size(competitorTrack.getRawFixes()); - } finally { - competitorTrack.unlockAfterRead(); - } - } - for (Mark mark : race.getMarks()) { - GPSFixTrack markTrack = race.getOrCreateTrack(mark); - markTrack.lockForRead(); - try { - numberOfGPSFixes += Util.size(markTrack.getRawFixes()); - } finally { - markTrack.unlockAfterRead(); - } - } - for (WindSource windSource : race.getWindSources()) { - // don't count the "virtual" wind sources - if (windSource.canBeStored() || windSource.getType() == WindSourceType.RACECOMMITTEE) { - WindTrack windTrack = race.getOrCreateWindTrack(windSource); - windTrack.lockForRead(); - try { - numberOfWindFixes += Util.size(windTrack.getRawFixes()); - } finally { - windTrack.unlockAfterRead(); - } - } - } - addNamedElementWithValue(raceElement, "numberOfGPSFixes", numberOfGPSFixes); - addNamedElementWithValue(raceElement, "numberOfWindFixes", numberOfWindFixes); - - // sort competitors according to their distance to the starboard side of the start line - List allCompetitorsSortedByDistanceToStarboardSide = new ArrayList(allCompetitors.size()); - allCompetitorsSortedByDistanceToStarboardSide.addAll(allCompetitors); - Collections.sort(allCompetitorsSortedByDistanceToStarboardSide, new Comparator() { - @Override - public int compare(Competitor o1, Competitor o2) { - Distance o1Distance = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o1); - Distance o2Distance = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o2); - if (o1Distance != null && o2Distance != null) { - return o1Distance.compareTo(o2Distance); - } else if (o1Distance == null && o2Distance == null) { - return 0; - } else { - // one of the distances is null - we can't really tell - // which competitor is better in terms of sorting but we can try - // by giving the competitor that has a null value a very big distance - if (o1Distance == null) { - return new MeterDistance(100000).compareTo(o2Distance); - } else { - return o1Distance.compareTo(new MeterDistance(100000)); - } - } - } - }); - - Map competitorToDistanceRank = new HashMap(); - int raceRankSorted = 0; - for (Competitor competitorSorted : allCompetitorsSortedByDistanceToStarboardSide) { - raceRankSorted += 1; - competitorToDistanceRank.put(competitorSorted, raceRankSorted); - } - - List competitorsForColumn = this.raceColumnToCompetitors.get(column); - if (competitorsForColumn == null) { - competitorsForColumn = new ArrayList<>(); - } - // it can happen that there are competitors that did not race but got points - int additionalCompetitorCount = 0; - for (Competitor competitorInLeaderboard : leaderboard.getAllCompetitors()) { - if (!allCompetitors.contains(competitorInLeaderboard)) { - // found a competitor that is available in leaderboard but not in that race - // check if he has an overwritten score for that race - MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, race.getEndOfRace()); - Fleet fleetCompetitorIsSailingIn = column.getFleetOfCompetitor(competitorInLeaderboard); - if (fleetCompetitorIsSailingIn != null && fleetCompetitorIsSailingIn.equals(fleet) && !competitorsForColumn.contains(competitorInLeaderboard)) { - if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { - // add this competitor to the list to have him evaluated - Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitorInLeaderboard, column, fleetCompetitorIsSailingIn); - Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); - Element competitorRaceDataElement = new Element("competitor_race_data"); - MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, race.getEndOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); - boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitorInLeaderboard, column, race.getEndOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); - Double finalRaceScore = leaderboard.getNetPoints(competitorInLeaderboard, column, race.getEndOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); - competitorElement.addContent(competitorRaceDataElement); - raceElement.addContent(competitorElement); - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitorInLeaderboard.getName() + " has no valid data for this race!", 0.2, raceConfidenceAndErrorMessages); - additionalCompetitorCount++; - competitorsForColumn.add(competitorInLeaderboard); - } - } - } - } - addNamedElementWithValue(raceElement, "race_score_participant_count", allCompetitors.size()+additionalCompetitorCount); - - int raceRank = 0; - for (Competitor competitor : allCompetitors) { - Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? - Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); - Element competitorRaceDataElement = new Element("competitor_race_data"); - MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, column, race.getEndOfRace()); - if (maxPointsReason != null && !maxPointsReason.equals(MaxPointsReason.NONE)) { - competitorsForColumn.add(competitor); - } - addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); - boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitor, column, race.getEndOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); - Double finalRaceScore = leaderboard.getNetPoints(competitor, column, race.getEndOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); - if (maxPointsReason.equals(MaxPointsReason.DNS) || race.getMarkPassings(competitor).isEmpty()) { - // we do not want to include competitors that did not start the race - competitorElement.addContent(competitorRaceDataElement); - raceElement.addContent(competitorElement); - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid data for this race!", 0.1, raceConfidenceAndErrorMessages); - continue; - } - - Iterable maneuvers = getManeuvers(race, competitor, /*waitForLatest*/ false); - addNamedElementWithValue(competitorRaceDataElement, "number_of_maneuvers", maneuvers != null ? Util.size(maneuvers) : 0); - addNamedElementWithValue(competitorRaceDataElement, "number_of_tacks", getNumberOfTacks(maneuvers)); - addNamedElementWithValue(competitorRaceDataElement, "number_of_jibes", getNumberOfJibes(maneuvers)); - addNamedElementWithValue(competitorRaceDataElement, "number_of_penalty_circles", getNumberOfPenaltyCircles(maneuvers)); - - GPSFixTrack gpsFixesForCompetitor = race.getTrack(competitor); - if (gpsFixesForCompetitor != null) { - Duration averageInterval = gpsFixesForCompetitor.getAverageIntervalBetweenFixes(); - if (averageInterval != null) { - addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_outliers_removed_as_millis", averageInterval.asMillis()); - } - Duration averageIntervallRaw = gpsFixesForCompetitor.getAverageIntervalBetweenRawFixes(); - if (averageIntervallRaw != null) { - addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_raw_as_millis", averageIntervallRaw.asMillis()); - } - } else { - addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_outliers_removed_as_millis", 0); - addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_raw_as_millis", 0); - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid gps track for this race!", 0.5, raceConfidenceAndErrorMessages); - } - - int[] timePointsInSecondsBeforeStart = new int[]{0, 5, 10, 20, 30}; - for (int i : timePointsInSecondsBeforeStart) { - TimePoint beforeRaceStartTime = race.getStartOfRace().minus(i*1000); - Distance distanceToStartLineBeforeStart = race.getDistanceToStartLine(competitor, beforeRaceStartTime); - if (distanceToStartLineBeforeStart == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance to startline " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_"+i+"seconds_before_start_in_meters", distanceToStartLineBeforeStart != null ? distanceToStartLineBeforeStart.getMeters() : 0); - Speed estimatedSpeedBeforeStarttime = race.getTrack(competitor).getEstimatedSpeed(beforeRaceStartTime); - if (estimatedSpeedBeforeStarttime == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "speed_"+i+"seconds_before_start_of_race_in_knots", estimatedSpeedBeforeStarttime != null ? estimatedSpeedBeforeStarttime.getKnots() : 0); - - Distance distanceToStarboardSide = race.getDistanceFromStarboardSideOfStartLine(competitor, beforeRaceStartTime); - if (distanceToStarboardSide == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance to starboard side " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_"+i+"seconds_before_start_in_meters", distanceToStarboardSide != null ? distanceToStarboardSide.getMeters() : 0); - - LineDetails raceStartLine = race.getStartLine(beforeRaceStartTime); - if (raceStartLine == null) { - addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_port_mark_to_starboard_mark"+i+"seconds_before_start_in_degrees", 0); - addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_projected_position_to_starboard_mark"+i+"seconds_before_start_in_degrees", 0); - addNamedElementWithValue(competitorRaceDataElement, "bearing_to_starboard_mark_"+i+"seconds_before_start_in_degrees", 0); - addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "false"); - addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", 0); - addNamedElementWithValue(competitorRaceDataElement, "projected_position_onto_startline_"+i+"seconds_before_start", 0); - raceConfidenceAndErrorMessages = updateConfidence("Race " + race.getRace().getName() + " has no valid startline! Data related to startline will be wrong.", 0.2, raceConfidenceAndErrorMessages); - } else { - Iterator marksForStartLine = race.getStartLine(beforeRaceStartTime).getWaypoint().getControlPoint().getMarks().iterator(); - Mark first = marksForStartLine.next(); - Mark second = null; - if (marksForStartLine.hasNext()) { - second = marksForStartLine.next(); - Position firstMarkPosition = race.getOrCreateTrack(first).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); - Position secondMarkPosition = race.getOrCreateTrack(second).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); - Position competitorPosition = race.getTrack(competitor).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); - if (firstMarkPosition != null && secondMarkPosition != null) { - Position projectedCompetitorPositionOntoStartLine = getOrthogonalProjectionOntoLine( - competitorPosition, - firstMarkPosition, - secondMarkPosition - ); - // now compute the distance from starboard mark - Mark starboardMark = race.getStartLine(beforeRaceStartTime).getStarboardMarkWhileApproachingLine(); - Mark portMark = null; - if (starboardMark.equals(first)) { - portMark = second; - } else { - portMark = first; - } - Position portMarkPosition = race.getOrCreateTrack(portMark).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); - Position starboardMarkPosition = race.getOrCreateTrack(starboardMark).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); - Distance projectedDistance = projectedCompetitorPositionOntoStartLine.getDistance(starboardMarkPosition); - Bearing bearingToStarboardMarkFromCompetitorPosition = competitorPosition.getBearingGreatCircle(starboardMarkPosition); - Bearing bearingFromPortToStarboardMark = portMarkPosition.getBearingGreatCircle(starboardMarkPosition); - Bearing bearingFromProjectedCompetitorPositionToStarboardMark = projectedCompetitorPositionOntoStartLine.getBearingGreatCircle(starboardMarkPosition); - addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_port_mark_to_starboard_mark"+i+"seconds_before_start_in_degrees", bearingFromPortToStarboardMark.getDegrees()); - addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_projected_position_to_starboard_mark"+i+"seconds_before_start_in_degrees", bearingFromProjectedCompetitorPositionToStarboardMark.getDegrees()); - addNamedElementWithValue(competitorRaceDataElement, "bearing_to_starboard_mark_"+i+"seconds_before_start_in_degrees", bearingToStarboardMarkFromCompetitorPosition.getDegrees()); - if (Math.rint(bearingFromPortToStarboardMark.getDegrees()) == Math.rint(bearingFromProjectedCompetitorPositionToStarboardMark.getDegrees())) { - addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "true"); - addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", projectedDistance.getMeters()); - } else { - addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "false"); - addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", 0-projectedDistance.getMeters()); - } - addNamedElementWithValue(competitorRaceDataElement, "projected_position_onto_startline_"+i+"seconds_before_start", projectedCompetitorPositionOntoStartLine.toString()); - } - } - } - } - Tack startTack = race.getTack(competitor, race.getStartOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "start_tack", startTack != null ? startTack.name() : "UNKNOWN"); - LineDetails startLine = race.getStartLine(race.getStartOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "starboard_mark_name", startLine != null ? startLine.getStarboardMarkWhileApproachingLine().getName() : "UNKNOWN"); - Distance distanceToStartLine = race.getDistanceToStartLine(competitor, race.getStartOfRace()); - addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_on_race_start_in_meters", distanceToStartLine != null ? distanceToStartLine.getMeters() : 0); - Speed estimatedSpeedAtStartSignal = race.getTrack(competitor).getEstimatedSpeed(race.getStartOfRace()); - if (estimatedSpeedAtStartSignal == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed at start for this race!", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "speed_on_start_signal_of_race_in_knots", estimatedSpeedAtStartSignal != null ? estimatedSpeedAtStartSignal.getKnots() : 0); - Distance distanceFromStarboardSideWhenPassingStart = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(competitor); - if (distanceFromStarboardSideWhenPassingStart == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance from line at start for this race!", 0.1, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_when_passing_start_in_meters", distanceFromStarboardSideWhenPassingStart != null ? distanceFromStarboardSideWhenPassingStart.getMeters() : 0); - addNamedElementWithValue(competitorRaceDataElement, "rank_based_on_distance_from_starboard_side_of_start_line", competitorToDistanceRank.get(competitor)); - Speed speedWhenCrossingStartline = race.getSpeedWhenCrossingStartLine(competitor); - if (speedWhenCrossingStartline == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed when passing startline for this race!", 0.2, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "speed_when_crossing_start_line_in_knots", speedWhenCrossingStartline != null ? speedWhenCrossingStartline.getKnots() : 0); - com.sap.sse.common.Util.Triple gpsFixWithSpeedAndLegInformation = getMaximumSpeedOverGround(competitor, race); - if (gpsFixWithSpeedAndLegInformation != null && gpsFixWithSpeedAndLegInformation.getB() != null) { - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_in_knots", gpsFixWithSpeedAndLegInformation.getB().getKnots()); - competitorRaceDataElement.addContent(createTimedXML("maximum_race_speed_measured_at_", gpsFixWithSpeedAndLegInformation.getA().getTimePoint())); - if (gpsFixWithSpeedAndLegInformation.getC() != null) { - // check which leg number it is - int legCounterForMaxSpeed = 0; - for (Leg leg : race.getRace().getCourse().getLegs()) { - legCounterForMaxSpeed++; - if (leg.equals(gpsFixWithSpeedAndLegInformation.getC().getLeg())) { - break; - } - } - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", legCounterForMaxSpeed); - TrackedLeg trackedLegWithTypeInformation = gpsFixWithSpeedAndLegInformation.getC().getTrackedLeg(); - if (trackedLegWithTypeInformation != null) { - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", trackedLegWithTypeInformation.getLegType(gpsFixWithSpeedAndLegInformation.getA().getTimePoint()).name()); - } else { - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", "UNKNOWN"); - } - } else { - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", 0); - } - } else { - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_in_knots", 0.0); - competitorRaceDataElement.addContent(createTimedXML("maximum_race_speed_measured_at_", race.getStartOfRace())); - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", "UNKNOWN"); - addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", 0); - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid maximum speed for this race!", 0.5, raceConfidenceAndErrorMessages); - } - Distance distanceTraveledInThisRace = race.getDistanceTraveled(competitor, race.getEndOfRace()); - if (distanceTraveledInThisRace == null) { - raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance traveled for this race! Check distance traveled including non finished legs.", 0.3, raceConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorRaceDataElement, "distance_traveled_in_meters", distanceTraveledInThisRace == null ? 0.0 : distanceTraveledInThisRace.getMeters()); - addNamedElementWithValue(competitorRaceDataElement, "distance_traveled_including_non_finished_legs_in_meters", getDistanceTraveled(race, competitor, race.getEndOfRace(), /*alsoReturnDistanceIfCompetitorHasNotFinishedRace*/ true).getMeters()); - Speed averageSpeedOverGround = getAverageSpeedOverGround(race, competitor, race.getEndOfRace(), true); - addNamedElementWithValue(competitorRaceDataElement, "average_speed_over_ground_in_knots", averageSpeedOverGround == null ? 0.0 : averageSpeedOverGround.getKnots()); - addNamedElementWithValue(competitorRaceDataElement, "final_race_rank", ++raceRank); - TrackedLegOfCompetitor trackedLegOfCompetitor = race.getTrackedLeg(competitor, race.getRace().getCourse().getFirstLeg()); - if (trackedLegOfCompetitor != null && trackedLegOfCompetitor.getFinishTime() != null) { - addNamedElementWithValue(competitorRaceDataElement, "rank_at_end_of_first_leg", trackedLegOfCompetitor.getRank(trackedLegOfCompetitor.getFinishTime())); - } else { - addNamedElementWithValue(competitorRaceDataElement, "rank_at_end_of_first_leg", 0); - raceConfidenceAndErrorMessages = updateConfidence("It seems that competitor " + competitor.getName() + " has not finished first leg!", 0.1, raceConfidenceAndErrorMessages); - } - Distance averageCrossTrackError = race.getAverageAbsoluteCrossTrackError(competitor, race.getStartOfRace(), race.getEndOfRace(), /*upwindOnly*/ false, /*waitForLatestAnalysis*/ false); - addNamedElementWithValue(competitorRaceDataElement, "average_cross_track_error_in_meters", averageCrossTrackError != null ? averageCrossTrackError.getMeters() : -1.0); - Distance averageSignedCrossTrackError = race.getAverageSignedCrossTrackError(competitor, race.getStartOfRace(), race.getEndOfRace(), /*upwindOnly*/ false, /*waitForLatestAnalysis*/ false); - addNamedElementWithValue(competitorRaceDataElement, "average_signed_cross_track_error_in_meters", averageSignedCrossTrackError != null ? averageSignedCrossTrackError.getMeters() : -1.0); - competitorElement.addContent(competitorRaceDataElement); - raceElement.addContent(competitorElement); - } - - this.raceColumnToCompetitors.put(column, competitorsForColumn); - raceElement.addContent(createDataConfidenceXML(raceConfidenceAndErrorMessages)); - raceElement.addContent(legs); - return raceElement; - } - - /** - * Creates xml elements related to a competitor. - * @param shortVersion when set to true then only the name and UUID is returned - */ - private Element createCompetitorXML(Competitor competitor, Boat boatOfCompetitor, Leaderboard leaderboard, - boolean shortVersion, Util.Pair> competitorConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { - TimePoint timeSpent = MillisecondsTimePoint.now(); - Element competitorElement = new Element("competitor"); - addNamedElementWithValue(competitorElement, "uuid", competitor.getId().toString()); - addNamedElementWithValue(competitorElement, "name", competitor.getName()); - - if (shortVersion) - return competitorElement; - - if (boatOfCompetitor != null) { - addNamedElementWithValue(competitorElement, "sail_id", cleanSailId(boatOfCompetitor.getSailID(), competitor)); - addNamedElementWithValue(competitorElement, "boat_class", boatOfCompetitor.getBoatClass().getName()); - addNamedElementWithValue(competitorElement, "boat_name", boatOfCompetitor.getName()); - } else { - addNamedElementWithValue(competitorElement, "sail_id", ""); - addNamedElementWithValue(competitorElement, "boat_class", ""); - addNamedElementWithValue(competitorElement, "boat_name", ""); - } - - if (competitor.getTeam() != null && competitor.getTeam().getNationality() != null) { - addNamedElementWithValue(competitorElement, "nationality_name", competitor.getTeam().getNationality().getName()); - addNamedElementWithValue(competitorElement, "nationality_ioc", competitor.getTeam().getNationality().getThreeLetterIOCAcronym()); - } else { - addNamedElementWithValue(competitorElement, "nationality_name", ""); - addNamedElementWithValue(competitorElement, "nationality_ioc", ""); - } - - // determine the last race and take the timepoint from there - TimePoint timePointOfLatestModification = null; - RaceColumn lastRaceColumnWithTrackedRace = null; - for (RaceColumn column : leaderboard.getRaceColumns()) { - if (column.hasTrackedRaces()) { - lastRaceColumnWithTrackedRace = column; - } - } - TimePoint endOfRaceForLastTrackedRaceInLeaderboard = null; - if (lastRaceColumnWithTrackedRace != null) { - TrackedRace lastTrackedRace = lastRaceColumnWithTrackedRace.getTrackedRace(competitor); - if (lastTrackedRace != null) { - endOfRaceForLastTrackedRaceInLeaderboard = lastTrackedRace.getEndOfRace(); - } else { - // can happen that for this competitor there is no tracked race - // leave time null so that leaderboard latest modification time - // will kick in - } - } - // first look for latest modification of leaderboard - // if there is no latest modification then take the last races time - if (leaderboard.getTimePointOfLatestModification() != null) { - timePointOfLatestModification = leaderboard.getTimePointOfLatestModification(); - } else { - if (endOfRaceForLastTrackedRaceInLeaderboard != null) { - timePointOfLatestModification = endOfRaceForLastTrackedRaceInLeaderboard; - } else { - // make sure that the timepoint is far in the future - could be that the export is called too early - timePointOfLatestModification = MillisecondsTimePoint.now().plus(Duration.ONE_YEAR); - } - } - Duration totalTimeSailed = leaderboard.getTotalTimeSailed(competitor, timePointOfLatestModification); - if (totalTimeSailed != null) { - addNamedElementWithValue(competitorElement, "total_time_sailed_in_milliseconds", totalTimeSailed.asMillis()); - } else { - addNamedElementWithValue(competitorElement, "total_time_sailed_in_milliseconds", 0); - } - addNamedElementWithValue(competitorElement, "total_time_sailed_including_non_finished_races_in_milliseconds", getTotalTimeSailedInMilliseconds(competitor, timePointOfLatestModification, true)); - Distance totalDistanceSailed = leaderboard.getTotalDistanceTraveled(competitor, timePointOfLatestModification); - if (totalDistanceSailed == null) { - competitorConfidenceAndErrorMessages = updateConfidence("Competitor has not finished all races in this leaderboard! His distance sailed is not comparable to others!", 0.1, competitorConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorElement, "total_distance_sailed_in_meters", totalDistanceSailed != null ? totalDistanceSailed.getMeters() : 0); - Distance totalDistanceSailedIncludingNonFinishedRaces = getTotalDistanceTraveled(leaderboard, competitor, timePointOfLatestModification); - addNamedElementWithValue(competitorElement, "total_distance_sailed_including_non_finished_races_in_meters", totalDistanceSailedIncludingNonFinishedRaces != null ? totalDistanceSailedIncludingNonFinishedRaces.getMeters() : 0); - Pair maximumLeaderboardSpeedOverGround = leaderboard.getMaximumSpeedOverGround(competitor, timePointOfLatestModification); - addNamedElementWithValue(competitorElement, "maximum_speed_over_ground_in_knots", maximumLeaderboardSpeedOverGround != null ? maximumLeaderboardSpeedOverGround.getB().getKnots() : 0); - Speed averageSpeed = leaderboard.getAverageSpeedOverGround(competitor, timePointOfLatestModification); - if (averageSpeed == null) { - competitorConfidenceAndErrorMessages = updateConfidence("Competitor has not finished all races in this leaderboard! His average speed over ground is not comparable to others!", 0.1, competitorConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorElement, "average_speed_over_ground_from_start_mark_passing_in_knots", averageSpeed != null ? averageSpeed.getKnots() : 0); - Speed averageSpeedOverGroundIncludingNonCompletedRaces = getAverageSpeedOverGround(leaderboard, competitor, timePointOfLatestModification, true); - addNamedElementWithValue(competitorElement, "average_speed_over_ground_including_non_finished_races_in_knots", averageSpeedOverGroundIncludingNonCompletedRaces == null ? 0 : averageSpeedOverGroundIncludingNonCompletedRaces.getKnots()); - addNamedElementWithValue(competitorElement, "overall_rank", leaderboard.getTotalRankOfCompetitor(competitor, timePointOfLatestModification)); - addNamedElementWithValue(competitorElement, "overall_score", leaderboard.getNetPoints(competitor, timePointOfLatestModification)); - competitorElement.addContent(createDataConfidenceXML(competitorConfidenceAndErrorMessages)); - TimePoint elapsedTime = MillisecondsTimePoint.now().minus(timeSpent.asMillis()); - addNamedElementWithValue(competitorElement, "generation_time_in_milliseconds", elapsedTime.asMillis()); - return competitorElement; - } - - /** - * Create xml elements related to a leg. - */ - private Element createLegXML(TrackedLeg trackedLeg, Leaderboard leaderboard, int legCounter, - Util.Pair> raceConfidenceAndErrorMessages, - Util.Pair> legConfidenceAndErrorMessages) throws NoWindException, IOException, - ServletException { - TimePoint timeSpent = MillisecondsTimePoint.now(); - Leg leg = trackedLeg.getLeg(); - Element legElement = new Element("leg"); - legElement.addContent(createDataConfidenceXML(legConfidenceAndErrorMessages)); - if (trackedLeg.getTrackedRace().isLive(MillisecondsTimePoint.now())) { - return legElement; - } - addNamedElementWithValue(legElement, "position", legCounter); - addNamedElementWithValue(legElement, "mark_from", leg.getFrom().getName()); - addNamedElementWithValue(legElement, "mark_to", leg.getTo().getName()); - addNamedElementWithValue(legElement, "leg_type", trackedLeg.getLegType(trackedLeg.getTrackedRace().getStartOfRace()).name()); - addNamedElementWithValue(legElement, "great_circle_distance_at_start_of_race_in_meters", trackedLeg.getGreatCircleDistance(trackedLeg.getTrackedRace().getStartOfRace()).getMeters()); - addNamedElementWithValue(legElement, "great_circle_distance_at_end_of_race_in_meters", trackedLeg.getGreatCircleDistance(trackedLeg.getTrackedRace().getEndOfRace()).getMeters()); - - for (Competitor competitor : trackedLeg.getTrackedRace().getCompetitorsFromBestToWorst(/*timePoint*/ trackedLeg.getTrackedRace().getEndOfRace())) { - Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? - Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); - Element competitorLegDataElement = new Element("competitor_leg_data"); - TrackedLegOfCompetitor competitorLeg = trackedLeg.getTrackedLeg(competitor); - - /* if there is no start time then ignore all data of this leg */ - if (competitorLeg == null || competitorLeg.getStartTime() == null || competitorLeg.getFinishTime() == null || competitorLeg.getTrackedLeg().getTrackedRace().getMarkPassings(competitor).isEmpty()) { - competitorElement.addContent(competitorLegDataElement); - legElement.addContent(competitorElement); - continue; - } - TimePoint legFinishTime = competitorLeg.getFinishTime(); - final RankingInfo rankingMetricAtLegFinishTime = trackedLeg.getTrackedRace().getRankingMetric().getRankingInfo(legFinishTime); - competitorLegDataElement.addContent(createTimedXML("leg_started_time_", competitorLeg.getStartTime())); - Util.Pair maximumSpeed = competitorLeg.getMaximumSpeedOverGround(legFinishTime); - addNamedElementWithValue(competitorLegDataElement, "maximum_speed_over_ground_in_knots", maximumSpeed != null ? maximumSpeed.getB().getKnots() : -1); - if (maximumSpeed == null) { - legConfidenceAndErrorMessages = updateConfidence("Competitor "+ competitor.getName() +" has not finished this leg! His maximum speed for this leg is not comparable to others!", 0.1, legConfidenceAndErrorMessages); - } - Speed averageVelocityMadeGood = competitorLeg.getAverageVelocityMadeGood(legFinishTime); - addNamedElementWithValue(competitorLegDataElement, "average_velocity_made_good_in_knots", averageVelocityMadeGood != null ? averageVelocityMadeGood.getKnots() : 0); - addNamedElementWithValue(competitorLegDataElement, "leg_finished_time_as_millis", handleValue(legFinishTime)); - addNamedElementWithValue(competitorLegDataElement, "total_race_time_elapsed_as_millis", handleValue(legFinishTime)-handleValue(trackedLeg.getTrackedRace().getStartOfRace())); - Duration timeSpentInThisLeg = competitorLeg.getTime(legFinishTime); - if (timeSpentInThisLeg == null) { - legConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " seems to not have finished this leg before end of tracking time.", 0.1, legConfidenceAndErrorMessages); - } - addNamedElementWithValue(competitorLegDataElement, "time_spend_in_this_leg_as_millis", timeSpentInThisLeg != null ? timeSpentInThisLeg.asMillis() : new MillisecondsDurationImpl(0).asMillis()); - addNamedElementWithValue(competitorLegDataElement, "gap_to_leader_at_finish_in_seconds", competitorLeg.getGapToLeader(legFinishTime, rankingMetricAtLegFinishTime, WindPositionMode.LEG_MIDDLE).asSeconds()); - Distance windwardDistanceToCompetitorFarthestAhead = competitorLeg.getWindwardDistanceToCompetitorFarthestAhead(legFinishTime, WindPositionMode.LEG_MIDDLE, rankingMetricAtLegFinishTime); - // TODO bug1018 decide whether the following field should be renamed to express that it's not the distance to the "leader" but the competitor farthest ahead; discussed with Simon on 2015-05-28; Simon says we leave it like this for now - addNamedElementWithValue(competitorLegDataElement, "windward_distance_to_overall_leader_that_has_finished_this_leg_in_meters", windwardDistanceToCompetitorFarthestAhead != null ? windwardDistanceToCompetitorFarthestAhead.getMeters() : 0); - addNamedElementWithValue(competitorLegDataElement, "distance_traveled_in_meters", competitorLeg.getDistanceTraveled(legFinishTime).getMeters()); - addNamedElementWithValue(competitorLegDataElement, "average_speed_over_ground_in_knots", competitorLeg.getAverageSpeedOverGround(legFinishTime).getKnots()); - - addNamedElementWithValue(competitorLegDataElement, "number_of_jibes", competitorLeg.getNumberOfJibes(legFinishTime, /* waitForLatest */ false)); - addNamedElementWithValue(competitorLegDataElement, "number_of_tacks", competitorLeg.getNumberOfTacks(legFinishTime, /* waitForLatest */ false)); - addNamedElementWithValue(competitorLegDataElement, "number_of_penalty_circles", competitorLeg.getNumberOfPenaltyCircles(legFinishTime, /* waitForLatest */ false)); - - addNamedElementWithValue(competitorLegDataElement, "leg_rank_at_leg_start", competitorLeg.getRank(competitorLeg.getStartTime())); - addNamedElementWithValue(competitorLegDataElement, "leg_rank_at_leg_finish", competitorLeg.getRank(legFinishTime)); - - if (legCounter>1) { - final TrackedLegOfCompetitor previousLeg = competitorLeg.getTrackedLeg().getTrackedRace().getTrackedLegFinishingAt(competitorLeg.getLeg().getFrom()).getTrackedLeg(competitor); - addNamedElementWithValue(competitorLegDataElement, "rank_gain_for_this_leg_between_start_and_finish", previousLeg.getRank(previousLeg.getFinishTime())-competitorLeg.getRank(legFinishTime)); - } else { - addNamedElementWithValue(competitorLegDataElement, "rank_gain_for_this_leg_between_start_and_finish", 0); - } - - Iterable maneuvers = competitorLeg.getManeuvers(legFinishTime, /*waitForLatest*/false); - addNamedElementWithValue(competitorLegDataElement, "maneuver_count", Util.size(maneuvers)); - Element maneuversElement = new Element("maneuvers"); - int maneuverCounter = 0; - for (Maneuver man : maneuvers) { - maneuverCounter += 1; - Element maneuverInformation = new Element("maneuver"); - addNamedElementWithValue(maneuverInformation, "type", man.getType().toString()); - addNamedElementWithValue(maneuverInformation, "position", maneuverCounter); - addNamedElementWithValue(maneuverInformation, "direction_change_in_degrees", man.getDirectionChangeInDegrees()); - Distance maneuverLoss = man.getManeuverLoss(); - addNamedElementWithValue(maneuverInformation, "loss_in_meters", maneuverLoss != null ? maneuverLoss.getMeters() : 0.0); - addNamedElementWithValue(maneuverInformation, "speed_before_in_knots", man.getSpeedWithBearingBefore().getKnots()); - addNamedElementWithValue(maneuverInformation, "speed_after_in_knots", man.getSpeedWithBearingAfter().getKnots()); - maneuversElement.addContent(maneuverInformation); - } - competitorLegDataElement.addContent(maneuversElement); - - Distance averageCrossTrackError = competitorLeg.getAverageAbsoluteCrossTrackError(legFinishTime, /*waitForLatestAnalysis*/ false); - addNamedElementWithValue(competitorLegDataElement, "average_cross_track_error_in_meters", averageCrossTrackError != null ? averageCrossTrackError.getMeters() : -1); - Distance averageSignedCrossTrackError = competitorLeg.getAverageSignedCrossTrackError(legFinishTime, /*waitForLatestAnalysis*/ false); - addNamedElementWithValue(competitorLegDataElement, "average_signed_cross_track_error_in_meters", averageSignedCrossTrackError != null ? averageSignedCrossTrackError.getMeters() : -1); - - competitorElement.addContent(competitorLegDataElement); - legElement.addContent(competitorElement); - } - TimePoint elapsedTime = MillisecondsTimePoint.now().minus(timeSpent.asMillis()); - addNamedElementWithValue(legElement, "generation_time_in_milliseconds", elapsedTime.asMillis()); - return legElement; - } - - private List createFullWindDataXML(TrackedRace race, Fleet fleet, int sameDayIndex) { - final List windElements = new ArrayList<>(); - final List windSourcesToDeliver = new ArrayList(); - final WindSource windSource = new WindSourceImpl(WindSourceType.COMBINED); - windSourcesToDeliver.add(windSource); - final TimePoint fromTimePoint = race.getStartOfRace(); - if (fromTimePoint != null) { - final TimePoint toTimePoint = race.getEndOfRace(); - final Duration samplingInterval = Duration.ONE_MINUTE.times(5); - final WindTrack windTrack = race.getOrCreateWindTrack(windSource); - TimePoint timePoint = fromTimePoint; - int attemptedNumberOfFixes = 0; - while (toTimePoint == null ? (attemptedNumberOfFixes<5) : (timePoint.compareTo(toTimePoint) < 0)) { - WindWithConfidence> averagedWindWithConfidence = windTrack - .getAveragedWindWithConfidence(null, timePoint); - if (averagedWindWithConfidence != null) { - Element windElement = new Element("windFix"); - addNamedElementWithValue(windElement, "same_day_index", sameDayIndex); - addNamedElementWithValue(windElement, "race_name", race.getRace().getName()); - addNamedElementWithValue(windElement, "fleet_name", fleet.getName()); - windElement.addContent(createTimedXML("", averagedWindWithConfidence.getObject().getTimePoint())); - addNamedElementWithValue(windElement, "bearingInDegrees", averagedWindWithConfidence.getObject().getBearing().getDegrees()); - addNamedElementWithValue(windElement, "directionFromInDegrees", averagedWindWithConfidence.getObject().getBearing().reverse().getDegrees()); - windElement.addContent(createWindXML("", new SpeedWithConfidenceImpl(new KnotSpeedImpl(averagedWindWithConfidence.getObject().getKnots()), - averagedWindWithConfidence.getConfidence(), timePoint))); - windElements.add(windElement); - } - timePoint = timePoint.plus(samplingInterval); - attemptedNumberOfFixes++; - } - } - return windElements; - } - - /** - * Creates xml elements that indicate confidence. - */ - private Element createDataConfidenceXML(Util.Pair> confidenceAndMessages) { - Element confidenceDataElement = new Element("confidence"); - addNamedElementWithValue(confidenceDataElement, "simple_confidence_value", confidenceAndMessages.getA().doubleValue()); - Element messagesElement = new Element("messages"); - for (String message : confidenceAndMessages.getB()) { - addNamedElementWithValue(messagesElement, "message", message); - } - confidenceDataElement.addContent(messagesElement); - return confidenceDataElement; - } - - /** - * Update confidence - * @param message The message that contains information why confidence is decreased - * @param decreaseConfidenceBy Value telling how much the confidence should be decreased - */ - private Util.Pair> updateConfidence(String message, double decreaseConfidenceBy, Util.Pair> confidencePair) { - Vector messages = confidencePair.getB(); - messages.add(message); - return new Util.Pair>(confidencePair.getA().doubleValue()-decreaseConfidenceBy, messages); - } - - private Util.Pair> checkData(TrackedLeg leg) throws Exception { - double simpleConfidence = 1.0; Vector messages = new Vector(); - TimePoint now = MillisecondsTimePoint.now(); - for (TrackedLegOfCompetitor competitorLeg : leg.getTrackedLegsOfCompetitors()) { - if (competitorLeg == null) { - messages.add("Found one leg for a competitor that is null!"); - simpleConfidence = 0.0; - continue; - } - if (competitorLeg.getCompetitor() == null) { - messages.add("Found a leg where the associated competitor is just null!"); - simpleConfidence = 0.0; - continue; - } - if (competitorLeg.getTrackedLeg().getTrackedRace().getMarkPassings(competitorLeg.getCompetitor()).isEmpty()) { - messages.add("Competitor "+ competitorLeg.getCompetitor().getName() + " has no mark passings for the complete race!"); - simpleConfidence -= 0.02; - } - if (!competitorLeg.hasFinishedLeg(now) || competitorLeg.getFinishTime() == null) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has not finished this leg! Leg data won't be available!"); - simpleConfidence -= 0.08; - } - if (!competitorLeg.hasStartedLeg(now) || competitorLeg.getStartTime() == null) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has not started this leg! Leg data won't be available!"); - simpleConfidence -= 0.08; - } - if (competitorLeg.getMaximumSpeedOverGround(now) == null) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no maximum speed for this leg!"); - simpleConfidence -= 0.05; - } - if (competitorLeg.getAverageAbsoluteCrossTrackError(now, /*waitForLatestAnalysis*/ false) == null) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no average cross track error for this leg!"); - simpleConfidence -= 0.02; - } - if (competitorLeg.getAverageSignedCrossTrackError(now, /*waitForLatestAnalysis*/ false) == null) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no average signed cross track error for this leg!"); - simpleConfidence -= 0.02; - } - if (competitorLeg.getStartTime() != null && competitorLeg.getStartTime().before(leg.getTrackedRace().getStartOfRace())) { - if ((leg.getTrackedRace().getStartOfRace().asMillis()-competitorLeg.getStartTime().asMillis())>=MAX_EARLY_START_DIFFERENCE) { - messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has a start time of " + competitorLeg.getStartTime() + " that is 10 seconds or more before start of race time (" + leg.getTrackedRace().getStartOfRace() + ")."); - simpleConfidence -= 0.01; - } - } - } - return new Util.Pair>(simpleConfidence, messages); - } - - private Util.Pair> checkData(TrackedRace race) throws Exception { - double simpleConfidence = 1.0; Vector messages = new Vector(); - TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l); - if (race == null) { - messages.add("Tracked race is null - no race seems to be connected!"); - simpleConfidence -= 1; - } else { - if (race.getStartOfRace() == null || race.getStartOfRace().before(dateAtYear2000)) { - messages.add("Start time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); - simpleConfidence -= 1; - } - if (race.getEndOfRace() == null || race.getEndOfRace().before(dateAtYear2000)) { - messages.add("End time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); - simpleConfidence -= 1; - } - if (race.getStartOfTracking() == null || race.getStartOfTracking().before(dateAtYear2000)) { - messages.add("Start tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); - simpleConfidence -= 0.2; - } - if (race.getEndOfTracking() == null || race.getEndOfTracking().before(dateAtYear2000)) { - messages.add("End tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); - simpleConfidence -= 0.2; - } - if (race.isLive(MillisecondsTimePoint.now())) { - messages.add("This race is live - data for this race will not be available until the race has been finished!"); - } - } - return new Util.Pair>(simpleConfidence, messages); - } - - private Util.Pair> checkData(Competitor competitor, Boat boatOfCompetitor) throws Exception { - double simpleConfidence = 1.0; Vector messages = new Vector(); - if (competitor.getName() == null || competitor.getName().equals("")) { - messages.add("Competitor " + competitor.getId() + " has no name!"); - simpleConfidence -= 1; - } - if (boatOfCompetitor == null || boatOfCompetitor.getSailID() == null || boatOfCompetitor.getSailID().equals("")) { - messages.add("Competitor " + competitor.getId() + " has no sail id that can be used!"); - simpleConfidence -= 1; - } - if (competitor.getTeam() == null || competitor.getTeam().getNationality() == null) { - messages.add("Either team for "+ competitor.getId() + " is null or nationality could not be determined"); - simpleConfidence -= 0.2; - } - return new Util.Pair>(simpleConfidence, messages); - } - - private Util.Pair> checkData(Leaderboard leaderboard) throws Exception { - double simpleConfidence = 1.0; Vector messages = new Vector(); - int raceColumnCount = 0; int attachedRaceToColumnCount = 0; - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - if (raceColumn.hasTrackedRaces()) { - attachedRaceToColumnCount++; - } - raceColumnCount++; - } - if (raceColumnCount == 0) { - messages.add("Could not find any race columns or none of the race columns has tracked races attached!"); - simpleConfidence -= 1.0; - } - if (attachedRaceToColumnCount < raceColumnCount) { - messages.add("Not all race columns contain attached races! Data being aggregated over all races could be wrong!"); - simpleConfidence -= 0.3; - } - int competitorCount = 0; - for (Iterator iterator = leaderboard.getAllCompetitors().iterator(); iterator.hasNext();) { - iterator.next(); - competitorCount++; - } - if (competitorCount == 0) { - messages.add("Could not find any competitors in this leaderboard!"); - simpleConfidence -= 1.0; - } - TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l); - if (leaderboard.getTimePointOfLatestModification() != null && leaderboard.getTimePointOfLatestModification().before(dateAtYear2000)) { - messages.add("The time point of the last modification for this leaderboard is very old."); - simpleConfidence -= 0.4; - } - return new Util.Pair>(simpleConfidence, messages); - } - - /** - * Groups races together that have been on the same day - */ - private int getSameDayGroupIndex(TrackedRace currentRace, TrackedRace raceBefore) { - if (raceBefore != null && !raceBefore.equals(currentRace)) { - if (currentRace != null && currentRace.getStartOfRace() != null && raceBefore.getStartOfRace() != null) { - Calendar timedDateForCurrentRace = Calendar.getInstance(); - timedDateForCurrentRace.setTime(currentRace.getStartOfRace().asDate()); - String formattedCurrent = new SimpleDateFormat("dd.MM.yyyy").format(timedDateForCurrentRace.getTime()); - - Calendar timedDateForRaceBefore = Calendar.getInstance(); - timedDateForRaceBefore.setTime(raceBefore.getStartOfRace().asDate()); - String formattedBefore = new SimpleDateFormat("dd.MM.yyyy").format(timedDateForRaceBefore.getTime()); - - if (formattedCurrent.equals(formattedBefore)) { - return 0; - } - } - } else { - return 0; - } - return 1; - } - - public void perform() throws Exception { - final Leaderboard leaderboard = getLeaderboard(); - TimePoint timeSpent = MillisecondsTimePoint.now(); - log.info("Starting XML export of " + leaderboard.getName()); - Util.Pair> leaderboardConfidenceAndErrorMessages = checkData(leaderboard); - final List racesElements = new ArrayList(); - final List competitorElements = new ArrayList(); - for (Competitor competitor : leaderboard.getAllCompetitors()) { - Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? - Util.Pair> competitorConfidenceAndErrorMessages = checkData(competitor, boatOfCompetitor); - competitorElements.add(createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); - } - List windData = new ArrayList(); - TrackedRace raceBefore = null; int sameDayGroupIndex = 0; int raceCounter = 0; - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - if (trackedRace != null) { - sameDayGroupIndex += getSameDayGroupIndex(raceColumn.getTrackedRace(fleet), raceBefore); - } - TimePoint timeSpentForRace = MillisecondsTimePoint.now(); - Util.Pair> raceConfidenceAndErrorMessages = checkData(trackedRace); - final List legs = new ArrayList(); - if (trackedRace != null && trackedRace.hasGPSData()) { - windData.addAll(createFullWindDataXML(trackedRace, fleet, sameDayGroupIndex)); - int legCounter = 0; - for (TrackedLeg leg : trackedRace.getTrackedLegs()) { - Util.Pair> legConfidenceAndErrorMessages = checkData(leg); - legs.add(createLegXML(leg, leaderboard, ++legCounter, raceConfidenceAndErrorMessages, legConfidenceAndErrorMessages)); - } - Element raceElement = createRaceXML(trackedRace, fleet, legs, raceColumn, leaderboard, sameDayGroupIndex, ++raceCounter, raceConfidenceAndErrorMessages); - TimePoint elapsedTimeForRace = MillisecondsTimePoint.now().minus(timeSpentForRace.asMillis()); - addNamedElementWithValue(raceElement, "generation_time_in_milliseconds", elapsedTimeForRace.asMillis()); - racesElements.add(raceElement); - log.info("Exported complete race " + trackedRace.getRace().getName() + " in " + elapsedTimeForRace.asMillis() + " milliseconds!"); - } else { - racesElements.add(createRaceXMLWithoutRaceData(fleet, raceColumn, leaderboard, sameDayGroupIndex, ++raceCounter, raceConfidenceAndErrorMessages)); - log.info("Exported empty race in race column " + raceColumn.getName() + " with fleet " + fleet.getName()); - } - raceBefore = trackedRace; - } - } - log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds"); - Element dataToExport = createLeaderboardXML(leaderboard, windData, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages); - sendDocument(dataToExport, leaderboard.getName() + ".xml"); - } -} +package com.sap.sailing.xmlexport; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import java.util.logging.Logger; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jdom.Element; + +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Fleet; +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.SpeedWithConfidence; +import com.sap.sailing.domain.base.impl.SpeedWithConfidenceImpl; +import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.NauticalSide; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.Tack; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.impl.KnotSpeedImpl; +import com.sap.sailing.domain.common.impl.MeterDistance; +import com.sap.sailing.domain.common.impl.WindSourceImpl; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.LineDetails; +import com.sap.sailing.domain.tracking.Maneuver; +import com.sap.sailing.domain.tracking.TrackedLeg; +import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.WindPositionMode; +import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tracking.WindWithConfidence; +import com.sap.sailing.server.RacingEventService; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +/** + * Exports all data from a leaderboard into XML format. + * + * @author Simon Marcel Pamies + */ +public class LeaderboardData extends ExportAction { + + private static final int MAX_EARLY_START_DIFFERENCE = 10*1000; // 10 seconds + + private final Logger log = Logger.getLogger(LeaderboardData.class.getName()); + + private static final String VERY_LIGHT_WIND_DESCRIPTION = "Very Light"; + private static final String LIGHT_WIND_DESCRIPTION = "Light"; + private static final String MEDIUM_WIND_DESCRIPTION = "Medium"; + private static final String MEDIUM_STRONG_WIND_DESCRIPTION = "Medium Strong"; + private static final String STRONG_WIND_DESCRIPTION = "Strong"; + private static final String VERY_STRONG_WIND_DESCRIPTION = "Very Strong"; + + private final Map> raceColumnToCompetitors; + + public LeaderboardData(HttpServletRequest req, HttpServletResponse res, RacingEventService service) { + super(req, res, service); + this.raceColumnToCompetitors = new HashMap<>(); + } + + public LeaderboardData(Leaderboard leaderboard) { + super(leaderboard); + this.raceColumnToCompetitors = new HashMap<>(); + } + + /** + * Creates XML for a leaderboard. Expects a list of generated competitors and races XML elements that are associated with the leaderboard. + *
      +     *  
      +     *     ESS 2014 Qingdao (Extreme40)
      +     *     Qingdao
      +     *     8000
      +     *     HIGH_POINT_FIRST_GETS_TEN
      +     *     Extreme40
      +     *       
      +     *       1.0
      +     *       
      +     *     
      +     *     
      +     *     
      +     *  
      + */ + private Element createLeaderboardXML(Leaderboard leaderboard, List windData, List competitors, List races, Util.Pair> leaderboardConfidenceAndErrorMessages) { + Element leaderboardElement = new Element("leaderboard"); + addNamedElementWithValue(leaderboardElement, "name", leaderboard.getName()); + addNamedElementWithValue(leaderboardElement, "display_name", leaderboard.getDisplayName()); + addNamedElementWithValue(leaderboardElement, "delay_to_live_in_millis", leaderboard.getDelayToLiveInMillis()); + addNamedElementWithValue(leaderboardElement, "scoring_scheme", leaderboard.getScoringScheme().getType().name()); + addNamedElementWithValue(leaderboardElement, "boat_class", getBoatClassName(leaderboard)); + leaderboardElement.addContent(createTimedXML("last_modification_", leaderboard.getTimePointOfLatestModification())); + leaderboardElement.addContent(createDataConfidenceXML(leaderboardConfidenceAndErrorMessages)); + Element windContainer = new Element("wind"); + windContainer.addContent(windData); + leaderboardElement.addContent(windContainer); + leaderboardElement.addContent(competitors); + leaderboardElement.addContent(races); + return leaderboardElement; + } + + /** + * For the given {@link TimePoint} creates elements with several representations + * of that {@link TimePoint}. + *
      +     *   2014
      +     *   4
      +     *   4
      +     *   9
      +     *   3
      +     *   45
      +     *   04.05.2014 09:03:45
      +     *   1399194225000
      +     * 
      + */ + private List createTimedXML(String prefix, TimePoint timepoint) { + List timedElements = new ArrayList(); + Calendar timedDate = Calendar.getInstance(); + if (timepoint != null) { + timedDate.setTime(timepoint.asDate()); + + timedElements.add(createNamedElementWithValue(prefix+"year", timedDate.get(Calendar.YEAR))); + timedElements.add(createNamedElementWithValue(prefix+"month", timedDate.get(Calendar.MONTH))); + timedElements.add(createNamedElementWithValue(prefix+"day", timedDate.get(Calendar.DAY_OF_MONTH))); + timedElements.add(createNamedElementWithValue(prefix+"hour", timedDate.get(Calendar.HOUR_OF_DAY))); + timedElements.add(createNamedElementWithValue(prefix+"minute", timedDate.get(Calendar.MINUTE))); + timedElements.add(createNamedElementWithValue(prefix+"second", timedDate.get(Calendar.SECOND))); + + SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); + timedElements.add(createNamedElementWithValue(prefix+"formatted", dateFormatter.format(timedDate.getTime()))); + timedElements.add(createNamedElementWithValue(prefix+"millis_since_epoch", timepoint.asMillis())); + } else { + timedElements.add(createNamedElementWithValue(prefix+"year", "")); + timedElements.add(createNamedElementWithValue(prefix+"month", "")); + timedElements.add(createNamedElementWithValue(prefix+"day", "")); + timedElements.add(createNamedElementWithValue(prefix+"hour", "")); + timedElements.add(createNamedElementWithValue(prefix+"minute", "")); + timedElements.add(createNamedElementWithValue(prefix+"second", "")); + timedElements.add(createNamedElementWithValue(prefix+"formatted", "")); + timedElements.add(createNamedElementWithValue(prefix+"millis_since_epoch", "")); + } + return timedElements; + } + + /** + * Creates elements related to the given speed fix. Implies that this is related to wind. + *
      +     *       10.985139054212647
      +     *       5.652159186143912
      +     *       4.0
      +     *       0.24242981000649663
      +     *       Medium
      +     *       8-12kn
      +     * 
      + */ + public List createWindXML(String prefix, SpeedWithConfidence speedWithConfidence) { + List windElements = new ArrayList(); + if (speedWithConfidence == null) { + speedWithConfidence = new SpeedWithConfidenceImpl(new KnotSpeedImpl(0.0), 0, MillisecondsTimePoint.now()); + } + windElements.add(createNamedElementWithValue(prefix+"speed_in_knots", speedWithConfidence.getObject().getKnots())); + windElements.add(createNamedElementWithValue(prefix+"speed_in_meters_per_second", speedWithConfidence.getObject().getMetersPerSecond())); + windElements.add(createNamedElementWithValue(prefix+"speed_in_beaufort", Math.rint(speedWithConfidence.getObject().getBeaufort()))); + windElements.add(createNamedElementWithValue(prefix+"confidence", speedWithConfidence.getConfidence())); + + double speedInKnots = speedWithConfidence.getObject().getKnots(); + String windSpeedAsHumanReadableString = ""; + String windSpeedAsInterval = ""; + if (speedInKnots <= 4) { + windSpeedAsHumanReadableString = VERY_LIGHT_WIND_DESCRIPTION; + windSpeedAsInterval = "0-4kn"; + } else if (speedInKnots > 4 && speedInKnots <= 8) { + windSpeedAsHumanReadableString = LIGHT_WIND_DESCRIPTION; + windSpeedAsInterval = "4-8kn"; + } else if (speedInKnots > 8 && speedInKnots <= 12) { + windSpeedAsHumanReadableString = MEDIUM_WIND_DESCRIPTION; + windSpeedAsInterval = "8-12kn"; + } else if (speedInKnots > 12 && speedInKnots <= 16) { + windSpeedAsHumanReadableString = MEDIUM_STRONG_WIND_DESCRIPTION; + windSpeedAsInterval = "12-16kn"; + } else if (speedInKnots > 16 && speedInKnots <= 20) { + windSpeedAsHumanReadableString = STRONG_WIND_DESCRIPTION; + windSpeedAsInterval = "16-20kn"; + } else if (speedInKnots > 20) { + windSpeedAsHumanReadableString = VERY_STRONG_WIND_DESCRIPTION; + windSpeedAsInterval = "20-80kn"; + } + windElements.add(createNamedElementWithValue(prefix+"human_readable", windSpeedAsHumanReadableString)); + windElements.add(createNamedElementWithValue(prefix+"knots_interval", windSpeedAsInterval)); + return windElements; + } + + private Element createRaceXMLWithoutRaceData(final Fleet fleet, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Util.Pair> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { + Element raceElement = new Element("race"); + addNamedElementWithValue(raceElement, "name", column.getName()+'-'+fleet.getName()); + addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter); + addNamedElementWithValue(raceElement, "fleet_name", fleet.getName()); + addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex); + addNamedElementWithValue(raceElement, "is_live", "false"); + TimePoint timepointToBeUsed = MillisecondsTimePoint.now(); + List competitorsForColumn = this.raceColumnToCompetitors.get(column); + if (competitorsForColumn == null) { + competitorsForColumn = new ArrayList<>(); + } + List competitors = leaderboard.getCompetitorsFromBestToWorst(column, timepointToBeUsed); + for (Competitor competitorInLeaderboard : competitors) { + // we must keep track of competitors that we are associated to fleets + // in order to not export the score correction twice. This is needed + // because the score correction does not know about fleets and we do not + // know to which fleet the competitor belongs because no races are linked + if (!competitorsForColumn.contains(competitorInLeaderboard)) { + MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); + if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { + // add this competitor to the list to have him evaluated + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); + Element competitorRaceDataElement = new Element("competitor_race_data"); + MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, timepointToBeUsed); + addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); + boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitorInLeaderboard, column, timepointToBeUsed); + addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); + Double finalRaceScore = leaderboard.getNetPoints(competitorInLeaderboard, column, timepointToBeUsed); + addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); + competitorElement.addContent(competitorRaceDataElement); + raceElement.addContent(competitorElement); + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitorInLeaderboard.getName() + " has no valid data for this race!", 0.2, raceConfidenceAndErrorMessages); + competitorsForColumn.add(competitorInLeaderboard); + } + } + } + this.raceColumnToCompetitors.put(column, competitorsForColumn); + return raceElement; + } + + /** + * Creates elements containing information about a race + */ + private Element createRaceXML(final TrackedRace race, final Fleet fleet, final List legs, final RaceColumn column, final Leaderboard leaderboard, int sameDayGroupIndex, int raceCounter, Util.Pair> raceConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { + Element raceElement = new Element("race"); + addNamedElementWithValue(raceElement, "name", cleanRaceName(race.getRace().getName())); + addNamedElementWithValue(raceElement, "race_index_in_leaderboard", raceCounter); + addNamedElementWithValue(raceElement, "fleet_name", fleet.getName()); + addNamedElementWithValue(raceElement, "same_day_index", sameDayGroupIndex); + addNamedElementWithValue(raceElement, "is_live", race.isLive(MillisecondsTimePoint.now()) ? "true" : "false"); + + addNamedElementWithValue(raceElement, "start_type", race.getTrackedLeg(race.getRace().getCourse().getFirstLeg()).getLegType(race.getStartOfRace()).name()); + addNamedElementWithValue(raceElement, "delay_to_live_in_millis", race.getDelayToLiveInMillis()); + addNamedElementWithValue(raceElement, "multiplication_factor", column.getExplicitFactor() == null ? 1.0d : column.getExplicitFactor()); + + addNamedElementWithValue(raceElement, "timepoint_of_last_event_as_millis", handleValue(race.getTimePointOfLastEvent())); + addNamedElementWithValue(raceElement, "timepoint_of_newest_event_as_millis", handleValue(race.getTimePointOfNewestEvent())); + addNamedElementWithValue(raceElement, "timepoint_of_oldest_event_as_millis", handleValue(race.getTimePointOfOldestEvent())); + + if (race.isLive(MillisecondsTimePoint.now())) { + // we can't tell meaningful values about live races + raceElement.addContent(createDataConfidenceXML(raceConfidenceAndErrorMessages)); + raceElement.addContent(legs); + return raceElement; + } + + raceElement.addContent(createTimedXML("start_time_", race.getStartOfRace())); + raceElement.addContent(createTimedXML("end_time_", race.getEndOfRace())); + addNamedElementWithValue(raceElement, "start_of_tracking_time_as_millis", handleValue(race.getStartOfTracking())); + addNamedElementWithValue(raceElement, "end_of_tracking_time_as_millis", handleValue(race.getEndOfTracking())); + + LineDetails start = race.getStartLine(race.getStartOfRace()); + if (start != null) { + if (start.getLength() != null) { + addNamedElementWithValue(raceElement, "start_line_length_in_meters", start.getLength().getMeters()); + } else { + addNamedElementWithValue(raceElement, "start_line_length_in_meters", 0); + } + Distance advantage = start.getAdvantage(); + addNamedElementWithValue(raceElement, "start_advantage_in_meters", advantage != null ? advantage.getMeters() : 0); + NauticalSide nauticalSideWhileApproaching = start.getAdvantageousSideWhileApproachingLine(); + addNamedElementWithValue(raceElement, "advantageous_side_while_approaching_start_line", nauticalSideWhileApproaching != null ? nauticalSideWhileApproaching.name() : "UNKNOWN"); + } else { + addNamedElementWithValue(raceElement, "start_line_length_in_meters", 0); + addNamedElementWithValue(raceElement, "start_advantage_in_meters", 0); + addNamedElementWithValue(raceElement, "advantageous_side_while_approaching_start_line", "UNKNOWN"); + } + + Distance raceCourseLength = race.getCourseLength(); + if (raceCourseLength == null) { + raceConfidenceAndErrorMessages = updateConfidence("Race " + race.getRace().getName() + " has no course length.", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(raceElement, "course_length_in_meters", raceCourseLength != null ? raceCourseLength.getMeters() : 0); + raceElement.addContent(createWindXML("wind_", race.getAverageWindSpeedWithConfidence(/*resolutionInMillis*/ 5*60*1000))); + + final List allCompetitors = race.getCompetitorsFromBestToWorst(/*timePoint*/ race.getEndOfRace()); + addNamedElementWithValue(raceElement, "race_participant_count", allCompetitors.size()); + + boolean isDiscarded = leaderboard.isDiscarded(allCompetitors.get(0), column, race.getEndOfRace()); + addNamedElementWithValue(raceElement, "is_discarded_by_looking_at_first_competitor", isDiscarded == true ? "true" : "false"); + + long numberOfGPSFixes = 0, numberOfWindFixes = 0; + for (Competitor competitor : race.getRace().getCompetitors()) { + GPSFixTrack competitorTrack = race.getTrack(competitor); + competitorTrack.lockForRead(); + try { + numberOfGPSFixes += Util.size(competitorTrack.getRawFixes()); + } finally { + competitorTrack.unlockAfterRead(); + } + } + for (Mark mark : race.getMarks()) { + GPSFixTrack markTrack = race.getOrCreateTrack(mark); + markTrack.lockForRead(); + try { + numberOfGPSFixes += Util.size(markTrack.getRawFixes()); + } finally { + markTrack.unlockAfterRead(); + } + } + for (WindSource windSource : race.getWindSources()) { + // don't count the "virtual" wind sources + if (windSource.canBeStored() || windSource.getType() == WindSourceType.RACECOMMITTEE) { + WindTrack windTrack = race.getOrCreateWindTrack(windSource); + windTrack.lockForRead(); + try { + numberOfWindFixes += Util.size(windTrack.getRawFixes()); + } finally { + windTrack.unlockAfterRead(); + } + } + } + addNamedElementWithValue(raceElement, "numberOfGPSFixes", numberOfGPSFixes); + addNamedElementWithValue(raceElement, "numberOfWindFixes", numberOfWindFixes); + + // sort competitors according to their distance to the starboard side of the start line + List allCompetitorsSortedByDistanceToStarboardSide = new ArrayList(allCompetitors.size()); + allCompetitorsSortedByDistanceToStarboardSide.addAll(allCompetitors); + Collections.sort(allCompetitorsSortedByDistanceToStarboardSide, new Comparator() { + @Override + public int compare(Competitor o1, Competitor o2) { + Distance o1Distance = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o1); + Distance o2Distance = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(o2); + if (o1Distance != null && o2Distance != null) { + return o1Distance.compareTo(o2Distance); + } else if (o1Distance == null && o2Distance == null) { + return 0; + } else { + // one of the distances is null - we can't really tell + // which competitor is better in terms of sorting but we can try + // by giving the competitor that has a null value a very big distance + if (o1Distance == null) { + return new MeterDistance(100000).compareTo(o2Distance); + } else { + return o1Distance.compareTo(new MeterDistance(100000)); + } + } + } + }); + + Map competitorToDistanceRank = new HashMap(); + int raceRankSorted = 0; + for (Competitor competitorSorted : allCompetitorsSortedByDistanceToStarboardSide) { + raceRankSorted += 1; + competitorToDistanceRank.put(competitorSorted, raceRankSorted); + } + + List competitorsForColumn = this.raceColumnToCompetitors.get(column); + if (competitorsForColumn == null) { + competitorsForColumn = new ArrayList<>(); + } + // it can happen that there are competitors that did not race but got points + int additionalCompetitorCount = 0; + for (Competitor competitorInLeaderboard : leaderboard.getAllCompetitors()) { + if (!allCompetitors.contains(competitorInLeaderboard)) { + // found a competitor that is available in leaderboard but not in that race + // check if he has an overwritten score for that race + MaxPointsReason mpr = leaderboard.getScoreCorrection().getMaxPointsReason(competitorInLeaderboard, column, race.getEndOfRace()); + Fleet fleetCompetitorIsSailingIn = column.getFleetOfCompetitor(competitorInLeaderboard); + if (fleetCompetitorIsSailingIn != null && fleetCompetitorIsSailingIn.equals(fleet) && !competitorsForColumn.contains(competitorInLeaderboard)) { + if (mpr != null && !mpr.equals(MaxPointsReason.NONE)) { + // add this competitor to the list to have him evaluated + Boat boatOfCompetitor = leaderboard.getBoatOfCompetitor(competitorInLeaderboard, column, fleetCompetitorIsSailingIn); + Element competitorElement = createCompetitorXML(competitorInLeaderboard, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); + Element competitorRaceDataElement = new Element("competitor_race_data"); + MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitorInLeaderboard, column, race.getEndOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); + boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitorInLeaderboard, column, race.getEndOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); + Double finalRaceScore = leaderboard.getNetPoints(competitorInLeaderboard, column, race.getEndOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); + competitorElement.addContent(competitorRaceDataElement); + raceElement.addContent(competitorElement); + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitorInLeaderboard.getName() + " has no valid data for this race!", 0.2, raceConfidenceAndErrorMessages); + additionalCompetitorCount++; + competitorsForColumn.add(competitorInLeaderboard); + } + } + } + } + addNamedElementWithValue(raceElement, "race_score_participant_count", allCompetitors.size()+additionalCompetitorCount); + + int raceRank = 0; + for (Competitor competitor : allCompetitors) { + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); + Element competitorRaceDataElement = new Element("competitor_race_data"); + MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, column, race.getEndOfRace()); + if (maxPointsReason != null && !maxPointsReason.equals(MaxPointsReason.NONE)) { + competitorsForColumn.add(competitor); + } + addNamedElementWithValue(competitorRaceDataElement, "max_points_reason", maxPointsReason.toString()); + boolean isDiscardedForCompetitor = leaderboard.isDiscarded(competitor, column, race.getEndOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "is_discarded", isDiscardedForCompetitor == true ? "true" : "false"); + Double finalRaceScore = leaderboard.getNetPoints(competitor, column, race.getEndOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "final_race_score", finalRaceScore); + if (maxPointsReason.equals(MaxPointsReason.DNS) || race.getMarkPassings(competitor).isEmpty()) { + // we do not want to include competitors that did not start the race + competitorElement.addContent(competitorRaceDataElement); + raceElement.addContent(competitorElement); + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid data for this race!", 0.1, raceConfidenceAndErrorMessages); + continue; + } + + Iterable maneuvers = getManeuvers(race, competitor, /*waitForLatest*/ false); + addNamedElementWithValue(competitorRaceDataElement, "number_of_maneuvers", maneuvers != null ? Util.size(maneuvers) : 0); + addNamedElementWithValue(competitorRaceDataElement, "number_of_tacks", getNumberOfTacks(maneuvers)); + addNamedElementWithValue(competitorRaceDataElement, "number_of_jibes", getNumberOfJibes(maneuvers)); + addNamedElementWithValue(competitorRaceDataElement, "number_of_penalty_circles", getNumberOfPenaltyCircles(maneuvers)); + + GPSFixTrack gpsFixesForCompetitor = race.getTrack(competitor); + if (gpsFixesForCompetitor != null) { + Duration averageInterval = gpsFixesForCompetitor.getAverageIntervalBetweenFixes(); + if (averageInterval != null) { + addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_outliers_removed_as_millis", averageInterval.asMillis()); + } + Duration averageIntervallRaw = gpsFixesForCompetitor.getAverageIntervalBetweenRawFixes(); + if (averageIntervallRaw != null) { + addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_raw_as_millis", averageIntervallRaw.asMillis()); + } + } else { + addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_outliers_removed_as_millis", 0); + addNamedElementWithValue(competitorRaceDataElement, "average_interval_between_fixes_raw_as_millis", 0); + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid gps track for this race!", 0.5, raceConfidenceAndErrorMessages); + } + + int[] timePointsInSecondsBeforeStart = new int[]{0, 5, 10, 20, 30}; + for (int i : timePointsInSecondsBeforeStart) { + TimePoint beforeRaceStartTime = race.getStartOfRace().minus(i*1000); + Distance distanceToStartLineBeforeStart = race.getDistanceToStartLine(competitor, beforeRaceStartTime); + if (distanceToStartLineBeforeStart == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance to startline " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_"+i+"seconds_before_start_in_meters", distanceToStartLineBeforeStart != null ? distanceToStartLineBeforeStart.getMeters() : 0); + Speed estimatedSpeedBeforeStarttime = race.getTrack(competitor).getEstimatedSpeed(beforeRaceStartTime); + if (estimatedSpeedBeforeStarttime == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "speed_"+i+"seconds_before_start_of_race_in_knots", estimatedSpeedBeforeStarttime != null ? estimatedSpeedBeforeStarttime.getKnots() : 0); + + Distance distanceToStarboardSide = race.getDistanceFromStarboardSideOfStartLine(competitor, beforeRaceStartTime); + if (distanceToStarboardSide == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance to starboard side " + i + " seconds before start for this race!", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_"+i+"seconds_before_start_in_meters", distanceToStarboardSide != null ? distanceToStarboardSide.getMeters() : 0); + + LineDetails raceStartLine = race.getStartLine(beforeRaceStartTime); + if (raceStartLine == null) { + addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_port_mark_to_starboard_mark"+i+"seconds_before_start_in_degrees", 0); + addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_projected_position_to_starboard_mark"+i+"seconds_before_start_in_degrees", 0); + addNamedElementWithValue(competitorRaceDataElement, "bearing_to_starboard_mark_"+i+"seconds_before_start_in_degrees", 0); + addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "false"); + addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", 0); + addNamedElementWithValue(competitorRaceDataElement, "projected_position_onto_startline_"+i+"seconds_before_start", 0); + raceConfidenceAndErrorMessages = updateConfidence("Race " + race.getRace().getName() + " has no valid startline! Data related to startline will be wrong.", 0.2, raceConfidenceAndErrorMessages); + } else { + Iterator marksForStartLine = race.getStartLine(beforeRaceStartTime).getWaypoint().getControlPoint().getMarks().iterator(); + Mark first = marksForStartLine.next(); + Mark second = null; + if (marksForStartLine.hasNext()) { + second = marksForStartLine.next(); + Position firstMarkPosition = race.getOrCreateTrack(first).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); + Position secondMarkPosition = race.getOrCreateTrack(second).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); + Position competitorPosition = race.getTrack(competitor).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); + if (firstMarkPosition != null && secondMarkPosition != null) { + Position projectedCompetitorPositionOntoStartLine = getOrthogonalProjectionOntoLine( + competitorPosition, + firstMarkPosition, + secondMarkPosition + ); + // now compute the distance from starboard mark + Mark starboardMark = race.getStartLine(beforeRaceStartTime).getStarboardMarkWhileApproachingLine(); + Mark portMark = null; + if (starboardMark.equals(first)) { + portMark = second; + } else { + portMark = first; + } + Position portMarkPosition = race.getOrCreateTrack(portMark).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); + Position starboardMarkPosition = race.getOrCreateTrack(starboardMark).getEstimatedPosition(beforeRaceStartTime, /*extrapolate*/ false); + Distance projectedDistance = projectedCompetitorPositionOntoStartLine.getDistance(starboardMarkPosition); + Bearing bearingToStarboardMarkFromCompetitorPosition = competitorPosition.getBearingGreatCircle(starboardMarkPosition); + Bearing bearingFromPortToStarboardMark = portMarkPosition.getBearingGreatCircle(starboardMarkPosition); + Bearing bearingFromProjectedCompetitorPositionToStarboardMark = projectedCompetitorPositionOntoStartLine.getBearingGreatCircle(starboardMarkPosition); + addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_port_mark_to_starboard_mark"+i+"seconds_before_start_in_degrees", bearingFromPortToStarboardMark.getDegrees()); + addNamedElementWithValue(competitorRaceDataElement, "bearing_fom_projected_position_to_starboard_mark"+i+"seconds_before_start_in_degrees", bearingFromProjectedCompetitorPositionToStarboardMark.getDegrees()); + addNamedElementWithValue(competitorRaceDataElement, "bearing_to_starboard_mark_"+i+"seconds_before_start_in_degrees", bearingToStarboardMarkFromCompetitorPosition.getDegrees()); + if (Math.rint(bearingFromPortToStarboardMark.getDegrees()) == Math.rint(bearingFromProjectedCompetitorPositionToStarboardMark.getDegrees())) { + addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "true"); + addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", projectedDistance.getMeters()); + } else { + addNamedElementWithValue(competitorRaceDataElement, "competitor_in_startline_box_"+i+"seconds_before_start", "false"); + addNamedElementWithValue(competitorRaceDataElement, "projected_starboard_mark_distance_"+i+"seconds_before_start_in_meters", 0-projectedDistance.getMeters()); + } + addNamedElementWithValue(competitorRaceDataElement, "projected_position_onto_startline_"+i+"seconds_before_start", projectedCompetitorPositionOntoStartLine.toString()); + } + } + } + } + Tack startTack = race.getTack(competitor, race.getStartOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "start_tack", startTack != null ? startTack.name() : "UNKNOWN"); + LineDetails startLine = race.getStartLine(race.getStartOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "starboard_mark_name", startLine != null ? startLine.getStarboardMarkWhileApproachingLine().getName() : "UNKNOWN"); + Distance distanceToStartLine = race.getDistanceToStartLine(competitor, race.getStartOfRace()); + addNamedElementWithValue(competitorRaceDataElement, "distance_to_start_line_on_race_start_in_meters", distanceToStartLine != null ? distanceToStartLine.getMeters() : 0); + Speed estimatedSpeedAtStartSignal = race.getTrack(competitor).getEstimatedSpeed(race.getStartOfRace()); + if (estimatedSpeedAtStartSignal == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed at start for this race!", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "speed_on_start_signal_of_race_in_knots", estimatedSpeedAtStartSignal != null ? estimatedSpeedAtStartSignal.getKnots() : 0); + Distance distanceFromStarboardSideWhenPassingStart = race.getDistanceFromStarboardSideOfStartLineWhenPassingStart(competitor); + if (distanceFromStarboardSideWhenPassingStart == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance from line at start for this race!", 0.1, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "distance_from_starboard_side_of_start_line_when_passing_start_in_meters", distanceFromStarboardSideWhenPassingStart != null ? distanceFromStarboardSideWhenPassingStart.getMeters() : 0); + addNamedElementWithValue(competitorRaceDataElement, "rank_based_on_distance_from_starboard_side_of_start_line", competitorToDistanceRank.get(competitor)); + Speed speedWhenCrossingStartline = race.getSpeedWhenCrossingStartLine(competitor); + if (speedWhenCrossingStartline == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid speed when passing startline for this race!", 0.2, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "speed_when_crossing_start_line_in_knots", speedWhenCrossingStartline != null ? speedWhenCrossingStartline.getKnots() : 0); + com.sap.sse.common.Util.Triple gpsFixWithSpeedAndLegInformation = getMaximumSpeedOverGround(competitor, race); + if (gpsFixWithSpeedAndLegInformation != null && gpsFixWithSpeedAndLegInformation.getB() != null) { + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_in_knots", gpsFixWithSpeedAndLegInformation.getB().getKnots()); + competitorRaceDataElement.addContent(createTimedXML("maximum_race_speed_measured_at_", gpsFixWithSpeedAndLegInformation.getA().getTimePoint())); + if (gpsFixWithSpeedAndLegInformation.getC() != null) { + // check which leg number it is + int legCounterForMaxSpeed = 0; + for (Leg leg : race.getRace().getCourse().getLegs()) { + legCounterForMaxSpeed++; + if (leg.equals(gpsFixWithSpeedAndLegInformation.getC().getLeg())) { + break; + } + } + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", legCounterForMaxSpeed); + TrackedLeg trackedLegWithTypeInformation = gpsFixWithSpeedAndLegInformation.getC().getTrackedLeg(); + if (trackedLegWithTypeInformation != null) { + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", trackedLegWithTypeInformation.getLegType(gpsFixWithSpeedAndLegInformation.getA().getTimePoint()).name()); + } else { + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", "UNKNOWN"); + } + } else { + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", 0); + } + } else { + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_in_knots", 0.0); + competitorRaceDataElement.addContent(createTimedXML("maximum_race_speed_measured_at_", race.getStartOfRace())); + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg_with_type", "UNKNOWN"); + addNamedElementWithValue(competitorRaceDataElement, "maximum_race_speed_over_ground_reached_in_leg", 0); + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid maximum speed for this race!", 0.5, raceConfidenceAndErrorMessages); + } + Distance distanceTraveledInThisRace = race.getDistanceTraveled(competitor, race.getEndOfRace()); + if (distanceTraveledInThisRace == null) { + raceConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " has no valid distance traveled for this race! Check distance traveled including non finished legs.", 0.3, raceConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorRaceDataElement, "distance_traveled_in_meters", distanceTraveledInThisRace == null ? 0.0 : distanceTraveledInThisRace.getMeters()); + addNamedElementWithValue(competitorRaceDataElement, "distance_traveled_including_non_finished_legs_in_meters", getDistanceTraveled(race, competitor, race.getEndOfRace(), /*alsoReturnDistanceIfCompetitorHasNotFinishedRace*/ true).getMeters()); + Speed averageSpeedOverGround = getAverageSpeedOverGround(race, competitor, race.getEndOfRace(), true); + addNamedElementWithValue(competitorRaceDataElement, "average_speed_over_ground_in_knots", averageSpeedOverGround == null ? 0.0 : averageSpeedOverGround.getKnots()); + addNamedElementWithValue(competitorRaceDataElement, "final_race_rank", ++raceRank); + TrackedLegOfCompetitor trackedLegOfCompetitor = race.getTrackedLeg(competitor, race.getRace().getCourse().getFirstLeg()); + if (trackedLegOfCompetitor != null && trackedLegOfCompetitor.getFinishTime() != null) { + addNamedElementWithValue(competitorRaceDataElement, "rank_at_end_of_first_leg", trackedLegOfCompetitor.getRank(trackedLegOfCompetitor.getFinishTime())); + } else { + addNamedElementWithValue(competitorRaceDataElement, "rank_at_end_of_first_leg", 0); + raceConfidenceAndErrorMessages = updateConfidence("It seems that competitor " + competitor.getName() + " has not finished first leg!", 0.1, raceConfidenceAndErrorMessages); + } + Distance averageCrossTrackError = race.getAverageAbsoluteCrossTrackError(competitor, race.getStartOfRace(), race.getEndOfRace(), /*upwindOnly*/ false, /*waitForLatestAnalysis*/ false); + addNamedElementWithValue(competitorRaceDataElement, "average_cross_track_error_in_meters", averageCrossTrackError != null ? averageCrossTrackError.getMeters() : -1.0); + Distance averageSignedCrossTrackError = race.getAverageSignedCrossTrackError(competitor, race.getStartOfRace(), race.getEndOfRace(), /*upwindOnly*/ false, /*waitForLatestAnalysis*/ false); + addNamedElementWithValue(competitorRaceDataElement, "average_signed_cross_track_error_in_meters", averageSignedCrossTrackError != null ? averageSignedCrossTrackError.getMeters() : -1.0); + competitorElement.addContent(competitorRaceDataElement); + raceElement.addContent(competitorElement); + } + + this.raceColumnToCompetitors.put(column, competitorsForColumn); + raceElement.addContent(createDataConfidenceXML(raceConfidenceAndErrorMessages)); + raceElement.addContent(legs); + return raceElement; + } + + /** + * Creates xml elements related to a competitor. + * @param shortVersion when set to true then only the name and UUID is returned + */ + private Element createCompetitorXML(Competitor competitor, Boat boatOfCompetitor, Leaderboard leaderboard, + boolean shortVersion, Util.Pair> competitorConfidenceAndErrorMessages) throws NoWindException, IOException, ServletException { + TimePoint timeSpent = MillisecondsTimePoint.now(); + Element competitorElement = new Element("competitor"); + addNamedElementWithValue(competitorElement, "uuid", competitor.getId().toString()); + addNamedElementWithValue(competitorElement, "name", competitor.getName()); + + if (shortVersion) + return competitorElement; + + if (boatOfCompetitor != null) { + addNamedElementWithValue(competitorElement, "sail_id", cleanSailId(boatOfCompetitor.getSailID(), competitor)); + addNamedElementWithValue(competitorElement, "boat_class", boatOfCompetitor.getBoatClass().getName()); + addNamedElementWithValue(competitorElement, "boat_name", boatOfCompetitor.getName()); + } else { + addNamedElementWithValue(competitorElement, "sail_id", ""); + addNamedElementWithValue(competitorElement, "boat_class", ""); + addNamedElementWithValue(competitorElement, "boat_name", ""); + } + + if (competitor.getTeam() != null && competitor.getTeam().getNationality() != null) { + addNamedElementWithValue(competitorElement, "nationality_name", competitor.getTeam().getNationality().getName()); + addNamedElementWithValue(competitorElement, "nationality_ioc", competitor.getTeam().getNationality().getThreeLetterIOCAcronym()); + } else { + addNamedElementWithValue(competitorElement, "nationality_name", ""); + addNamedElementWithValue(competitorElement, "nationality_ioc", ""); + } + + // determine the last race and take the timepoint from there + TimePoint timePointOfLatestModification = null; + RaceColumn lastRaceColumnWithTrackedRace = null; + for (RaceColumn column : leaderboard.getRaceColumns()) { + if (column.hasTrackedRaces()) { + lastRaceColumnWithTrackedRace = column; + } + } + TimePoint endOfRaceForLastTrackedRaceInLeaderboard = null; + if (lastRaceColumnWithTrackedRace != null) { + TrackedRace lastTrackedRace = lastRaceColumnWithTrackedRace.getTrackedRace(competitor); + if (lastTrackedRace != null) { + endOfRaceForLastTrackedRaceInLeaderboard = lastTrackedRace.getEndOfRace(); + } else { + // can happen that for this competitor there is no tracked race + // leave time null so that leaderboard latest modification time + // will kick in + } + } + // first look for latest modification of leaderboard + // if there is no latest modification then take the last races time + if (leaderboard.getTimePointOfLatestModification() != null) { + timePointOfLatestModification = leaderboard.getTimePointOfLatestModification(); + } else { + if (endOfRaceForLastTrackedRaceInLeaderboard != null) { + timePointOfLatestModification = endOfRaceForLastTrackedRaceInLeaderboard; + } else { + // make sure that the timepoint is far in the future - could be that the export is called too early + timePointOfLatestModification = MillisecondsTimePoint.now().plus(Duration.ONE_YEAR); + } + } + Duration totalTimeSailed = leaderboard.getTotalTimeSailed(competitor, timePointOfLatestModification); + if (totalTimeSailed != null) { + addNamedElementWithValue(competitorElement, "total_time_sailed_in_milliseconds", totalTimeSailed.asMillis()); + } else { + addNamedElementWithValue(competitorElement, "total_time_sailed_in_milliseconds", 0); + } + addNamedElementWithValue(competitorElement, "total_time_sailed_including_non_finished_races_in_milliseconds", getTotalTimeSailedInMilliseconds(competitor, timePointOfLatestModification, true)); + Distance totalDistanceSailed = leaderboard.getTotalDistanceTraveled(competitor, timePointOfLatestModification); + if (totalDistanceSailed == null) { + competitorConfidenceAndErrorMessages = updateConfidence("Competitor has not finished all races in this leaderboard! His distance sailed is not comparable to others!", 0.1, competitorConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorElement, "total_distance_sailed_in_meters", totalDistanceSailed != null ? totalDistanceSailed.getMeters() : 0); + Distance totalDistanceSailedIncludingNonFinishedRaces = getTotalDistanceTraveled(leaderboard, competitor, timePointOfLatestModification); + addNamedElementWithValue(competitorElement, "total_distance_sailed_including_non_finished_races_in_meters", totalDistanceSailedIncludingNonFinishedRaces != null ? totalDistanceSailedIncludingNonFinishedRaces.getMeters() : 0); + Pair maximumLeaderboardSpeedOverGround = leaderboard.getMaximumSpeedOverGround(competitor, timePointOfLatestModification); + addNamedElementWithValue(competitorElement, "maximum_speed_over_ground_in_knots", maximumLeaderboardSpeedOverGround != null ? maximumLeaderboardSpeedOverGround.getB().getKnots() : 0); + Speed averageSpeed = leaderboard.getAverageSpeedOverGround(competitor, timePointOfLatestModification); + if (averageSpeed == null) { + competitorConfidenceAndErrorMessages = updateConfidence("Competitor has not finished all races in this leaderboard! His average speed over ground is not comparable to others!", 0.1, competitorConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorElement, "average_speed_over_ground_from_start_mark_passing_in_knots", averageSpeed != null ? averageSpeed.getKnots() : 0); + Speed averageSpeedOverGroundIncludingNonCompletedRaces = getAverageSpeedOverGround(leaderboard, competitor, timePointOfLatestModification, true); + addNamedElementWithValue(competitorElement, "average_speed_over_ground_including_non_finished_races_in_knots", averageSpeedOverGroundIncludingNonCompletedRaces == null ? 0 : averageSpeedOverGroundIncludingNonCompletedRaces.getKnots()); + addNamedElementWithValue(competitorElement, "overall_rank", leaderboard.getTotalRankOfCompetitor(competitor, timePointOfLatestModification)); + addNamedElementWithValue(competitorElement, "overall_score", leaderboard.getNetPoints(competitor, timePointOfLatestModification)); + competitorElement.addContent(createDataConfidenceXML(competitorConfidenceAndErrorMessages)); + TimePoint elapsedTime = MillisecondsTimePoint.now().minus(timeSpent.asMillis()); + addNamedElementWithValue(competitorElement, "generation_time_in_milliseconds", elapsedTime.asMillis()); + return competitorElement; + } + + /** + * Create xml elements related to a leg. + */ + private Element createLegXML(TrackedLeg trackedLeg, Leaderboard leaderboard, int legCounter, + Util.Pair> raceConfidenceAndErrorMessages, + Util.Pair> legConfidenceAndErrorMessages) throws NoWindException, IOException, + ServletException { + TimePoint timeSpent = MillisecondsTimePoint.now(); + Leg leg = trackedLeg.getLeg(); + Element legElement = new Element("leg"); + legElement.addContent(createDataConfidenceXML(legConfidenceAndErrorMessages)); + if (trackedLeg.getTrackedRace().isLive(MillisecondsTimePoint.now())) { + return legElement; + } + addNamedElementWithValue(legElement, "position", legCounter); + addNamedElementWithValue(legElement, "mark_from", leg.getFrom().getName()); + addNamedElementWithValue(legElement, "mark_to", leg.getTo().getName()); + addNamedElementWithValue(legElement, "leg_type", trackedLeg.getLegType(trackedLeg.getTrackedRace().getStartOfRace()).name()); + addNamedElementWithValue(legElement, "great_circle_distance_at_start_of_race_in_meters", trackedLeg.getGreatCircleDistance(trackedLeg.getTrackedRace().getStartOfRace()).getMeters()); + addNamedElementWithValue(legElement, "great_circle_distance_at_end_of_race_in_meters", trackedLeg.getGreatCircleDistance(trackedLeg.getTrackedRace().getEndOfRace()).getMeters()); + + for (Competitor competitor : trackedLeg.getTrackedRace().getCompetitorsFromBestToWorst(/*timePoint*/ trackedLeg.getTrackedRace().getEndOfRace())) { + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Element competitorElement = createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ true, null); + Element competitorLegDataElement = new Element("competitor_leg_data"); + TrackedLegOfCompetitor competitorLeg = trackedLeg.getTrackedLeg(competitor); + + /* if there is no start time then ignore all data of this leg */ + if (competitorLeg == null || competitorLeg.getStartTime() == null || competitorLeg.getFinishTime() == null || competitorLeg.getTrackedLeg().getTrackedRace().getMarkPassings(competitor).isEmpty()) { + competitorElement.addContent(competitorLegDataElement); + legElement.addContent(competitorElement); + continue; + } + TimePoint legFinishTime = competitorLeg.getFinishTime(); + final RankingInfo rankingMetricAtLegFinishTime = trackedLeg.getTrackedRace().getRankingMetric().getRankingInfo(legFinishTime); + competitorLegDataElement.addContent(createTimedXML("leg_started_time_", competitorLeg.getStartTime())); + Util.Pair maximumSpeed = competitorLeg.getMaximumSpeedOverGround(legFinishTime); + addNamedElementWithValue(competitorLegDataElement, "maximum_speed_over_ground_in_knots", maximumSpeed != null ? maximumSpeed.getB().getKnots() : -1); + if (maximumSpeed == null) { + legConfidenceAndErrorMessages = updateConfidence("Competitor "+ competitor.getName() +" has not finished this leg! His maximum speed for this leg is not comparable to others!", 0.1, legConfidenceAndErrorMessages); + } + Speed averageVelocityMadeGood = competitorLeg.getAverageVelocityMadeGood(legFinishTime); + addNamedElementWithValue(competitorLegDataElement, "average_velocity_made_good_in_knots", averageVelocityMadeGood != null ? averageVelocityMadeGood.getKnots() : 0); + addNamedElementWithValue(competitorLegDataElement, "leg_finished_time_as_millis", handleValue(legFinishTime)); + addNamedElementWithValue(competitorLegDataElement, "total_race_time_elapsed_as_millis", handleValue(legFinishTime)-handleValue(trackedLeg.getTrackedRace().getStartOfRace())); + Duration timeSpentInThisLeg = competitorLeg.getTime(legFinishTime); + if (timeSpentInThisLeg == null) { + legConfidenceAndErrorMessages = updateConfidence("Competitor " + competitor.getName() + " seems to not have finished this leg before end of tracking time.", 0.1, legConfidenceAndErrorMessages); + } + addNamedElementWithValue(competitorLegDataElement, "time_spend_in_this_leg_as_millis", timeSpentInThisLeg != null ? timeSpentInThisLeg.asMillis() : new MillisecondsDurationImpl(0).asMillis()); + addNamedElementWithValue(competitorLegDataElement, "gap_to_leader_at_finish_in_seconds", competitorLeg.getGapToLeader(legFinishTime, rankingMetricAtLegFinishTime, WindPositionMode.LEG_MIDDLE).asSeconds()); + Distance windwardDistanceToCompetitorFarthestAhead = competitorLeg.getWindwardDistanceToCompetitorFarthestAhead(legFinishTime, WindPositionMode.LEG_MIDDLE, rankingMetricAtLegFinishTime); + // TODO bug1018 decide whether the following field should be renamed to express that it's not the distance to the "leader" but the competitor farthest ahead; discussed with Simon on 2015-05-28; Simon says we leave it like this for now + addNamedElementWithValue(competitorLegDataElement, "windward_distance_to_overall_leader_that_has_finished_this_leg_in_meters", windwardDistanceToCompetitorFarthestAhead != null ? windwardDistanceToCompetitorFarthestAhead.getMeters() : 0); + addNamedElementWithValue(competitorLegDataElement, "distance_traveled_in_meters", competitorLeg.getDistanceTraveled(legFinishTime).getMeters()); + addNamedElementWithValue(competitorLegDataElement, "average_speed_over_ground_in_knots", competitorLeg.getAverageSpeedOverGround(legFinishTime).getKnots()); + + addNamedElementWithValue(competitorLegDataElement, "number_of_jibes", competitorLeg.getNumberOfJibes(legFinishTime, /* waitForLatest */ false)); + addNamedElementWithValue(competitorLegDataElement, "number_of_tacks", competitorLeg.getNumberOfTacks(legFinishTime, /* waitForLatest */ false)); + addNamedElementWithValue(competitorLegDataElement, "number_of_penalty_circles", competitorLeg.getNumberOfPenaltyCircles(legFinishTime, /* waitForLatest */ false)); + + addNamedElementWithValue(competitorLegDataElement, "leg_rank_at_leg_start", competitorLeg.getRank(competitorLeg.getStartTime())); + addNamedElementWithValue(competitorLegDataElement, "leg_rank_at_leg_finish", competitorLeg.getRank(legFinishTime)); + + if (legCounter>1) { + final TrackedLegOfCompetitor previousLeg = competitorLeg.getTrackedLeg().getTrackedRace().getTrackedLegFinishingAt(competitorLeg.getLeg().getFrom()).getTrackedLeg(competitor); + addNamedElementWithValue(competitorLegDataElement, "rank_gain_for_this_leg_between_start_and_finish", previousLeg.getRank(previousLeg.getFinishTime())-competitorLeg.getRank(legFinishTime)); + } else { + addNamedElementWithValue(competitorLegDataElement, "rank_gain_for_this_leg_between_start_and_finish", 0); + } + + Iterable maneuvers = competitorLeg.getManeuvers(legFinishTime, /*waitForLatest*/false); + addNamedElementWithValue(competitorLegDataElement, "maneuver_count", Util.size(maneuvers)); + Element maneuversElement = new Element("maneuvers"); + int maneuverCounter = 0; + for (Maneuver man : maneuvers) { + maneuverCounter += 1; + Element maneuverInformation = new Element("maneuver"); + addNamedElementWithValue(maneuverInformation, "type", man.getType().toString()); + addNamedElementWithValue(maneuverInformation, "position", maneuverCounter); + addNamedElementWithValue(maneuverInformation, "direction_change_in_degrees", man.getDirectionChangeInDegrees()); + Distance maneuverLoss = man.getManeuverLoss(); + addNamedElementWithValue(maneuverInformation, "loss_in_meters", maneuverLoss != null ? maneuverLoss.getMeters() : 0.0); + addNamedElementWithValue(maneuverInformation, "speed_before_in_knots", man.getSpeedWithBearingBefore().getKnots()); + addNamedElementWithValue(maneuverInformation, "speed_after_in_knots", man.getSpeedWithBearingAfter().getKnots()); + maneuversElement.addContent(maneuverInformation); + } + competitorLegDataElement.addContent(maneuversElement); + + Distance averageCrossTrackError = competitorLeg.getAverageAbsoluteCrossTrackError(legFinishTime, /*waitForLatestAnalysis*/ false); + addNamedElementWithValue(competitorLegDataElement, "average_cross_track_error_in_meters", averageCrossTrackError != null ? averageCrossTrackError.getMeters() : -1); + Distance averageSignedCrossTrackError = competitorLeg.getAverageSignedCrossTrackError(legFinishTime, /*waitForLatestAnalysis*/ false); + addNamedElementWithValue(competitorLegDataElement, "average_signed_cross_track_error_in_meters", averageSignedCrossTrackError != null ? averageSignedCrossTrackError.getMeters() : -1); + + competitorElement.addContent(competitorLegDataElement); + legElement.addContent(competitorElement); + } + TimePoint elapsedTime = MillisecondsTimePoint.now().minus(timeSpent.asMillis()); + addNamedElementWithValue(legElement, "generation_time_in_milliseconds", elapsedTime.asMillis()); + return legElement; + } + + private List createFullWindDataXML(TrackedRace race, Fleet fleet, int sameDayIndex) { + final List windElements = new ArrayList<>(); + final List windSourcesToDeliver = new ArrayList(); + final WindSource windSource = new WindSourceImpl(WindSourceType.COMBINED); + windSourcesToDeliver.add(windSource); + final TimePoint fromTimePoint = race.getStartOfRace(); + if (fromTimePoint != null) { + final TimePoint toTimePoint = race.getEndOfRace(); + final Duration samplingInterval = Duration.ONE_MINUTE.times(5); + final WindTrack windTrack = race.getOrCreateWindTrack(windSource); + TimePoint timePoint = fromTimePoint; + int attemptedNumberOfFixes = 0; + while (toTimePoint == null ? (attemptedNumberOfFixes<5) : (timePoint.compareTo(toTimePoint) < 0)) { + WindWithConfidence> averagedWindWithConfidence = windTrack + .getAveragedWindWithConfidence(null, timePoint); + if (averagedWindWithConfidence != null) { + Element windElement = new Element("windFix"); + addNamedElementWithValue(windElement, "same_day_index", sameDayIndex); + addNamedElementWithValue(windElement, "race_name", race.getRace().getName()); + addNamedElementWithValue(windElement, "fleet_name", fleet.getName()); + windElement.addContent(createTimedXML("", averagedWindWithConfidence.getObject().getTimePoint())); + addNamedElementWithValue(windElement, "bearingInDegrees", averagedWindWithConfidence.getObject().getBearing().getDegrees()); + addNamedElementWithValue(windElement, "directionFromInDegrees", averagedWindWithConfidence.getObject().getBearing().reverse().getDegrees()); + windElement.addContent(createWindXML("", new SpeedWithConfidenceImpl(new KnotSpeedImpl(averagedWindWithConfidence.getObject().getKnots()), + averagedWindWithConfidence.getConfidence(), timePoint))); + windElements.add(windElement); + } + timePoint = timePoint.plus(samplingInterval); + attemptedNumberOfFixes++; + } + } + return windElements; + } + + /** + * Creates xml elements that indicate confidence. + */ + private Element createDataConfidenceXML(Util.Pair> confidenceAndMessages) { + Element confidenceDataElement = new Element("confidence"); + addNamedElementWithValue(confidenceDataElement, "simple_confidence_value", confidenceAndMessages.getA().doubleValue()); + Element messagesElement = new Element("messages"); + for (String message : confidenceAndMessages.getB()) { + addNamedElementWithValue(messagesElement, "message", message); + } + confidenceDataElement.addContent(messagesElement); + return confidenceDataElement; + } + + /** + * Update confidence + * @param message The message that contains information why confidence is decreased + * @param decreaseConfidenceBy Value telling how much the confidence should be decreased + */ + private Util.Pair> updateConfidence(String message, double decreaseConfidenceBy, Util.Pair> confidencePair) { + Vector messages = confidencePair.getB(); + messages.add(message); + return new Util.Pair>(confidencePair.getA().doubleValue()-decreaseConfidenceBy, messages); + } + + private Util.Pair> checkData(TrackedLeg leg) throws Exception { + double simpleConfidence = 1.0; Vector messages = new Vector(); + TimePoint now = MillisecondsTimePoint.now(); + for (TrackedLegOfCompetitor competitorLeg : leg.getTrackedLegsOfCompetitors()) { + if (competitorLeg == null) { + messages.add("Found one leg for a competitor that is null!"); + simpleConfidence = 0.0; + continue; + } + if (competitorLeg.getCompetitor() == null) { + messages.add("Found a leg where the associated competitor is just null!"); + simpleConfidence = 0.0; + continue; + } + if (competitorLeg.getTrackedLeg().getTrackedRace().getMarkPassings(competitorLeg.getCompetitor()).isEmpty()) { + messages.add("Competitor "+ competitorLeg.getCompetitor().getName() + " has no mark passings for the complete race!"); + simpleConfidence -= 0.02; + } + if (!competitorLeg.hasFinishedLeg(now) || competitorLeg.getFinishTime() == null) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has not finished this leg! Leg data won't be available!"); + simpleConfidence -= 0.08; + } + if (!competitorLeg.hasStartedLeg(now) || competitorLeg.getStartTime() == null) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has not started this leg! Leg data won't be available!"); + simpleConfidence -= 0.08; + } + if (competitorLeg.getMaximumSpeedOverGround(now) == null) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no maximum speed for this leg!"); + simpleConfidence -= 0.05; + } + if (competitorLeg.getAverageAbsoluteCrossTrackError(now, /*waitForLatestAnalysis*/ false) == null) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no average cross track error for this leg!"); + simpleConfidence -= 0.02; + } + if (competitorLeg.getAverageSignedCrossTrackError(now, /*waitForLatestAnalysis*/ false) == null) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has no average signed cross track error for this leg!"); + simpleConfidence -= 0.02; + } + if (competitorLeg.getStartTime() != null && competitorLeg.getStartTime().before(leg.getTrackedRace().getStartOfRace())) { + if ((leg.getTrackedRace().getStartOfRace().asMillis()-competitorLeg.getStartTime().asMillis())>=MAX_EARLY_START_DIFFERENCE) { + messages.add("Competitor " + competitorLeg.getCompetitor().getName() + " has a start time of " + competitorLeg.getStartTime() + " that is 10 seconds or more before start of race time (" + leg.getTrackedRace().getStartOfRace() + ")."); + simpleConfidence -= 0.01; + } + } + } + return new Util.Pair>(simpleConfidence, messages); + } + + private Util.Pair> checkData(TrackedRace race) throws Exception { + double simpleConfidence = 1.0; Vector messages = new Vector(); + TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l); + if (race == null) { + messages.add("Tracked race is null - no race seems to be connected!"); + simpleConfidence -= 1; + } else { + if (race.getStartOfRace() == null || race.getStartOfRace().before(dateAtYear2000)) { + messages.add("Start time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); + simpleConfidence -= 1; + } + if (race.getEndOfRace() == null || race.getEndOfRace().before(dateAtYear2000)) { + messages.add("End time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); + simpleConfidence -= 1; + } + if (race.getStartOfTracking() == null || race.getStartOfTracking().before(dateAtYear2000)) { + messages.add("Start tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); + simpleConfidence -= 0.2; + } + if (race.getEndOfTracking() == null || race.getEndOfTracking().before(dateAtYear2000)) { + messages.add("End tracking time of race " + race.getRaceIdentifier().getRaceName() + " is either null or not valid!"); + simpleConfidence -= 0.2; + } + if (race.isLive(MillisecondsTimePoint.now())) { + messages.add("This race is live - data for this race will not be available until the race has been finished!"); + } + } + return new Util.Pair>(simpleConfidence, messages); + } + + private Util.Pair> checkData(Competitor competitor, Boat boatOfCompetitor) throws Exception { + double simpleConfidence = 1.0; Vector messages = new Vector(); + if (competitor.getName() == null || competitor.getName().equals("")) { + messages.add("Competitor " + competitor.getId() + " has no name!"); + simpleConfidence -= 1; + } + if (boatOfCompetitor == null || boatOfCompetitor.getSailID() == null || boatOfCompetitor.getSailID().equals("")) { + messages.add("Competitor " + competitor.getId() + " has no sail id that can be used!"); + simpleConfidence -= 1; + } + if (competitor.getTeam() == null || competitor.getTeam().getNationality() == null) { + messages.add("Either team for "+ competitor.getId() + " is null or nationality could not be determined"); + simpleConfidence -= 0.2; + } + return new Util.Pair>(simpleConfidence, messages); + } + + private Util.Pair> checkData(Leaderboard leaderboard) throws Exception { + double simpleConfidence = 1.0; Vector messages = new Vector(); + int raceColumnCount = 0; int attachedRaceToColumnCount = 0; + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + if (raceColumn.hasTrackedRaces()) { + attachedRaceToColumnCount++; + } + raceColumnCount++; + } + if (raceColumnCount == 0) { + messages.add("Could not find any race columns or none of the race columns has tracked races attached!"); + simpleConfidence -= 1.0; + } + if (attachedRaceToColumnCount < raceColumnCount) { + messages.add("Not all race columns contain attached races! Data being aggregated over all races could be wrong!"); + simpleConfidence -= 0.3; + } + int competitorCount = 0; + for (Iterator iterator = leaderboard.getAllCompetitors().iterator(); iterator.hasNext();) { + iterator.next(); + competitorCount++; + } + if (competitorCount == 0) { + messages.add("Could not find any competitors in this leaderboard!"); + simpleConfidence -= 1.0; + } + TimePoint dateAtYear2000 = new MillisecondsTimePoint(946681200000l); + if (leaderboard.getTimePointOfLatestModification() != null && leaderboard.getTimePointOfLatestModification().before(dateAtYear2000)) { + messages.add("The time point of the last modification for this leaderboard is very old."); + simpleConfidence -= 0.4; + } + return new Util.Pair>(simpleConfidence, messages); + } + + /** + * Groups races together that have been on the same day + */ + private int getSameDayGroupIndex(TrackedRace currentRace, TrackedRace raceBefore) { + if (raceBefore != null && !raceBefore.equals(currentRace)) { + if (currentRace != null && currentRace.getStartOfRace() != null && raceBefore.getStartOfRace() != null) { + Calendar timedDateForCurrentRace = Calendar.getInstance(); + timedDateForCurrentRace.setTime(currentRace.getStartOfRace().asDate()); + String formattedCurrent = new SimpleDateFormat("dd.MM.yyyy").format(timedDateForCurrentRace.getTime()); + + Calendar timedDateForRaceBefore = Calendar.getInstance(); + timedDateForRaceBefore.setTime(raceBefore.getStartOfRace().asDate()); + String formattedBefore = new SimpleDateFormat("dd.MM.yyyy").format(timedDateForRaceBefore.getTime()); + + if (formattedCurrent.equals(formattedBefore)) { + return 0; + } + } + } else { + return 0; + } + return 1; + } + + public void perform() throws Exception { + final Leaderboard leaderboard = getLeaderboard(); + TimePoint timeSpent = MillisecondsTimePoint.now(); + log.info("Starting XML export of " + leaderboard.getName()); + Util.Pair> leaderboardConfidenceAndErrorMessages = checkData(leaderboard); + final List racesElements = new ArrayList(); + final List competitorElements = new ArrayList(); + for (Competitor competitor : leaderboard.getAllCompetitors()) { + Boat boatOfCompetitor = null; // TODO: Where can we get the boat here? + Util.Pair> competitorConfidenceAndErrorMessages = checkData(competitor, boatOfCompetitor); + competitorElements.add(createCompetitorXML(competitor, boatOfCompetitor, leaderboard, /*shortVersion*/ false, competitorConfidenceAndErrorMessages)); + } + List windData = new ArrayList(); + TrackedRace raceBefore = null; int sameDayGroupIndex = 0; int raceCounter = 0; + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + if (trackedRace != null) { + sameDayGroupIndex += getSameDayGroupIndex(raceColumn.getTrackedRace(fleet), raceBefore); + } + TimePoint timeSpentForRace = MillisecondsTimePoint.now(); + Util.Pair> raceConfidenceAndErrorMessages = checkData(trackedRace); + final List legs = new ArrayList(); + if (trackedRace != null && trackedRace.hasGPSData()) { + windData.addAll(createFullWindDataXML(trackedRace, fleet, sameDayGroupIndex)); + int legCounter = 0; + for (TrackedLeg leg : trackedRace.getTrackedLegs()) { + Util.Pair> legConfidenceAndErrorMessages = checkData(leg); + legs.add(createLegXML(leg, leaderboard, ++legCounter, raceConfidenceAndErrorMessages, legConfidenceAndErrorMessages)); + } + Element raceElement = createRaceXML(trackedRace, fleet, legs, raceColumn, leaderboard, sameDayGroupIndex, ++raceCounter, raceConfidenceAndErrorMessages); + TimePoint elapsedTimeForRace = MillisecondsTimePoint.now().minus(timeSpentForRace.asMillis()); + addNamedElementWithValue(raceElement, "generation_time_in_milliseconds", elapsedTimeForRace.asMillis()); + racesElements.add(raceElement); + log.info("Exported complete race " + trackedRace.getRace().getName() + " in " + elapsedTimeForRace.asMillis() + " milliseconds!"); + } else { + racesElements.add(createRaceXMLWithoutRaceData(fleet, raceColumn, leaderboard, sameDayGroupIndex, ++raceCounter, raceConfidenceAndErrorMessages)); + log.info("Exported empty race in race column " + raceColumn.getName() + " with fleet " + fleet.getName()); + } + raceBefore = trackedRace; + } + } + log.info("Finished XML export of leaderboard " + leaderboard.getName() + " in " + MillisecondsTimePoint.now().minus(timeSpent.asMillis()).asMillis() + " milliseconds"); + Element dataToExport = createLeaderboardXML(leaderboard, windData, competitorElements, racesElements, leaderboardConfidenceAndErrorMessages); + sendDocument(dataToExport, leaderboard.getName() + ".xml"); + } +} diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index ab8ab0f4b8f..44ace0f6b93 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -1,265 +1,265 @@ -package com.sap.sailing.racecommittee.app.data; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; - -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.domain.base.LeaderboardGroupBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.configuration.ConfigurationLoader; -import com.sap.sailing.domain.base.configuration.DeviceConfiguration; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; -import com.sap.sailing.domain.base.configuration.RegattaConfiguration; -import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; -import com.sap.sailing.domain.base.impl.BoatClassImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.MarkImpl; -import com.sap.sailing.domain.base.impl.RaceColumnFactorImpl; -import com.sap.sailing.domain.base.impl.StrippedEventImpl; -import com.sap.sailing.domain.base.racegroup.RaceGroup; -import com.sap.sailing.domain.base.racegroup.SeriesWithRows; -import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl; -import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.racecommittee.app.AppPreferences; -import com.sap.sailing.racecommittee.app.data.clients.LoadClient; -import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult; -import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks; -import com.sap.sailing.racecommittee.app.domain.CoursePosition; -import com.sap.sailing.racecommittee.app.domain.ManagedRace; -import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader; -import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl; -import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl; -import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class OfflineDataManager extends DataManager { - - private static boolean isInitialized = false; - private final Context context; - - protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) { - super(context, dataStore, domainFactory); - this.context = context; - if (!isInitialized) { - isInitialized = true; - fillDataStore(dataStore); - } - } - - private void fillDataStore(DataStore dataStore) { - Calendar cal = Calendar.getInstance(); - cal.set(2012, 12, 1); - final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - cal.set(2012, 12, 5); - final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections. emptySet())); - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections. emptySet())); - dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections. emptySet())); - EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections. emptySet()); - newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID())); - newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID())); - dataStore.addEvent(newEvent); - - SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, /* isFleetsCanRunInParallel */ true, null); - SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, /* isFleetsCanRunInParallel */ true, null); - RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying, - medal), new EmptyRegattaConfiguration()); - - List competitors = new ArrayList(); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.BLUE, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", "Muscat", Color.LIGHT_GRAY, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", "Red Bull", Color.RED, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", "Korea", Color.GREEN, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", "Realteam", Color.BLACK, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); - - RaceLog log = new RaceLogImpl(UUID.randomUUID()); - final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); - ConfigurationLoader configuration = PreferencesRegattaConfigurationLoader - .loadFromPreferences(preferences); - - log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, - new MillisecondsTimePoint(new Date().getTime() - 1000))); - - log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()), - AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING)); - - ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), - /* zeroBasedIndexInFleet */ 0); - - log = new RaceLogImpl(UUID.randomUUID()); - /* - * log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED, - * new MillisecondsTimePoint(new Date().getTime() + 100000))); - */ - - ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), - /* zeroBasedIndexInFleet */ 1); - - log = new RaceLogImpl(UUID.randomUUID()); - /* - * log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5, - * RaceLogRaceStatus.FINISHED)); - */ - ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup), - RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), - /* zeroBasedIndexInFleet */ 2); - /* - * ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal, - * raceGroup), null); - */ - dataStore.addRace(q1); - dataStore.addRace(q2); - dataStore.addRace(q3); - // dataStore.addRace(m1); - - Mark m1 = new MarkImpl("Red"); - Mark m2 = new MarkImpl("Green"); - Mark m3 = new MarkImpl("White"); - - dataStore.addMark(m1); - dataStore.addMark(m2); - dataStore.addMark(m3); - } - - @Override - public LoaderCallbacks>> createEventsLoader( - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getEvents(); - } - }); - } - - @Override - public LoaderCallbacks>> createCourseAreasLoader( - final Serializable parentEventId, LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getCourseAreas(dataStore.getEvent(parentEventId)); - } - }); - } - - @Override - public LoaderCallbacks>> createCourseAreasLoader( - final EventBase parentEvent, LoadClient> callback) { - // TODO Auto-generated method stub - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getCourseAreas(parentEvent); - } - }); - } - - @Override - public LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getRaces(); - } - }); - } - - @Override - public LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getMarks(); - } - }); - } - - @Override - public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, - LoadClient callback) { - return new ImmediateDataLoaderCallbacks(context, callback, new Callable() { - @Override - public CourseBase call() throws Exception { - return managedRace.getCourseOnServer(); - } - }); - } - - @Override - public LoaderCallbacks>> createCompetitorsLoader( - final ManagedRace managedRace, LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return managedRace.getCompetitors(); - } - }); - } - - @Override - public LoaderCallbacks> createConfigurationLoader( - DeviceConfigurationIdentifier identifier, LoadClient callback) { - return new ImmediateDataLoaderCallbacks(context, callback, - new Callable() { - @Override - public DeviceConfiguration call() throws Exception { - throw new IllegalStateException("No remote configuration in offline mode."); - } - }); - } - - @Override - public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation, - boolean showMapControls) { - throw new IllegalStateException("No wind map in offline mode."); - } - - @Override - public LoaderCallbacks>> createPositionLoader( - PositionListFragment positionListFragment) { - // TODO Auto-generated method stub - return null; - } - - @Override - public LoaderCallbacks> createRaceColumnFactorLoader(LoadClient callback) { - return null; - } -} +package com.sap.sailing.racecommittee.app.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Callable; + +import android.app.LoaderManager.LoaderCallbacks; +import android.content.Context; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.LeaderboardGroupBase; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.configuration.ConfigurationLoader; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; +import com.sap.sailing.domain.base.configuration.RegattaConfiguration; +import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CourseAreaImpl; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.MarkImpl; +import com.sap.sailing.domain.base.impl.RaceColumnFactorImpl; +import com.sap.sailing.domain.base.impl.StrippedEventImpl; +import com.sap.sailing.domain.base.racegroup.RaceGroup; +import com.sap.sailing.domain.base.racegroup.SeriesWithRows; +import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl; +import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.racecommittee.app.AppPreferences; +import com.sap.sailing.racecommittee.app.data.clients.LoadClient; +import com.sap.sailing.racecommittee.app.data.loaders.DataLoaderResult; +import com.sap.sailing.racecommittee.app.data.loaders.ImmediateDataLoaderCallbacks; +import com.sap.sailing.racecommittee.app.domain.CoursePosition; +import com.sap.sailing.racecommittee.app.domain.ManagedRace; +import com.sap.sailing.racecommittee.app.domain.configuration.impl.PreferencesRegattaConfigurationLoader; +import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceIdentifierImpl; +import com.sap.sailing.racecommittee.app.domain.impl.ManagedRaceImpl; +import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class OfflineDataManager extends DataManager { + + private static boolean isInitialized = false; + private final Context context; + + protected OfflineDataManager(Context context, DataStore dataStore, SharedDomainFactory domainFactory) { + super(context, dataStore, domainFactory); + this.context = context; + if (!isInitialized) { + isInitialized = true; + fillDataStore(dataStore); + } + } + + private void fillDataStore(DataStore dataStore) { + Calendar cal = Calendar.getInstance(); + cal.set(2012, 12, 1); + final TimePoint startDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + cal.set(2012, 12, 5); + final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", true, UUID.randomUUID(), Collections. emptySet())); + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, UUID.randomUUID(), Collections. emptySet())); + dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, UUID.randomUUID(), Collections. emptySet())); + EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", true, UUID.randomUUID(), Collections. emptySet()); + newEvent.getVenue().addCourseArea(new CourseAreaImpl("Offshore", UUID.randomUUID())); + newEvent.getVenue().addCourseArea(new CourseAreaImpl("Stadium", UUID.randomUUID())); + dataStore.addEvent(newEvent); + + SeriesWithRows qualifying = new SeriesWithRowsImpl("Qualifying", false, /* isFleetsCanRunInParallel */ true, null); + SeriesWithRows medal = new SeriesWithRowsImpl("Medal", true, /* isFleetsCanRunInParallel */ true, null); + RaceGroup raceGroup = new RaceGroupImpl("ESS", /* displayName */ null, new BoatClassImpl("X40", false), null, Arrays.asList(qualifying, + medal), new EmptyRegattaConfiguration()); + + List competitors = new ArrayList(); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.BLUE, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "The Wave Muscat", "Muscat", Color.LIGHT_GRAY, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Red Bull Extreme Sailing Team", "Red Bull", Color.RED, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", "Korea", Color.GREEN, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", "Realteam", Color.BLACK, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null)); + + RaceLog log = new RaceLogImpl(UUID.randomUUID()); + final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); + ConfigurationLoader configuration = PreferencesRegattaConfigurationLoader + .loadFromPreferences(preferences); + + log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, + new MillisecondsTimePoint(new Date().getTime() - 1000))); + + log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()), + AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING)); + + ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), + /* zeroBasedIndexInFleet */ 0); + + log = new RaceLogImpl(UUID.randomUUID()); + /* + * log.add(factory.createStartTimeEvent( new MillisecondsTimePoint(new Date()), 1, RaceLogRaceStatus.SCHEDULED, + * new MillisecondsTimePoint(new Date().getTime() + 100000))); + */ + + ManagedRace q2 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("B", new FleetImpl("A.A"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), + /* zeroBasedIndexInFleet */ 1); + + log = new RaceLogImpl(UUID.randomUUID()); + /* + * log.add(factory.createRaceStatusEvent( new MillisecondsTimePoint(new Date()), 5, + * RaceLogRaceStatus.FINISHED)); + */ + ManagedRace q3 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("Q3", new FleetImpl("Default"), qualifying, raceGroup), + RaceStateImpl.create(new AndroidRaceLogResolver(), log, AppPreferences.on(context).getAuthor(), configuration), + /* zeroBasedIndexInFleet */ 2); + /* + * ManagedRace m1 = new ManagedRaceImpl( new ManagedRaceIdentifierImpl( "M1", new FleetImpl("Default"), medal, + * raceGroup), null); + */ + dataStore.addRace(q1); + dataStore.addRace(q2); + dataStore.addRace(q3); + // dataStore.addRace(m1); + + Mark m1 = new MarkImpl("Red"); + Mark m2 = new MarkImpl("Green"); + Mark m3 = new MarkImpl("White"); + + dataStore.addMark(m1); + dataStore.addMark(m2); + dataStore.addMark(m3); + } + + @Override + public LoaderCallbacks>> createEventsLoader( + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getEvents(); + } + }); + } + + @Override + public LoaderCallbacks>> createCourseAreasLoader( + final Serializable parentEventId, LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getCourseAreas(dataStore.getEvent(parentEventId)); + } + }); + } + + @Override + public LoaderCallbacks>> createCourseAreasLoader( + final EventBase parentEvent, LoadClient> callback) { + // TODO Auto-generated method stub + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getCourseAreas(parentEvent); + } + }); + } + + @Override + public LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getRaces(); + } + }); + } + + @Override + public LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, + LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { + @Override + public Collection call() throws Exception { + return dataStore.getMarks(); + } + }); + } + + @Override + public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, + LoadClient callback) { + return new ImmediateDataLoaderCallbacks(context, callback, new Callable() { + @Override + public CourseBase call() throws Exception { + return managedRace.getCourseOnServer(); + } + }); + } + + @Override + public LoaderCallbacks>> createCompetitorsLoader( + final ManagedRace managedRace, LoadClient> callback) { + return new ImmediateDataLoaderCallbacks>(context, callback, + new Callable>() { + @Override + public Collection call() throws Exception { + return managedRace.getCompetitors(); + } + }); + } + + @Override + public LoaderCallbacks> createConfigurationLoader( + DeviceConfigurationIdentifier identifier, LoadClient callback) { + return new ImmediateDataLoaderCallbacks(context, callback, + new Callable() { + @Override + public DeviceConfiguration call() throws Exception { + throw new IllegalStateException("No remote configuration in offline mode."); + } + }); + } + + @Override + public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, boolean showSimulation, + boolean showMapControls) { + throw new IllegalStateException("No wind map in offline mode."); + } + + @Override + public LoaderCallbacks>> createPositionLoader( + PositionListFragment positionListFragment) { + // TODO Auto-generated method stub + return null; + } + + @Override + public LoaderCallbacks> createRaceColumnFactorLoader(LoadClient callback) { + return null; + } +} From 1dc46761951f1a6687212282a0405b984519e2d0 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 21 Jun 2017 15:40:59 +0200 Subject: [PATCH 034/271] Added some basic load/store tests for boats --- .../mongodb/test/StoreAndLoadBoatsTest.java | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadBoatsTest.java diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadBoatsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadBoatsTest.java new file mode 100644 index 00000000000..c992b6a0f36 --- /dev/null +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadBoatsTest.java @@ -0,0 +1,123 @@ +package com.sap.sailing.mongodb.test; + +import static org.junit.Assert.assertEquals; + +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.MongoException; +import com.mongodb.WriteConcern; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.impl.CollectionNames; +import com.sap.sse.common.Util; + +public class StoreAndLoadBoatsTest extends AbstractMongoDBTest { + private DomainFactory domainFactory; + private final static BoatClass boatClass505 = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + + public StoreAndLoadBoatsTest() throws UnknownHostException, MongoException { + super(); + } + + @Before + public void setUp() { + // clear the domainFactory competitor store for a clean start: + domainFactory = new DomainFactoryImpl((srlid)->null); + } + + private void dropBoatCollection() { + DB db = getMongoService().getDB(); + DBCollection boatCollection = db.getCollection(CollectionNames.BOATS.name()); + boatCollection.setWriteConcern(WriteConcern.SAFE); // ensure that the drop() has happened + boatCollection.drop(); + } + + @Test + public void testStoreAndUpdateBoat() throws URISyntaxException { + String sailID1 = "GER 1234"; + String sailID2 = "GER 12345"; + String boatName1 = "Hassos Boot"; + String boatName2 = "Hasso Plattners Boot"; + + MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); + dropBoatCollection(); + + DynamicBoat boat = (DynamicBoat) new BoatImpl("id12345", boatName1, boatClass505, sailID1); + mongoObjectFactory.storeBoat(boat); + + Collection allBoats= domainObjectFactory.loadAllBoats(); + assertEquals(1, Util.size(allBoats)); + DynamicBoat loadedBoat = (DynamicBoat) allBoats.iterator().next(); + assertEquals(sailID1, loadedBoat.getSailID()); + assertEquals(boatName1, loadedBoat.getName()); + + loadedBoat.setName(boatName2); + loadedBoat.setSailId(sailID2); + mongoObjectFactory.storeBoat(loadedBoat); + + allBoats = domainObjectFactory.loadAllBoats(); + assertEquals(1, Util.size(allBoats)); + loadedBoat = (DynamicBoat) allBoats.iterator().next(); + assertEquals(sailID2, loadedBoat.getSailID()); + assertEquals(boatName2, loadedBoat.getName()); + } + + @Test + public void testStoreAndUpdateBoatWithUUIDAsId() { + MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); + dropBoatCollection(); + + DynamicBoat boat = (DynamicBoat) new BoatImpl(UUID.randomUUID(), "Hasso", boatClass505, "GER 1234"); + mongoObjectFactory.storeBoat(boat); + assertEquals(1, Util.size(domainObjectFactory.loadAllBoats())); + boat.setName("Hasso Plattner"); + mongoObjectFactory.storeBoat(boat); + assertEquals(1, Util.size(domainObjectFactory.loadAllBoats())); + } + + @Test + public void testStoreAndRemoveBoat() { + MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); + dropBoatCollection(); + + DynamicBoat boat = (DynamicBoat) new BoatImpl("id12345", "Hassos boot", boatClass505, "GER 1234"); + mongoObjectFactory.storeBoat(boat); + assertEquals(1, Util.size(domainObjectFactory.loadAllBoats())); + + mongoObjectFactory.removeBoat(boat); + assertEquals(0, Util.size(domainObjectFactory.loadAllBoats())); + } + + @Test + public void testStoreAndRemoveCompetitorWithUUIDAsId() { + MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); + dropBoatCollection(); + + DynamicBoat boat = (DynamicBoat) new BoatImpl(UUID.randomUUID(), "Hassos boot", boatClass505, "GER 1234"); + mongoObjectFactory.storeBoat(boat); + assertEquals(1, Util.size(domainObjectFactory.loadAllBoats())); + + mongoObjectFactory.removeBoat(boat); + assertEquals(0, Util.size(domainObjectFactory.loadAllBoats())); + } +} From dc045b7f4be8e42ab0ca6d645dd4f0e8c44509c4 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 21 Jun 2017 15:41:48 +0200 Subject: [PATCH 035/271] added a load/store test case for new attribute shortName of competitor --- ...{StoreCompetitorTest.java => StoreAndLoadCompetitorsTest.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/{StoreCompetitorTest.java => StoreAndLoadCompetitorsTest.java} (100%) diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java similarity index 100% rename from java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreCompetitorTest.java rename to java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java From 244908246dd29475bc3a52d30f5a78c9bb5d0dce Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 21 Jun 2017 17:09:50 +0200 Subject: [PATCH 036/271] added a load/store test for the new shortName attribute of a competitor --- .../mongodb/test/StoreAndLoadCompetitorsTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java index 6c5713346e3..823cc4f3384 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java @@ -26,10 +26,10 @@ import com.sap.sailing.domain.persistence.impl.CollectionNames; import com.sap.sailing.domain.test.AbstractLeaderboardTest; import com.sap.sse.common.Util; -public class StoreCompetitorTest extends AbstractMongoDBTest { +public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { private DomainFactory domainFactory; - public StoreCompetitorTest() throws UnknownHostException, MongoException { + public StoreAndLoadCompetitorsTest() throws UnknownHostException, MongoException { super(); } @@ -52,12 +52,15 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { URI flagImageURI2 = new URI("http://www.sapsailing/flagimage2.jpg"); String competitorName1 = "Hasso"; String competitorName2 = "Hasso Plattner"; + String competitorShortName1 = "H."; + String competitorShortName2 = "H.P."; MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat(competitorName1).getCompetitor(); + c.setShortName(competitorShortName1); c.setFlagImage(flagImageURI1); mongoObjectFactory.storeCompetitor(c); @@ -66,8 +69,10 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next(); assertEquals(flagImageURI1, loadedCompetitor.getFlagImage()); assertEquals(competitorName1, loadedCompetitor.getName()); + assertEquals(competitorShortName1, loadedCompetitor.getShortName()); loadedCompetitor.setName(competitorName2); + loadedCompetitor.setShortName(competitorShortName2); loadedCompetitor.setFlagImage(flagImageURI2); mongoObjectFactory.storeCompetitor(loadedCompetitor); @@ -76,6 +81,7 @@ public class StoreCompetitorTest extends AbstractMongoDBTest { loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next(); assertEquals(flagImageURI2, loadedCompetitor.getFlagImage()); assertEquals(competitorName2, loadedCompetitor.getName()); + assertEquals(competitorShortName2, loadedCompetitor.getShortName()); } @Test From 69ea00be972c68f3e84d141cdcdbdc9e70c5f734 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Thu, 22 Jun 2017 13:41:41 +0200 Subject: [PATCH 037/271] fixed inconsistent name and parameter type of method TrackedRace.getBoatOfCompetitor(Serializable competitorId) to be TrackedRace.getBoatOfCompetitor(Competitor competitor) --- .../sap/sailing/domain/test/mock/MockedTrackedRace.java | 2 +- .../test/mock/MockedTrackedRaceWithStartTimeAndRanks.java | 2 +- .../src/com/sap/sailing/domain/tracking/TrackedRace.java | 2 +- .../sap/sailing/domain/tracking/impl/TrackedLegImpl.java | 2 +- .../sap/sailing/domain/tracking/impl/TrackedRaceImpl.java | 4 ++-- .../com/sap/sailing/gwt/ui/test/MockedTrackedRace.java | 2 +- .../server/gateway/jaxrs/api/RegattasResource.java | 6 +++--- .../TrackRaceBoatCompetitorMetadataReplicationTest.java | 2 +- .../sailing/server/impl/PersistentCompetitorStore.java | 8 ++++++-- .../sap/sailing/server/masterdata/DummyTrackedRace.java | 2 +- .../src/com/sap/sailing/xmlexport/FoilingData.java | 2 +- 11 files changed, 19 insertions(+), 15 deletions(-) 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 d40e8b3219c..86f7f236214 100644 --- 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 @@ -1151,7 +1151,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Boat getBoatOfCompetitor(Serializable competitorId) { + public Boat getBoatOfCompetitor(Competitor competitor) { return null; } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java index b802a8503ae..71fe259b958 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java @@ -705,7 +705,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { } @Override - public Boat getBoatOfCompetitor(Serializable competitorId) { + public Boat getBoatOfCompetitor(Competitor competitor) { return null; } } 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 5795c5bf69e..016e4be172b 100644 --- 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 @@ -710,7 +710,7 @@ public interface TrackedRace extends Serializable, IsManagedByCache(); for (Competitor competitor : competitors) { - trackedLegsOfCompetitors.put(competitor, new TrackedLegOfCompetitorImpl(this, competitor, trackedRace.getBoatOfCompetitor(competitor.getId()))); + trackedLegsOfCompetitors.put(competitor, new TrackedLegOfCompetitorImpl(this, competitor, trackedRace.getBoatOfCompetitor(competitor))); } trackedRace.addListener(new CacheClearingRaceChangeListener()); competitorTracksOrderedByRank = new ConcurrentHashMap<>(); 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 0bc351a4e0d..6825d89ec97 100644 --- 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 @@ -1416,8 +1416,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } @Override - public Boat getBoatOfCompetitor(Serializable competitorId) { - return getRace().getBoatOfCompetitorById(competitorId); + public Boat getBoatOfCompetitor(Competitor competitor) { + return getRace().getBoatOfCompetitorById(competitor.getId()); } @Override 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 5af4fbc966d..a4405b957c9 100644 --- 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 @@ -873,7 +873,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Boat getBoatOfCompetitor(Serializable competitorId) { + public Boat getBoatOfCompetitor(Competitor competitor) { return null; } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index dc84a325be7..db6d86f1c07 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -281,7 +281,7 @@ public class RegattasResource extends AbstractSailingServerResource { JSONObject jsonCompetitor = new JSONObject(); jsonCompetitor.put("id", competitor.getId() != null ? competitor.getId().toString() : null); jsonCompetitor.put("name", competitor.getName()); - jsonCompetitor.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()); + jsonCompetitor.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID()); jsonCompetitor.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); if(competitor.getFlagImage() != null) { jsonCompetitor.put("flagImage", competitor.getFlagImage().toString()); @@ -933,7 +933,7 @@ public class RegattasResource extends AbstractSailingServerResource { CompetitorWithBoatJsonSerializer serializer = new CompetitorWithBoatJsonSerializer(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { - Boat boat = trackedRace.getBoatOfCompetitor(c.getId()); + Boat boat = trackedRace.getBoatOfCompetitor(c); JSONObject jsonCompetitor = serializer.serialize(new CompetitorAndBoatImpl(c, boat)); result.add(jsonCompetitor); } @@ -1206,7 +1206,7 @@ public class RegattasResource extends AbstractSailingServerResource { } jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId().toString() : null); jsonCompetitorInLeg.put("name", competitor.getName()); - jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()); + jsonCompetitorInLeg.put("sailNumber", trackedRace.getBoatOfCompetitor(competitor).getSailID()); jsonCompetitorInLeg.put("color", competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); jsonCompetitorInLeg.put("rank", rank++); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java index 5a2f191dcba..efe2c708d28 100644 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/TrackRaceBoatCompetitorMetadataReplicationTest.java @@ -125,7 +125,7 @@ public class TrackRaceBoatCompetitorMetadataReplicationTest extends AbstractServ for (Competitor competitor : masterCompetitors) { Competitor replicaCompetitor = findCompetitor(replicaCompetitors, competitor); - Boat competitorBoat = masterTrackedRace.getBoatOfCompetitor(competitor.getId()); + Boat competitorBoat = masterTrackedRace.getBoatOfCompetitor(competitor); switch (competitorBoat.getSailID()) { case boat1CompetitorName: compareBoatOfCompetitors(masterTrackedRace.getRace().getBoatOfCompetitorById(competitor.getId()), diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 36ea61f7ef6..098340fd8f0 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.net.URI; +import java.util.Collection; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.base.Boat; @@ -52,10 +53,13 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo.removeAllCompetitors(); storeTo.removeAllBoats(); } else { - for (Competitor competitor : loadFrom.loadAllCompetitors()) { + // TODO bug2822: How to migrate the competitors with contained boats to competitors with separate boat + Collection allCompetitors = loadFrom.loadAllCompetitors(); + for (Competitor competitor : allCompetitors) { addCompetitorToTransientStore(competitor.getId(), competitor); } - for (Boat boat: loadFrom.loadAllBoats()) { + Collection allBoats = loadFrom.loadAllBoats(); + for (Boat boat: allBoats) { addBoatToTransientStore(boat.getId(), boat); } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java index 06fdc73c69d..8503125b310 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java @@ -624,7 +624,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { } @Override - public Boat getBoatOfCompetitor(Serializable competitorId) { + public Boat getBoatOfCompetitor(Competitor competitor) { return null; } diff --git a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java index b9d4d343f0a..6ef310ee28a 100644 --- a/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java +++ b/java/com.sap.sailing.xmlexport/src/com/sap/sailing/xmlexport/FoilingData.java @@ -139,7 +139,7 @@ public class FoilingData { result.append("UNKNOWN").append(";"); } result.append(competitor.getName()).append(";"); - result.append(trackedRace.getBoatOfCompetitor(competitor.getId()).getSailID()).append(";"); + result.append(trackedRace.getBoatOfCompetitor(competitor).getSailID()).append(";"); result.append(competitor.getId()).append(";"); result.append(speedOfCompetitor != null ? speedOfCompetitor.getKnots() : "0.0").append(";"); result.append(rideHeight).append(";"); From 3e78e7ed0e0ae7c081e496def587f071d4f7f99c Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Thu, 22 Jun 2017 15:26:55 +0200 Subject: [PATCH 038/271] use the boatId attribute of boat metadata from tractrac to create the sailId of the boat (instead of the short name) --- .../sap/sailing/domain/tractracadapter/DomainFactory.java | 2 +- .../domain/tractracadapter/impl/DomainFactoryImpl.java | 8 +++++--- .../domain/tractracadapter/impl/RaceCourseReceiver.java | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) 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 4081c549ab9..a2513cef915 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 @@ -264,7 +264,7 @@ public interface DomainFactory { */ RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds); - Map getCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass); + Map getOrCreateCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass); Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race); 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 13e4efd3b5e..7d3cf0c64f8 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 @@ -646,22 +646,24 @@ public class DomainFactoryImpl implements DomainFactory { * 2. Races without any boat information */ @Override - public Map getCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass) { + public Map getOrCreateCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass) { final Map competitorsAndBoats = new HashMap<>(); getCompetingCompetitors(race).forEach(rc->{ BoatMetaData competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); Boat boatOfCompetitor; - String sailId = rc.getCompetitor().getShortName(); + // Case 1 if (competitorBoatInfo != null) { // create an unique for such a boot an search in the boat store for it Serializable boatId = createUniqueBoatIdentifierFromBoatMetadata(race, competitorBoatInfo); + String sailId = competitorBoatInfo.getId(); // we take here the boatId as sailID which is a number like 1, 2, 3 boatOfCompetitor = getOrCreateBoat(boatId, competitorBoatInfo.getName(), - defaultBoatClass, sailId, AbstractColor.getCssColor(competitorBoatInfo.getColor()) ); + defaultBoatClass, sailId, AbstractColor.getCssColor(competitorBoatInfo.getColor())); } else { // Case 2 Serializable boatId = createUniqueBoatIdentifierFromCompetitor(race, rc); + String sailId = rc.getCompetitor().getShortName(); boatOfCompetitor = getOrCreateBoat(boatId, "Boat of " + sailId, defaultBoatClass, sailId, null); } 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 0682b77b922..d99329eabd8 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 @@ -157,7 +157,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue, BoatClass> competitorsAndDominantBoatClass = getDomainFactory().getCompetitorsAndDominantBoatClass(tractracRace); - Map competitorAndBoats = getDomainFactory().getCompetitorsAndTheirBoats(tractracRace, competitorsAndDominantBoatClass.getB()); + Map competitorAndBoats = getDomainFactory().getOrCreateCompetitorsAndTheirBoats(tractracRace, competitorsAndDominantBoatClass.getB()); trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace( getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getA(), competitorsAndDominantBoatClass.getB(), competitorAndBoats, course, sidelines, windStore, delayToLiveInMillis, From d9c27ec6df0678dd525e98f8b2996e19e989cff3 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Fri, 23 Jun 2017 14:09:35 +0200 Subject: [PATCH 039/271] fixed javadoc --- .../com/sap/sailing/domain/common/dto/CompetitorDTO.java | 9 +++++++++ .../domain/common/dto/CompetitorWithoutBoatDTO.java | 3 +++ 2 files changed, 12 insertions(+) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index dba6af298db..8eb43825e79 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -1,5 +1,14 @@ package com.sap.sailing.domain.common.dto; +/** + * Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the + * {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the + * {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject + * to change for a competitor while the ID remains unchanged. + * + * @author Axel Uhl (d043530) + * + */ public interface CompetitorDTO extends CompetitorWithoutBoatDTO { String getSailID(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java index 3a22072d24d..b1f3adfc5d9 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorWithoutBoatDTO.java @@ -6,6 +6,9 @@ import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; +/** + * Equality and hash code are based on the {@link #getIdAsString() ID} and all contained attributes like name, shortName, email, etc. + */ public interface CompetitorWithoutBoatDTO extends Serializable, MappableToDevice { String getTwoLetterIsoCountryCode(); From 2edc3ee9283b6622b3abfd058021da58cf8c0118 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 26 Jun 2017 14:27:57 +0200 Subject: [PATCH 040/271] updated (only) the shortName attribute of a competitor in case we have a boat info available --- .../tractracadapter/impl/DomainFactoryImpl.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 7d3cf0c64f8..2331b60e6d0 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 @@ -668,6 +668,20 @@ public class DomainFactoryImpl implements DomainFactory { } Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); + if (competitorBoatInfo != null && existingCompetitor.getShortName() != rc.getCompetitor().getShortName()) { + // in case we find a boat info we only want to update the shortName field of the competitor (instead of using sailID) + CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); + boolean isOldCompetitorToUpdateDuringGetOrCreate = competitorStore.isCompetitorToUpdateDuringGetOrCreate(existingCompetitor); + competitorStore.allowCompetitorResetToDefaults(existingCompetitor); + existingCompetitor = competitorStore.getOrCreateCompetitor(existingCompetitor.getId(), existingCompetitor.getName(), + rc.getCompetitor().getShortName(), existingCompetitor.getColor(), existingCompetitor.getEmail(), + existingCompetitor.getFlagImage(), (DynamicTeam) existingCompetitor.getTeam(), existingCompetitor.getTimeOnTimeFactor(), + existingCompetitor.getTimeOnDistanceAllowancePerNauticalMile(), existingCompetitor.getSearchTag()); + if (isOldCompetitorToUpdateDuringGetOrCreate) { + competitorStore.allowCompetitorResetToDefaults(existingCompetitor); + } + + } competitorsAndBoats.put(existingCompetitor, boatOfCompetitor); }); return competitorsAndBoats; From 18067e6599da2bbf76059a1dd34080b84e2708fe Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 26 Jun 2017 15:49:21 +0200 Subject: [PATCH 041/271] Added a RegisterBoat racelog event (with persistence) Removed BoatClassDTO from CompetitorDTO as it is contained in the BoatDTO as well --- .../domain/common/dto/CompetitorDTO.java | 5 +- .../domain/common/dto/CompetitorDTOImpl.java | 16 ++---- .../impl/DomainObjectFactoryImpl.java | 18 +++++++ .../impl/MongoObjectFactoryImpl.java | 8 +++ .../impl/MongoRegattaLogStoreVisitor.java | 6 +++ .../tracking/RaceLogRegisterBoatEvent.java | 10 ++++ .../RaceLogUseBoatsFromRaceLogEvent.java | 18 +++++++ .../regatta/RegattaLogEventVisitor.java | 3 ++ .../events/RegattaLogRegisterBoatEvent.java | 10 ++++ .../impl/RegattaLogRegisterBoatEventImpl.java | 39 ++++++++++++++ .../impl/BaseRegattaLogEventVisitor.java | 5 ++ .../regatta/impl/RegattaLogEventListener.java | 6 +++ .../shared/events/RegisterBoatEvent.java | 22 ++++++++ .../RegisterCompetitorAndBoatEvent.java | 11 ++-- .../events/RegisterCompetitorEvent.java | 3 +- .../impl/BaseRegisterBoatEventImpl.java | 51 +++++++++++++++++++ ...aseRegisterCompetitorAndBoatEventImpl.java | 11 +++- .../impl/TransientCompetitorStoreImpl.java | 1 - .../test/LeaderboardDTODiffingTest.java | 8 +-- .../ui/adminconsole/CompetitorEditDialog.java | 4 +- .../adminconsole/CompetitorTableWrapper.java | 35 +++++++++++-- 21 files changed, 254 insertions(+), 36 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index 8eb43825e79..bb36f8d7254 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -12,10 +12,11 @@ package com.sap.sailing.domain.common.dto; public interface CompetitorDTO extends CompetitorWithoutBoatDTO { String getSailID(); + BoatDTO getBoat(); + + // TODO bug2822: Should we remove this? BoatClassDTO getBoatClass(); - BoatDTO getBoat(); - /** * A regular instance will simply return this object. A compacted version may compute the result by looking it up * from the previous version of the enclosing leaderboard. diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 57cf3bab7e7..988b35aa804 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -7,26 +7,23 @@ import com.sap.sse.common.Duration; public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements CompetitorDTO, Serializable { private static final long serialVersionUID = -4997852354821083154L; - private BoatClassDTO boatClass; private BoatDTO boat; public CompetitorDTOImpl() {} public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, String countryName, String idAsString, String imageURL, String flagImageURL, - BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + BoatDTO boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { super(name, shortName, color, email, twoLetterIsoCountryCode, threeLetterIocCountryCode, countryName, idAsString, imageURL, flagImageURL, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); this.boat = boat; - this.boatClass = boatClass; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); result = prime * result + ((boat == null) ? 0 : boat.hashCode()); return result; } @@ -40,11 +37,6 @@ public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements C if (getClass() != obj.getClass()) return false; CompetitorDTOImpl other = (CompetitorDTOImpl) obj; - if (boatClass == null) { - if (other.boatClass != null) - return false; - } else if (!boatClass.equals(other.boatClass)) - return false; if (boat == null) { if (other.boat != null) return false; @@ -60,16 +52,16 @@ public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements C @Override public String getSailID() { - return boat==null?null:boat.getSailId(); + return boat == null ? null : boat.getSailId(); } @Override public BoatClassDTO getBoatClass() { - return boatClass; + return boat == null ? null : boat.getBoatClass(); } @Override public BoatDTO getBoat() { return boat; - } + } } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index df81dfb3983..06358e9a8a0 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -104,6 +104,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEnde import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -114,6 +115,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; @@ -1732,6 +1734,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName())) { return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass.equals(RegattaLogRegisterBoatEvent.class.getSimpleName())) { + return loadRegattaLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { @@ -1807,6 +1811,20 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return result; } + private RegattaLogRegisterBoatEvent loadRegattaLogRegisterBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + Boat boat = getBoatByID(dbObject); + final RegattaLogRegisterBoatEvent result; + if (boat == null) { + result = null; + logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ + " from registration event with ID "+id+". Skipping this boat registration."); + } else { + result = new RegattaLogRegisterBoatEventImpl(createdAt, logicalTimePoint, author, id, boat); + } + return result; + } + private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Competitor comp = getCompetitorByID(dbObject); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 986ccb4acdb..6174f0ebc8b 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -57,6 +57,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompeti import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -1501,6 +1502,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterBoatEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterBoatEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_BOAT_ID.name(), event.getBoat().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java index 2dd3aa01f86..2a3d97d0671 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -53,6 +54,11 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); } + @Override + public void visit(RegattaLogRegisterBoatEvent event) { + mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java new file mode 100644 index 00000000000..41cce095b27 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java @@ -0,0 +1,10 @@ +package com.sap.sailing.domain.abstractlog.race.tracking; + +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; + +public interface RaceLogRegisterBoatEvent extends RaceLogEvent, +RegisterBoatEvent { + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java new file mode 100644 index 00000000000..b8e394b37e0 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java @@ -0,0 +1,18 @@ +package com.sap.sailing.domain.abstractlog.race.tracking; + +import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; + +/** + * This is a marker event, which marks a {@link RaceLog} for using it's own boat registrations. When present, + * boats are not registered on the RegattaLog corresponding to the RaceLog, but on the RaceLog itself. + * + * See bug2851. + * + * @see RaceLogUsesOwnBoatsAnalyzer + * @author Frank Mittag + * + */ +public interface RaceLogUseBoatsFromRaceLogEvent extends RaceLogEvent, Revokable { +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index 08837b2c531..86d9f917ecc 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -5,6 +5,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -22,6 +23,8 @@ public interface RegattaLogEventVisitor { void visit(RegattaLogCloseOpenEndedDeviceMappingEvent event); + void visit(RegattaLogRegisterBoatEvent event); + void visit(RegattaLogRegisterCompetitorEvent event); void visit(RegattaLogRegisterCompetitorAndBoatEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java new file mode 100644 index 00000000000..2a14d08cf9f --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java @@ -0,0 +1,10 @@ +package com.sap.sailing.domain.abstractlog.regatta.events; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; + +public interface RegattaLogRegisterBoatEvent extends RegattaLogEvent, +RegisterBoatEvent { + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java new file mode 100644 index 00000000000..3a4c4f0269f --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java @@ -0,0 +1,39 @@ +package com.sap.sailing.domain.abstractlog.regatta.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.TimePoint; + +public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl + implements RegattaLogRegisterBoatEvent { + private static final long serialVersionUID = -4531928509653259811L; + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public RegattaLogRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, Boat boat) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, boat); + } + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public RegattaLogRegisterBoatEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Boat boat) throws IllegalArgumentException { + super(logicalTimePoint, author, boat); + } + + @Override + public void accept(RegattaLogEventVisitor visitor) { + visitor.visit(this); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java index df2c6e92249..409064f0827 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java @@ -6,6 +6,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -34,6 +35,10 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor { public void visit(RegattaLogCloseOpenEndedDeviceMappingEvent event) { } + @Override + public void visit(RegattaLogRegisterBoatEvent event) { + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java index dbe0f594062..7f4ae3f34ca 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java @@ -7,6 +7,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEve import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; @@ -36,6 +37,11 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor eventAdded(event); } + @Override + public void visit(RegattaLogRegisterBoatEvent event) { + eventAdded(event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { eventAdded(event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java new file mode 100644 index 00000000000..094a20c5d8d --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java @@ -0,0 +1,22 @@ +package com.sap.sailing.domain.abstractlog.shared.events; + +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; +import com.sap.sse.common.IsManagedByCache; + +/** + * Register a boat for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. + * + * A dummy {@link Boat} implementation with only an {@link Boat#getId() id} may be used, + * if the boat is known to already exist on the server, as it is + * {@link IsManagedByCache#resolve(com.sap.sailing.domain.base.SharedDomainFactory) resolved} + * on arrival. + * @author Frank Mittag + * + */ +public interface RegisterBoatEvent extends AbstractLogEvent, Revokable { + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java index 2b5298f7a19..f1fb754ec8b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java @@ -1,14 +1,12 @@ package com.sap.sailing.domain.abstractlog.shared.events; -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.IsManagedByCache; /** - * Register a competitor and the boat for that race using the {@link RaceLog} in racelog-tracked races. + * Register a competitor together with a boat for {@link RaceLog} and {@link RegattaLog} trackeds race and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, * if the competitor is known to already exist on the server, as it is @@ -17,8 +15,5 @@ import com.sap.sse.common.IsManagedByCache; * @author Frank Mittag * */ -public interface RegisterCompetitorAndBoatEvent extends AbstractLogEvent, Revokable { - Competitor getCompetitor(); - - Boat getBoat(); +public interface RegisterCompetitorAndBoatEvent extends RegisterBoatEvent, RegisterCompetitorEvent { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java index 9533e293da3..95897699c6c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java @@ -3,11 +3,12 @@ package com.sap.sailing.domain.abstractlog.shared.events; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.IsManagedByCache; /** - * Register a competitor for that race using the {@link RaceLog} in racelog-tracked races. + * Register a competitor for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, * if the competitor is known to already exist on the server, as it is diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java new file mode 100644 index 00000000000..8e57146971f --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java @@ -0,0 +1,51 @@ +package com.sap.sailing.domain.abstractlog.shared.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.base.Boat; +import com.sap.sse.common.TimePoint; + +public abstract class BaseRegisterBoatEventImpl extends AbstractLogEventImpl implements + RegisterBoatEvent { + private static final long serialVersionUID = -224096196692372694L; + private final Boat boat; + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public BaseRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Boat boat) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, pId); + checkBoat(boat); + this.boat = boat; + } + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public BaseRegisterBoatEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Boat boat) throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), boat); + } + + private static void checkBoat(Boat boat) throws IllegalArgumentException { + if (boat == null) { + throw new IllegalArgumentException("Boat may not be null"); + } + } + + @Override + public Boat getBoat() { + return boat; + } + + @Override + public String getShortInfo() { + return "boat: " + getBoat().toString(); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java index 4803a13a1bf..3baedc08e17 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorAndBoatEventImpl.java @@ -17,19 +17,20 @@ public abstract class BaseRegisterCompetitorAndBoatEventImpl extends A /** * @throws IllegalArgumentException - * if {@code competitor} is null + * if {@code competitor} is null or if {@code boat} is null */ public BaseRegisterCompetitorAndBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Competitor competitor, Boat boat) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, pId); checkCompetitor(competitor); + checkBoat(boat); this.competitor = competitor; this.boat = boat; } /** * @throws IllegalArgumentException - * if {@code competitor} is null + * if {@code competitor} is null or if {@code boat} is null */ public BaseRegisterCompetitorAndBoatEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Competitor competitor, Boat boat) throws IllegalArgumentException { @@ -42,6 +43,12 @@ public abstract class BaseRegisterCompetitorAndBoatEventImpl extends A } } + private static void checkBoat(Boat boat) throws IllegalArgumentException { + if (boat == null) { + throw new IllegalArgumentException("Boat may not be null"); + } + } + @Override public Competitor getCompetitor() { return competitor; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 92d59e841d7..49cd193c618 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -304,7 +304,6 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab c.getImageURL(), c.getFlagImageURL(), boatDTO, - boatClassDTO, c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); return competitorDTO; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index 986c7e34c9a..080546cdec0 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -236,7 +236,7 @@ public class LeaderboardDTODiffingTest { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), - new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), /* timeOnTimeFactor */ null, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS"); @@ -258,7 +258,7 @@ public class LeaderboardDTODiffingTest { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), - new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), /* timeOnTimeFactor */ null, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well @@ -282,7 +282,7 @@ public class LeaderboardDTODiffingTest { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), - new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), /* timeOnTimeFactor */ null, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); newVersion.competitorDisplayNames = new HashMap(newVersion.competitorDisplayNames); @@ -313,7 +313,7 @@ public class LeaderboardDTODiffingTest { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), - new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), /* timeOnTimeFactor */ null, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); newVersion.competitors.add(somebodyNew); newOrdering.add(somebodyNew); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index befc676de53..76ff9149bfc 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -61,7 +61,7 @@ public class CompetitorEditDialog extends DataEntryDialog { * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. * @param boatClass * The boat class is the default shown boat class for new competitors. Set null if your competitor is - * already initialized or you don�t want a default boat class. + * already initialized or you don't want a default boat class. */ public CompetitorEditDialog(final StringMessages stringMessages, CompetitorDTO competitorToEdit, DialogCallback callback, String boatClass) { @@ -202,7 +202,7 @@ public class CompetitorEditDialog extends DataEntryDialog { /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), /* countryName */ null, competitorToEdit.getIdAsString(), - imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boat, boatClass, + imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boat, timeOnTimeFactor.getValue(), timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue() == null ? null : new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000)), searchTag.getValue()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index c315bcb3e40..ae0ccf61c7d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -108,7 +108,33 @@ public class CompetitorTableWrapper flagImageColumn = new Column(new SafeHtmlCell()) { + @Override + public SafeHtml getValue(CompetitorDTO competitor) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + ImageResourceRenderer renderer = new ImageResourceRenderer(); + final String twoLetterIsoCountryCode = competitor.getTwoLetterIsoCountryCode(); + final String flagImageURL = competitor.getFlagImageURL(); + if (flagImageURL != null && !flagImageURL.isEmpty()) { + sb.appendHtmlConstant(""); + sb.appendHtmlConstant(" "); + } else { + final ImageResource flagImageResource; + if (twoLetterIsoCountryCode==null || twoLetterIsoCountryCode.isEmpty()) { + flagImageResource = FlagImageResolver.getEmptyFlagImageResource(); + } else { + flagImageResource = FlagImageResolver.getFlagImageResource(twoLetterIsoCountryCode); + } + if (flagImageResource != null) { + sb.append(renderer.render(flagImageResource)); + sb.appendHtmlConstant(" "); + } + } + return sb.toSafeHtml(); + } + }; + Column sailIdColumn = new Column(new SafeHtmlCell()) { @Override public SafeHtml getValue(CompetitorDTO competitor) { @@ -268,7 +294,7 @@ public class CompetitorTableWrapper Date: Mon, 3 Jul 2017 14:18:22 +0200 Subject: [PATCH 042/271] Adapated competitor creation and edit UIs --- .../domain/common/dto/CompetitorDTOImpl.java | 2 +- .../impl/TransientCompetitorStoreImpl.java | 12 +- .../test/LeaderboardDTODiffingTest.java | 28 ++- .../ui/adminconsole/CompetitorEditDialog.java | 216 ++++------------ .../gwt/ui/adminconsole/CompetitorPanel.java | 4 +- .../CompetitorRegistrationsPanel.java | 3 +- .../adminconsole/CompetitorTableWrapper.java | 57 ++++- .../CompetitorWithoutBoatEditDialog.java | 235 ++++++++++++++++++ .../ImportCompetitorCallback.java | 2 +- .../sailing/gwt/ui/client/SailingService.java | 7 +- .../gwt/ui/client/SailingServiceAsync.java | 7 +- .../gwt/ui/server/SailingServiceImpl.java | 100 +++++--- 12 files changed, 426 insertions(+), 247 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithoutBoatEditDialog.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 988b35aa804..07670d978ef 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -13,7 +13,7 @@ public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements C public CompetitorDTOImpl(String name, String shortName, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, String countryName, String idAsString, String imageURL, String flagImageURL, - BoatDTO boat, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag) { + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, BoatDTO boat) { super(name, shortName, color, email, twoLetterIsoCountryCode, threeLetterIocCountryCode, countryName, idAsString, imageURL, flagImageURL, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 49cd193c618..e4f7af0fb7c 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -297,14 +297,10 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab boat.getBoatClass().getHullLength(), boat.getBoatClass().getHullBeam()); boatDTO = new BoatDTO(boat.getId().toString(), boat.getName(), boatClassDTO, boat.getSailID(), boat.getColor()); } - CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), c.getTwoLetterIsoCountryCode(), - c.getThreeLetterIocCountryCode(), - c.getCountryName(), - c.getIdAsString(), - c.getImageURL(), - c.getFlagImageURL(), - boatDTO, - c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag()); + CompetitorDTO competitorDTO = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), + c.getTwoLetterIsoCountryCode(), c.getThreeLetterIocCountryCode(), c.getCountryName(), c.getIdAsString(), + c.getImageURL(), c.getFlagImageURL(), c.getTimeOnTimeFactor(), + c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag(), boatDTO); return competitorDTO; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index 080546cdec0..470a4c9a064 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -234,10 +234,13 @@ public class LeaderboardDTODiffingTest { @Test public void testCompetitorListChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version + BoatDTO boat = new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"); CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), + /* imageURL */ null, /* flagImageURL */ null, /* timeOnTimeFactor */ null, - /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* timeOnDistanceAllowancePerNauticalMile */ null, + /* searchTag */ null, + boat); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS"); newVersion.competitors.remove(wolfgang); @@ -256,10 +259,13 @@ public class LeaderboardDTODiffingTest { Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); newVersion.setSuppressedCompetitors(newSuppressedCompetitors); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version + BoatDTO boat = new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"); CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), + /* imageURL */ null, /* flagImageURL */ null, /* timeOnTimeFactor */ null, - /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* timeOnDistanceAllowancePerNauticalMile */ null, + /* searchTag */ null, + boat); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well List newSuppressedCompetitorsBeforeStripping = new ArrayList(); @@ -280,10 +286,13 @@ public class LeaderboardDTODiffingTest { @Test public void testDisplayNameChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version + BoatDTO boat = new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"); CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), + /* imageURL */ null, /* flagImageURL */ null, /* timeOnTimeFactor */ null, - /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* timeOnDistanceAllowancePerNauticalMile */ null, + /* searchTag */ null, + boat); newVersion.competitors.add(somebodyNew); newVersion.competitorDisplayNames = new HashMap(newVersion.competitorDisplayNames); newVersion.competitorDisplayNames.put(newVersion.competitors.get(13), "Humba"); @@ -311,10 +320,13 @@ public class LeaderboardDTODiffingTest { List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version + BoatDTO boat = new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"); CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", "SN", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("123", "LSC", new BoatClassDTO("505", BoatClassMasterdata._5O5.getHullLength(), BoatClassMasterdata._5O5.getHullBeam()), "GER 1234"), + /* imageURL */ null, /* flagImageURL */ null, /* timeOnTimeFactor */ null, - /* timeOnDistanceAllowancePerNauticalMile */ null, null); + /* timeOnDistanceAllowancePerNauticalMile */ null, + /* searchTag */ null, + boat); newVersion.competitors.add(somebodyNew); newOrdering.add(somebodyNew); CompetitorDTO formerRank13 = newOrdering.remove(13); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index 76ff9149bfc..dd5f6ba5e1c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -1,33 +1,20 @@ package com.sap.sailing.gwt.ui.adminconsole; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import com.google.gwt.user.client.ui.DoubleBox; import com.google.gwt.user.client.ui.FocusWidget; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sse.common.Color; -import com.sap.sse.common.CountryCode; -import com.sap.sse.common.CountryCodeFactory; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsDurationImpl; -import com.sap.sse.common.impl.RGBColor; -import com.sap.sse.gwt.adminconsole.URLFieldWithFileUpload; -import com.sap.sse.gwt.client.dialog.DataEntryDialog; /** * The competitors produced by this dialog will have a null @@ -38,21 +25,32 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; * @author Axel Uhl (d043530) * */ -public class CompetitorEditDialog extends DataEntryDialog { - private final CompetitorDTO competitorToEdit; - private final TextBox name; - private final TextBox shortName; +public class CompetitorEditDialog extends CompetitorWithoutBoatEditDialog { private final SuggestBox boatClassName; - private final TextBox displayColorTextBox; - private final ListBox threeLetterIocCountryCode; private final TextBox sailId; - private final TextBox email; - private final TextBox searchTag; - private final StringMessages stringMessages; - private final URLFieldWithFileUpload flagImageURL; - private final URLFieldWithFileUpload imageUrlAndUploadComposite; - private final DoubleBox timeOnTimeFactor; - private final DoubleBox timeOnDistanceAllowanceInSecondsPerNauticalMile; + + protected static class CompetitorValidator extends CompetitorWithoutBoatValidator { + protected final StringMessages stringMessages; + + public CompetitorValidator(StringMessages stringMessages) { + super(stringMessages); + + this.stringMessages = stringMessages; + } + + @Override + public String getErrorMessage(CompetitorDTO valueToValidate) { + String result = super.getErrorMessage(valueToValidate); + if (result == null) { + if (valueToValidate.getSailID() == null || valueToValidate.getSailID().isEmpty()) { + result = stringMessages.pleaseEnterASailNumber(); + } else if (valueToValidate.getBoatClass().getName() == null || valueToValidate.getBoatClass().getName().isEmpty()) { + result = stringMessages.pleaseEnterABoatClass(); + } + } + return result; + } + } /** * The class creates the UI-dialog to type in the Data about a competitor. @@ -65,177 +63,51 @@ public class CompetitorEditDialog extends DataEntryDialog { */ public CompetitorEditDialog(final StringMessages stringMessages, CompetitorDTO competitorToEdit, DialogCallback callback, String boatClass) { - super(stringMessages.editCompetitor(), null, stringMessages.ok(), stringMessages - .cancel(), new Validator() { - @Override - public String getErrorMessage(CompetitorDTO valueToValidate) { - String result = null; - if (valueToValidate.getName() == null || valueToValidate.getName().isEmpty()) { - result = stringMessages.pleaseEnterAName(); - } else if (valueToValidate.getSailID() == null || valueToValidate.getSailID().isEmpty()) { - result = stringMessages.pleaseEnterASailNumber(); - } else if (valueToValidate.getColor() != null) { - Color displayColor = valueToValidate.getColor(); - if (displayColor instanceof InvalidColor) { - result = displayColor.getAsHtml(); - } - } else if (valueToValidate.getBoatClass().getName() == null || valueToValidate.getBoatClass().getName().isEmpty()) { - result = stringMessages.pleaseEnterABoatClass(); - } - return result; - } - }, /* animationEnabled */true, callback); + super(stringMessages, competitorToEdit, new CompetitorEditDialog.CompetitorValidator(stringMessages), callback); this.ensureDebugId("CompetitorEditDialog"); - this.stringMessages = stringMessages; - this.competitorToEdit = competitorToEdit; this.boatClassName = createSuggestBox(new BoatClassMasterdataSuggestOracle()); boatClassName.ensureDebugId("BoatClassNameSuggestBox"); - int i=0; if (competitorToEdit.getBoatClass() != null) { boatClassName.setValue(competitorToEdit.getBoatClass().getName()); boatClassName.setEnabled(false); } else { boatClassName.setValue(boatClass); // widgets have to accept null values here } - this.name = createTextBox(competitorToEdit.getName()); - name.ensureDebugId("NameTextBox"); - this.shortName = createTextBox(competitorToEdit.getShortName()); - shortName.ensureDebugId("ShortNameTextBox"); - this.email = createTextBox(competitorToEdit.getEmail()); - this.searchTag = createTextBox(competitorToEdit.getSearchTag()); - this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); - this.threeLetterIocCountryCode = createListBox(/* isMultipleSelect */ false); - CountryCodeFactory ccf = CountryCodeFactory.INSTANCE; - i=0; - List ccs = new ArrayList(); - Util.addAll(ccf.getAll(), ccs); - ccs.add(null); // representing no nationality (NONE / white flag) - Collections.sort(ccs, new Comparator() { - @Override - public int compare(CountryCode o1, CountryCode o2) { - return Util.compareToWithNull(o1 == null ? null : o1.getThreeLetterIOCCode(), o2 == null ? null : o2.getThreeLetterIOCCode(), /* nullIsLess */ true); - } - }); - for (CountryCode cc : ccs) { - if (cc == null) { - this.threeLetterIocCountryCode.addItem("", ""); // the NONE country code that uses the empty, white flag - if (competitorToEdit.getThreeLetterIocCountryCode() == null || competitorToEdit.getThreeLetterIocCountryCode().isEmpty()) { - this.threeLetterIocCountryCode.setSelectedIndex(i); - } - i++; - } else if (cc.getThreeLetterIOCCode() != null) { - this.threeLetterIocCountryCode.addItem(cc.getThreeLetterIOCCode() + " " + cc.getName(), cc.getThreeLetterIOCCode()); - if (cc.getThreeLetterIOCCode().equals(competitorToEdit.getThreeLetterIocCountryCode())) { - this.threeLetterIocCountryCode.setSelectedIndex(i); - } - i++; - } - } this.sailId = createTextBox(competitorToEdit.getSailID()); sailId.ensureDebugId("SailIdTextBox"); - this.flagImageURL = new URLFieldWithFileUpload(stringMessages); - this.flagImageURL.setURL(competitorToEdit.getFlagImageURL()); - this.imageUrlAndUploadComposite = new URLFieldWithFileUpload(stringMessages); - this.imageUrlAndUploadComposite.setURL(competitorToEdit.getImageURL()); - this.timeOnTimeFactor = createDoubleBox(competitorToEdit.getTimeOnTimeFactor(), 10); - this.timeOnDistanceAllowanceInSecondsPerNauticalMile = createDoubleBox( - competitorToEdit.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : competitorToEdit - .getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 10); } @Override protected FocusWidget getInitialFocusWidget() { - return name; - } - - /** - * Encodes an invalid color; can be used - * @author Axel Uhl (D043530) - * - */ - private class InvalidColor implements Color { - private static final long serialVersionUID = 4012986110898149543L; - private final Exception exception; - - protected InvalidColor(Exception exception) { - this.exception = exception; - } - - @Override - public com.sap.sse.common.Util.Triple getAsRGB() { - return null; - } - - @Override - public com.sap.sse.common.Util.Triple getAsHSV() { - return null; - } - - @Override - public String getAsHtml() { - return stringMessages.invalidColor(exception.getMessage()); - } - - @Override - public Color invert() { - return null; - } + return super.getInitialFocusWidget(); } @Override protected CompetitorDTO getResult() { - Color color; - if (displayColorTextBox.getText() == null || displayColorTextBox.getText().isEmpty()) { - color = null; - } else { - try { - color = new RGBColor(displayColorTextBox.getText()); - } catch (IllegalArgumentException iae) { - color = new InvalidColor(iae); - } - } + CompetitorWithoutBoatDTO c = super.getResult(); BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), Distance.NULL, Distance.NULL); // Use temporary competitorID as boat Id -> boat will be removed from competitor later on anyway - BoatDTO boat = new BoatDTO(competitorToEdit.getIdAsString(), name.getText(), boatClass, sailId.getText()); - CompetitorDTO result = new CompetitorDTOImpl(name.getText(), shortName.getText(), color, email.getText(), - /* twoLetterIsoCountryCode */ null, - threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), - /* countryName */ null, competitorToEdit.getIdAsString(), - imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boat, - timeOnTimeFactor.getValue(), - timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue() == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000)), searchTag.getValue()); + BoatDTO boat = new BoatDTO(getCompetitorToEdit().getIdAsString(), c.getName(), boatClass, sailId.getText()); + CompetitorDTO result = new CompetitorDTOImpl(c.getName(), c.getShortName(), c.getColor(), c.getEmail(), + c.getTwoLetterIsoCountryCode(), c.getThreeLetterIocCountryCode(), c.getCountryName(), + getCompetitorToEdit().getIdAsString(), + c.getImageURL(), c.getFlagImageURL(), + c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag(), + boat); return result; } @Override protected Widget getAdditionalWidget() { - Grid result = new Grid(12, 2); - result.setWidget(0, 0, new Label(stringMessages.name())); - result.setWidget(0, 1, name); - result.setWidget(1, 0, new Label(stringMessages.shortName())); - result.setWidget(1, 1, shortName); - result.setWidget(2, 0, new Label(stringMessages.sailNumber())); - result.setWidget(2, 1, sailId); - result.setWidget(3, 0, new Label(stringMessages.nationality())); - result.setWidget(3, 1, threeLetterIocCountryCode); - result.setWidget(4, 0, new Label(stringMessages.color())); - result.setWidget(4, 1, displayColorTextBox); - result.setWidget(5, 0, new Label(stringMessages.email())); - result.setWidget(5, 1, email); - result.setWidget(6, 0, new Label(stringMessages.searchTag())); - result.setWidget(6, 1, searchTag); - result.setWidget(7, 0, new Label(stringMessages.boatClass())); - result.setWidget(7, 1, boatClassName); - result.setWidget(8, 0, new Label(stringMessages.flagImageURL())); - result.setWidget(8, 1, flagImageURL); - result.setWidget(9, 0, new Label(stringMessages.imageURL())); - result.setWidget(9, 1, imageUrlAndUploadComposite); - result.setWidget(10, 0, new Label(stringMessages.timeOnTimeFactor())); - result.setWidget(10, 1, timeOnTimeFactor); - result.setWidget(11, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile())); - result.setWidget(11, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile); + VerticalPanel result = new VerticalPanel(); + result.add(super.getAdditionalWidget()); + Grid grid = new Grid(2, 2); + grid.setWidget(0, 0, new Label(getStringMessages().sailNumber())); + grid.setWidget(0, 1, sailId); + grid.setWidget(1, 0, new Label(getStringMessages().boatClass())); + grid.setWidget(1, 1, boatClassName); + result.add(grid); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java index 5d4d3c0724b..5d04ed3db54 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java @@ -13,7 +13,7 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.CompetitorDescriptor; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTOImpl; import com.sap.sailing.gwt.ui.adminconsole.CompetitorImportProviderSelectionDialog.MatchImportedCompetitorsDialogFactory; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -169,7 +169,7 @@ public class CompetitorPanel extends SimplePanel implements BusyDisplay { } private void openAddCompetitorDialog() { - competitorTable.openEditCompetitorDialog(new CompetitorDTOImpl(), /* boat class to be used from CompetitorDTO */ null); + competitorTable.openEditCompetitorWithoutBoatDialog(new CompetitorWithoutBoatDTOImpl()); } public void refreshCompetitorList() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java index b8862a4b78d..719da4ffb92 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java @@ -96,7 +96,8 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl addCompetitorButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - registeredCompetitorsTable.openEditCompetitorDialog(new CompetitorDTOImpl(), boatClass); + // TODO bug2822: with or without boat, that's the question + registeredCompetitorsTable.openEditCompetitorWithBoatDialog(new CompetitorDTOImpl(), boatClass); } }); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index ae0ccf61c7d..cb5fce62b40 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -21,6 +21,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.view.client.CellPreviewEvent; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithToolTipDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; import com.sap.sailing.gwt.ui.client.FlagImageResolver; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -278,10 +279,15 @@ public class CompetitorTableWrapper getSearchableStrings(CompetitorDTO t) { List string = new ArrayList(); string.add(t.getName()); - string.add(t.getSailID()); - string.add(t.getBoatClass().getName()); + string.add(t.getShortName()); string.add(t.getIdAsString()); string.add(t.getSearchTag()); + if (t.getBoatClass() != null) { + string.add(t.getBoatClass().getName()); + } + if (t.getSailID() != null) { + string.add(t.getSailID()); + } return string; } }; @@ -294,7 +300,11 @@ public class CompetitorTableWrapper result) { filterField.updateAll(result); } - - void openEditCompetitorDialog(final CompetitorDTO originalCompetitor, String boatClass) { + + void openEditCompetitorWithBoatDialog(final CompetitorDTO originalCompetitor, String boatClass) { final CompetitorEditDialog dialog = new CompetitorEditDialog(stringMessages, originalCompetitor, new DialogCallback() { @Override public void ok(final CompetitorDTO competitor) { - final List competitors = new ArrayList<>(); - competitors.add(competitor); - sailingService.addOrUpdateCompetitor(competitors, new AsyncCallback>() { + sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); + errorReporter.reportError("Error trying to update competitor with boat: " + caught.getMessage()); } @Override - public void onSuccess(List updatedCompetitor) { - assert updatedCompetitor.size() == 1; + public void onSuccess(CompetitorDTO updatedCompetitor) { //only reload selected competitors reloading with refreshCompetitorList(leaderboardName) //would not work in case the list is not based on a leaderboard e.g. AbstractCompetitorRegistrationDialog int editedCompetitorIndex = getFilterField().indexOf(originalCompetitor); getFilterField().remove(originalCompetitor); if (editedCompetitorIndex >= 0){ - getFilterField().add(editedCompetitorIndex, updatedCompetitor.iterator().next()); + getFilterField().add(editedCompetitorIndex, updatedCompetitor); } else { //in case competitor was not present --> not edit, but create - getFilterField().add(updatedCompetitor.iterator().next()); + getFilterField().add(updatedCompetitor); } getDataProvider().refresh(); } @@ -407,6 +414,30 @@ public class CompetitorTableWrapper dialog = CompetitorWithoutBoatEditDialog.create(stringMessages, originalCompetitor, new DialogCallback() { + @Override + public void ok(final CompetitorWithoutBoatDTO competitor) { + sailingService.addOrUpdateCompetitorWithoutBoat(competitor, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); + } + + @Override + public void onSuccess(CompetitorWithoutBoatDTO updatedCompetitor) { + } + }); + } + + @Override + public void cancel() { + } + }); + dialog.ensureDebugId("CompetitorWithoutBoatEditDialog"); + dialog.show(); + } + protected void allowUpdate(final Iterable competitors) { List serializableSingletonList = new ArrayList(); Util.addAll(competitors, serializableSingletonList); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithoutBoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithoutBoatEditDialog.java new file mode 100644 index 00000000000..2cce25cf497 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithoutBoatEditDialog.java @@ -0,0 +1,235 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.google.gwt.user.client.ui.DoubleBox; +import com.google.gwt.user.client.ui.FocusWidget; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTOImpl; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Color; +import com.sap.sse.common.CountryCode; +import com.sap.sse.common.CountryCodeFactory; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.common.impl.RGBColor; +import com.sap.sse.gwt.adminconsole.URLFieldWithFileUpload; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; + +/** + * The competitors produced by this dialog will have a null + * {@link CompetitorDTO#getTwoLetterIsoCountryCode() twoLetterIsoCountryCode} and a null + * {@link CompetitorDTO#getCountryName() countryName} because all of these can be derived from a valid + * {@link CompetitorDTO#getThreeLetterIocCountryCode() threeLetterIocCountryCode}. + * + * @author Axel Uhl (d043530) + * + */ +public class CompetitorWithoutBoatEditDialog extends DataEntryDialog { + private final CompetitorDTOType competitorToEdit; + private final TextBox name; + private final TextBox shortName; + private final TextBox displayColorTextBox; + private final ListBox threeLetterIocCountryCode; + private final TextBox email; + private final TextBox searchTag; + private final StringMessages stringMessages; + + private final URLFieldWithFileUpload flagImageURL; + private final URLFieldWithFileUpload imageUrlAndUploadComposite; + private final DoubleBox timeOnTimeFactor; + private final DoubleBox timeOnDistanceAllowanceInSecondsPerNauticalMile; + + protected static class CompetitorWithoutBoatValidator implements Validator { + protected final StringMessages stringMessages; + + public CompetitorWithoutBoatValidator(StringMessages stringMessages) { + this.stringMessages = stringMessages; + } + + @Override + public String getErrorMessage(T valueToValidate) { + String result = null; + if (valueToValidate.getName() == null || valueToValidate.getName().isEmpty()) { + result = stringMessages.pleaseEnterAName(); + } else if (valueToValidate.getColor() != null) { + Color displayColor = valueToValidate.getColor(); + if (displayColor instanceof CompetitorWithoutBoatEditDialog.InvalidColor) { + result = displayColor.getAsHtml(); + } + } + return result; + } + } + + public static CompetitorWithoutBoatEditDialog create(final StringMessages stringMessages, CompetitorWithoutBoatDTO competitorToEdit, + DialogCallback callback) { + return new CompetitorWithoutBoatEditDialog(stringMessages, competitorToEdit, + new CompetitorWithoutBoatEditDialog.CompetitorWithoutBoatValidator(stringMessages), callback); + } + + /** + * The class creates the UI-dialog to type in the data of a competitor. + * + * @param competitorToEdit + * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. + */ + protected CompetitorWithoutBoatEditDialog(final StringMessages stringMessages, CompetitorDTOType competitorToEdit, + Validator validator, DialogCallback callback) { + super(stringMessages.editCompetitor(), null, stringMessages.ok(), stringMessages.cancel(), + validator, /* animationEnabled */true, callback); + this.ensureDebugId("CompetitorEditDialog"); + this.stringMessages = stringMessages; + this.competitorToEdit = competitorToEdit; + + this.name = createTextBox(competitorToEdit.getName()); + name.ensureDebugId("NameTextBox"); + this.shortName = createTextBox(competitorToEdit.getShortName()); + shortName.ensureDebugId("ShortNameTextBox"); + this.email = createTextBox(competitorToEdit.getEmail()); + this.searchTag = createTextBox(competitorToEdit.getSearchTag()); + this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); + this.threeLetterIocCountryCode = createListBox(/* isMultipleSelect */ false); + CountryCodeFactory ccf = CountryCodeFactory.INSTANCE; + int i=0; + List ccs = new ArrayList(); + Util.addAll(ccf.getAll(), ccs); + ccs.add(null); // representing no nationality (NONE / white flag) + Collections.sort(ccs, new Comparator() { + @Override + public int compare(CountryCode o1, CountryCode o2) { + return Util.compareToWithNull(o1 == null ? null : o1.getThreeLetterIOCCode(), o2 == null ? null : o2.getThreeLetterIOCCode(), /* nullIsLess */ true); + } + }); + for (CountryCode cc : ccs) { + if (cc == null) { + this.threeLetterIocCountryCode.addItem("", ""); // the NONE country code that uses the empty, white flag + if (competitorToEdit.getThreeLetterIocCountryCode() == null || competitorToEdit.getThreeLetterIocCountryCode().isEmpty()) { + this.threeLetterIocCountryCode.setSelectedIndex(i); + } + i++; + } else if (cc.getThreeLetterIOCCode() != null) { + this.threeLetterIocCountryCode.addItem(cc.getThreeLetterIOCCode() + " " + cc.getName(), cc.getThreeLetterIOCCode()); + if (cc.getThreeLetterIOCCode().equals(competitorToEdit.getThreeLetterIocCountryCode())) { + this.threeLetterIocCountryCode.setSelectedIndex(i); + } + i++; + } + } + this.flagImageURL = new URLFieldWithFileUpload(stringMessages); + this.flagImageURL.setURL(competitorToEdit.getFlagImageURL()); + this.imageUrlAndUploadComposite = new URLFieldWithFileUpload(stringMessages); + this.imageUrlAndUploadComposite.setURL(competitorToEdit.getImageURL()); + this.timeOnTimeFactor = createDoubleBox(competitorToEdit.getTimeOnTimeFactor(), 10); + this.timeOnDistanceAllowanceInSecondsPerNauticalMile = createDoubleBox( + competitorToEdit.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : competitorToEdit + .getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 10); + } + + @Override + protected FocusWidget getInitialFocusWidget() { + return name; + } + + /** + * Encodes an invalid color; can be used + * @author Axel Uhl (D043530) + * + */ + private class InvalidColor implements Color { + private static final long serialVersionUID = 4012986110898149543L; + private final Exception exception; + + protected InvalidColor(Exception exception) { + this.exception = exception; + } + + @Override + public com.sap.sse.common.Util.Triple getAsRGB() { + return null; + } + + @Override + public com.sap.sse.common.Util.Triple getAsHSV() { + return null; + } + + @Override + public String getAsHtml() { + return stringMessages.invalidColor(exception.getMessage()); + } + + @Override + public Color invert() { + return null; + } + } + + @SuppressWarnings("unchecked") + @Override + protected CompetitorDTOType getResult() { + Color color; + if (displayColorTextBox.getText() == null || displayColorTextBox.getText().isEmpty()) { + color = null; + } else { + try { + color = new RGBColor(displayColorTextBox.getText()); + } catch (IllegalArgumentException iae) { + color = new InvalidColor(iae); + } + } + CompetitorWithoutBoatDTO result = new CompetitorWithoutBoatDTOImpl(name.getText(), shortName.getText(), color, email.getText(), + /* twoLetterIsoCountryCode */ null, + threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), + /* countryName */ null, competitorToEdit.getIdAsString(), + imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), + timeOnTimeFactor.getValue(), + timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue() == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000)), searchTag.getValue()); + return (CompetitorDTOType) result; + } + + @Override + protected Widget getAdditionalWidget() { + Grid result = new Grid(10, 2); + result.setWidget(0, 0, new Label(stringMessages.name())); + result.setWidget(0, 1, name); + result.setWidget(1, 0, new Label(stringMessages.shortName())); + result.setWidget(1, 1, shortName); + result.setWidget(2, 0, new Label(stringMessages.nationality())); + result.setWidget(2, 1, threeLetterIocCountryCode); + result.setWidget(3, 0, new Label(stringMessages.color())); + result.setWidget(3, 1, displayColorTextBox); + result.setWidget(4, 0, new Label(stringMessages.email())); + result.setWidget(4, 1, email); + result.setWidget(5, 0, new Label(stringMessages.searchTag())); + result.setWidget(5, 1, searchTag); + result.setWidget(6, 0, new Label(stringMessages.flagImageURL())); + result.setWidget(6, 1, flagImageURL); + result.setWidget(7, 0, new Label(stringMessages.imageURL())); + result.setWidget(7, 1, imageUrlAndUploadComposite); + result.setWidget(8, 0, new Label(stringMessages.timeOnTimeFactor())); + result.setWidget(8, 1, timeOnTimeFactor); + result.setWidget(9, 0, new Label(stringMessages.timeOnDistanceAllowanceInSecondsPerNauticalMile())); + result.setWidget(9, 1, timeOnDistanceAllowanceInSecondsPerNauticalMile); + return result; + } + + protected CompetitorDTOType getCompetitorToEdit() { + return competitorToEdit; + } + + protected StringMessages getStringMessages() { + return stringMessages; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java index 57f2e5cd61d..c51a0b342e3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java @@ -55,7 +55,7 @@ public class ImportCompetitorCallback implements DialogCallback(existingCompetitorsSelected), new MarkedAsyncCallback<>( + sailingService.addOrUpdateCompetitors(new ArrayList<>(existingCompetitorsSelected), new MarkedAsyncCallback<>( new AsyncCallback>() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index d3daa47a2f7..d3255c18aa7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -33,6 +33,7 @@ import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO; import com.sap.sailing.domain.common.dto.PersonDTO; @@ -436,7 +437,11 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Iterable getCompetitorsOfLeaderboard(String leaderboardName); - List addOrUpdateCompetitor(List competitors) throws Exception; + List addOrUpdateCompetitors(List competitors) throws Exception; + + CompetitorDTO addOrUpdateCompetitor(CompetitorDTO competitor) throws Exception; + + CompetitorWithoutBoatDTO addOrUpdateCompetitorWithoutBoat(CompetitorWithoutBoatDTO competitor) throws Exception; List addCompetitors(List competitorsForSaving, String searchTag) throws Exception; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 249161517a0..bb33860e1da 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -28,6 +28,7 @@ import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO; import com.sap.sailing.domain.common.dto.PersonDTO; @@ -590,8 +591,12 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void getCompetitorsOfLeaderboard(String leaderboardName, AsyncCallback> asyncCallback); - void addOrUpdateCompetitor(List competitors, AsyncCallback> asyncCallback); + void addOrUpdateCompetitors(List competitors, AsyncCallback> asyncCallback); + void addOrUpdateCompetitor(CompetitorDTO competitor, AsyncCallback asyncCallback); + + void addOrUpdateCompetitorWithoutBoat(CompetitorWithoutBoatDTO competitor, AsyncCallback asyncCallback); + void addCompetitors(List competitorsForSaving, String searchTag, AsyncCallback> asyncCallback); 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 ec402002979..33dfc22e856 100644 --- 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 @@ -188,6 +188,7 @@ import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLo import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.FullLeaderboardDTO; import com.sap.sailing.domain.common.dto.IncrementalLeaderboardDTO; @@ -4813,43 +4814,62 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public Iterable getCompetitorsOfLeaderboard(String leaderboardName) { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - return convertToCompetitorDTOs(leaderboard.getAllCompetitors()); + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + return convertToCompetitorDTOs(leaderboard.getAllCompetitors()); } @Override - public List addOrUpdateCompetitor(List competitors) throws URISyntaxException { - final List results = new ArrayList<>(); + public List addOrUpdateCompetitors(List competitors) throws URISyntaxException { + final List result = new ArrayList<>(); for (final CompetitorDTO competitor : competitors) { - Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitor.getIdAsString()); - Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null : - getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); - final CompetitorDTO result; - // new competitor - if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { - UUID competitorUUID = UUID.randomUUID(); - DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); - DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - result = getBaseDomainFactory().convertToCompetitorDTO( - getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag())); - } else { - result = getBaseDomainFactory().convertToCompetitorDTO( - getService().apply( - new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), competitor - .getColor(), competitor.getEmail(), nationality, - competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), - competitor.getSearchTag()))); - } - results.add(result); + result.add(addOrUpdateCompetitor(competitor)); } - return results; + return result; + } + + private Competitor addOrUpdateCompetitorWithoutBoatInternal(CompetitorWithoutBoatDTO competitor) throws URISyntaxException { + Competitor result; + Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitor.getIdAsString()); + Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null : + getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); + if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { + // new competitor + UUID competitorUUID = UUID.randomUUID(); + DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); + DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); + result = getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), competitor.getShortName(), + competitor.getColor(), competitor.getEmail(), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, + competitor.getTimeOnTimeFactor(), + competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag()); + + } else { + result = getService().apply( + new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), + competitor.getColor(), competitor.getEmail(), nationality, + competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), + competitor.getTimeOnTimeFactor(), + competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); + } + return result; + } + + @Override + public CompetitorWithoutBoatDTO addOrUpdateCompetitorWithoutBoat(CompetitorWithoutBoatDTO competitor) throws URISyntaxException { + return getBaseDomainFactory().convertToCompetitorDTO(addOrUpdateCompetitorWithoutBoatInternal(competitor)); + } + + @Override + public CompetitorDTO addOrUpdateCompetitor(CompetitorDTO competitor) throws URISyntaxException { + Boat addedOrUpdatedBoat = null; + if (competitor.getBoat() != null) { + addedOrUpdatedBoat = addOrUpdateBoatInternal(competitor.getBoat()); + } + Competitor addedOrUpdatedCompetitor = addOrUpdateCompetitorWithoutBoatInternal(competitor); + return getBaseDomainFactory().convertToCompetitorDTO(addedOrUpdatedCompetitor, addedOrUpdatedBoat); + } @Override @@ -4902,18 +4922,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public BoatDTO addOrUpdateBoat(BoatDTO boat) { + return getBaseDomainFactory().convertToBoatDTO(addOrUpdateBoatInternal(boat)); + } + + private Boat addOrUpdateBoatInternal(BoatDTO boat) { Boat existingBoat = getService().getCompetitorStore().getExistingBoatByIdAsString(boat.getIdAsString()); - final BoatDTO result; - // new boat + final Boat result; if (boat.getIdAsString() == null || boat.getIdAsString().isEmpty() || existingBoat == null) { + // new boat UUID boatUUID = UUID.randomUUID(); BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName()); - result = getBaseDomainFactory().convertToBoatDTO( - getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor())); + result = getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor()); } else { - result = getBaseDomainFactory().convertToBoatDTO( - getService().apply( - new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId()))); + result = getService().apply( + new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId())); } return result; } From 0c817abc486e6841d947dc4124a07f506014052e Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 3 Jul 2017 16:36:29 +0200 Subject: [PATCH 043/271] fixed creation for competitor AND boat for competitor importers added attribute 'shortName' to CompetitorDescriptor --- .../domain/common/CompetitorDescriptor.java | 8 +++++++- .../persistence/MongoObjectFactory.java | 6 ++++++ .../impl/MongoObjectFactoryImpl.java | 14 +++++++++++++ .../sailing/domain/base/CompetitorStore.java | 2 ++ .../impl/TransientCompetitorStoreImpl.java | 13 ++++++++++++ ...titorDescriptor_CustomFieldSerializer.java | 3 ++- .../gwt/ui/server/SailingServiceImpl.java | 20 ++++++++++++++----- .../resultimport/CompetitorImporter.java | 5 +++-- .../impl/PersistentCompetitorStore.java | 6 ++++++ 9 files changed, 68 insertions(+), 9 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/CompetitorDescriptor.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/CompetitorDescriptor.java index 07b0faf6443..eb6c2b7de38 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/CompetitorDescriptor.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/CompetitorDescriptor.java @@ -14,6 +14,7 @@ import com.sap.sse.common.impl.NamedImpl; public class CompetitorDescriptor extends NamedImpl implements Named { private static final long serialVersionUID = -6645726854552711646L; + private final String shortName; private final String eventName; private final String regattaName; private final String boatClassName; @@ -28,9 +29,10 @@ public class CompetitorDescriptor extends NamedImpl implements Named { private final Duration timeOnDistanceAllowancePerNauticalMile; public CompetitorDescriptor(String eventName, String regattaName, String boatClassName, String raceName, - String fleetName, String sailNumber, String name, String teamName, String boatName, CountryCode countryCode, + String fleetName, String sailNumber, String name, String shortName, String teamName, String boatName, CountryCode countryCode, Iterable persons, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) { super(name); + this.shortName = shortName; this.eventName = eventName; this.regattaName = regattaName; this.boatClassName = boatClassName; @@ -90,6 +92,10 @@ public class CompetitorDescriptor extends NamedImpl implements Named { return teamName; } + public String getShortName() { + return shortName; + } + public Duration getTimeOnDistanceAllowancePerNauticalMile() { return timeOnDistanceAllowancePerNauticalMile; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java index 2c1d2b47ab0..0595f886611 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java @@ -145,6 +145,12 @@ public interface MongoObjectFactory { */ void storeBoat(Boat boat); + /** + * Like {@link #storeBoat(Boat)}, but for a collection of boats that are all + * expected to be new, having a unique {@link Boat#getId() ID}. + */ + void storeBoats(Iterable boats); + void removeAllBoats(); void removeBoat(Boat boat); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index b361d4787e0..50cf8abca4e 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -1350,6 +1350,20 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); } + @Override + public void storeBoats(Iterable boats) { + if (boats != null && !Util.isEmpty(boats)) { + DBCollection collection = database.getCollection(CollectionNames.BOATS.name()); + List boatsDB = new ArrayList<>(); + for (Boat boat : boats) { + JSONObject json = boatSerializer.serialize(boat); + DBObject entry = (DBObject) JSON.parse(json.toString()); + boatsDB.add(entry); + } + collection.insert(boatsDB); + } + } + @Override public void removeAllBoats() { logger.info("Removing all persistent boats"); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 4692c8f9145..47e24499e51 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -132,6 +132,8 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { */ Boat updateBoat(String idAsString, String newName, Color newColor, String newSailId); + void addBoats(Iterable boats); + BoatDTO convertToBoatDTO(Boat boat); /** diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index e4f7af0fb7c..7b12a82791e 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -531,4 +531,17 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab LockUtil.unlockAfterWrite(lock); } } + + @Override + public void addBoats(Iterable boats) { + LockUtil.lockForWrite(lock); + try { + for (Boat boat: boats) { + boatCache.put(boat.getId(), boat); + boatsByIdAsString.put(boat.getId().toString(), boat); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/CompetitorDescriptor_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/CompetitorDescriptor_CustomFieldSerializer.java index 29b37f9a2e6..c91d26354df 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/CompetitorDescriptor_CustomFieldSerializer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/domain/common/CompetitorDescriptor_CustomFieldSerializer.java @@ -29,6 +29,7 @@ public class CompetitorDescriptor_CustomFieldSerializer extends CustomFieldSeria streamWriter.writeString(instance.getFleetName()); streamWriter.writeString(instance.getSailNumber()); streamWriter.writeString(instance.getName()); + streamWriter.writeString(instance.getShortName()); streamWriter.writeString(instance.getTeamName()); streamWriter.writeString(instance.getBoatName()); streamWriter.writeObject(instance.getCountryCode()); @@ -54,7 +55,7 @@ public class CompetitorDescriptor_CustomFieldSerializer extends CustomFieldSeria return new CompetitorDescriptor(streamReader.readString(), streamReader.readString(), streamReader.readString(), streamReader.readString(), streamReader.readString(), streamReader.readString(), streamReader.readString(), streamReader.readString(), - streamReader.readString(), (CountryCode) streamReader.readObject(), + streamReader.readString(), streamReader.readString(), (CountryCode) streamReader.readObject(), persons, (Double) streamReader.readObject(), (Duration) streamReader.readObject()); } 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 33dfc22e856..d34de69d7b6 100644 --- 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 @@ -99,6 +99,7 @@ import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.Regatt import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.Course; @@ -136,9 +137,12 @@ import com.sap.sailing.domain.base.configuration.impl.RacingProcedureWithConfigu import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; import com.sap.sailing.domain.base.configuration.impl.SWCStartConfigurationImpl; import com.sap.sailing.domain.base.configuration.procedures.ConfigurableStartModeFlagRacingProcedureConfiguration; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicPerson; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.base.impl.PersonImpl; @@ -455,6 +459,7 @@ import com.sap.sailing.xrr.structureimport.SeriesParameters; import com.sap.sailing.xrr.structureimport.StructureImporter; import com.sap.sailing.xrr.structureimport.buildstructure.SetRacenumberFromSeries; import com.sap.sse.ServerInfo; +import com.sap.sse.common.Color; import com.sap.sse.common.CountryCode; import com.sap.sse.common.Duration; import com.sap.sse.common.NoCorrespondingServiceRegisteredException; @@ -4875,11 +4880,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S @Override public List addCompetitors(List competitorDescriptors, String searchTag) throws URISyntaxException { List competitorsForSaving = new ArrayList<>(); + List boatsForSaving = new ArrayList<>(); for (final CompetitorDescriptor competitorDescriptor : competitorDescriptors) { - Competitor competitor = convertCompetitorDescriptorToCompetitor(competitorDescriptor, searchTag); - competitorsForSaving.add(competitor); + CompetitorAndBoat competitorWithBoat = convertCompetitorDescriptorToCompetitorAndBoat(competitorDescriptor, searchTag); + competitorsForSaving.add(competitorWithBoat.getCompetitor()); + boatsForSaving.add(competitorWithBoat.getBoat()); } getBaseDomainFactory().getCompetitorStore().addCompetitors(competitorsForSaving); + getBaseDomainFactory().getCompetitorStore().addBoats(boatsForSaving); return convertToCompetitorDTOs(competitorsForSaving); } @@ -4889,7 +4897,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * @param searchTag * set as the {@link Competitor#getSearchTag() searchTag} property of all new competitors */ - private Competitor convertCompetitorDescriptorToCompetitor(CompetitorDescriptor competitorDescriptor, String searchTag) throws URISyntaxException { + private CompetitorAndBoat convertCompetitorDescriptorToCompetitorAndBoat(CompetitorDescriptor competitorDescriptor, String searchTag) throws URISyntaxException { Nationality nationality = (competitorDescriptor.getCountryCode() == null || competitorDescriptor.getCountryCode().getThreeLetterIOCCode() == null || competitorDescriptor.getCountryCode().getThreeLetterIOCCode().isEmpty()) ? null @@ -4897,13 +4905,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S UUID competitorUUID = UUID.randomUUID(); DynamicPerson sailor = new PersonImpl(competitorDescriptor.getName(), nationality, null, null); DynamicTeam team = new TeamImpl(competitorDescriptor.getName(), Collections.singleton(sailor), null); + BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(competitorDescriptor.getBoatClassName()); + DynamicBoat boat = new BoatImpl(competitorUUID, competitorDescriptor.getBoatName(), boatClass, competitorDescriptor.getSailNumber()); Competitor competitor = new CompetitorImpl(competitorUUID, competitorDescriptor.getName(), competitorDescriptor.getSailNumber(), /* color */ null, /* eMail */ null, /* flag image */ null, team, competitorDescriptor.getTimeOnTimeFactor(), competitorDescriptor.getTimeOnDistanceAllowancePerNauticalMile(), searchTag); - - return competitor; + + return new CompetitorAndBoatImpl(competitor, boat); } @Override diff --git a/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/CompetitorImporter.java b/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/CompetitorImporter.java index 38402b3a55e..2158bfb4338 100644 --- a/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/CompetitorImporter.java +++ b/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/CompetitorImporter.java @@ -170,12 +170,13 @@ public class CompetitorImporter extends AbstractManage2SailProvider implements C nationality==null?null:nationality.getCountryCode().getThreeLetterIOCCode()); return person; }).collect(Collectors.toList()); + // TODO bug2822: Check where the 'short name' and 'boat name' should come from final CompetitorDescriptor competitorDescriptor = new CompetitorDescriptor( event==null?null:event.getTitle(), division==null?null:(division.getTitle() + (division.getGender() == null ? "" : division.getGender().name())), boatClassName, race != null ? race.getRaceName() : null, /* fleetName */ null, sailNumber, - team.getTeamName(), team.getTeamName(), boat.getBoatName(), - teamNationality[0] == null ? null : teamNationality[0].getCountryCode(), + /* name */ team.getTeamName(), /* short name */ team.getTeamName(), /* team name */ team.getTeamName(), + boat.getBoatName(), teamNationality[0] == null ? null : teamNationality[0].getCountryCode(), persons, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); return competitorDescriptor; } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 098340fd8f0..71ce5cb1ee2 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -152,4 +152,10 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo.storeBoat(result); return result; } + + @Override + public void addBoats(Iterable boats) { + storeTo.storeBoats(boats); + super.addBoats(boats); + } } From 4a87ba11a61616f83c07c6c681c0cdd90cd8367e Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 10 Jul 2017 18:58:53 +0200 Subject: [PATCH 044/271] first version of competitor <-> boat assignment dialog --- .../domain/common/dto/CompetitorDTO.java | 2 + .../domain/common/dto/CompetitorDTOImpl.java | 5 + .../common/dto/PreviousCompetitorDTOImpl.java | 6 + ...egistrationOnRaceLogDisabledException.java | 15 + .../CompetitorsAndBoatsInLogAnalyzer.java | 15 +- .../gwt/ui/adminconsole/BoatTableWrapper.java | 2 +- .../adminconsole/CompactBoatTableWrapper.java | 174 ++++++++++ .../CompactCompetitorConfigImagesBarCell.java | 28 ++ .../CompactCompetitorTableWrapper.java | 202 ++++++++++++ .../CompetitorToBoatMappingsPanel.java | 298 ++++++++++++++++++ .../EditCompetitorToBoatMappingsDialog.java | 56 ++++ .../adminconsole/LeaderboardConfigPanel.java | 23 +- .../LeaderboardRaceConfigImagesBarCell.java | 3 + .../sailing/gwt/ui/client/SailingService.java | 8 + .../gwt/ui/client/SailingServiceAsync.java | 8 + .../sailing/gwt/ui/client/StringMessages.java | 4 + .../gwt/ui/client/StringMessages.properties | 6 +- .../ui/client/StringMessages_de.properties | 6 +- .../gwt/ui/server/SailingServiceImpl.java | 84 ++++- 19 files changed, 926 insertions(+), 19 deletions(-) create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorConfigImagesBarCell.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorToBoatMappingsDialog.java diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index bb36f8d7254..41afc817e85 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -14,6 +14,8 @@ public interface CompetitorDTO extends CompetitorWithoutBoatDTO { BoatDTO getBoat(); + void setBoat(BoatDTO boat); + // TODO bug2822: Should we remove this? BoatClassDTO getBoatClass(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 07670d978ef..99c094a9798 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -60,6 +60,11 @@ public class CompetitorDTOImpl extends CompetitorWithoutBoatDTOImpl implements C return boat == null ? null : boat.getBoatClass(); } + @Override + public void setBoat(BoatDTO boat) { + this.boat = boat; + } + @Override public BoatDTO getBoat() { return boat; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java index 044e5262959..47f1bcefbf9 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java @@ -82,6 +82,12 @@ public class PreviousCompetitorDTOImpl implements CompetitorDTO { " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); } + @Override + public void setBoat(BoatDTO boat) { + throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ + " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); + } + @Override public Color getColor() { throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java new file mode 100644 index 00000000000..a6542af3b30 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.common.racelog.tracking; + +import java.io.Serializable; + +public class BoatRegistrationOnRaceLogDisabledException extends Exception implements Serializable { + private static final long serialVersionUID = -6656554635954928251L; + + public BoatRegistrationOnRaceLogDisabledException() { + super("Boat registration not allowed on race"); + } + + public BoatRegistrationOnRaceLogDisabledException(String message) { + super(message); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java index 409dbc641aa..20bfb5b1514 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsAndBoatsInLogAnalyzer.java @@ -6,26 +6,13 @@ import java.util.Map; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; /** - * This class searches for RegisterCompetitorEvents in the given log. + * This class searches for {@link RegisterCompetitorAndBoatEvent}s in the given log. * - * TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredCompetitorsAnalyzer} or {@link RaceLogRegisteredCompetitorsAnalyzer} - * - * Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered competitors for the race - * corresponding to the RaceLog/the races corresponding to the RegattaLog. - * - * This is the case as by default the competitors registered on the RegattaLog are used for each race of the regatta - * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the - * {@link RaceLogUseCompetitorsFromRaceLogEvent}. Is an event of this type present, the competitors written into the - * RaceLog are used instead of the competitors in the RegattaLog. - * */ public class CompetitorsAndBoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> extends BaseLogAnalyzer> { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java index 2b3db0eb8bb..43337b06e37 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -227,7 +227,7 @@ public class BoatTableWrapper> exte dialog.show(); } - protected void allowUpdate(final Iterable boats) { + public void allowUpdate(final Iterable boats) { List serializableSingletonList = new ArrayList(); Util.addAll(boats, serializableSingletonList); sailingService.allowBoatResetToDefaults(serializableSingletonList, new AsyncCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java new file mode 100644 index 00000000000..ce953505c78 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java @@ -0,0 +1,174 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import com.google.gwt.cell.client.SafeHtmlCell; +import com.google.gwt.core.client.Callback; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Label; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Color; +import com.sap.sse.common.util.NaturalComparator; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; + +public class CompactBoatTableWrapper> extends TableWrapper { + private final LabeledAbstractFilterablePanel filterField; + + public CompactBoatTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages,ErrorReporter errorReporter, + boolean multiSelection, boolean enablePager) { + super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + new EntityIdentityComparator() { + @Override + public boolean representSameEntity(BoatDTO dto1, BoatDTO dto2) { + return dto1.getIdAsString().equals(dto2.getIdAsString()); + } + @Override + public int hashCode(BoatDTO t) { + return t.getIdAsString().hashCode(); + } + }); + ListHandler boatColumnListHandler = getColumnSortHandler(); + + // boats table + TextColumn boatNameColumn = new TextColumn() { + @Override + public String getValue(BoatDTO boat) { + return boat.getName(); + } + }; + boatNameColumn.setSortable(true); + boatColumnListHandler.setComparator(boatNameColumn, new Comparator() { + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + TextColumn boatClassColumn = new TextColumn() { + @Override + public String getValue(BoatDTO competitor) { + return competitor.getBoatClass() != null ? competitor.getBoatClass().getName() : ""; + } + }; + boatClassColumn.setSortable(true); + boatColumnListHandler.setComparator(boatClassColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* caseSensitive */ false); + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return comparator.compare(o1.getBoatClass().getName(), o2.getBoatClass().getName()); + } + }); + + Column sailIdColumn = new Column(new SafeHtmlCell()) { + @Override + public SafeHtml getValue(BoatDTO competitor) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + sb.appendEscaped(competitor.getSailId()); + return sb.toSafeHtml(); + } + }; + sailIdColumn.setSortable(true); + boatColumnListHandler.setComparator(sailIdColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false); + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return comparator.compare(o1.getSailId(), o2.getSailId()); + } + }); + + Column boatColorColumn = new ColorColumn<>(new ColorRetriever() { + @Override + public Color getColor(BoatDTO t) { + return t.getColor(); + } + }); + + filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterBoats()), + new ArrayList(), table, dataProvider) { + @Override + public Iterable getSearchableStrings(BoatDTO boat) { + List string = new ArrayList(); + string.add(boat.getName()); + string.add(boat.getSailId()); + string.add(boat.getBoatClass().getName()); + return string; + } + }; + registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider()); + + mainPanel.insert(filterField, 0); + table.addColumnSortHandler(boatColumnListHandler); + table.addColumn(boatNameColumn, stringMessages.name()); + table.addColumn(sailIdColumn, stringMessages.sailNumber()); + table.addColumn(boatClassColumn, stringMessages.boatClass()); + table.addColumn(boatColorColumn, stringMessages.color()); + table.ensureDebugId("BoatsTable"); + } + + public Iterable getAllBoats() { + return filterField.getAll(); + } + + public LabeledAbstractFilterablePanel getFilterField() { + return filterField; + } + + public void filterBoats(Iterable boats) { + getFilteredBoats(boats); + } + + public void refreshBoatList() { + refreshBoatList(null); + } + + public void selectBoat(BoatDTO boatToSelect) { + for (BoatDTO boat: getAllBoats()) { + if (boat.getIdAsString().equals(boatToSelect.getIdAsString())) { + getSelectionModel().setSelected(boat, true); + break; + } + } + } + + public void clearSelection() { + getSelectionModel().clear(); + } + + public void refreshBoatList(final Callback, Throwable> callback) { + sailingService.getBoats(new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); + if (callback != null) { + callback.onFailure(caught); + } + } + + @Override + public void onSuccess(Iterable result) { + getFilteredBoats(result); + filterBoats(result); + if (callback != null) { + callback.onSuccess(result); + } + } + }); + } + + private void getFilteredBoats(Iterable result) { + filterField.updateAll(result); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorConfigImagesBarCell.java new file mode 100644 index 00000000000..fba7426d579 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorConfigImagesBarCell.java @@ -0,0 +1,28 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.core.client.GWT; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.shared.controls.ImagesBarCell; + +public class CompactCompetitorConfigImagesBarCell extends ImagesBarCell { + public final static String ACTION_UNLINK = "ACTION_UNLINK"; + + private final StringMessages stringMessages; + private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); + + public CompactCompetitorConfigImagesBarCell(StringMessages stringMessages) { + super(); + this.stringMessages = stringMessages; + } + + @Override + protected Iterable getImageSpecs() { + List result = new ArrayList(); + result.add(new ImageSpec(ACTION_UNLINK, stringMessages.actionBoatUnlink(), makeImagePrototype(resources.unlinkIcon()))); + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java new file mode 100644 index 00000000000..72c8acf72e1 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java @@ -0,0 +1,202 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import com.google.gwt.cell.client.SafeHtmlCell; +import com.google.gwt.core.client.Callback; +import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.ImageResourceRenderer; +import com.google.gwt.user.client.ui.Label; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.FlagImageResolver; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.util.NaturalComparator; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; +import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; + +/** + * A compact filterable competitor table. The data model is managed by the {@link #getFilterField() filter field}. In + * order to set an initial set of competitors to display by this table, use {@link #refreshCompetitorList(Iterable)}. + * The selected competitors can be obtained from the {@link #getSelectionModel() selection model}. + * The competitors currently in the table (regardless of the current filter settings) are returned by {@link #getAllCompetitors()}. + * + * @author Frank Mittag + * + * @param + */ +public class CompactCompetitorTableWrapper> extends TableWrapper { + private final LabeledAbstractFilterablePanel filterField; + + public CompactCompetitorTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter, + boolean multiSelection, boolean enablePager) { + super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + new EntityIdentityComparator() { + @Override + public boolean representSameEntity(CompetitorDTO dto1, CompetitorDTO dto2) { + return dto1.getIdAsString().equals(dto2.getIdAsString()); + } + @Override + public int hashCode(CompetitorDTO t) { + return t.getIdAsString().hashCode(); + } + }); + ListHandler competitorColumnListHandler = getColumnSortHandler(); + + // competitors table + TextColumn competitorNameColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + return competitor.getName(); + } + }; + competitorNameColumn.setSortable(true); + competitorColumnListHandler.setComparator(competitorNameColumn, new Comparator() { + @Override + public int compare(CompetitorDTO o1, CompetitorDTO o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + TextColumn competitorShortNameColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + return competitor.getShortName(); + } + }; + competitorShortNameColumn.setSortable(true); + competitorColumnListHandler.setComparator(competitorShortNameColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false); + @Override + public int compare(CompetitorDTO o1, CompetitorDTO o2) { + return comparator.compare(o1.getShortName(), o2.getShortName()); + } + }); + + Column flagImageColumn = new Column(new SafeHtmlCell()) { + @Override + public SafeHtml getValue(CompetitorDTO competitor) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + ImageResourceRenderer renderer = new ImageResourceRenderer(); + final String twoLetterIsoCountryCode = competitor.getTwoLetterIsoCountryCode(); + final String flagImageURL = competitor.getFlagImageURL(); + if (flagImageURL != null && !flagImageURL.isEmpty()) { + sb.appendHtmlConstant(""); + sb.appendHtmlConstant(" "); + } else { + final ImageResource flagImageResource; + if (twoLetterIsoCountryCode==null || twoLetterIsoCountryCode.isEmpty()) { + flagImageResource = FlagImageResolver.getEmptyFlagImageResource(); + } else { + flagImageResource = FlagImageResolver.getFlagImageResource(twoLetterIsoCountryCode); + } + if (flagImageResource != null) { + sb.append(renderer.render(flagImageResource)); + sb.appendHtmlConstant(" "); + } + } + return sb.toSafeHtml(); + } + }; + + TextColumn competitorSearchTagColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + return competitor.getSearchTag(); + } + }; + competitorSearchTagColumn.setSortable(true); + competitorColumnListHandler.setComparator(competitorSearchTagColumn, new Comparator() { + @Override + public int compare(CompetitorDTO o1, CompetitorDTO o2) { + return new NaturalComparator(false).compare(o1.getSearchTag(), o2.getSearchTag()); + } + }); + + TextColumn isBoatLinkedColumn = new TextColumn() { + @Override + public String getValue(CompetitorDTO competitor) { + boolean hasBoat = competitor.getBoat() != null; + return hasBoat ? stringMessages.yes() : stringMessages.no(); + } + }; + + filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterCompetitors()), + new ArrayList(), table, dataProvider) { + @Override + public Iterable getSearchableStrings(CompetitorDTO t) { + List string = new ArrayList(); + string.add(t.getName()); + string.add(t.getShortName()); + string.add(t.getSearchTag()); + return string; + } + }; + registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider()); + + mainPanel.insert(filterField, 0); + table.addColumnSortHandler(competitorColumnListHandler); + table.addColumn(competitorNameColumn, stringMessages.name()); + table.addColumn(competitorShortNameColumn, stringMessages.shortName()); + table.addColumn(flagImageColumn, stringMessages.flags()); + table.addColumn(competitorSearchTagColumn, stringMessages.searchTag()); + table.addColumn(isBoatLinkedColumn, stringMessages.islinked()); + table.ensureDebugId("CompactCompetitorsTable"); + } + + public Iterable getAllCompetitors() { + return filterField.getAll(); + } + + public LabeledAbstractFilterablePanel getFilterField() { + return filterField; + } + + public void refreshCompetitorList(Iterable competitors) { + getFilteredCompetitors(competitors); + } + + public void refreshCompetitorList(String leaderboardName, String raceColumnName, String fleetName) { + refreshCompetitorList(leaderboardName, raceColumnName, fleetName, null); + } + + /** + * @param leaderboardName If null, all existing competitors are loaded + */ + public void refreshCompetitorList(String leaderboardName, String raceColumnName, String fleetName, + final Callback, Throwable> callback) { + final AsyncCallback> myCallback = new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Remote Procedure Call getCompetitors() - Failure: " + caught.getMessage()); + if (callback != null) { + callback.onFailure(caught); + } + } + + @Override + public void onSuccess(Iterable result) { + getFilteredCompetitors(result); + refreshCompetitorList(result); + if (callback != null) { + callback.onSuccess(result); + } + } + }; + sailingService.getCompetitorsOfRace(leaderboardName, raceColumnName, fleetName, myCallback); + } + + private void getFilteredCompetitors(Iterable result) { + filterField.updateAll(result); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java new file mode 100644 index 00000000000..3ba3f638f47 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java @@ -0,0 +1,298 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.Set; + +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CaptionPanel; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; +import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; +import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; +import com.sap.sse.gwt.client.controls.busyindicator.BusyDisplay; +import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator; +import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator; + +/** + * Allows an administrator to view and edit boats assigned to the competitors of a race. + * + * @author Frank Mittag + * + */ +public class CompetitorToBoatMappingsPanel extends SimplePanel implements BusyDisplay { + private final CompactCompetitorTableWrapper> competitorTable; + private final CompactBoatTableWrapper> boatTable; + private final String leaderboardName; + private final String raceColumnName; + private final String fleetName; + private final SailingServiceAsync sailingService; + private final ErrorReporter errorReporter; + private final StringMessages stringMessages; + + private final RefreshableSelectionModel refreshableBoatSelectionModel; + private final RefreshableSelectionModel refreshableCompetitorSelectionModel; + + protected final SelectionChangeEvent.Handler boatListHandler; + protected HandlerRegistration boatListHandlerRegistration; + + private final BusyIndicator busyIndicator; + + public CompetitorToBoatMappingsPanel(final SailingServiceAsync sailingService, final String leaderboardName, + final String raceColumnName, final String fleetName, final StringMessages stringMessages, final ErrorReporter errorReporter) { + super(); + this.sailingService = sailingService; + this.leaderboardName = leaderboardName; + this.raceColumnName = raceColumnName; + this.fleetName = fleetName; + this.stringMessages = stringMessages; + this.errorReporter = errorReporter; + + this.competitorTable = new CompactCompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); + this.boatTable = new CompactBoatTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); + + ImagesBarColumn raceActionColumn = new ImagesBarColumn<>(new CompactCompetitorConfigImagesBarCell(stringMessages)); + raceActionColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, CompetitorDTO competitor, String value) { + if (CompactCompetitorConfigImagesBarCell.ACTION_UNLINK.equals(value)) { + unlinkBoatFromCompetitor(competitor); + } + } + }); + competitorTable.getTable().addColumn(raceActionColumn, stringMessages.actions()); + + refreshableBoatSelectionModel = boatTable.getSelectionModel(); + refreshableCompetitorSelectionModel = competitorTable.getSelectionModel(); + + boatListHandler = new SelectionChangeEvent.Handler() { + @Override + public void onSelectionChange(SelectionChangeEvent event) { + Set selectedBoats = refreshableBoatSelectionModel.getSelectedSet(); + CompetitorDTO selectedCompetitor = getSelectedCompetitor(); + // if no competitor is selected, ignore the boat selection change + if (selectedCompetitor != null) { + if (selectedBoats.isEmpty()) { + if (hasLink(selectedCompetitor)) { + unlinkBoatFromCompetitor(selectedCompetitor); + } + } else { + BoatDTO selectedBoat = selectedBoats.iterator().next(); + boolean a = hasLink(selectedCompetitor); + boolean b = isLinkedToBoat(selectedCompetitor, selectedBoat); + if (hasLink(selectedCompetitor) && !isLinkedToBoat(selectedCompetitor, selectedBoat)) { + if (Window.confirm(stringMessages.boatAlreadyLinked())) { + linkBoatToSelectedCompetitor(selectedCompetitor, selectedBoat); + } else { + selectBoatForCompetitor(selectedCompetitor); + } + } else { + linkBoatToSelectedCompetitor(selectedCompetitor, selectedBoat); + } + } + } + } + + private boolean hasLink(CompetitorDTO selectedCompetitor) { + return selectedCompetitor.getBoat() != null; + } + + private boolean isLinkedToBoat(CompetitorDTO selectedCompetitor, BoatDTO selectedBoat){ + return selectedBoat.equals(selectedCompetitor.getBoat()); + } + }; + boatListHandlerRegistration = refreshableBoatSelectionModel.addSelectionChangeHandler(boatListHandler); + + refreshableCompetitorSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + // If the selection on the competitorTable changes, + // you don't want to link or unlink competitors with the + // boatListHandler. + removeBoatListHandlerTemporarily(); + competitorSelectionChanged(); + } + }); + + busyIndicator = new SimpleBusyIndicator(false, 0.8f); + + VerticalPanel mainPanel = new VerticalPanel(); + this.setWidget(mainPanel); + mainPanel.setWidth("100%"); + + CaptionPanel competitorsPanel = new CaptionPanel(stringMessages.competitors()); + competitorsPanel.ensureDebugId("CompetitorsSection"); + competitorsPanel.setContentWidget(this.competitorTable.asWidget()); + + CaptionPanel boatsPanel = new CaptionPanel(stringMessages.boats()); + boatsPanel.ensureDebugId("BoatsSection"); + boatsPanel.setContentWidget(this.boatTable.asWidget()); + + HorizontalPanel buttonPanel = new HorizontalPanel(); + buttonPanel.setSpacing(5); + Button refreshButton = new Button(stringMessages.refresh()); + refreshButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + refreshData(); + } + }); + refreshButton.ensureDebugId("RefreshButton"); + buttonPanel.add(refreshButton); + + mainPanel.add(buttonPanel); + mainPanel.add(busyIndicator); + + Grid grid = new Grid(1,2); + grid.setWidget(0, 0, competitorsPanel); + grid.setWidget(0, 1, boatsPanel); + grid.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_TOP); + grid.getCellFormatter().setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_TOP); + mainPanel.add(grid); + + refreshData(); + } + + private void linkBoatToSelectedCompetitor(CompetitorDTO selectedCompetitor, BoatDTO selectedBoat) { + sailingService.linkBoatToCompetitorForRace(leaderboardName, raceColumnName, fleetName, selectedCompetitor.getIdAsString(), selectedBoat.getIdAsString(), + new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to link boat " + selectedBoat.getIdAsString() + " with competitor " + + selectedCompetitor.getIdAsString() + " for raceColumn " + raceColumnName + " and fleet " + fleetName + + " of leaderboard " + leaderboardName + ": " + t.getMessage()); + boatTable.getSelectionModel().clear(); + } + + @Override + public void onSuccess(Boolean success) { + if (success) { + selectedCompetitor.setBoat(selectedBoat); + competitorTable.getDataProvider().refresh(); + } + } + })); + } + + private void unlinkBoatFromCompetitor(CompetitorDTO selectedCompetitor) { + sailingService.unlinkBoatFromCompetitorForRace(leaderboardName, raceColumnName, fleetName, selectedCompetitor.getIdAsString(), + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to unlink boat from competitor " + + selectedCompetitor.getIdAsString() + " for raceColumn " + raceColumnName + " and fleet " + fleetName + + " of leaderboard " + leaderboardName + ": " + t.getMessage()); + } + + @Override + public void onSuccess(Boolean success) { + if (success) { + boatTable.getSelectionModel().clear(); + getSelectedCompetitor().setBoat(null); + competitorTable.getDataProvider().refresh(); + } + } + }); + } + + private void competitorSelectionChanged() { + CompetitorDTO selectedCompetitor = getSelectedCompetitor(); + if (selectedCompetitor != null) { + selectBoatForCompetitor(selectedCompetitor); + } else { + boatTable.getSelectionModel().clear();; + } + } + + private void selectBoatInList(BoatDTO boat) { + boatTable.selectBoat(boat); + } + + private void selectBoatForCompetitor(CompetitorDTO selectedCompetitor) { + sailingService.getBoatLinkedToCompetitorForRace(leaderboardName, + raceColumnName, fleetName, selectedCompetitor.getIdAsString(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onFailure(Throwable t) { + errorReporter.reportError("Error trying to determine boat linked to competitor " + + raceColumnName + " in leaderboard " + leaderboardName + ": " + + t.getMessage()); + } + + @Override + public void onSuccess(BoatDTO boat) { + // This method should select the linked boat. + // So you don't want to link or unlink it again throw the trackedRaceListHandler. + removeBoatListHandlerTemporarily(); + if (boat != null) { + selectBoatInList(boat); + } else { + boatTable.clearSelection(); + } + } + })); + } + + /** + * Removes the {@link SelectionChangeEvent.Handler} until the browser regains control. The handler will be added + * again using {@link Scheduler#scheduleDeferred(ScheduledCommand)} method. + *

      + * Use this method if you change the {@link ListDataProvider} or {@link RefreshableSelectionModel} of + * {@link BoatTableWrapper} and you don't want to trigger the + * {@link SelectionChangeEvent.Handler#onSelectionChange(SelectionChangeEvent)}. + */ + private void removeBoatListHandlerTemporarily() { + if (boatListHandlerRegistration == null) { + return; + } + boatListHandlerRegistration.removeHandler(); + boatListHandlerRegistration = null; + // It is necessary to do this with the ScheduleDeferred() method, + // because the SelectionChangeEvent isn't fired directly after + // selection changes. So an remove of SelectionChangeHandler before + // the selection change and and new registration directly after it + // isn't possible. + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + @Override + public void execute() { + boatListHandlerRegistration = refreshableBoatSelectionModel.addSelectionChangeHandler(boatListHandler); + } + }); + } + + private CompetitorDTO getSelectedCompetitor() { + if (competitorTable.getSelectionModel().getSelectedSet().isEmpty()) { + return null; + } + return competitorTable.getSelectionModel().getSelectedSet().iterator().next(); + } + + public void refreshData() { + competitorTable.refreshCompetitorList(leaderboardName, raceColumnName, fleetName); + boatTable.refreshBoatList(); + } + + @Override + public void setBusy(boolean isBusy) { + if (busyIndicator.isBusy() != isBusy) { + busyIndicator.setBusy(isBusy); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorToBoatMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorToBoatMappingsDialog.java new file mode 100644 index 00000000000..57f4af56252 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorToBoatMappingsDialog.java @@ -0,0 +1,56 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.List; + +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.dialog.DataEntryDialog; + +public class EditCompetitorToBoatMappingsDialog extends DataEntryDialog> { + private final SailingServiceAsync sailingService; + private final StringMessages stringMessages; + private final ErrorReporter errorReporter; + private final String leaderboardName; + private final String raceColumnName; + private final String fleetName; + + protected static class CompetitorsValidator implements Validator> { + public CompetitorsValidator() { + super(); + } + + @Override + public String getErrorMessage(List valueToValidate) { + return null; + } + } + + public EditCompetitorToBoatMappingsDialog(final SailingServiceAsync sailingService, String leaderboardName, + final String raceColumnName, final String fleetName, String raceName, final StringMessages stringMessages, + final ErrorReporter errorReporter, DialogCallback> callback) { + super(stringMessages.actionEditCompetitorToBoatAssignmentsForRace(raceName), + null, stringMessages.ok(), stringMessages.cancel(), new CompetitorsValidator(), callback); + this.sailingService = sailingService; + this.stringMessages = stringMessages; + this.errorReporter = errorReporter; + this.leaderboardName = leaderboardName; + this.raceColumnName = raceColumnName; + this.fleetName = fleetName; + } + + @Override + protected List getResult() { + return null; + } + + @Override + protected Widget getAdditionalWidget() { + CompetitorToBoatMappingsPanel competitorPanel = new CompetitorToBoatMappingsPanel(sailingService, + leaderboardName, raceColumnName, fleetName, stringMessages, errorReporter); + + return competitorPanel; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index 53563ae9983..955c8fd6bf5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -31,6 +31,7 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.view.client.ListDataProvider; +import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; import com.sap.sailing.domain.common.ScoringSchemeType; @@ -308,7 +309,6 @@ TrackedRaceChangedListener, LeaderboardsDisplayer { } }); editCompetitorsDialog.show(); - } else if (LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL.equals(value)) { openLeaderboardUrlConfigDialog(leaderboardDTO); } else if (LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML.equals(value)) { @@ -466,6 +466,8 @@ TrackedRaceChangedListener, LeaderboardsDisplayer { setStartTime(object.getA(), object.getB()); } else if (LeaderboardRaceConfigImagesBarCell.ACTION_SHOW_RACELOG.equals(value)) { showRaceLog(object.getA(), object.getB()); + } else if (LeaderboardRaceConfigImagesBarCell.ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS.equals(value)) { + editCompetitorToBoatMappings(object.getA(), object.getB()); } } }); @@ -584,6 +586,25 @@ TrackedRaceChangedListener, LeaderboardsDisplayer { dialog.show(); } + private void editCompetitorToBoatMappings(final RaceColumnDTO raceColumnDTO, final FleetDTO fleetDTO) { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final String raceColumnName = raceColumnDTO.getName(); + final String fleetName = fleetDTO.getName(); + final String raceName = LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName) ? raceColumnName : raceColumnName + ", " + fleetName; + EditCompetitorToBoatMappingsDialog dialog = new EditCompetitorToBoatMappingsDialog(sailingService, + selectedLeaderboardName, raceColumnName, fleetName, raceName, stringMessages, + errorReporter, new DialogCallback>() { + @Override + public void cancel() { + } + + @Override + public void ok(final List result) { + } + }); + dialog.show(); + } + private void setStartTime(RaceColumnDTO raceColumnDTO, FleetDTO fleetDTO) { new SetStartTimeDialog(sailingService, errorReporter, getSelectedLeaderboardName(), raceColumnDTO.getName(), fleetDTO.getName(), stringMessages, new DialogCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index bbc0d8b56d4..109eb683d9a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -16,6 +16,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { public final static String ACTION_REFRESH_RACELOG = "ACTION_REFRESH_RACE_LOG"; public final static String ACTION_SET_STARTTIME = "ACTION_SET_STARTTIME"; public final static String ACTION_SHOW_RACELOG = "ACTION_SHOW_RACELOG"; + public final static String ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS = "ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS"; private final StringMessages stringMessages; private final SelectedLeaderboardProvider selectedLeaderboardProvider; @@ -40,6 +41,8 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); result.add(new ImageSpec(ACTION_SHOW_RACELOG, stringMessages.raceLog(), makeImagePrototype(resources.flagIcon()))); + result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon()))); + return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index d3255c18aa7..49fc27ede82 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -437,6 +437,8 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Iterable getCompetitorsOfLeaderboard(String leaderboardName); + Iterable getCompetitorsOfRace(String leaderboardName, String raceColumnName, String fleetName); + List addOrUpdateCompetitors(List competitors) throws Exception; CompetitorDTO addOrUpdateCompetitor(CompetitorDTO competitor) throws Exception; @@ -453,6 +455,12 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS void allowBoatResetToDefaults(Iterable boats); + boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, String boatIdAsString); + + boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString); + + BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString); + List getDeviceConfigurationMatchers(); DeviceConfigurationDTO getDeviceConfiguration(DeviceConfigurationMatcherDTO matcher); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index bb33860e1da..e949b92e89f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -591,6 +591,8 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void getCompetitorsOfLeaderboard(String leaderboardName, AsyncCallback> asyncCallback); + void getCompetitorsOfRace(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> asyncCallback); + void addOrUpdateCompetitors(List competitors, AsyncCallback> asyncCallback); void addOrUpdateCompetitor(CompetitorDTO competitor, AsyncCallback asyncCallback); @@ -608,6 +610,12 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void allowBoatResetToDefaults(Iterable boats, AsyncCallback asyncCallback); + void linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, String boatIdAsString, AsyncCallback asyncCallback); + + void unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, AsyncCallback asyncCallback); + + void getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, AsyncCallback asyncCallback); + void getDeviceConfigurationMatchers(AsyncCallback> asyncCallback); void getDeviceConfiguration(DeviceConfigurationMatcherDTO matcher, AsyncCallback callback); 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 6c992cf1ce9..496b7a2a303 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 @@ -215,6 +215,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String actionEdit(); String actionEditScores(); String actionEditCompetitors(); + String actionEditCompetitorToBoatAssignmentsForRace(String raceName); String actionOpenBrowser(); String actionRemove(); String actionEditSeries(); @@ -223,6 +224,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String actionRaceRemove(); String actionExportXML(); String actionOpenDashboard(); + String actionBoatUnlink(); String filterLeaderboardsByName(); String actions(); String islinked(); @@ -964,6 +966,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String doYouReallyWantToRemoveCompetitors(); String doYouReallyWantToRemoveCompetitor(String name); String filterCompetitors(); + String filterBoats(); String editCompetitor(); String pleaseEnterASailNumber(); String successfullyAllowedCompetitorReset(String names); @@ -1815,6 +1818,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String unknownLeaderboardType(String name); String selectCompetitorsToEliminate(); String trackedRaceAlreadyLinked(); + String boatAlreadyLinked(); String reallyRemoveSeries(String seriesName); String settingsId(); String documentSettingsId(); 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 b4642c0ff96..5331a591c8d 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 @@ -216,6 +216,7 @@ filterMediaByName=Filter media by name trackSettings=Track settings actionEdit=Edit actionEditCompetitors=Edit competitors +actionEditCompetitorToBoatAssignmentsForRace=Edit used boats for competitors of race {0} actionEditScores=Edit scores actionOpenBrowser=Open in Browser actionRemove=Remove @@ -225,6 +226,7 @@ actionRaceUnlink=Unlink race actionRaceRemove=Remove race actionExportXML=Export as XML actionOpenDashboard=Open Coach Dashboard +actionBoatUnlink=Unlink boat filterLeaderboardsByName=Filter leaderboards by name actions=Actions islinked=Is linked @@ -938,7 +940,8 @@ line=Line offset=Offset doYouReallyWantToRemoveCompetitors=Do you really want to remove the selected competitors? doYouReallyWantToRemoveCompetitor=Do you really want to remove competitor {0}? -filterCompetitors=Filter competitors by name, boat class, sail number, search tag or ID +filterCompetitors=Filter competitors by name, short name, search tag or ID +filterBoats=Filter boats by name, boat class, sail number, search tag or ID editCompetitor=Edit Competitor pleaseEnterASailNumber=Please enter a sail number successfullyAllowedCompetitorReset=Successfully allowed reload of competitor(s) {0}. @@ -1794,6 +1797,7 @@ useOnlyOneOfStartTimeInferenceAndControlTrackingFromStartAndFinishTimes=Use only unknownLeaderboardType=Unknown leaderboard type {0} selectCompetitorsToEliminate=Select competitors to eliminate trackedRaceAlreadyLinked=The race is already linked to a race column. Do you really want to change the link? +boatAlreadyLinked=The boat is already linked to a competitor. Do you really want to change the link? reallyRemoveSeries=Do you really want to remove the series ''{0}''? Note: all race logs for the attached race columns will also permanently be removed! settingsId=Settings ID documentSettingsId=Document settings ID 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 f754de8bc49..1345d7fb1b4 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 @@ -218,6 +218,7 @@ filterByRegatta=nach Regatta filterMediaByName=Medien nach Name filtern actionEdit=Ändern actionEditCompetitors=Teilnehmer ändern +actionEditCompetitorToBoatAssignmentsForRace=Ändere die Boote für die Teilnehmer im Rennen {0} actionEditScores=Punkte ändern actionOpenBrowser=Im Browser öffnen actionRemove=Entfernen @@ -227,6 +228,7 @@ actionRaceUnlink=Rennverknüpfung entfernen actionRaceRemove=Rennen entfernen actionExportXML=Als XML exportieren actionOpenDashboard=Coach Dashboard öffnen +actionBoatUnlink=Bootsverknüpfung entfernen filterLeaderboardsByName=Ranglisten nach Name filtern actions=Aktionen islinked=Verknüpft @@ -927,7 +929,8 @@ line=Linie offset=Ablauftonne doYouReallyWantToRemoveCompetitors=Möchten Sie wirlich die ausgewählten Teilnehmer entfernen? doYouReallyWantToRemoveCompetitor=Möchten Sie wirklicn den Teilnehmer {0} entfernen? -filterCompetitors=Filtere Teilnehmer nach Name, Bootsklasse, Segelnummer, Suchhilfe oder ID +filterCompetitors=Filtere Teilnehmer nach Name, Kurzname, Suchhilfe oder ID +filterBoats=Filtere Boote nach Name, Bootsklasse, Segelnummer, Suchhilfe oder ID editCompetitor=Teilnehmer bearbeiten pleaseEnterASailNumber=Bitte Segelnummer eingeben successfullyAllowedCompetitorReset=Aktualisierung der Daten zu Teilnehmer(n) {0} erfolgreich ermöglicht.id=ID @@ -1777,6 +1780,7 @@ useOnlyOneOfStartTimeInferenceAndControlTrackingFromStartAndFinishTimes=Höchste unknownLeaderboardType=Unbekannter Ranglistentyp {0} selectCompetitorsToEliminate=Zu eliminierende Teilnehmer auswählen trackedRaceAlreadyLinked=Das Rennen ist bereits mit einer Renn-Spalte verlinkt. Wollen Sie die Verbindung wirklich ändern? +boatAlreadyLinked=Das Boot ist bereits mit einem Teilnehmer Spalte verlinkt. Wollen Sie die Verbindung wirklich ändern? reallyRemoveSeries=Möchten Sie die Serie ''{0}'' wirklich entfernen? Achtung: alle Ereignisprotokolle (RaceLogs) der zugehörigen Renn-Spalten werden unwiederbringlich gelöscht! settingsId=Einstellungs ID documentSettingsId=ID der Dokumenten-Einstellungen 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 d34de69d7b6..ed4018f9e8c 100644 --- 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 @@ -56,9 +56,11 @@ import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.competitorimport.CompetitorProvider; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; @@ -83,7 +85,9 @@ import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.ReadonlyGateStartRacingProcedure; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.ConfigurableStartModeFlagRacingProcedure; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; @@ -96,6 +100,8 @@ import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.BaseRe import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogOpenEndedDeviceMappingCloser; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -459,7 +465,6 @@ import com.sap.sailing.xrr.structureimport.SeriesParameters; import com.sap.sailing.xrr.structureimport.StructureImporter; import com.sap.sailing.xrr.structureimport.buildstructure.SetRacenumberFromSeries; import com.sap.sse.ServerInfo; -import com.sap.sse.common.Color; import com.sap.sse.common.CountryCode; import com.sap.sse.common.Duration; import com.sap.sse.common.NoCorrespondingServiceRegisteredException; @@ -4823,6 +4828,28 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return convertToCompetitorDTOs(leaderboard.getAllCompetitors()); } + @Override + public Iterable getCompetitorsOfRace(String leaderboardName, String raceColumnName, String fleetName) { + List result = null; + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + if (leaderboard != null && raceLog != null) { + result = new ArrayList<>(); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + Fleet fleet = leaderboard.getFleet(fleetName); + Map competitorAndBoats = new CompetitorsAndBoatsInLogAnalyzer<>(raceLog).analyze(); + for (Competitor competitor: leaderboard.getCompetitors(raceColumn, fleet)) { + CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitor); + Boat boatOfCompetitor = competitorAndBoats.get(competitor); + if (boatOfCompetitor != null) { + competitorDTO.setBoat(baseDomainFactory.convertToBoatDTO(boatOfCompetitor)); + } + result.add(competitorDTO); + } + } + return result; + } + @Override public List addOrUpdateCompetitors(List competitors) throws URISyntaxException { final List result = new ArrayList<>(); @@ -4959,6 +4986,61 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); } + @Override + public boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, String boatIdAsString) { + boolean result = false; + Boat existingBoat = getService().getCompetitorStore().getExistingBoatByIdAsString(boatIdAsString); + Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + if (raceLog != null && existingCompetitor != null && existingBoat != null) { + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), + getService().getServerAuthor(), raceLog.getCurrentPassId(), existingCompetitor, existingBoat)); + result = true; + } + return result; + } + + @Override + public boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) { + boolean result = false; + Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + if (raceLog != null && existingCompetitor != null) { + List linkEventsToRevoke = new ArrayList<>(); + for (RaceLogEvent event : raceLog.getUnrevokedEventsDescending()) { + if (event instanceof RaceLogRegisterCompetitorAndBoatEvent) { + linkEventsToRevoke.add((RaceLogRegisterCompetitorAndBoatEvent) event); + } + } + try { + for (RaceLogRegisterCompetitorAndBoatEvent eventToRevoke : linkEventsToRevoke) { + raceLog.revokeEvent(getService().getServerAuthor(), eventToRevoke, "unlink competitor from boat"); + } + } catch (NotRevokableException e) { + logger.log(Level.WARNING, "Could not unlink competitor from boat by adding RevokeEvent", e); + } + + result = true; + } + return result; + } + + @Override + public BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) { + BoatDTO result = null; + Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString); + RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + if (raceLog != null && existingCompetitor != null) { + Map competitorAndBoats = new CompetitorsAndBoatsInLogAnalyzer<>(raceLog).analyze(); + Boat boatOfCompetitor = competitorAndBoats.get(existingCompetitor); + if (boatOfCompetitor != null) { + result = baseDomainFactory.convertToBoatDTO(boatOfCompetitor); + } + } + return result; + + } + @Override public List getDeviceConfigurationMatchers() { List configs = new ArrayList(); From c295bce93c50abd6cc8667a099ed8e1594034dec Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 12 Jul 2017 17:05:17 +0200 Subject: [PATCH 045/271] added a couple of racelog events for competitor/boats assignments (not sure we will need all of them) --- .../impl/DomainObjectFactoryImpl.java | 20 ++ .../impl/MongoObjectFactoryImpl.java | 31 +++ .../impl/MongoRaceLogStoreVisitor.java | 14 ++ .../abstractlog/race/RaceLogEventVisitor.java | 8 +- .../impl/AbstractRaceLogChangedVisitor.java | 12 + .../race/impl/BaseRaceLogEventVisitor.java | 12 + .../impl/RaceLogRegisterBoatEventImpl.java | 62 +++++ .../RaceLogUseBoatsFromRaceLogEventImpl.java | 31 +++ .../shared/analyzing/BoatDeregistrator.java | 70 ++++++ .../shared/analyzing/BoatsInLogAnalyzer.java | 46 ++++ .../domain/test/mock/MockedTrackedRace.java | 27 ++ .../impl/RaceColumnRaceLogReplicator.java | 12 + .../sailing/domain/base/impl/RegattaImpl.java | 53 +++- .../HasRaceColumnsAndRegattaLike.java | 2 + .../impl/AbstractLeaderboardImpl.java | 64 +++++ ...ProviderFromRaceColumnsAndRegattaLike.java | 234 ++++++++++++++++++ ...aLeaderboardWithCompetitorElimination.java | 36 ++- .../domain/regattalike/HasRegattaLike.java | 25 ++ .../LeaderboardRaceConfigImagesBarCell.java | 2 +- ...ckingEventManagementRaceImagesBarCell.java | 3 +- ...martphoneTrackingEventManagementPanel.java | 24 +- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 1 + .../ui/client/StringMessages_de.properties | 1 + .../gwt/ui/server/SailingServiceImpl.java | 1 - .../impl/RaceLogEventDeserializer.java | 13 + .../RaceLogRegisterBoatEventDeserializer.java | 32 +++ ...terCompetitorAndBoatEventDeserializer.java | 27 ++ ...gUseBoatsFromRaceLogEventDeserializer.java | 30 +++ .../racelog/impl/RaceLogEventSerializer.java | 28 ++- .../RaceLogRegisterBoatEventSerializer.java | 20 ++ ...isterCompetitorAndBoatEventSerializer.java | 20 ++ ...LogUseBoatsFromRaceLogEventSerializer.java | 21 ++ .../racelog/RaceLogEventSerializerTest.java | 11 +- 34 files changed, 983 insertions(+), 11 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java create mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventSerializer.java create mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index f91aeced1c3..c69b30f9052 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -89,14 +89,18 @@ import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformat import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; @@ -1431,6 +1435,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRevokeEvent.class.getSimpleName())) { return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogRegisterBoatEvent.class.getSimpleName())) { + return loadRaceLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { @@ -1443,6 +1449,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())){ return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName())){ + return loadRaceLogUseBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); @@ -1453,6 +1461,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return new RaceLogUseCompetitorsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } + private RaceLogEvent loadRaceLogUseBoatsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + return new RaceLogUseBoatsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); + } + private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name())); @@ -1484,6 +1497,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { revokedEventId, revokedEventType, revokedEventShortInfo, reason); } + private RaceLogEvent loadRaceLogRegisterBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + Serializable id, Integer passId, List competitors, DBObject dbObject) { + Serializable boatId = (Serializable) dbObject.get(FieldNames.RACE_LOG_BOAT_ID.name()); + Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); + return new RaceLogRegisterBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, boat); + } + private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 50cf8abca4e..f9ef8c2131f 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -48,9 +48,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; @@ -911,6 +913,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterBoatEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterBoatEvent(event)); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1058,6 +1067,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + private Object storeRaceLogRegisterBoatEvent(RaceLogRegisterBoatEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterBoatEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_BOAT_ID.name(), event.getBoat().getId()); + return result; + } + private Object storeRaceLogRegisterCompetitorEvent(RaceLogRegisterCompetitorEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); @@ -1082,6 +1099,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseBoatsFromRaceLogEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogUseBoatsFromRaceLogEvent(event)); + return result; + } + public DBObject storeRaceLogUseCompetitorsFromRaceLogEvent(RaceLogUseCompetitorsFromRaceLogEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); @@ -1089,6 +1113,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + public DBObject storeRaceLogUseBoatsFromRaceLogEvent(RaceLogUseBoatsFromRaceLogEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName()); + return result; + } + private Object storeRaceLogFixedMarkPassingEvent(RaceLogFixedMarkPassingEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java index f5aa8f03605..1af71fbe8bf 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java @@ -25,9 +25,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -141,6 +143,12 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { mongoObjectFactory.storeRaceLogEventEvent(object); } + @Override + public void visit(RaceLogRegisterBoatEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + mongoObjectFactory.storeRaceLogEventEvent(object); + } + @Override public void visit(RaceLogRegisterCompetitorEvent event) { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); @@ -194,4 +202,10 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); mongoObjectFactory.storeRaceLogEventEvent(object); } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + mongoObjectFactory.storeRaceLogEventEvent(object); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java index 2bad51f8c54..185eb802d15 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java @@ -2,9 +2,11 @@ package com.sap.sailing.domain.abstractlog.race; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -40,7 +42,9 @@ public interface RaceLogEventVisitor { public void visit(RaceLogDenoteForTrackingEvent event); public void visit(RaceLogStartTrackingEvent event); - + + public void visit(RaceLogRegisterBoatEvent event); + public void visit(RaceLogRegisterCompetitorEvent event); public void visit(RaceLogRegisterCompetitorAndBoatEvent event); @@ -58,4 +62,6 @@ public interface RaceLogEventVisitor { public void visit(RaceLogEndOfTrackingEvent event); public void visit(RaceLogUseCompetitorsFromRaceLogEvent event); + + public void visit(RaceLogUseBoatsFromRaceLogEvent event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java index 9f036e7adfa..c72362098fc 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java @@ -23,9 +23,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisitor { @@ -105,6 +107,11 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit notifyListenerAboutEventAdded(event); } + @Override + public void visit(RaceLogRegisterBoatEvent event) { + notifyListenerAboutEventAdded(event); + } + @Override public void visit(RaceLogRegisterCompetitorEvent event) { notifyListenerAboutEventAdded(event); @@ -149,4 +156,9 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { notifyListenerAboutEventAdded(event); } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + notifyListenerAboutEventAdded(event); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java index c6fdaaa1c9c..2376ee89d4d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java @@ -22,9 +22,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; /** @@ -117,6 +119,11 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { } + @Override + public void visit(RaceLogRegisterBoatEvent event) { + + } + @Override public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { @@ -156,4 +163,9 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java new file mode 100644 index 00000000000..6d54ed0395f --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java @@ -0,0 +1,62 @@ +package com.sap.sailing.domain.abstractlog.race.tracking.impl; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventData; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sse.common.TimePoint; + +public class RaceLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl implements + RaceLogRegisterBoatEvent { + private static final long serialVersionUID = -856679388199355195L; + private final RaceLogEventData raceLogEventData; + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public RaceLogRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, int passId, Boat boat) + throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, boat); + this.raceLogEventData = new RaceLogEventDataImpl(null, passId); + } + + /** + * @throws IllegalArgumentException + * if {@code boat} is null + */ + public RaceLogRegisterBoatEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int passId, Boat boat) + throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), passId, boat); + } + + @Override + public int getPassId() { + return raceLogEventData.getPassId(); + } + + @Override + public String toString() { + return raceLogEventData.toString(); + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } + + @Override + public List getInvolvedBoats() { + return Collections.emptyList(); + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java new file mode 100644 index 00000000000..4fff51b1271 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java @@ -0,0 +1,31 @@ +package com.sap.sailing.domain.abstractlog.race.tracking.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sse.common.TimePoint; + +public class RaceLogUseBoatsFromRaceLogEventImpl extends RaceLogEventImpl implements + RaceLogUseBoatsFromRaceLogEvent { + private static final long serialVersionUID = -1859200551195623389L; + + public RaceLogUseBoatsFromRaceLogEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, int passId) + throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, null, passId); + } + + @Override + public String toString() { + return "This RaceLog uses the boats registered on the RaceLog instead of the boats on the RegattaLog"; + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java new file mode 100644 index 00000000000..6c66f7e9d86 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java @@ -0,0 +1,70 @@ +package com.sap.sailing.domain.abstractlog.shared.analyzing; + +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Level; +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.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sse.common.Util; + +/** + * Finds the boat registration events for a given set of {@link Boat boats} that must be + * {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent) revoked} in order to deregister the + * boats. Note that the de-registration cannot be performed during analysis because + * {@link BaseLogAnalyzer#analyze()} obtains a read lock on the log whereas + * {@link AbstractLog#revokeEvent(AbstractLogEventAuthor, AbstractLogEvent)} requires a write lock, and upgrading from a + * read to a write lock is not possible.

      + * + * Clients must call {@link #deregister} with the result of {@link #analyze()} in order to actually perform the + * deregistration. + * + * @author Frank Mittag + * + */ +public class BoatDeregistrator, EventT extends AbstractLogEvent, VisitorT> +extends BaseLogAnalyzer> { + + private static final Logger logger = Logger.getLogger(BoatDeregistrator.class.getName()); + protected final Iterable boatsToDeregister; + private AbstractLogEventAuthor eventAuthor; + + public BoatDeregistrator(LogT log, Iterable boatsToDeregister, AbstractLogEventAuthor eventAuthor) { + super(log); + this.boatsToDeregister = boatsToDeregister; + this.eventAuthor = eventAuthor; + } + + @Override + protected Set performAnalysis() { + final Set result = new HashSet<>(); + final HashSet boatSet = new HashSet(); + Util.addAll(boatsToDeregister, boatSet); + for (EventT event : log.getUnrevokedEventsDescending()) { + if (event instanceof RegisterBoatEvent) { + RegisterBoatEvent registerEvent = (RegisterBoatEvent) event; + if (boatSet.contains(registerEvent.getBoat())) { + result.add(event); + } + } + } + return result; + } + + public void deregister(final Set boatRegistrationEvents) { + for (final EventT event : boatRegistrationEvents) { + try { + log.revokeEvent(eventAuthor, event, + "unregistering boat because no longer selected for registration"); + } catch (NotRevokableException e) { + logger.log(Level.WARNING, "could not unregister boat by adding RevokeEvent", e); + } + } + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java new file mode 100644 index 00000000000..9e08af03170 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java @@ -0,0 +1,46 @@ +package com.sap.sailing.domain.abstractlog.shared.analyzing; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.base.Boat; + +/** + * This class searches for RegisterBoatsEvents in the given log. + * + * TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredBoatsAnalyzer} or {@link RaceLogRegisteredBoatsAnalyzer} + * + * Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered boats for the race + * corresponding to the RaceLog/the races corresponding to the RegattaLog. + * + * This is the case as by default the boats registered on the RegattaLog are used for each race of the regatta + * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the + * {@link RaceLogUseBoatsFromRaceLogEvent}. Is an event of this type present, the boats written into the + * RaceLog are used instead of the boats in the RegattaLog. + * + */ +public class BoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public BoatsInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Set performAnalysis() { + Set result = new HashSet(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegisterBoatEvent) { + result.add(((RegisterBoatEvent) event).getBoat()); + } + } + + return result; + } +} \ No newline at end of file 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 86f7f236214..f56f77e97fc 100644 --- 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 @@ -46,6 +46,7 @@ import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.SensorFix; import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; @@ -551,6 +552,32 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } + @Override + public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { + return null; + } + + @Override + public Iterable getBoatsRegisteredInRegattaLog() { + return null; + } + + @Override + public void registerBoat(Boat boat) { + } + + @Override + public void registerBoats(Iterable boat) { + } + + @Override + public void deregisterBoat(Boat boat) { + } + + @Override + public void deregisterBoats(Iterable boat) { + } + @Override public boolean isControlTrackingFromStartAndFinishTimes() { return false; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java index ff3d2e86e7c..22a916927da 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java @@ -25,9 +25,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -130,6 +132,11 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali notifyOnAdd(event); } + @Override + public void visit(RaceLogRegisterBoatEvent event) { + notifyOnAdd(event); + } + @Override public void visit(RaceLogRegisterCompetitorEvent event) { notifyOnAdd(event); @@ -174,4 +181,9 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { notifyOnAdd(event); } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + notifyOnAdd(event); + } } 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 e031bca128c..f13c76ae151 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 @@ -25,7 +25,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; +import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; @@ -51,6 +54,7 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.AbstractLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -155,6 +159,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene private boolean useStartTimeInference; private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; + private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; private AbstractLogEventAuthor regattaLogEventAuthorForRegatta = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -419,7 +424,15 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } return competitorsProvider; } - + + @Override + public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { + if (boatsProvider == null) { + boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); + } + return boatsProvider; + } + @Override public Iterable getAllCompetitors() { Set result = new HashSet(); @@ -879,4 +892,42 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene CompetitorDeregistrator deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForRegatta); deregisterer.deregister(deregisterer.analyze()); } + + // boat functions + @Override + public Iterable getBoatsRegisteredInRegattaLog() { + RegattaLog regattaLog = getRegattaLog(); + BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + regattaLog); + return analyzer.analyze(); + } + + @Override + public void registerBoat(Boat boat) { + registerBoats(Collections.singleton(boat)); + } + + @Override + public void registerBoats(Iterable boats) { + RegattaLog regattaLog = getRegattaLike().getRegattaLog(); + TimePoint now = MillisecondsTimePoint.now(); + + for (Boat boat : boats) { + regattaLog.add(new RegattaLogRegisterBoatEventImpl(now, now, regattaLogEventAuthorForRegatta, + UUID.randomUUID(), boat)); + } + } + + @Override + public void deregisterBoat(Boat boat) { + deregisterBoats(Collections.singleton(boat)); + } + + @Override + public void deregisterBoats(Iterable boats) { + RegattaLog regattaLog = getRegattaLike().getRegattaLog(); + BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForRegatta); + deregisterer.deregister(deregisterer.analyze()); + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java index 0316ccf8a66..f67e9ae5fc4 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.leaderboard; +import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.regattalike.HasRegattaLike; @@ -7,4 +8,5 @@ public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceCol CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider(); + BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 48a20dd1505..3be2500817a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -13,7 +13,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; +import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; @@ -50,6 +53,12 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI */ private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; + /** + * Cache for the combined boats of this leaderboard; taken from the {@link TrackedRace#getRace() races of the + * tracked races} associated with this leaderboard. Updated when the set of tracked races changes. + */ + private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; + private final AbstractLogEventAuthor regattaLogEventAuthorForAbstractLeaderboard = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -117,6 +126,14 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return competitorsProvider; } + @Override + public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { + if (boatsProvider == null) { + boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); + } + return boatsProvider; + } + @Override public Competitor getCompetitorByIdAsString(String idAsString) { for (Competitor competitor : getAllCompetitors()) { @@ -236,4 +253,51 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI CompetitorDeregistrator deregisterer = new CompetitorDeregistrator<>(regattaLog, competitors, regattaLogEventAuthorForAbstractLeaderboard); deregisterer.deregister(deregisterer.analyze()); } + + // boat functions + /** + * This default implementation collects all boats by visiting all {@link TrackedRace}s associated with this + * leaderboard's columns (see {@link #getTrackedRaces()}). + */ + @Override + public Iterable getAllBoats() { + return getOrCreateBoatsProvider().getAllBoats(); + } + + + @Override + public Iterable getBoatsRegisteredInRegattaLog() { + RegattaLog regattaLog = getRegattaLike().getRegattaLog(); + BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + regattaLog); + return analyzer.analyze(); + } + + @Override + public void registerBoat(Boat boat) { + registerBoats(Collections.singleton(boat)); + } + + @Override + public void registerBoats(Iterable boats) { + RegattaLog regattaLog = getRegattaLike().getRegattaLog(); + TimePoint now = MillisecondsTimePoint.now(); + + for (Boat boat : boats) { + regattaLog.add(new RegattaLogRegisterBoatEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, + UUID.randomUUID(), boat)); + } + } + + @Override + public void deregisterBoat(Boat boat) { + deregisterBoats(Collections.singleton(boat)); + } + + @Override + public void deregisterBoats(Iterable boats) { + RegattaLog regattaLog = getRegattaLike().getRegattaLog(); + BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); + deregisterer.deregister(deregisterer.analyze()); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java new file mode 100644 index 00000000000..2e2a64996f3 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java @@ -0,0 +1,234 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +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.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction; +import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; + +/** + * A caching provider of a boat set, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of + * a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been + * provided, it is cached. The cache is invalidated when one of the following events occurs: + *

        + *
      • a boat is registered with or unregistered from a race log of any of the race columns or the regatta log
      • + *
      • a race column is added or removed
      • + *
      • a tracked race is linked to or unlinked from any of the race columns
      • + *
      • the racelog is marked as providing it's own boats via the {@link RaceLogUseBoatsFromRaceLogEvent}
      • + *
      • the racelog is marked as no longer providing it's own boats by revoking an event of type {@link RaceLogUseBoatsFromRaceLogEvent}
      • + *
      + * + * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient + * fields if they want to be serializable themselves. + * + * @author Frank Mittag + * + */ +public class BoatProviderFromRaceColumnsAndRegattaLike { + private static final Logger logger = Logger.getLogger(BoatProviderFromRaceColumnsAndRegattaLike.class + .getName()); + + private final HasRaceColumnsAndRegattaLike provider; + + private final RegattaLogEventVisitor regattaLogBoatsCacheInvalidationListener; + + private final RaceLogEventVisitor raceLogBoatsCacheInvalidationListener; + + private final RaceColumnListener raceColumnListener; + + private Iterable allBoatsCache; + + private final ConcurrentMap, Iterable> allBoatsCacheByRace; + + public BoatProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) { + super(); + this.provider = provider; + this.allBoatsCacheByRace = new ConcurrentHashMap<>(); + // A note regarding listener serializability: RaceLogListener and RegattaLogListener objects + // don't need to be serializable as the log listeners are a transient structure. The race column + // listeners, however, need to explicitly declare that they are transient. + // This enclosing object is intended not to be serialized and shall be re-constructed by + // its users after de-serialization. Therefore, the transient-ness of the log listeners works + // as intended, and the race column listener explicitly returns true from its isTransient() + // method. + regattaLogBoatsCacheInvalidationListener = new BaseRegattaLogEventVisitor() { + @Override + public void visit(RegattaLogRegisterBoatEvent event) { + invalidateAllBoatsCaches(); + } + + @Override + public void visit(RegattaLogRevokeEvent event) { + try { + if (RegattaLogRegisterBoatEvent.class.isAssignableFrom(Class.forName(event + .getRevokedEventType()))) { + invalidateAllBoatsCaches(); + } + } catch (ClassNotFoundException e) { + logger.log(Level.WARNING, + "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); + } + } + }; + raceLogBoatsCacheInvalidationListener = new BaseRaceLogEventVisitor() { + @Override + public void visit(RaceLogRegisterBoatEvent event) { + invalidateAllBoatsCaches(); + } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + invalidateAllBoatsCaches(); + } + + @Override + public void visit(RaceLogRevokeEvent event) { + try { + final Class revokedEventClass = Class.forName(event.getRevokedEventType()); + // + if (RaceLogRegisterBoatEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogUseBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { + invalidateAllBoatsCaches(); + } + } catch (ClassNotFoundException e) { + logger.log(Level.WARNING, + "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); + } + } + }; + raceColumnListener = new RaceColumnListenerWithDefaultAction() { + private static final long serialVersionUID = -8678230058730043052L; + + @Override + public void defaultAction() { + } + + /** + * As the entire provider object is considered transient, its listeners are so, too. + */ + @Override + public boolean isTransient() { + return true; + } + + @Override + public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + invalidateAllBoatsCaches(); + } + + @Override + public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { + invalidateAllBoatsCaches(); + } + + @Override + public void raceColumnAddedToContainer(RaceColumn raceColumn) { + invalidateAllBoatsCaches(); + } + + @Override + public void raceColumnRemovedFromContainer(RaceColumn raceColumn) { + invalidateAllBoatsCaches(); + } + }; + } + + public Iterable getAllBoats() { + if (allBoatsCache == null) { + final Set result = new HashSet<>(); + boolean hasRaceColumns = false; + for (RaceColumn rc : provider.getRaceColumns()) { + hasRaceColumns = true; + Util.addAll(rc.getAllCompetitorsAndTheirBoats().values(), result); + for (final Fleet fleet : rc.getFleets()) { + rc.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); + } + } + final RegattaLog regattaLog = provider.getRegattaLike().getRegattaLog(); + if (!hasRaceColumns) { + // If no race exists, the regatta log-provided boat registrations will not have + // been considered yet; add them: + final Set regattaLogProvidedBoats = new BoatsInLogAnalyzer<>(regattaLog).analyze(); + result.addAll(regattaLogProvidedBoats); + } + // else, don't add regatta log boats because they have been added in each column already. + // The boats are collected from the races. Those, however, will be the regatta log + // boats if the race does not define its own. + // Note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's + // listeners set + provider.addRaceColumnListener(raceColumnListener); + // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there + regattaLog.addListener(regattaLogBoatsCacheInvalidationListener); + allBoatsCache = result; + } + return allBoatsCache; + } + + /** + * Obtains boats from the regatta log and adds those from the tracked race for the raceColumn/fleet + * combination or the race log, if no tracked race is attached for this combination. + */ + public Iterable getAllBoats(final RaceColumn raceColumn, final Fleet fleet) { + Pair key = new Pair<>(raceColumn, fleet); + Iterable result = allBoatsCacheByRace.get(key); + if (result == null) { + final Set resultSet = new HashSet<>(); + // raceColumn already considers trackedRace, RaceLog and RegattaLog + Util.addAll(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values(), resultSet); + // note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's + // listeners set + raceColumn.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); + provider.addRaceColumnListener(raceColumnListener); + // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there + provider.getRegattaLike().getRegattaLog().addListener(regattaLogBoatsCacheInvalidationListener); + result = resultSet; + allBoatsCacheByRace.put(key, result); + } + return result; + } + + private void invalidateAllBoatsCaches() { + allBoatsCache = null; + // note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's + // listeners set + provider.getRegattaLike().getRegattaLog().removeListener(regattaLogBoatsCacheInvalidationListener); + for (final RaceColumn rc : provider.getRaceColumns()) { + for (final Fleet fleet : rc.getFleets()) { + // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race + // log's listeners set + rc.getRaceLog(fleet).removeListener(raceLogBoatsCacheInvalidationListener); + } + } + // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column + // listeners set + provider.removeRaceColumnListener(raceColumnListener); + allBoatsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it + // should be good enough. + // The change frequency of boats lists on individual races is much lower than the access frequency to this + // structure. + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java index b08c6291896..d55d72bd7e0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java @@ -185,6 +185,10 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr return getFullLeaderboard().getOrCreateCompetitorsProvider(); } + public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { + return getFullLeaderboard().getOrCreateBoatsProvider(); + } + public Regatta getRegatta() { return getFullLeaderboard().getRegatta(); } @@ -216,7 +220,7 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr public void deregisterCompetitors(Iterable competitor) { getFullLeaderboard().deregisterCompetitors(competitor); } - + public Iterable getAllCompetitors() { return getFullLeaderboard().getAllCompetitors(); } @@ -460,4 +464,34 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr getFullLeaderboard(); oos.defaultWriteObject(); } + + @Override + public Iterable getBoatsRegisteredInRegattaLog() { + return getFullLeaderboard().getBoatsRegisteredInRegattaLog(); + } + + @Override + public Iterable getAllBoats() { + return getFullLeaderboard().getAllBoats(); + } + + @Override + public void registerBoat(Boat boat) { + getFullLeaderboard().registerBoat(boat); + } + + @Override + public void registerBoats(Iterable boats) { + getFullLeaderboard().registerBoats(boats); + } + + @Override + public void deregisterBoat(Boat boat) { + getFullLeaderboard().deregisterBoat(boat); + } + + @Override + public void deregisterBoats(Iterable boats) { + getFullLeaderboard().deregisterBoats(boats); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/HasRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/HasRegattaLike.java index 9a73f72b3d6..b5b4f1f93c3 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/HasRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/HasRegattaLike.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.regattalike; import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; @@ -40,4 +41,28 @@ public interface HasRegattaLike { void deregisterCompetitor(Competitor competitor); void deregisterCompetitors(Iterable competitor); + + /** + * Determines the boats registered in the regatta log. Note that this is not necessarily the complete set of + * boats participating in this "regatta." For that, use {@link #getAllBoats()}. + */ + Iterable getBoatsRegisteredInRegattaLog(); + + /** + * Determines the combined set of all boats from all race columns that this object's {@link IsRegattaLike} + * has, as well as those coming from registrations on the {@link #getRegattaLike()}'s + * {@link IsRegattaLike#getRegattaLog() regatta log}. + * + * @see #getRegattaLike() + * @see IsRegattaLike#getRaceColumnByName(String) + * @see RaceColumn#getAllBoats() + */ + Iterable getAllBoats(); + + void registerBoat(Boat boat); + void registerBoats(Iterable boat); + + void deregisterBoat(Boat boat); + void deregisterBoats(Iterable boat); + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index 109eb683d9a..704e2f3e1a2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -41,7 +41,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); result.add(new ImageSpec(ACTION_SHOW_RACELOG, stringMessages.raceLog(), makeImagePrototype(resources.flagIcon()))); - result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon()))); + result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java index 5e54ee20605..a39f820a385 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java @@ -23,7 +23,7 @@ public class RaceLogTrackingEventManagementRaceImagesBarCell extends ImagesBarCe public final static String ACTION_SET_TRACKING_TIMES = "ACTION_SET_TRACKING_TIMES"; public final static String ACTION_STOP_TRACKING = "ACTION_STOP_TRACKING"; public final static String ACTION_START_TRACKING = "ACTION_START_TRACKING"; - + public final static String ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS = "ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS"; private final StringMessages stringMessages; private SmartphoneTrackingEventManagementPanel smartphoneTrackingEventManagementPanel; @@ -61,6 +61,7 @@ public class RaceLogTrackingEventManagementRaceImagesBarCell extends ImagesBarCe result.add(new ImageSpec(ACTION_STOP_TRACKING, stringMessages.stopTracking(), makeImagePrototype(resources.stopRaceLogTracking()))); } } + result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java index ad701c892df..1a5453ceb22 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java @@ -33,6 +33,7 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaIdentifier; @@ -388,7 +389,9 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC startTracking(Collections.singleton(raceColumnDTOAndFleetDTO), trackWind.getValue(), correctWindDirectionForDeclination.getValue()); } else if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_STOP_TRACKING.equals(value)) { stopTracking(Collections.singleton(raceColumnDTOAndFleetDTO)); - } + } else if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS.equals(value)) { + editCompetitorToBoatMappings(raceColumnDTOAndFleetDTO.getA(), raceColumnDTOAndFleetDTO.getB()); + } } }); @@ -788,6 +791,25 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC }).show(); } + private void editCompetitorToBoatMappings(final RaceColumnDTO raceColumnDTO, final FleetDTO fleetDTO) { + final String selectedLeaderboardName = getSelectedLeaderboardName(); + final String raceColumnName = raceColumnDTO.getName(); + final String fleetName = fleetDTO.getName(); + final String raceName = LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName) ? raceColumnName : raceColumnName + ", " + fleetName; + EditCompetitorToBoatMappingsDialog dialog = new EditCompetitorToBoatMappingsDialog(sailingService, + selectedLeaderboardName, raceColumnName, fleetName, raceName, stringMessages, + errorReporter, new DialogCallback>() { + @Override + public void cancel() { + } + + @Override + public void ok(final List result) { + } + }); + dialog.show(); + } + private String getLocaleInfo() { return LocaleInfo.getCurrentLocale().getLocaleName(); } 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 496b7a2a303..92cdb9e694d 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 @@ -215,6 +215,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String actionEdit(); String actionEditScores(); String actionEditCompetitors(); + String actionEditCompetitorToBoatAssignments(); String actionEditCompetitorToBoatAssignmentsForRace(String raceName); String actionOpenBrowser(); String actionRemove(); 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 0af5641b6d7..92f6e59f450 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 @@ -216,6 +216,7 @@ filterMediaByName=Filter media by name trackSettings=Track settings actionEdit=Edit actionEditCompetitors=Edit competitors +actionEditCompetitorToBoatAssignments=Edit used boats for competitors actionEditCompetitorToBoatAssignmentsForRace=Edit used boats for competitors of race {0} actionEditScores=Edit scores actionOpenBrowser=Open in Browser 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 65fa5c062de..eda3183c94f 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 @@ -218,6 +218,7 @@ filterByRegatta=nach Regatta filterMediaByName=Medien nach Name filtern actionEdit=Ändern actionEditCompetitors=Teilnehmer ändern +actionEditCompetitorToBoatAssignments=Ändere die Boote für die Teilnehmer actionEditCompetitorToBoatAssignmentsForRace=Ändere die Boote für die Teilnehmer im Rennen {0} actionEditScores=Punkte ändern actionOpenBrowser=Im Browser öffnen 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 be50d4d5da2..4e34b0f294a 100644 --- 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 @@ -56,7 +56,6 @@ import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.competitorimport.CompetitorProvider; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java index 8201335ef90..6e7eeed396b 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java @@ -14,6 +14,7 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.CourseBase import com.sap.sailing.server.gateway.deserialization.coursedata.impl.GateDeserializer; import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer; import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceIdentifierJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; @@ -80,12 +81,15 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogDenoteForTrackingEventDeserializer(competitorDeserializer, domainFactory), new RaceLogStartTrackingEventDeserializer(competitorDeserializer), new RaceLogRevokeEventDeserializer(competitorDeserializer), + new RaceLogRegisterBoatEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer), + new RaceLogRegisterCompetitorAndBoatEventDeserializer(competitorDeserializer), new RaceLogAdditionalScoringInformationEventDeserializer(competitorDeserializer), new RaceLogFixedMarkPassingEventDeserializer(competitorDeserializer), new RaceLogSuppressedMarkPassingsEventDeserializer(competitorDeserializer), new RaceLogStartOfTrackingEventDeserializer(competitorDeserializer), new RaceLogUseCompetitorsFromRaceLogEventDeserializer(competitorDeserializer), + new RaceLogUseBoatsFromRaceLogEventDeserializer(competitorDeserializer), new RaceLogEndOfTrackingEventDeserializer(competitorDeserializer)); } @@ -106,13 +110,16 @@ public class RaceLogEventDeserializer implements JsonDeserializer protected final JsonDeserializer denoteForTrackingEventDeserializer; protected final JsonDeserializer startTrackingEventDeserializer; protected final JsonDeserializer revokeEventDeserializer; + protected final JsonDeserializer registerBoatEventDeserializer; protected final JsonDeserializer registerCompetitorEventDeserializer; + protected final JsonDeserializer registerCompetitorAndBoatEventDeserializer; protected final JsonDeserializer additionalScoringInformationEventDeserializer; protected final JsonDeserializer fixedMarkPassingEventDeserializer; protected final JsonDeserializer suppressedMarkPassingsDeserializer; protected final JsonDeserializer startOfTrackingDeserializer; protected final JsonDeserializer endOfTrackingDeserializer; protected final JsonDeserializer useCompetitorsFromRaceLogDeserializer; + protected final JsonDeserializer useBoatsFromRaceLogDeserializer; public RaceLogEventDeserializer(JsonDeserializer flagEventDeserializer, JsonDeserializer startTimeEventDeserializer, @@ -131,12 +138,15 @@ public class RaceLogEventDeserializer implements JsonDeserializer JsonDeserializer denoteForTrackingEventDeserializer, JsonDeserializer startTrackingEventDeserializer, JsonDeserializer revokeEventDeserializer, + JsonDeserializer registerBoatEventDeserializer, JsonDeserializer registerCompetitorEventDeserializer, + JsonDeserializer registerCompetitorAndBoatEventDeserializer, JsonDeserializer additionalScoringInformationEventDeserializer, JsonDeserializer fixedMarkPassingEventDeserializer, JsonDeserializer suppressedMarkPassingsEventDeserializer, JsonDeserializer startOfTrackingEventDeserializer, JsonDeserializer useCompetitorsFromRaceLogDeserializer, + JsonDeserializer useBoatsFromRaceLogDeserializer, JsonDeserializer endOfTrackingEventDeserializer) { this.flagEventDeserializer = flagEventDeserializer; this.startTimeEventDeserializer = startTimeEventDeserializer; @@ -155,13 +165,16 @@ public class RaceLogEventDeserializer implements JsonDeserializer this.denoteForTrackingEventDeserializer = denoteForTrackingEventDeserializer; this.startTrackingEventDeserializer = startTrackingEventDeserializer; this.revokeEventDeserializer = revokeEventDeserializer; + this.registerBoatEventDeserializer = registerCompetitorEventDeserializer; this.registerCompetitorEventDeserializer = registerCompetitorEventDeserializer; + this.registerCompetitorAndBoatEventDeserializer = registerCompetitorAndBoatEventDeserializer; this.additionalScoringInformationEventDeserializer = additionalScoringInformationEventDeserializer; this.fixedMarkPassingEventDeserializer = fixedMarkPassingEventDeserializer; this.suppressedMarkPassingsDeserializer = suppressedMarkPassingsEventDeserializer; this.startOfTrackingDeserializer = startOfTrackingEventDeserializer; this.endOfTrackingDeserializer = endOfTrackingEventDeserializer; this.useCompetitorsFromRaceLogDeserializer = useCompetitorsFromRaceLogDeserializer; + this.useBoatsFromRaceLogDeserializer = useBoatsFromRaceLogDeserializer; } protected JsonDeserializer getDeserializer(JSONObject object) throws JsonDeserializationException { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java new file mode 100644 index 00000000000..d34f1b723af --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java @@ -0,0 +1,32 @@ +package com.sap.sailing.server.gateway.deserialization.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; +import com.sap.sse.common.TimePoint; + +public class RaceLogRegisterBoatEventDeserializer extends BaseRaceLogEventDeserializer { + private BoatJsonDeserializer boatDeserializer; + + public RaceLogRegisterBoatEventDeserializer(JsonDeserializer competitorDeserializer, BoatJsonDeserializer boatDeserializer) { + super(competitorDeserializer); + this.boatDeserializer = boatDeserializer; + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { + Boat boat = boatDeserializer.deserialize(object); + return new RaceLogRegisterBoatEventImpl(createdAt, timePoint, author, id, passId, boat); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java new file mode 100644 index 00000000000..7192c557549 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java @@ -0,0 +1,27 @@ +package com.sap.sailing.server.gateway.deserialization.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sse.common.TimePoint; + +public class RaceLogRegisterCompetitorAndBoatEventDeserializer extends BaseRaceLogEventDeserializer { + + public RaceLogRegisterCompetitorAndBoatEventDeserializer(JsonDeserializer competitorDeserializer) { + super(competitorDeserializer); + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { + assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; + return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0)); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java new file mode 100644 index 00000000000..ace23aa456c --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java @@ -0,0 +1,30 @@ +package com.sap.sailing.server.gateway.deserialization.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseBoatsFromRaceLogEventImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sse.common.TimePoint; + +public class RaceLogUseBoatsFromRaceLogEventDeserializer extends BaseRaceLogEventDeserializer implements + JsonDeserializer { + + public RaceLogUseBoatsFromRaceLogEventDeserializer(JsonDeserializer competitorDeserializer) { + super(competitorDeserializer); + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) + throws JsonDeserializationException { + return new RaceLogUseBoatsFromRaceLogEventImpl(createdAt, author, timePoint, id, passId); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index c543199f77f..1886dc1410d 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -25,9 +25,11 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; @@ -75,13 +77,16 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), new RaceLogStartTrackingEventSerializer(competitorSerializer), new RaceLogRevokeEventSerializer(competitorSerializer), + new RaceLogRegisterBoatEventSerializer(competitorSerializer), new RaceLogRegisterCompetitorEventSerializer(competitorSerializer), + new RaceLogRegisterCompetitorAndBoatEventSerializer(competitorSerializer), new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), new RaceLogFixedMarkPassingEventSerializer(competitorSerializer), new RaceLogSuppressedMarkPassingsEventSerializer(competitorSerializer), new RaceLogDependentStartTimeEventSerializer(competitorSerializer), new RaceLogStartOfTrackingEventSerializer(competitorSerializer), new RaceLogUseCompetitorsFromRaceLogEventSerializer(competitorSerializer), + new RaceLogUseBoatsFromRaceLogEventSerializer(competitorSerializer), new RaceLogEndOfTrackingEventSerializer(competitorSerializer)); } @@ -101,7 +106,9 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac private final JsonSerializer denoteForTrackingSerializer; private final JsonSerializer startTrackingSerializer; private final JsonSerializer revokeSerializer; + private final JsonSerializer registerBoatSerializer; private final JsonSerializer registerCompetitorSerializer; + private final JsonSerializer registerCompetitorAndBoatSerializer; private final JsonSerializer additionalScoringInformationSerializer; private final JsonSerializer fixedMarkPassingEventSerializer; private final JsonSerializer suppressedMarkPassingsEventSerializer; @@ -109,6 +116,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac private final JsonSerializer startOfTrackingEventSerializer; private final JsonSerializer endOfTrackingEventSerializer; private final JsonSerializer useCompetitorsFromRaceLogEventSerializer; + private final JsonSerializer useBoatsFromRaceLogEventSerializer; private JsonSerializer chosenSerializer; @@ -130,14 +138,17 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac JsonSerializer denoteForTrackingSerializer, JsonSerializer createRaceSerializer, JsonSerializer revokeSerializer, + JsonSerializer registerBoatSerializer, JsonSerializer registerCompetitorSerializer, + JsonSerializer registerCompetitorAndBoatSerializer, JsonSerializer additionalScoringInformationSerializer, JsonSerializer fixedMarkPassingEventSerializer, JsonSerializer suppressedMarkPassingsSerializer, JsonSerializer dependentStartTimeEventSerializer, JsonSerializer startOfTrackingEventSerializer, JsonSerializer endOfTrackingEventSerializer, - JsonSerializer useCompetitorsFromRaceLogEventSerializer) { + JsonSerializer useCompetitorsFromRaceLogEventSerializer, + JsonSerializer useBoatsFromRaceLogEventSerializer) { this.flagEventSerializer = flagEventSerializer; this.startTimeSerializer = startTimeSerializer; this.raceStatusSerializer = raceStatusSerializer; @@ -154,7 +165,9 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac this.denoteForTrackingSerializer = denoteForTrackingSerializer; this.startTrackingSerializer = createRaceSerializer; this.revokeSerializer = revokeSerializer; + this.registerBoatSerializer = registerBoatSerializer; this.registerCompetitorSerializer = registerCompetitorSerializer; + this.registerCompetitorAndBoatSerializer = registerCompetitorAndBoatSerializer; this.additionalScoringInformationSerializer = additionalScoringInformationSerializer; this.fixedMarkPassingEventSerializer = fixedMarkPassingEventSerializer; this.suppressedMarkPassingsEventSerializer = suppressedMarkPassingsSerializer; @@ -162,6 +175,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac this.startOfTrackingEventSerializer = startOfTrackingEventSerializer; this.endOfTrackingEventSerializer = endOfTrackingEventSerializer; this.useCompetitorsFromRaceLogEventSerializer = useCompetitorsFromRaceLogEventSerializer; + this.useBoatsFromRaceLogEventSerializer = useBoatsFromRaceLogEventSerializer; this.chosenSerializer = null; } @@ -260,6 +274,11 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac chosenSerializer = revokeSerializer; } + @Override + public void visit(RaceLogRegisterBoatEvent event) { + chosenSerializer = registerBoatSerializer; + } + @Override public void visit(RaceLogRegisterCompetitorEvent event) { chosenSerializer = registerCompetitorSerializer; @@ -267,7 +286,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac @Override public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { - chosenSerializer = registerCompetitorSerializer; + chosenSerializer = registerCompetitorAndBoatSerializer; } @Override @@ -304,4 +323,9 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { chosenSerializer = useCompetitorsFromRaceLogEventSerializer; } + + @Override + public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + chosenSerializer = useBoatsFromRaceLogEventSerializer; + } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java new file mode 100644 index 00000000000..7729f67d5ee --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java @@ -0,0 +1,20 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogRegisterBoatEventSerializer extends BaseRaceLogEventSerializer { + + public static final String VALUE_CLASS = RegisterBoatEvent.class.getSimpleName(); + + public RaceLogRegisterBoatEventSerializer( + JsonSerializer competitorSerializer) { + super(competitorSerializer); + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventSerializer.java new file mode 100644 index 00000000000..4d3e3f35413 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventSerializer.java @@ -0,0 +1,20 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogRegisterCompetitorAndBoatEventSerializer extends BaseRaceLogEventSerializer { + + public static final String VALUE_CLASS = RegisterCompetitorAndBoatEvent.class.getSimpleName(); + + public RaceLogRegisterCompetitorAndBoatEventSerializer( + JsonSerializer competitorSerializer) { + super(competitorSerializer); + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java new file mode 100644 index 00000000000..7f66e7b5abf --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java @@ -0,0 +1,21 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogUseBoatsFromRaceLogEventSerializer extends BaseRaceLogEventSerializer implements + JsonSerializer { + public static final String VALUE_CLASS = RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName(); + + public RaceLogUseBoatsFromRaceLogEventSerializer(JsonSerializer competitorSerializer) { + super(competitorSerializer); + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 6dc673f0670..007975c5c36 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -57,13 +57,16 @@ public class RaceLogEventSerializerTest { private JsonSerializer denoteForTrackingEventSerializer; private JsonSerializer startTrackingEventSerializer; private JsonSerializer revokeEventSerializer; + private JsonSerializer registerBoatEventSerializer; private JsonSerializer registerCompetitorEventSerializer; + private JsonSerializer registerCompetitorAndBoatEventSerializer; private JsonSerializer additionalScoringInformationSerializer; private JsonSerializer fixedMarkPassingEventSerializer; private JsonSerializer suppressedMarkPassingsSerializer; private JsonSerializer dependentStartTimeEventSerializer; private JsonSerializer startOfTrackingEventSerializer; private JsonSerializer useCompetitorsFromRaceLogEventSerializer; + private JsonSerializer useBoatsFromRaceLogEventSerializer; private JsonSerializer endOfTrackingEventSerializer; private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); @@ -87,13 +90,16 @@ public class RaceLogEventSerializerTest { denoteForTrackingEventSerializer = mock(JsonSerializer.class); startTrackingEventSerializer = mock(JsonSerializer.class); revokeEventSerializer = mock(JsonSerializer.class); + registerBoatEventSerializer = mock(JsonSerializer.class); registerCompetitorEventSerializer = mock(JsonSerializer.class); + registerCompetitorAndBoatEventSerializer = mock(JsonSerializer.class); additionalScoringInformationSerializer = mock(JsonSerializer.class); fixedMarkPassingEventSerializer = mock(JsonSerializer.class); suppressedMarkPassingsSerializer = mock(JsonSerializer.class); dependentStartTimeEventSerializer = mock(JsonSerializer.class); startOfTrackingEventSerializer = mock(JsonSerializer.class); useCompetitorsFromRaceLogEventSerializer = mock(JsonSerializer.class); + useBoatsFromRaceLogEventSerializer = mock(JsonSerializer.class); endOfTrackingEventSerializer = mock(JsonSerializer.class); serializer = new RaceLogEventSerializer(flagEventSerializer, startTimeSerializer, raceStatusSerializer, @@ -102,9 +108,10 @@ public class RaceLogEventSerializerTest { pathfinderEventSerializer, gateLineOpeningTimeEventSerializer, startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer, denoteForTrackingEventSerializer, startTrackingEventSerializer, revokeEventSerializer, - registerCompetitorEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, + registerBoatEventSerializer, registerCompetitorEventSerializer, registerCompetitorAndBoatEventSerializer, + fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, additionalScoringInformationSerializer, dependentStartTimeEventSerializer, - startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer, + startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer, useBoatsFromRaceLogEventSerializer, endOfTrackingEventSerializer); } From a95b217381683ae021d1bd19318a62d19628bb7a Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 12 Jul 2017 17:24:02 +0200 Subject: [PATCH 046/271] removed warnings --- .../server/test/MasterDataImportTest.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 355d2c4c00f..70bbfd900bc 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -258,7 +258,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -269,7 +268,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -583,7 +581,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -592,7 +589,6 @@ public class MasterDataImportTest { sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor2); @@ -907,7 +903,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); @@ -917,7 +912,6 @@ public class MasterDataImportTest { sailors2.add(new PersonImpl("Test Mustermann", new NationalityImpl("GER"), new Date(645487200000L), "desc")); DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, "Froderik", "F", Color.RED, "noone@nowhere.de", null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); @@ -1068,7 +1062,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1079,7 +1072,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1272,7 +1264,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1283,7 +1274,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1374,7 +1364,6 @@ public class MasterDataImportTest { 645487200000L), "Der Lennart halt"); DynamicTeam teamToOverride = new TeamImpl("Pros", sailorsToOverride, coachToOverride); BoatClass boatClassToOverride = new BoatClassImpl("H16", true); - DynamicBoat boatToOverride = new BoatImpl("123", "Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, "c", Color.BLUE, "noone@nowhere.de", null, teamToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ @@ -1383,7 +1372,7 @@ public class MasterDataImportTest { Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( regattaToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); - TrackedRace trackedRace2 = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClass, competitorsToOverride), + TrackedRace trackedRace2 = new DummyTrackedRace(raceId, createCompetitorsAndBoatsMap(boatClassToOverride, competitorsToOverride), regattaToOverride, null, sourceService.getWindStore()); RaceColumn columnToOverride = leaderboardToOverride.getRaceColumns().iterator().next(); columnToOverride.setTrackedRace(testFleet1ToOverride, trackedRace2); @@ -1576,7 +1565,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1587,7 +1575,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1713,7 +1700,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1724,7 +1710,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -1961,7 +1946,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -1972,7 +1956,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); @@ -2192,7 +2175,6 @@ public class MasterDataImportTest { "Der Lennart halt"); DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); - DynamicBoat boat = new BoatImpl("123", "Wingy", boatClass, "GER70133"); CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", "KYC", Color.RED, null, null, team, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitor); @@ -2203,7 +2185,6 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Peer Steinbrueck", new NationalityImpl("GER"), new Date(645487200000L), "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); - DynamicBoat boat2 = new BoatImpl("456", "LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", "KYC", Color.RED, null, null, team2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null); competitors.add(competitorToSuppress); From 4965ebcaff94598fa9d41dc2a30ac3e16ad56dc1 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 12 Jul 2017 17:46:46 +0200 Subject: [PATCH 047/271] added canBoatsOfCompetitorsChangePerRace to AbtractLeaderboardDTO which can only be true for RegattaLeaderboards --- .../sailing/domain/common/dto/AbstractLeaderboardDTO.java | 1 + .../regatta/events/impl/RegattaLogRegisterBoatEventImpl.java | 1 - .../gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java | 2 -- .../ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java | 5 ++++- .../RaceLogTrackingEventManagementRaceImagesBarCell.java | 5 ++++- .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 ++ 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java index fa05c11bcf3..98597594b33 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java @@ -36,6 +36,7 @@ public abstract class AbstractLeaderboardDTO implements Serializable { public String defaultCourseAreaName; public ScoringSchemeType scoringScheme; public LeaderboardType type; + public boolean canBoatsOfCompetitorsChangePerRace; private Long delayToLiveInMillisForLatestRace; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java index 3a4c4f0269f..69e959e8b19 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java @@ -7,7 +7,6 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java index 3ba3f638f47..c501aba4714 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsPanel.java @@ -45,7 +45,6 @@ public class CompetitorToBoatMappingsPanel extends SimplePanel implements BusyDi private final String fleetName; private final SailingServiceAsync sailingService; private final ErrorReporter errorReporter; - private final StringMessages stringMessages; private final RefreshableSelectionModel refreshableBoatSelectionModel; private final RefreshableSelectionModel refreshableCompetitorSelectionModel; @@ -62,7 +61,6 @@ public class CompetitorToBoatMappingsPanel extends SimplePanel implements BusyDi this.leaderboardName = leaderboardName; this.raceColumnName = raceColumnName; this.fleetName = fleetName; - this.stringMessages = stringMessages; this.errorReporter = errorReporter; this.competitorTable = new CompactCompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index 704e2f3e1a2..2e91a54b4e1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -41,7 +41,10 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); result.add(new ImageSpec(ACTION_SHOW_RACELOG, stringMessages.raceLog(), makeImagePrototype(resources.flagIcon()))); - result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); + + if (selectedLeaderboardProvider.getSelectedLeaderboard().canBoatsOfCompetitorsChangePerRace) { + result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); + } return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java index a39f820a385..055841ad50f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java @@ -61,7 +61,10 @@ public class RaceLogTrackingEventManagementRaceImagesBarCell extends ImagesBarCe result.add(new ImageSpec(ACTION_STOP_TRACKING, stringMessages.stopTracking(), makeImagePrototype(resources.stopRaceLogTracking()))); } } - result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); + + if (smartphoneTrackingEventManagementPanel.getSelectedLeaderboard().canBoatsOfCompetitorsChangePerRace) { + result.add(new ImageSpec(ACTION_EDIT_COMPETITOR_TO_BOAT_MAPPINGS, stringMessages.actionEditCompetitorToBoatAssignments(), makeImagePrototype(resources.competitorsIcon()))); + } return result; } 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 4e34b0f294a..f961f306a4c 100644 --- 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 @@ -2485,8 +2485,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Regatta regatta = regattaLeaderboard.getRegatta(); leaderboardDTO.regattaName = regatta.getName(); leaderboardDTO.scoringScheme = regatta.getScoringScheme().getType(); + leaderboardDTO.canBoatsOfCompetitorsChangePerRace = regatta.canBoatsOfCompetitorsChangePerRace(); } else { leaderboardDTO.scoringScheme = leaderboard.getScoringScheme().getType(); + leaderboardDTO.canBoatsOfCompetitorsChangePerRace = false; } if (leaderboard.getDefaultCourseArea() != null) { leaderboardDTO.defaultCourseAreaId = leaderboard.getDefaultCourseArea().getId(); From 6c1ff9066bbb8ee5a8f0aa832f7f777c251196b2 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 19 Jul 2017 17:19:08 +0200 Subject: [PATCH 048/271] Improved the scenario to create the boats/competitor mapping based on the competitor metadata from tractrac. Cleanup of some RaceLogEvent classes to prepare racelog tracking scenario --- ...egistrationOnRaceLogDisabledException.java | 15 ----- ...egistrationOnRaceLogDisabledException.java | 15 +++++ .../impl/DomainObjectFactoryImpl.java | 25 +++----- .../impl/MongoObjectFactoryImpl.java | 26 ++------ .../impl/MongoRaceLogStoreVisitor.java | 11 +--- .../abstractlog/race/RaceLogEventVisitor.java | 7 +-- .../impl/AbstractRaceLogChangedVisitor.java | 10 +-- .../race/impl/BaseRaceLogEventVisitor.java | 10 +-- .../tracking/RaceLogRegisterBoatEvent.java | 10 --- ...eCompetitorsAndBoatsFromRaceLogEvent.java} | 2 +- ...LogUsesOwnCompetitorsAndBoatsAnalyzer.java | 29 +++++++++ .../impl/RaceLogRegisterBoatEventImpl.java | 62 ------------------- ...petitorsAndBoatsFromRaceLogEventImpl.java} | 10 +-- .../shared/analyzing/BoatsInLogAnalyzer.java | 4 +- .../domain/test/mock/MockedTrackedRace.java | 4 ++ .../domain/tractracadapter/DomainFactory.java | 6 +- .../impl/DomainFactoryImpl.java | 21 ++++--- .../impl/RaceCourseReceiver.java | 5 +- .../sap/sailing/domain/base/RaceColumn.java | 35 +++++++++++ .../com/sap/sailing/domain/base/Regatta.java | 6 ++ .../domain/base/impl/AbstractRaceColumn.java | 54 +++++++++++++++- .../domain/base/impl/DomainFactoryImpl.java | 2 +- .../impl/RaceColumnRaceLogReplicator.java | 10 +-- .../sailing/domain/base/impl/RegattaImpl.java | 7 ++- .../base/impl/SimpleAbstractRaceColumn.java | 13 ++++ ...ProviderFromRaceColumnsAndRegattaLike.java | 18 +++--- .../meta/MetaLeaderboardColumn.java | 8 +++ .../domain/regattalike/IsRegattaLike.java | 2 +- .../adminconsole/CompactBoatTableWrapper.java | 21 ++++++- .../CompetitorToBoatMappingsPanel.java | 2 - .../gwt/ui/client/StringMessages.properties | 2 +- .../ui/client/StringMessages_de.properties | 2 +- .../gwt/ui/server/SailingServiceImpl.java | 33 +++++----- .../impl/RaceLogEventDeserializer.java | 14 ++--- .../RaceLogRegisterBoatEventDeserializer.java | 32 ---------- ...terCompetitorAndBoatEventDeserializer.java | 15 +++-- ...AndBoatsFromRaceLogEventDeserializer.java} | 8 +-- .../racelog/impl/RaceLogEventSerializer.java | 22 +++---- ...rsAndBoatsFromRaceLogEventSerializer.java} | 8 +-- .../sailing/server/RacingEventService.java | 3 + .../server/impl/RacingEventServiceImpl.java | 36 ++++++++++- 41 files changed, 332 insertions(+), 293 deletions(-) delete mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java create mode 100644 java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/CompetitorAndBoatRegistrationOnRaceLogDisabledException.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java rename java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/{RaceLogUseBoatsFromRaceLogEvent.java => RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java} (84%) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogUsesOwnCompetitorsAndBoatsAnalyzer.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java rename java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/{RaceLogUseBoatsFromRaceLogEventImpl.java => RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl.java} (65%) delete mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java rename java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/{RaceLogUseBoatsFromRaceLogEventDeserializer.java => RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer.java} (70%) rename java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/{RaceLogUseBoatsFromRaceLogEventSerializer.java => RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer.java} (55%) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java deleted file mode 100644 index a6542af3b30..00000000000 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/BoatRegistrationOnRaceLogDisabledException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sap.sailing.domain.common.racelog.tracking; - -import java.io.Serializable; - -public class BoatRegistrationOnRaceLogDisabledException extends Exception implements Serializable { - private static final long serialVersionUID = -6656554635954928251L; - - public BoatRegistrationOnRaceLogDisabledException() { - super("Boat registration not allowed on race"); - } - - public BoatRegistrationOnRaceLogDisabledException(String message) { - super(message); - } -} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/CompetitorAndBoatRegistrationOnRaceLogDisabledException.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/CompetitorAndBoatRegistrationOnRaceLogDisabledException.java new file mode 100644 index 00000000000..cf9a7e93eb4 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/tracking/CompetitorAndBoatRegistrationOnRaceLogDisabledException.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.common.racelog.tracking; + +import java.io.Serializable; + +public class CompetitorAndBoatRegistrationOnRaceLogDisabledException extends Exception implements Serializable { + private static final long serialVersionUID = -6656554635954928251L; + + public CompetitorAndBoatRegistrationOnRaceLogDisabledException() { + super("Competitor AND Boat registration not allowed on race"); + } + + public CompetitorAndBoatRegistrationOnRaceLogDisabledException(String message) { + super(message); + } +} diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index c69b30f9052..77ee5663531 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -89,18 +89,16 @@ import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformat import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseBoatsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; @@ -1189,7 +1187,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); // for backward compatibility if(canBoatsOfCompetitorsChangePerRace == null) { - canBoatsOfCompetitorsChangePerRace = true; + canBoatsOfCompetitorsChangePerRace = false; } final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta); result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true, @@ -1435,8 +1433,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRevokeEvent.class.getSimpleName())) { return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogRegisterBoatEvent.class.getSimpleName())) { - return loadRaceLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { @@ -1449,8 +1445,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())){ return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName())){ - return loadRaceLogUseBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName())){ + return loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); @@ -1461,9 +1457,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return new RaceLogUseCompetitorsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } - private RaceLogEvent loadRaceLogUseBoatsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, + private RaceLogEvent loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - return new RaceLogUseBoatsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); + return new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1497,13 +1493,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { revokedEventId, revokedEventType, revokedEventShortInfo, reason); } - private RaceLogEvent loadRaceLogRegisterBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Serializable boatId = (Serializable) dbObject.get(FieldNames.RACE_LOG_BOAT_ID.name()); - Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); - return new RaceLogRegisterBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, boat); - } - private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index f9ef8c2131f..10ef00bba75 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -48,11 +48,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; @@ -913,13 +912,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterBoatEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterBoatEvent(event)); - return result; - } - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); @@ -1067,14 +1059,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - private Object storeRaceLogRegisterBoatEvent(RaceLogRegisterBoatEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterBoatEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_BOAT_ID.name(), event.getBoat().getId()); - return result; - } - private Object storeRaceLogRegisterCompetitorEvent(RaceLogRegisterCompetitorEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); @@ -1099,10 +1083,10 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseBoatsFromRaceLogEvent event) { + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { BasicDBObject result = new BasicDBObject(); storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogUseBoatsFromRaceLogEvent(event)); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(event)); return result; } @@ -1113,10 +1097,10 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } - public DBObject storeRaceLogUseBoatsFromRaceLogEvent(RaceLogUseBoatsFromRaceLogEvent event) { + public DBObject storeRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName()); return result; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java index 1af71fbe8bf..e1c58bdb151 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java @@ -25,11 +25,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -143,12 +142,6 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { mongoObjectFactory.storeRaceLogEventEvent(object); } - @Override - public void visit(RaceLogRegisterBoatEvent event) { - DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); - mongoObjectFactory.storeRaceLogEventEvent(object); - } - @Override public void visit(RaceLogRegisterCompetitorEvent event) { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); @@ -204,7 +197,7 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); mongoObjectFactory.storeRaceLogEventEvent(object); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java index 185eb802d15..e9f42b315c7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventVisitor.java @@ -2,11 +2,10 @@ package com.sap.sailing.domain.abstractlog.race; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; @@ -43,8 +42,6 @@ public interface RaceLogEventVisitor { public void visit(RaceLogStartTrackingEvent event); - public void visit(RaceLogRegisterBoatEvent event); - public void visit(RaceLogRegisterCompetitorEvent event); public void visit(RaceLogRegisterCompetitorAndBoatEvent event); @@ -63,5 +60,5 @@ public interface RaceLogEventVisitor { public void visit(RaceLogUseCompetitorsFromRaceLogEvent event); - public void visit(RaceLogUseBoatsFromRaceLogEvent event); + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java index c72362098fc..2af32e3541f 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/AbstractRaceLogChangedVisitor.java @@ -23,11 +23,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisitor { @@ -107,11 +106,6 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit notifyListenerAboutEventAdded(event); } - @Override - public void visit(RaceLogRegisterBoatEvent event) { - notifyListenerAboutEventAdded(event); - } - @Override public void visit(RaceLogRegisterCompetitorEvent event) { notifyListenerAboutEventAdded(event); @@ -158,7 +152,7 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { notifyListenerAboutEventAdded(event); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java index 2376ee89d4d..7279488d400 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java @@ -22,11 +22,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; /** @@ -119,11 +118,6 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { } - @Override - public void visit(RaceLogRegisterBoatEvent event) { - - } - @Override public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { @@ -165,7 +159,7 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java deleted file mode 100644 index 41cce095b27..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterBoatEvent.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race.tracking; - -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; - -public interface RaceLogRegisterBoatEvent extends RaceLogEvent, -RegisterBoatEvent { - -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java similarity index 84% rename from java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java index b8e394b37e0..460c633d444 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseBoatsFromRaceLogEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java @@ -14,5 +14,5 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; * @author Frank Mittag * */ -public interface RaceLogUseBoatsFromRaceLogEvent extends RaceLogEvent, Revokable { +public interface RaceLogUseCompetitorsAndBoatsFromRaceLogEvent extends RaceLogEvent, Revokable { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogUsesOwnCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogUsesOwnCompetitorsAndBoatsAnalyzer.java new file mode 100644 index 00000000000..3d3fdc86a28 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogUsesOwnCompetitorsAndBoatsAnalyzer.java @@ -0,0 +1,29 @@ +package com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl; + +import java.util.List; + +import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; + +/** + * Determines whether the race log claims to authoritatively define the competitors and boats for the race to which it belongs. + * This depends on the presence of an unrevoked {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent} event in the race log. + * + * @author Jan Bross + * + */ +public class RaceLogUsesOwnCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer{ + public RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected Boolean performAnalysis() { + RaceLog raceLog = getLog(); + List event = new AllEventsOfTypeFinder<>(raceLog, /*only unrevoked*/ true, RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class).analyze(); + return event.size() >= 1; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java deleted file mode 100644 index 6d54ed0395f..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterBoatEventImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race.tracking.impl; - -import java.io.Serializable; -import java.util.Collections; -import java.util.List; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventData; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sse.common.TimePoint; - -public class RaceLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl implements - RaceLogRegisterBoatEvent { - private static final long serialVersionUID = -856679388199355195L; - private final RaceLogEventData raceLogEventData; - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public RaceLogRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, int passId, Boat boat) - throws IllegalArgumentException { - super(createdAt, logicalTimePoint, author, id, boat); - this.raceLogEventData = new RaceLogEventDataImpl(null, passId); - } - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public RaceLogRegisterBoatEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, Boat boat) - throws IllegalArgumentException { - this(now(), logicalTimePoint, author, randId(), passId, boat); - } - - @Override - public int getPassId() { - return raceLogEventData.getPassId(); - } - - @Override - public String toString() { - return raceLogEventData.toString(); - } - - @Override - public void accept(RaceLogEventVisitor visitor) { - visitor.visit(this); - } - - @Override - public List getInvolvedBoats() { - return Collections.emptyList(); - } -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl.java similarity index 65% rename from java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl.java index 4fff51b1271..3e3e93bf8b9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseBoatsFromRaceLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl.java @@ -5,14 +5,14 @@ import java.io.Serializable; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sse.common.TimePoint; -public class RaceLogUseBoatsFromRaceLogEventImpl extends RaceLogEventImpl implements - RaceLogUseBoatsFromRaceLogEvent { +public class RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl extends RaceLogEventImpl implements + RaceLogUseCompetitorsAndBoatsFromRaceLogEvent { private static final long serialVersionUID = -1859200551195623389L; - public RaceLogUseBoatsFromRaceLogEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, + public RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, int passId) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, id, null, passId); @@ -20,7 +20,7 @@ public class RaceLogUseBoatsFromRaceLogEventImpl extends RaceLogEventImpl implem @Override public String toString() { - return "This RaceLog uses the boats registered on the RaceLog instead of the boats on the RegattaLog"; + return "This RaceLog uses the competitors and boats registered on the RaceLog instead of the boats on the RegattaLog"; } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java index 9e08af03170..cc6ff4cebbf 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java @@ -6,7 +6,7 @@ import java.util.Set; import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; import com.sap.sailing.domain.base.Boat; @@ -20,7 +20,7 @@ import com.sap.sailing.domain.base.Boat; * * This is the case as by default the boats registered on the RegattaLog are used for each race of the regatta * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the - * {@link RaceLogUseBoatsFromRaceLogEvent}. Is an event of this type present, the boats written into the + * {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}. Is an event of this type present, the boats written into the * RaceLog are used instead of the boats in the RegattaLog. * */ 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 f56f77e97fc..9c5c12ebf3d 100644 --- 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 @@ -336,6 +336,10 @@ public class MockedTrackedRace implements DynamicTrackedRace { return false; } + @Override + public void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) { + } + @Override public void addRace(RaceDefinition race) { } 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 a2513cef915..bafaaae3541 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 @@ -207,8 +207,8 @@ public interface DomainFactory { * @param tractracRace TODO */ DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitorsAndBoats, BoatClass boatClass, - Map competitorBoats, Course course, Iterable sidelines, WindStore windStore, + String raceName, BoatClass boatClass, Map competitorBoats, + Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver, Consumer runBeforeExposingRace, IRace tractracRace); @@ -264,7 +264,7 @@ public interface DomainFactory { */ RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds); - Map getOrCreateCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass); + Map getOrCreateCompetitorsAndTheirBoats(DynamicTrackedRegatta trackedRegatta, IRace race, BoatClass defaultBoatClass); Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race); 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 2331b60e6d0..1ab39143036 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 @@ -385,7 +385,7 @@ public class DomainFactoryImpl implements DomainFactory { if (result == null) { result = new RegattaImpl(raceLogStore, regattaLogStore, RegattaImpl.getDefaultName( defaultRegattaNameAndBoatClass.getA(), boatClass.getName()), boatClass, - /* canBoatsOfCompetitorsChangePerRace */ true, /*startDate*/ null, /*endDate*/ null, + /* canBoatsOfCompetitorsChangePerRace */ false, /*startDate*/ null, /*endDate*/ null, trackedRegattaRegistry, // use the low-point system as the default scoring scheme getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), race.getId(), null); @@ -520,9 +520,8 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitors, BoatClass boatClass, - Map competitorsAndBoats, Course course, Iterable sidelines, WindStore windStore, + public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, + String raceName, BoatClass boatClass, Map competitorsAndBoats, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver, @@ -646,20 +645,28 @@ public class DomainFactoryImpl implements DomainFactory { * 2. Races without any boat information */ @Override - public Map getOrCreateCompetitorsAndTheirBoats(IRace race, BoatClass defaultBoatClass) { + public Map getOrCreateCompetitorsAndTheirBoats(DynamicTrackedRegatta trackedRegatta, IRace race, BoatClass defaultBoatClass) { final Map competitorsAndBoats = new HashMap<>(); getCompetingCompetitors(race).forEach(rc->{ BoatMetaData competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); + boolean isSeparateBoat = competitorBoatInfo != null; Boat boatOfCompetitor; // Case 1 - if (competitorBoatInfo != null) { - // create an unique for such a boot an search in the boat store for it + if (isSeparateBoat) { + // create an unique identifier for such a boot and search in the boat store for it Serializable boatId = createUniqueBoatIdentifierFromBoatMetadata(race, competitorBoatInfo); String sailId = competitorBoatInfo.getId(); // we take here the boatId as sailID which is a number like 1, 2, 3 boatOfCompetitor = getOrCreateBoat(boatId, competitorBoatInfo.getName(), defaultBoatClass, sailId, AbstractColor.getCssColor(competitorBoatInfo.getColor())); + + // If the tractrac race contains boat metadata we assume the regatta can have changing boats per race. + // As the attribute 'canBoatsOfCompetitorsChangePerRace' is new we need to set it's value to true for the regatta (default is false) + if (trackedRegatta.getRegatta().canBoatsOfCompetitorsChangePerRace() == false) { + // we need to set this to true for the regatta to make it possible to edit the boat/competitor mappings + trackedRegatta.getRegatta().setCanBoatsOfCompetitorsChangePerRace(true); + } } else { // Case 2 Serializable boatId = createUniqueBoatIdentifierFromCompetitor(race, rc); 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 d99329eabd8..8b288d2917c 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 @@ -23,6 +23,7 @@ import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tractracadapter.DomainFactory; import com.sap.sailing.domain.tractracadapter.TracTracControlPoint; @@ -157,9 +158,9 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue, BoatClass> competitorsAndDominantBoatClass = getDomainFactory().getCompetitorsAndDominantBoatClass(tractracRace); - Map competitorAndBoats = getDomainFactory().getOrCreateCompetitorsAndTheirBoats(tractracRace, competitorsAndDominantBoatClass.getB()); + Map competitorAndBoats = getDomainFactory().getOrCreateCompetitorsAndTheirBoats(getTrackedRegatta(), tractracRace, competitorsAndDominantBoatClass.getB()); trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace( - getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getA(), + getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getB(), competitorAndBoats, course, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, tracTracUpdateURI, getTracTracEvent().getId(), tracTracUsername, tracTracPassword, useInternalMarkPassingAlgorithm, raceLogResolver, tr->updateRaceTimes(tractracRace, tr), tractracRace); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index 55ff5258fa3..147bfd81995 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorAndBoatRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.MetaLeaderboard; @@ -329,6 +330,17 @@ public interface RaceColumn extends Named { */ boolean isCompetitorRegistrationInRacelogEnabled(Fleet fleet); + /** + * Checks whether competitor and boat registration on RaceLog is enabled. + * + * @return boolean if competitor and boat registration on the RaceLog is enabled, false in case this column belongs to a + * {@link MetaLeaderboard} + * + * @see #enableCompetitorAndBoatRegistrationOnRaceLog(Fleet) + * @see #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) + */ + boolean isCompetitorAndBoatRegistrationInRacelogEnabled(Fleet fleet); + /** * Activates competitor registration on the race column's race log associated to the passed fleet. As a result, * competitor registrations that were added to the race log before this was disabled by @@ -349,7 +361,28 @@ public interface RaceColumn extends Named { * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. */ void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; + + /** + * Activates competitor and boat registration on the race column's race log associated to the passed fleet. As a result, + * competitor and boat registrations that were added to the race log before this was disabled by + * {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet)} will again be honored.

      + * + * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. + */ + void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet); + /** + * Disables competitor and boat registration on the race column's race log associated to the passed fleet. Performs nothing + * in case this column belongs to a {@link MetaLeaderboard}. If there are already competitor and boat registrations on the + * race log, those will not be removed from the log but they will be ignored, and the regatta log's competitor and boat + * registrations will be used instead. Re-{@link #enableCompetitorAndBoatRegistrationOnRaceLog(Fleet) enabling} competitor and boat + * registrations in the race log will cause such existing registrations to be honored again. + *

      + * + * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. + */ + void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; + /** * Registers a competitor on the the race column's race log associated to the passed fleet. * @@ -386,4 +419,6 @@ public interface RaceColumn extends Named { */ void deregisterCompetitors(Iterable currentlyRegisteredCompetitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; + void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; + void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index f9d71025472..54f26b5eb1f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -131,6 +131,12 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe RegattaIdentifier getRegattaIdentifier(); + /** + * Changes whether the competitors use the same boat for the whole regatta or change the boat used during the competition. + * Actually this should never be called as this should not change once set, but we need it to migrate older regattas to the new model. + */ + void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace); + /** * Regattas may be constructed as implicit default regattas in which case they won't need to be stored durably and * don't contain valuable information worth being preserved; or they are constructed explicitly with series and race diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index 138eec9bd1e..b4ebbf1e361 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -20,10 +20,13 @@ 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.analyzing.impl.LastPublishedCourseDesignFinder; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; @@ -37,6 +40,7 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorAndBoatRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -321,7 +325,29 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem UUID.randomUUID(), passId, competitor)); } } - + + @Override + public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { + Map competitorsAndBoats = new HashMap<>(); + competitorsAndBoats.put(competitor, boat); + registerCompetitorsAndBoats(competitorsAndBoats, fleet); + } + + @Override + public void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) + throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { + if (!isCompetitorAndBoatRegistrationInRacelogEnabled(fleet)) { + throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException("Competitor and boat registration not allowed for fleet "+fleet+" in column "+this); + } + TimePoint now = MillisecondsTimePoint.now(); + RaceLog raceLog = getRaceLog(fleet); + int passId = raceLog.getCurrentPassId(); + for (Entry competitorAndBoat : competitorsAndBoats.entrySet()) { + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(now, now, raceLogEventAuthorForRaceColumn, + UUID.randomUUID(), passId, competitorAndBoat.getKey(), competitorAndBoat.getValue())); + } + } + @Override public void deregisterCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { @@ -434,4 +460,30 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem } } } + + @Override + public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) { + TimePoint now = MillisecondsTimePoint.now(); + RaceLog raceLog = getRaceLog(fleet); + int passId = raceLog.getCurrentPassId(); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(now, raceLogEventAuthorForRaceColumn, now, UUID.randomUUID(), passId)); + } + + @Override + public void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException { + RaceLog raceLog = getRaceLog(fleet); + List events = new AllEventsOfTypeFinder<>(raceLog, true, RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class).analyze(); + for (RaceLogEvent event : events) { + raceLog.lockForRead(); + try { + event = raceLog.getEventById(event.getId()); + } finally { + raceLog.unlockAfterRead(); + } + if (event != null) { + raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event, "revoke triggered by GWT user action"); + } + } + } + } \ No newline at end of file diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index a37289a69b1..d0e703287d2 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -76,7 +76,7 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain private static Logger logger = Logger.getLogger(DomainFactoryImpl.class.getName()); /** - * Uses a transient competitor store + * Uses a transient competitor and boat store */ public DomainFactoryImpl(RaceLogResolver raceLogResolver) { super(new TransientCompetitorStoreImpl(), raceLogResolver); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java index 22a916927da..8fa55ed196d 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceColumnRaceLogReplicator.java @@ -25,11 +25,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -132,11 +131,6 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali notifyOnAdd(event); } - @Override - public void visit(RaceLogRegisterBoatEvent event) { - notifyOnAdd(event); - } - @Override public void visit(RaceLogRegisterCompetitorEvent event) { notifyOnAdd(event); @@ -183,7 +177,7 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { notifyOnAdd(event); } } 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 f13c76ae151..e90c18cc3c4 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 @@ -151,7 +151,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene */ private boolean controlTrackingFromStartAndFinishTimes; - private final boolean canBoatsOfCompetitorsChangePerRace; + private boolean canBoatsOfCompetitorsChangePerRace; /** * Defaults to true. See {@link Regatta#useStartTimeInference()}. @@ -732,6 +732,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return canBoatsOfCompetitorsChangePerRace; } + @Override + public void setCanBoatsOfCompetitorsChangePerRace(boolean canBoatsOfCompetitorsChangePerRace) { + this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace; + } + @Override public RegattaLog getRegattaLog() { return regattaLikeHelper.getRegattaLog(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java index 3cebd9d3d06..c4cd3aa8feb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java @@ -5,6 +5,7 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -141,4 +142,16 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn { return analyzer.analyze(); } } + + @Override + public boolean isCompetitorAndBoatRegistrationInRacelogEnabled(final Fleet fleet) { + RaceLog raceLog = getRaceLog(fleet); + if (raceLog == null) { + return false; + } else { + RaceLogUsesOwnCompetitorsAndBoatsAnalyzer analyzer = new RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(raceLog); + return analyzer.analyze(); + } + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java index 2e2a64996f3..8d3414e002c 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java @@ -11,8 +11,8 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; @@ -37,8 +37,8 @@ import com.sap.sse.common.Util.Pair; *

    7. a boat is registered with or unregistered from a race log of any of the race columns or the regatta log
    8. *
    9. a race column is added or removed
    10. *
    11. a tracked race is linked to or unlinked from any of the race columns
    12. - *
    13. the racelog is marked as providing it's own boats via the {@link RaceLogUseBoatsFromRaceLogEvent}
    14. - *
    15. the racelog is marked as no longer providing it's own boats by revoking an event of type {@link RaceLogUseBoatsFromRaceLogEvent}
    16. + *
    17. the racelog is marked as providing it's own boats via the {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
    18. + *
    19. the racelog is marked as no longer providing it's own boats by revoking an event of type {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
    20. * * * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient @@ -94,13 +94,9 @@ public class BoatProviderFromRaceColumnsAndRegattaLike { } }; raceLogBoatsCacheInvalidationListener = new BaseRaceLogEventVisitor() { - @Override - public void visit(RaceLogRegisterBoatEvent event) { - invalidateAllBoatsCaches(); - } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { invalidateAllBoatsCaches(); } @@ -109,8 +105,8 @@ public class BoatProviderFromRaceColumnsAndRegattaLike { try { final Class revokedEventClass = Class.forName(event.getRevokedEventType()); // - if (RaceLogRegisterBoatEvent.class.isAssignableFrom(revokedEventClass) || - RaceLogUseBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { + if (RaceLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { invalidateAllBoatsCaches(); } } catch (ClassNotFoundException e) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 506455f26a8..4fde6f3071e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -294,6 +294,14 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { } + @Override + public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { + } + + @Override + public void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { + } + @Override public Map getAllCompetitorsAndTheirBoats() { // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas 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 00ff5e42d8e..0ef58e39d4d 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 @@ -31,7 +31,7 @@ public interface IsRegattaLike extends Serializable { * @return true when the competitors change their boats, false otherwise */ boolean canBoatsOfCompetitorsChangePerRace(); - + RaceColumn getRaceColumnByName(String raceColumnName); RegattaLikeIdentifier getRegattaLikeIdentifier(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java index ce953505c78..7cdc0848600 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java @@ -95,7 +95,24 @@ public class CompactBoatTableWrapper boatIdColumn = new Column(new SafeHtmlCell()) { + @Override + public SafeHtml getValue(BoatDTO competitor) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + sb.appendEscaped(competitor.getIdAsString()); + return sb.toSafeHtml(); + } + }; + boatIdColumn.setSortable(true); + boatColumnListHandler.setComparator(boatIdColumn, new Comparator() { + private final NaturalComparator comparator = new NaturalComparator(/* case sensitive */ false); + @Override + public int compare(BoatDTO o1, BoatDTO o2) { + return comparator.compare(o1.getIdAsString(), o2.getIdAsString()); + } + }); + filterField = new LabeledAbstractFilterablePanel(new Label(stringMessages.filterBoats()), new ArrayList(), table, dataProvider) { @Override @@ -103,6 +120,7 @@ public class CompactBoatTableWrapper string = new ArrayList(); string.add(boat.getName()); string.add(boat.getSailId()); + string.add(boat.getIdAsString()); string.add(boat.getBoatClass().getName()); return string; } @@ -115,6 +133,7 @@ public class CompactBoatTableWrapper getCompetitorsOfRace(String leaderboardName, String raceColumnName, String fleetName) { List result = null; + Map competitorAndBoats = getService().getCompetitorToBoatMappingsForRace(leaderboardName, raceColumnName, fleetName); Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - if (leaderboard != null && raceLog != null) { - result = new ArrayList<>(); + if (leaderboard != null) { RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); Fleet fleet = leaderboard.getFleet(fleetName); - Map competitorAndBoats = new CompetitorsAndBoatsInLogAnalyzer<>(raceLog).analyze(); - for (Competitor competitor: leaderboard.getCompetitors(raceColumn, fleet)) { - CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitor); - Boat boatOfCompetitor = competitorAndBoats.get(competitor); - if (boatOfCompetitor != null) { - competitorDTO.setBoat(baseDomainFactory.convertToBoatDTO(boatOfCompetitor)); + if (raceColumn != null && fleet != null) { + result = new ArrayList<>(); + for (Competitor competitor: leaderboard.getCompetitors(raceColumn, fleet)) { + CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitor); + Boat boatOfCompetitor = competitorAndBoats.get(competitor); + if (boatOfCompetitor != null) { + competitorDTO.setBoat(baseDomainFactory.convertToBoatDTO(boatOfCompetitor)); + } + result.add(competitorDTO); } - result.add(competitorDTO); } } return result; @@ -5030,16 +5029,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) { BoatDTO result = null; Competitor existingCompetitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorIdAsString); - RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - if (raceLog != null && existingCompetitor != null) { - Map competitorAndBoats = new CompetitorsAndBoatsInLogAnalyzer<>(raceLog).analyze(); - Boat boatOfCompetitor = competitorAndBoats.get(existingCompetitor); + Map competitorToBoatMappingsForRace = getService().getCompetitorToBoatMappingsForRace(leaderboardName, raceColumnName, fleetName); + if (existingCompetitor != null) { + Boat boatOfCompetitor = competitorToBoatMappingsForRace.get(existingCompetitor); if (boatOfCompetitor != null) { result = baseDomainFactory.convertToBoatDTO(boatOfCompetitor); } - } + } return result; - } @Override diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java index 6e7eeed396b..719283d959f 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java @@ -81,15 +81,14 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogDenoteForTrackingEventDeserializer(competitorDeserializer, domainFactory), new RaceLogStartTrackingEventDeserializer(competitorDeserializer), new RaceLogRevokeEventDeserializer(competitorDeserializer), - new RaceLogRegisterBoatEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer), - new RaceLogRegisterCompetitorAndBoatEventDeserializer(competitorDeserializer), + new RaceLogRegisterCompetitorAndBoatEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogAdditionalScoringInformationEventDeserializer(competitorDeserializer), new RaceLogFixedMarkPassingEventDeserializer(competitorDeserializer), new RaceLogSuppressedMarkPassingsEventDeserializer(competitorDeserializer), new RaceLogStartOfTrackingEventDeserializer(competitorDeserializer), new RaceLogUseCompetitorsFromRaceLogEventDeserializer(competitorDeserializer), - new RaceLogUseBoatsFromRaceLogEventDeserializer(competitorDeserializer), + new RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer(competitorDeserializer), new RaceLogEndOfTrackingEventDeserializer(competitorDeserializer)); } @@ -110,7 +109,6 @@ public class RaceLogEventDeserializer implements JsonDeserializer protected final JsonDeserializer denoteForTrackingEventDeserializer; protected final JsonDeserializer startTrackingEventDeserializer; protected final JsonDeserializer revokeEventDeserializer; - protected final JsonDeserializer registerBoatEventDeserializer; protected final JsonDeserializer registerCompetitorEventDeserializer; protected final JsonDeserializer registerCompetitorAndBoatEventDeserializer; protected final JsonDeserializer additionalScoringInformationEventDeserializer; @@ -119,7 +117,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer protected final JsonDeserializer startOfTrackingDeserializer; protected final JsonDeserializer endOfTrackingDeserializer; protected final JsonDeserializer useCompetitorsFromRaceLogDeserializer; - protected final JsonDeserializer useBoatsFromRaceLogDeserializer; + protected final JsonDeserializer useCompetitorsAndBoatsFromRaceLogDeserializer; public RaceLogEventDeserializer(JsonDeserializer flagEventDeserializer, JsonDeserializer startTimeEventDeserializer, @@ -138,7 +136,6 @@ public class RaceLogEventDeserializer implements JsonDeserializer JsonDeserializer denoteForTrackingEventDeserializer, JsonDeserializer startTrackingEventDeserializer, JsonDeserializer revokeEventDeserializer, - JsonDeserializer registerBoatEventDeserializer, JsonDeserializer registerCompetitorEventDeserializer, JsonDeserializer registerCompetitorAndBoatEventDeserializer, JsonDeserializer additionalScoringInformationEventDeserializer, @@ -146,7 +143,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer JsonDeserializer suppressedMarkPassingsEventDeserializer, JsonDeserializer startOfTrackingEventDeserializer, JsonDeserializer useCompetitorsFromRaceLogDeserializer, - JsonDeserializer useBoatsFromRaceLogDeserializer, + JsonDeserializer useCompetitorsAndBoatsFromRaceLogDeserializer, JsonDeserializer endOfTrackingEventDeserializer) { this.flagEventDeserializer = flagEventDeserializer; this.startTimeEventDeserializer = startTimeEventDeserializer; @@ -165,7 +162,6 @@ public class RaceLogEventDeserializer implements JsonDeserializer this.denoteForTrackingEventDeserializer = denoteForTrackingEventDeserializer; this.startTrackingEventDeserializer = startTrackingEventDeserializer; this.revokeEventDeserializer = revokeEventDeserializer; - this.registerBoatEventDeserializer = registerCompetitorEventDeserializer; this.registerCompetitorEventDeserializer = registerCompetitorEventDeserializer; this.registerCompetitorAndBoatEventDeserializer = registerCompetitorAndBoatEventDeserializer; this.additionalScoringInformationEventDeserializer = additionalScoringInformationEventDeserializer; @@ -174,7 +170,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer this.startOfTrackingDeserializer = startOfTrackingEventDeserializer; this.endOfTrackingDeserializer = endOfTrackingEventDeserializer; this.useCompetitorsFromRaceLogDeserializer = useCompetitorsFromRaceLogDeserializer; - this.useBoatsFromRaceLogDeserializer = useBoatsFromRaceLogDeserializer; + this.useCompetitorsAndBoatsFromRaceLogDeserializer = useCompetitorsAndBoatsFromRaceLogDeserializer; } protected JsonDeserializer getDeserializer(JSONObject object) throws JsonDeserializationException { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java deleted file mode 100644 index d34f1b723af..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterBoatEventDeserializer.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sap.sailing.server.gateway.deserialization.racelog.impl; - -import java.io.Serializable; -import java.util.List; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterBoatEventImpl; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sse.common.TimePoint; - -public class RaceLogRegisterBoatEventDeserializer extends BaseRaceLogEventDeserializer { - private BoatJsonDeserializer boatDeserializer; - - public RaceLogRegisterBoatEventDeserializer(JsonDeserializer competitorDeserializer, BoatJsonDeserializer boatDeserializer) { - super(competitorDeserializer); - this.boatDeserializer = boatDeserializer; - } - - @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - Boat boat = boatDeserializer.deserialize(object); - return new RaceLogRegisterBoatEventImpl(createdAt, timePoint, author, id, passId, boat); - } - -} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java index 7192c557549..ba85cdddb62 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java @@ -7,21 +7,26 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorAndBoatEventDeserializer extends BaseRaceLogEventDeserializer { + private BoatJsonDeserializer boatDeserializer; - public RaceLogRegisterCompetitorAndBoatEventDeserializer(JsonDeserializer competitorDeserializer) { + public RaceLogRegisterCompetitorAndBoatEventDeserializer(JsonDeserializer competitorDeserializer, BoatJsonDeserializer boatDeserializer) { super(competitorDeserializer); + this.boatDeserializer = boatDeserializer; } @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; - return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0)); + Boat boat = boatDeserializer.deserialize(object); + return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0), boat); } - } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer.java similarity index 70% rename from java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java rename to java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer.java index ace23aa456c..8c259fb957f 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer.java @@ -7,16 +7,16 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseBoatsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sse.common.TimePoint; -public class RaceLogUseBoatsFromRaceLogEventDeserializer extends BaseRaceLogEventDeserializer implements +public class RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer extends BaseRaceLogEventDeserializer implements JsonDeserializer { - public RaceLogUseBoatsFromRaceLogEventDeserializer(JsonDeserializer competitorDeserializer) { + public RaceLogUseCompetitorsAndBoatsFromRaceLogEventDeserializer(JsonDeserializer competitorDeserializer) { super(competitorDeserializer); } @@ -24,7 +24,7 @@ public class RaceLogUseBoatsFromRaceLogEventDeserializer extends BaseRaceLogEven protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - return new RaceLogUseBoatsFromRaceLogEventImpl(createdAt, author, timePoint, id, passId); + return new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(createdAt, author, timePoint, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index 1886dc1410d..bfbabdc06be 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -25,11 +25,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; @@ -86,7 +85,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac new RaceLogDependentStartTimeEventSerializer(competitorSerializer), new RaceLogStartOfTrackingEventSerializer(competitorSerializer), new RaceLogUseCompetitorsFromRaceLogEventSerializer(competitorSerializer), - new RaceLogUseBoatsFromRaceLogEventSerializer(competitorSerializer), + new RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer(competitorSerializer), new RaceLogEndOfTrackingEventSerializer(competitorSerializer)); } @@ -106,7 +105,6 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac private final JsonSerializer denoteForTrackingSerializer; private final JsonSerializer startTrackingSerializer; private final JsonSerializer revokeSerializer; - private final JsonSerializer registerBoatSerializer; private final JsonSerializer registerCompetitorSerializer; private final JsonSerializer registerCompetitorAndBoatSerializer; private final JsonSerializer additionalScoringInformationSerializer; @@ -116,7 +114,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac private final JsonSerializer startOfTrackingEventSerializer; private final JsonSerializer endOfTrackingEventSerializer; private final JsonSerializer useCompetitorsFromRaceLogEventSerializer; - private final JsonSerializer useBoatsFromRaceLogEventSerializer; + private final JsonSerializer useCompetitorsAndBoatsFromRaceLogEventSerializer; private JsonSerializer chosenSerializer; @@ -148,7 +146,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac JsonSerializer startOfTrackingEventSerializer, JsonSerializer endOfTrackingEventSerializer, JsonSerializer useCompetitorsFromRaceLogEventSerializer, - JsonSerializer useBoatsFromRaceLogEventSerializer) { + JsonSerializer useCompetitorsAndBoatsFromRaceLogEventSerializer) { this.flagEventSerializer = flagEventSerializer; this.startTimeSerializer = startTimeSerializer; this.raceStatusSerializer = raceStatusSerializer; @@ -165,7 +163,6 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac this.denoteForTrackingSerializer = denoteForTrackingSerializer; this.startTrackingSerializer = createRaceSerializer; this.revokeSerializer = revokeSerializer; - this.registerBoatSerializer = registerBoatSerializer; this.registerCompetitorSerializer = registerCompetitorSerializer; this.registerCompetitorAndBoatSerializer = registerCompetitorAndBoatSerializer; this.additionalScoringInformationSerializer = additionalScoringInformationSerializer; @@ -175,7 +172,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac this.startOfTrackingEventSerializer = startOfTrackingEventSerializer; this.endOfTrackingEventSerializer = endOfTrackingEventSerializer; this.useCompetitorsFromRaceLogEventSerializer = useCompetitorsFromRaceLogEventSerializer; - this.useBoatsFromRaceLogEventSerializer = useBoatsFromRaceLogEventSerializer; + this.useCompetitorsAndBoatsFromRaceLogEventSerializer = useCompetitorsAndBoatsFromRaceLogEventSerializer; this.chosenSerializer = null; } @@ -274,11 +271,6 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac chosenSerializer = revokeSerializer; } - @Override - public void visit(RaceLogRegisterBoatEvent event) { - chosenSerializer = registerBoatSerializer; - } - @Override public void visit(RaceLogRegisterCompetitorEvent event) { chosenSerializer = registerCompetitorSerializer; @@ -325,7 +317,7 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac } @Override - public void visit(RaceLogUseBoatsFromRaceLogEvent event) { - chosenSerializer = useBoatsFromRaceLogEventSerializer; + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { + chosenSerializer = useCompetitorsAndBoatsFromRaceLogEventSerializer; } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer.java similarity index 55% rename from java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java rename to java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer.java index 7f66e7b5abf..c64235e36cf 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseBoatsFromRaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer.java @@ -1,15 +1,15 @@ package com.sap.sailing.server.gateway.serialization.racelog.impl; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -public class RaceLogUseBoatsFromRaceLogEventSerializer extends BaseRaceLogEventSerializer implements +public class RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer extends BaseRaceLogEventSerializer implements JsonSerializer { - public static final String VALUE_CLASS = RaceLogUseBoatsFromRaceLogEvent.class.getSimpleName(); + public static final String VALUE_CLASS = RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName(); - public RaceLogUseBoatsFromRaceLogEventSerializer(JsonSerializer competitorSerializer) { + public RaceLogUseCompetitorsAndBoatsFromRaceLogEventSerializer(JsonSerializer competitorSerializer) { super(competitorSerializer); } 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 69cf38b69cb..ee06781bf13 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 @@ -19,6 +19,7 @@ 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.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.CourseArea; @@ -473,6 +474,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName); + Map getCompetitorToBoatMappingsForRace(String leaderboardName, String raceColumnName, String fleetName); + /** * @param controlTrackingFromStartAndFinishTimes TODO * @param rankingMetricConstructor TODO 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 e58b981bb1d..2acd7a366ef 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 @@ -57,6 +57,8 @@ import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.CompetitorStore.CompetitorUpdateListener; @@ -3269,7 +3271,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes public String toString() { return "RacingEventService: " + this.hashCode() + " Build: " + ServerInfo.getBuildVersion(); } - + @Override public void reloadRaceLog(String leaderboardName, String raceColumnName, String fleetName) { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); @@ -3283,7 +3285,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes logger.info("Reloaded race log for fleet " + fleetImpl + " for race column " + raceColumn.getName() + " for leaderboard " + leaderboard.getName()); } - } + } } } @@ -3354,6 +3356,36 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes return null; } + public Map getCompetitorToBoatMappingsForRace(String leaderboardName, String raceColumnName, String fleetName) { + Map result = new HashMap<>(); + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + Fleet fleet = leaderboard.getFleet(fleetName); + if (raceColumn != null && fleet != null) { + RaceLog raceLog = raceColumn.getRaceLog(fleet); + // take the boats first from the racelog + if (raceLog != null) { + Map competitorAndBoatsInRacelog = new CompetitorsAndBoatsInLogAnalyzer<>(raceLog).analyze(); + result.putAll(competitorAndBoatsInRacelog); + } + // now look into the tracked race for mappings of competitors without a boat + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + if (trackedRace != null) { + Map competitorsAndBoatsFromRaceDef = trackedRace.getRace().getCompetitorsAndTheirBoats(); + for (Competitor competitor: competitorsAndBoatsFromRaceDef.keySet()) { + if (!result.containsKey(competitor)) { + result.put(competitor, competitorsAndBoatsFromRaceDef.get(competitor)); + } + } + } + } + } + return result; + } + + + @Override public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( String leaderboardName, String raceColumnName, String fleetName) { From 797f0d0a752605410be74a66b1affe4c2138b506 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Thu, 20 Jul 2017 11:58:30 +0200 Subject: [PATCH 049/271] fixed missing implementation of 2 methods --- .../leaderboard/meta/MetaLeaderboardColumn.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 4fde6f3071e..13356340de0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -15,6 +15,7 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.impl.SimpleAbstractRaceColumn; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorAndBoatRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; @@ -274,6 +275,19 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R throw new CompetitorRegistrationOnRaceLogDisabledException(); } + + @Override + public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) + throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { + throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException(); + } + + @Override + public void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) + throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { + throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException(); + } + @Override public void deregisterCompetitor(Competitor competitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { From 9e9f5aeaec4cdaa68d2e908c08b8bacfbe1a72ac Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Fri, 21 Jul 2017 16:41:38 +0200 Subject: [PATCH 050/271] changed loading of competitors in competitorStore to load the old competitors with the contained boat --- .../domain/persistence/DomainObjectFactory.java | 4 ++-- .../persistence/impl/DomainObjectFactoryImpl.java | 13 +++++++------ .../sap/sailing/domain/base/CompetitorWithBoat.java | 7 +------ .../src/com/sap/sailing/domain/base/WithBoat.java | 11 +++++++++++ .../domain/base/impl/CompetitorAndBoatImpl.java | 5 +++++ .../domain/base/impl/CompetitorWithBoatImpl.java | 7 +++++++ .../tractracadapter/impl/DomainFactoryImpl.java | 2 +- .../mongodb/test/StoreAndLoadCompetitorsTest.java | 4 ++-- .../impl/CompetitorWithBoatJsonDeserializer.java | 10 +++++----- .../server/impl/PersistentCompetitorStore.java | 7 ++++--- 10 files changed, 45 insertions(+), 25 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/WithBoat.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java index aba08a3bd21..843f475b970 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java @@ -12,7 +12,7 @@ import com.mongodb.DBObject; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; @@ -131,7 +131,7 @@ public interface DomainObjectFactory { /** * Loads all competitors, and resolves them via the domain factory. */ - Collection loadAllCompetitors(); + Collection loadAllCompetitors(); /** * Loads all boats, and resolves them via the domain factory. diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 77ee5663531..7e7499b59c9 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -127,6 +127,7 @@ import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; @@ -223,7 +224,7 @@ import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer; @@ -251,7 +252,7 @@ import com.sap.sse.util.ThreadPoolUtil; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); - private final CompetitorJsonDeserializer competitorDeserializer; + private final CompetitorWithBoatJsonDeserializer competitorWithBoatDeserializer; private final BoatJsonDeserializer boatDeserializer; private final DB database; @@ -281,7 +282,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { this.raceTrackingConnectivityParamsServiceFinder = null; } this.baseDomainFactory = baseDomainFactory; - this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); + this.competitorWithBoatDeserializer = CompetitorWithBoatJsonDeserializer.create(baseDomainFactory); this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } @@ -2124,13 +2125,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public Collection loadAllCompetitors() { - ArrayList result = new ArrayList(); + public Collection loadAllCompetitors() { + ArrayList result = new ArrayList<>(); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); try { for (DBObject o : collection.find()) { JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o))); - Competitor c = competitorDeserializer.deserialize(json); + CompetitorWithBoat c = competitorWithBoatDeserializer.deserialize(json); result.add(c); } } catch (Exception e) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java index ae23b7c6ca3..f74ffc61b9b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoat.java @@ -1,14 +1,9 @@ package com.sap.sailing.domain.base; -import com.sap.sse.datamining.annotations.Connector; - /** * A competitor having an assigned boat * This makes sense e.g. in the context of a race where a competitor needs a boat in order to compete * @author fmittag - * */ -public interface CompetitorWithBoat extends Competitor { - @Connector(messageKey = "Boat", ordinal = 10) - Boat getBoat(); +public interface CompetitorWithBoat extends Competitor, WithBoat { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/WithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/WithBoat.java new file mode 100644 index 00000000000..593d883fd8b --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/WithBoat.java @@ -0,0 +1,11 @@ +package com.sap.sailing.domain.base; + +import com.sap.sse.datamining.annotations.Connector; + +/** + * Something with a boat. + */ +public interface WithBoat { + @Connector(messageKey = "Boat", ordinal = 10) + Boat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java index f8339fd5030..287a0f182ef 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorAndBoatImpl.java @@ -4,6 +4,11 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorAndBoat; +/** + * A utility class to hold a combination of a competitor and a boat + * @author Frank Mittag + * + */ public class CompetitorAndBoatImpl implements CompetitorAndBoat { private static final long serialVersionUID = 6057339511208358777L; private final Competitor competitor; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java index 57b85639e34..e137a34e322 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.net.URI; import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; @@ -20,6 +21,12 @@ public class CompetitorWithBoatImpl extends CompetitorImpl implements Competitor this.boat = boat; } + public CompetitorWithBoatImpl(Competitor competitor, Boat boat) { + this(competitor.getId(), competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + competitor.getFlagImage(), (DynamicTeam) competitor.getTeam(), competitor.getTimeOnTimeFactor(), + competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), boat); + } + @Override public Boat getBoat() { return boat; 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 5bcec918a22..75dfcd195d1 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 @@ -675,7 +675,7 @@ public class DomainFactoryImpl implements DomainFactory { } Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); - if (competitorBoatInfo != null && existingCompetitor.getShortName() != rc.getCompetitor().getShortName()) { + if (isSeparateBoat && existingCompetitor.getShortName() != rc.getCompetitor().getShortName()) { // in case we find a boat info we only want to update the shortName field of the competitor (instead of using sailID) CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); boolean isOldCompetitorToUpdateDuringGetOrCreate = competitorStore.isCompetitorToUpdateDuringGetOrCreate(existingCompetitor); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java index 823cc4f3384..c02a07b0145 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java @@ -15,7 +15,7 @@ import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.MongoException; import com.mongodb.WriteConcern; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.base.impl.DynamicCompetitor; @@ -64,7 +64,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { c.setFlagImage(flagImageURI1); mongoObjectFactory.storeCompetitor(c); - Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); + Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); assertEquals(1, Util.size(allCompetitors)); DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next(); assertEquals(flagImageURI1, loadedCompetitor.getFlagImage()); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java index 7051156dde1..663514ab034 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java @@ -9,10 +9,10 @@ import java.util.logging.Logger; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.base.CompetitorFactory; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; @@ -23,7 +23,7 @@ import com.sap.sse.common.Color; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.RGBColor; -public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { +public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { protected final CompetitorFactory competitorFactory; protected final JsonDeserializer teamJsonDeserializer; protected final JsonDeserializer boatJsonDeserializer; @@ -45,7 +45,7 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); @@ -97,7 +97,7 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer allCompetitors = loadFrom.loadAllCompetitors(); - for (Competitor competitor : allCompetitors) { + Collection allCompetitors = loadFrom.loadAllCompetitors(); + for (CompetitorWithBoat competitor : allCompetitors) { addCompetitorToTransientStore(competitor.getId(), competitor); } Collection allBoats = loadFrom.loadAllBoats(); @@ -86,7 +87,7 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); } - private void addCompetitorToTransientStore(Serializable id, Competitor competitor) { + private void addCompetitorToTransientStore(Serializable id, CompetitorWithBoat competitor) { super.addNewCompetitor(id, competitor); } From 20bc27a3dadeb57770aeda67ddc0680c5bab7ac9 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Fri, 21 Jul 2017 17:28:49 +0200 Subject: [PATCH 051/271] Improved name of a serializer --- ...lizer.java => CompetitorAndBoatJsonSerializer.java} | 10 +++++----- .../serialization/impl/ManeuversJsonSerializer.java | 4 ++-- .../serialization/impl/MarkPassingsJsonSerializer.java | 2 +- .../server/gateway/jaxrs/api/RegattasResource.java | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) rename java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/{CompetitorWithBoatJsonSerializer.java => CompetitorAndBoatJsonSerializer.java} (73%) diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java similarity index 73% rename from java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java rename to java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java index 7738db556c5..1494ca5d317 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java @@ -8,19 +8,19 @@ import com.sap.sailing.domain.base.CompetitorAndBoat; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -public class CompetitorWithBoatJsonSerializer implements JsonSerializer { +public class CompetitorAndBoatJsonSerializer implements JsonSerializer { private final JsonSerializer boatJsonSerializer; private final JsonSerializer competitorJsonSerializer; - public static CompetitorWithBoatJsonSerializer create() { - return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); + public static CompetitorAndBoatJsonSerializer create() { + return new CompetitorAndBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); } - public CompetitorWithBoatJsonSerializer() { + public CompetitorAndBoatJsonSerializer() { this(null, null); } - public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { + public CompetitorAndBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { this.competitorJsonSerializer = competitorJsonSerializer; this.boatJsonSerializer = boatJsonSerializer; } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java index 4fe254c74e1..748c11f7608 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java @@ -16,10 +16,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public final static String MANEUVERS = "maneuvers"; - private final CompetitorWithBoatJsonSerializer competitorSerializer; + private final CompetitorAndBoatJsonSerializer competitorSerializer; private final ManeuverJsonSerializer maneuverSerializer; - public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + public ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { super(); this.competitorSerializer = competitorSerializer; this.maneuverSerializer = maneuverSerializer; diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java index 905a043ff6f..c9bf8b687eb 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java @@ -26,7 +26,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria public JSONObject serialize(TrackedRace trackedRace) { final Course course = trackedRace.getRace().getCourse(); JSONObject result = new JSONObject(); - CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); + CompetitorAndBoatJsonSerializer competitorWithBoatSerializer = CompetitorAndBoatJsonSerializer.create(); CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index 428ffdc75e8..aef98773eb3 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -67,7 +67,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJson import com.sap.sailing.server.gateway.serialization.impl.AbstractTrackedRaceDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DefaultWindTrackJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DistanceJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer; @@ -211,7 +211,7 @@ public class RegattasResource extends AbstractSailingServerResource { if (race == null) { response = getBadRaceErrorResponse(regattaName, raceName); } else { - CompetitorWithBoatJsonSerializer competitorJsonSerializer = CompetitorWithBoatJsonSerializer.create(); + CompetitorAndBoatJsonSerializer competitorJsonSerializer = CompetitorAndBoatJsonSerializer.create(); JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorJsonSerializer); JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race); @@ -861,7 +861,7 @@ public class RegattasResource extends AbstractSailingServerResource { .build(); } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); - ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorWithBoatJsonSerializer(), + ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorAndBoatJsonSerializer(), new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer())); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); @@ -930,7 +930,7 @@ public class RegattasResource extends AbstractSailingServerResource { return result; }); } - CompetitorWithBoatJsonSerializer serializer = new CompetitorWithBoatJsonSerializer(); + CompetitorAndBoatJsonSerializer serializer = new CompetitorAndBoatJsonSerializer(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { Boat boat = trackedRace.getBoatOfCompetitor(c); From 48162c73bedb91ff0965eb72c3ca8a6d998699a8 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Thu, 24 Aug 2017 18:04:38 +0200 Subject: [PATCH 052/271] major refacoring and cleanup of RaceLog and RegattaLog events needed for the new way of registering boats and competitors as separate entities -> UI is still not ready for it. --- .../persistence/DomainObjectFactory.java | 12 +- .../persistence/MongoObjectFactory.java | 23 +- .../persistence/impl/CollectionNames.java | 7 +- .../impl/DomainObjectFactoryImpl.java | 1062 ++++++++++------- .../impl/MongoObjectFactoryImpl.java | 57 +- .../impl/MongoRegattaLogStoreVisitor.java | 6 + .../impl/CreateAndTrackWithRaceLogTest.java | 20 +- .../impl/RaceLogTrackingAdapterImpl.java | 19 +- .../test/CompetitorDeregistrationTest.java | 17 +- .../abstractlog/race/RaceLogEventData.java | 2 +- .../analyzing/impl/MarkPassingDataFinder.java | 4 +- .../RaceLogRegisteredCompetitorsAnalyzer.java | 8 +- ...RegisteredCompetitorsAndBoatsAnalyzer.java | 31 + .../race/impl/RaceLogEventDataImpl.java | 4 +- .../race/impl/RaceLogEventImpl.java | 4 +- .../RaceLogFixedMarkPassingEventImpl.java | 4 +- .../race/impl/RaceLogRevokeEventImpl.java | 4 +- ...aceLogSuppressedMarkPassingsEventImpl.java | 2 +- .../RaceLogRegisterCompetitorEvent.java | 7 +- ...seCompetitorsAndBoatsFromRaceLogEvent.java | 3 - .../impl/RegisteredCompetitorsAnalyzer.java | 8 +- ...RegisteredCompetitorsAndBoatsAnalyzer.java | 2 +- ...LogRegisterCompetitorAndBoatEventImpl.java | 2 +- .../RaceLogRegisterCompetitorEventImpl.java | 9 +- .../regatta/RegattaLogEventVisitor.java | 3 + .../events/RegattaLogRegisterBoatEvent.java | 9 +- ...attaLogRegisterCompetitorAndBoatEvent.java | 6 + .../RegattaLogRegisterCompetitorEvent.java | 8 +- .../events/RegattaLogRegisterEntryEvent.java | 15 + .../impl/RegattaLogRegisterBoatEventImpl.java | 27 +- ...RegattaLogRegisterCompetitorEventImpl.java | 6 +- .../RegattaLogRegisterEntryEventImpl.java | 60 + .../impl/BaseRegattaLogEventVisitor.java | 5 + .../regatta/impl/RegattaLogEventListener.java | 6 + .../impl/RegattaLogBoatDeregistrator.java} | 14 +- .../impl/RegattaLogBoatsInLogAnalyzer.java | 38 + .../impl/RegattaLogEntriesInLogAnalyzer.java | 38 + .../shared/analyzing/BoatsInLogAnalyzer.java | 46 - .../analyzing/CompetitorsInLogAnalyzer.java | 8 +- .../shared/events/RegisterBoatEvent.java | 22 - .../RegisterCompetitorAndBoatEvent.java | 10 +- .../events/RegisterCompetitorEvent.java | 6 +- .../impl/BaseRegisterBoatEventImpl.java | 51 - .../impl/BaseRegisterCompetitorEventImpl.java | 15 +- .../sailing/domain/base/CompetitorStore.java | 77 +- .../base/CompetitorWithBoatFactory.java | 33 + .../domain/base/SharedDomainFactory.java | 2 +- .../base/impl/CompetitorWithBoatImpl.java | 12 +- .../base/impl/DynamicCompetitorWithBoat.java | 7 + .../base/impl/SharedDomainFactoryImpl.java | 22 + .../impl/TransientCompetitorStoreImpl.java | 234 +++- .../domain/test/AbstractLeaderboardTest.java | 37 +- ...mpetitorProviderCacheInvalidationTest.java | 55 +- ...ttaLogEventNotificationForwardingTest.java | 20 +- .../sailing/domain/test/TrackBasedTest.java | 2 +- .../domain/test/mock/MockedTrackedRace.java | 6 - .../impl/DomainFactoryImpl.java | 3 + .../sap/sailing/domain/base/RaceColumn.java | 59 +- .../domain/base/impl/AbstractRaceColumn.java | 68 +- .../sailing/domain/base/impl/RegattaImpl.java | 27 +- .../base/impl/SimpleAbstractRaceColumn.java | 22 +- .../HasRaceColumnsAndRegattaLike.java | 3 - .../impl/AbstractLeaderboardImpl.java | 32 +- ...ProviderFromRaceColumnsAndRegattaLike.java | 230 ---- ...ProviderFromRaceColumnsAndRegattaLike.java | 37 +- ...aLeaderboardWithCompetitorElimination.java | 4 - .../meta/MetaLeaderboardColumn.java | 45 +- .../impl/DynamicTrackedRaceLogListener.java | 8 +- .../gwt/ui/server/SailingServiceImpl.java | 40 +- .../test/StoreAndLoadCompetitorsTest.java | 45 +- .../test/StoreAndLoadRaceLogEventsTest.java | 17 +- ...estStoringAndLoadingEventsAndRegattas.java | 24 +- ...ingAndRetrievingRaceLogInLeaderboards.java | 4 +- ...tStoringAndRetrievingRaceLogInRegatta.java | 6 +- .../CompetitorWithBoatJsonDeserializer.java | 22 +- .../impl/RaceLogEventDeserializer.java | 5 +- ...terCompetitorAndBoatEventDeserializer.java | 2 +- ...ogRegisterCompetitorEventDeserializer.java | 11 +- ... => CompetitorWithBoatJsonSerializer.java} | 22 +- .../impl/BaseRaceLogEventSerializer.java | 2 +- .../racelog/impl/RaceLogEventSerializer.java | 2 - .../RaceLogRegisterBoatEventSerializer.java | 20 - .../racelog/AbstractEventSerializerTest.java | 2 +- ...ourseDesignChangedEventSerializerTest.java | 4 +- .../racelog/RaceLogEventSerializerTest.java | 22 +- ...sitioningConfirmedEventSerializerTest.java | 12 +- .../RaceLogWindFixEventSerializerTest.java | 4 +- .../impl/ManeuversJsonSerializer.java | 9 +- .../impl/MarkPassingsJsonSerializer.java | 7 +- .../impl/RaceEntriesJsonSerializer.java | 17 +- ...LeaderboardsResourceCheckinAndOutTest.java | 6 +- .../gateway/jaxrs/api/RegattasResource.java | 13 +- .../test/RaceLogReplicationTest.java | 2 +- .../test/RegattaLogReplicationTest.java | 4 +- .../server/test/CompetitorStoreTest.java | 49 +- .../server/test/MasterDataImportTest.java | 5 +- .../impl/PersistentCompetitorStore.java | 60 +- .../server/impl/RacingEventServiceImpl.java | 20 +- 98 files changed, 1898 insertions(+), 1315 deletions(-) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java rename java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/{shared/analyzing/BoatDeregistrator.java => regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java} (77%) create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java create mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java delete mode 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java rename java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/{CompetitorAndBoatJsonSerializer.java => CompetitorWithBoatJsonSerializer.java} (51%) delete mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java index 843f475b970..b91cdc8a1b4 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/DomainObjectFactory.java @@ -12,6 +12,7 @@ import com.mongodb.DBObject; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; @@ -129,12 +130,17 @@ public interface DomainObjectFactory { RegattaLog loadRegattaLog(RegattaLikeIdentifier identifier); /** - * Loads all competitors, and resolves them via the domain factory. + * Loads all competitors and resolves them via the domain factory. */ - Collection loadAllCompetitors(); + Collection loadAllCompetitors(); /** - * Loads all boats, and resolves them via the domain factory. + * Loads all competitors with boats and resolves them via the domain factory. + */ + Collection loadAllCompetitorsWithBoat(); + + /** + * Loads all boats and resolves them via the domain factory. */ Collection loadAllBoats(); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java index 0595f886611..71dea119b70 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java @@ -7,6 +7,7 @@ import com.mongodb.DB; import com.mongodb.DBObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; @@ -118,9 +119,23 @@ public interface MongoObjectFactory { void storeRegattaForRaceID(String id, Regatta regatta); void removeRegattaForRaceID(String raceIDAsString, Regatta regatta); - + /** - * Stores a competitor, including the team and boat. This should not be done for competitors for which + * Stores a competitor, including the boat. This should not be done for competitors for which + * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, + * where this data is otherwise not recoverable. + * @param competitor the competitor to store/update in the database + */ + void storeCompetitorWithBoat(CompetitorWithBoat competitor); + + /** + * Like {@link #storeCompetitorWithBoat(CompetitorWithBoat)}, but for a collection of competitors that are all + * expected to be new, having a unique {@link Competitor#getId() ID}. + */ + void storeCompetitorsWithBoat(Iterable competitors); + + /** + * Stores a competitor. This should not be done for competitors for which * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, * where this data is otherwise not recoverable. * @param competitor the competitor to store/update in the database @@ -135,8 +150,12 @@ public interface MongoObjectFactory { void removeAllCompetitors(); + void removeAllCompetitorsWithBoat(); + void removeCompetitor(Competitor competitor); + void removeCompetitorWithBoat(CompetitorWithBoat competitor); + /** * Stores a boat. This should not be done for boats for which * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java index f746c06801d..b13ee1a8744 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/CollectionNames.java @@ -71,10 +71,15 @@ public enum CollectionNames { /** - * Stores competitors. + * Stores competitors with boats. */ COMPETITORS, + /** + * Stores competitors with boats. + */ + COMPETITORS_WITHOUT_BOAT, + /** * Stores boats. */ diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 7e7499b59c9..866be5c3518 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -109,6 +109,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -120,6 +121,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnTimeFactorEventImpl; @@ -224,6 +226,7 @@ import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; @@ -253,40 +256,45 @@ import com.sap.sse.util.ThreadPoolUtil; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); private final CompetitorWithBoatJsonDeserializer competitorWithBoatDeserializer; + private final CompetitorJsonDeserializer competitorDeserializer; private final BoatJsonDeserializer boatDeserializer; private final DB database; - + private final DomainFactory baseDomainFactory; private final TypeBasedServiceFinderFactory serviceFinderFactory; private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinder raceTrackingConnectivityParamsServiceFinder; - + /** - * Uses null as the {@link TypeBasedServiceFinder}, meaning that no {@link DeviceIdentifier}s can be loaded - * using this instance of a {@link DomainObjectFactory}. + * Uses null as the {@link TypeBasedServiceFinder}, meaning that no {@link DeviceIdentifier}s can be + * loaded using this instance of a {@link DomainObjectFactory}. */ public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory) { this(db, baseDomainFactory, /* deviceTypeServiceFinder */ null); } - - public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory, TypeBasedServiceFinderFactory serviceFinderFactory) { + + public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory, + TypeBasedServiceFinderFactory serviceFinderFactory) { super(); this.serviceFinderFactory = serviceFinderFactory; if (serviceFinderFactory != null) { - this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class); + this.deviceIdentifierServiceFinder = serviceFinderFactory + .createServiceFinder(DeviceIdentifierMongoHandler.class); this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler()); - this.raceTrackingConnectivityParamsServiceFinder = serviceFinderFactory.createServiceFinder(RaceTrackingConnectivityParametersHandler.class); + this.raceTrackingConnectivityParamsServiceFinder = serviceFinderFactory + .createServiceFinder(RaceTrackingConnectivityParametersHandler.class); } else { this.deviceIdentifierServiceFinder = null; this.raceTrackingConnectivityParamsServiceFinder = null; } this.baseDomainFactory = baseDomainFactory; this.competitorWithBoatDeserializer = CompetitorWithBoatJsonDeserializer.create(baseDomainFactory); + this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } - + @Override public DomainFactory getBaseDomainFactory() { return baseDomainFactory; @@ -307,7 +315,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return null; } } - + public static TimePoint loadTimePoint(DBObject object, String fieldName) { TimePoint result = null; Number timePointAsNumber = (Number) object.get(fieldName); @@ -320,7 +328,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public static TimePoint loadTimePoint(DBObject object, FieldNames field) { return loadTimePoint(object, field.name()); } - + public static TimeRange loadTimeRange(DBObject object, FieldNames field) { DBObject timeRangeObj = (DBObject) object.get(field.name()); if (timeRangeObj == null) { @@ -330,6 +338,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { TimePoint to = loadTimePoint(timeRangeObj, FieldNames.TO_MILLIS); return new TimeRangeImpl(from, to); } + /** * Loads a {@link TimePoint} on the given object at {@link FieldNames#TIME_AS_MILLIS}. */ @@ -372,8 +381,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { "Setting the unique index on the %s collection failed because you have too many duplicates. " + "This leads to the mongo error code %s and the following message: %s \nTo fix this follow " + "the steps provided on the wiki page: http://wiki.sapsailing.com/wiki/howto/misc/cook-book#Remove-" - + "duplicates-from-WIND_TRACK-collection", CollectionNames.WIND_TRACKS.name(), - exception.getCode(), exception.getMessage())); + + "duplicates-from-WIND_TRACK-collection", + CollectionNames.WIND_TRACKS.name(), exception.getCode(), exception.getMessage())); } else { logger.severe(String.format( "Setting the unique index on the %s collection failed with error code %s and message: %s", @@ -383,7 +392,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public Leaderboard loadLeaderboard(String name, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Leaderboard loadLeaderboard(String name, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); Leaderboard result = null; try { @@ -394,7 +404,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } catch (Exception e) { // something went wrong during DB access; report, then use empty new wind track - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard "+name+"."); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard " + name + "."); logger.log(Level.SEVERE, "loadLeaderboard", e); } return result; @@ -405,12 +415,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String leaderboardName, String wrappedRegattaLeaderboardName, LeaderboardRegistry leaderboardRegistry) { final RegattaLeaderboardWithEliminations result; BasicDBList eliminatedCompetitorIds = (BasicDBList) dbLeaderboard.get(FieldNames.ELMINATED_COMPETITORS.name()); - result = new DelegatingRegattaLeaderboardWithCompetitorElimination(()-> - (RegattaLeaderboard) leaderboardRegistry.getLeaderboardByName(wrappedRegattaLeaderboardName), leaderboardName); + result = new DelegatingRegattaLeaderboardWithCompetitorElimination( + () -> (RegattaLeaderboard) leaderboardRegistry.getLeaderboardByName(wrappedRegattaLeaderboardName), + leaderboardName); for (Object eliminatedCompetitorId : eliminatedCompetitorIds) { - Competitor eliminatedCompetitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorById((Serializable) eliminatedCompetitorId); + Competitor eliminatedCompetitor = baseDomainFactory.getCompetitorStore() + .getExistingCompetitorById((Serializable) eliminatedCompetitorId); if (eliminatedCompetitor == null) { - logger.warning("Couldn't find eliminated competitor with ID "+eliminatedCompetitorId); + logger.warning("Couldn't find eliminated competitor with ID " + eliminatedCompetitorId); } else { result.setEliminated(eliminatedCompetitor, true); } @@ -438,25 +450,29 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { * {@link RegattaLeaderboard} cannot be found; the leaderboard loaded or found in * leaderboardRegistry, otherwise */ - private Leaderboard loadLeaderboard(DBObject dbLeaderboard, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry, - LeaderboardGroup groupForMetaLeaderboard) { + private Leaderboard loadLeaderboard(DBObject dbLeaderboard, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry, LeaderboardGroup groupForMetaLeaderboard) { Leaderboard result = null; String leaderboardName = (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()); if (leaderboardRegistry != null) { result = leaderboardRegistry.getLeaderboardByName(leaderboardName); } if (result == null) { - String wrappedRegattaLeaderboardName = (String) dbLeaderboard.get(FieldNames.WRAPPED_REGATTA_LEADERBOARD_NAME.name()); + String wrappedRegattaLeaderboardName = (String) dbLeaderboard + .get(FieldNames.WRAPPED_REGATTA_LEADERBOARD_NAME.name()); if (wrappedRegattaLeaderboardName != null) { - result = loadRegattaLeaderboardWithEliminations(dbLeaderboard, leaderboardName, wrappedRegattaLeaderboardName, leaderboardRegistry); + result = loadRegattaLeaderboardWithEliminations(dbLeaderboard, leaderboardName, + wrappedRegattaLeaderboardName, leaderboardRegistry); } else { if (groupForMetaLeaderboard != null) { result = new LeaderboardGroupMetaLeaderboard(groupForMetaLeaderboard, - loadScoringScheme(dbLeaderboard), loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS)); + loadScoringScheme(dbLeaderboard), + loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS)); groupForMetaLeaderboard.setOverallLeaderboard(result); } else { String regattaName = (String) dbLeaderboard.get(FieldNames.REGATTA_NAME.name()); - ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, + FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); if (regattaName == null) { result = loadFlexibleLeaderboard(dbLeaderboard, resultDiscardingRule); } else { @@ -465,8 +481,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } if (result != null) { - DelayedLeaderboardCorrections loadedLeaderboardCorrections = new DelayedLeaderboardCorrectionsImpl(result, baseDomainFactory); - loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, result.getScoreCorrection()); + DelayedLeaderboardCorrections loadedLeaderboardCorrections = new DelayedLeaderboardCorrectionsImpl( + result, baseDomainFactory); + loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, + result.getScoreCorrection()); loadSuppressedCompetitors(dbLeaderboard, loadedLeaderboardCorrections); loadColumnFactors(dbLeaderboard, result); } @@ -477,7 +495,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // add the leaderboard to the registry if (leaderboardRegistry != null) { leaderboardRegistry.addLeaderboard(result); - logger.info("loaded leaderboard "+result.getName()+" into "+leaderboardRegistry); + logger.info("loaded leaderboard " + result.getName() + " into " + leaderboardRegistry); } } } @@ -494,15 +512,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (raceColumn != null) { raceColumn.setFactor(factor); } else { - logger.warning("Expected to find race column named "+raceColumnName+" in leaderboard "+result.getName()+ - " to apply column factor "+factor+", but the race column wasn't found. Ignoring factor."); + logger.warning("Expected to find race column named " + raceColumnName + " in leaderboard " + + result.getName() + " to apply column factor " + factor + + ", but the race column wasn't found. Ignoring factor."); } } } } - private void loadSuppressedCompetitors(DBObject dbLeaderboard, DelayedLeaderboardCorrections loadedLeaderboardCorrections) { - BasicDBList dbSuppressedCompetitorIDs = (BasicDBList) dbLeaderboard.get(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name()); + private void loadSuppressedCompetitors(DBObject dbLeaderboard, + DelayedLeaderboardCorrections loadedLeaderboardCorrections) { + BasicDBList dbSuppressedCompetitorIDs = (BasicDBList) dbLeaderboard + .get(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name()); if (dbSuppressedCompetitorIDs != null) { for (Object competitorId : dbSuppressedCompetitorIDs) { loadedLeaderboardCorrections.suppressCompetitorByID((Serializable) competitorId); @@ -511,7 +532,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } /** - * @param dbObject expects to find a field identified by field which holds a {@link BasicDBList} + * @param dbObject + * expects to find a field identified by field which holds a {@link BasicDBList} */ private ThresholdBasedResultDiscardingRule loadResultDiscardingRule(DBObject dbObject, FieldNames field) { BasicDBList dbDiscardIndexResultsStartingWithHowManyRaces = (BasicDBList) dbObject.get(field.name()); @@ -533,27 +555,30 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { /** * @return null if the regatta cannot be resolved; otherwise the leaderboard for the regatta specified */ - private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName, DBObject dbLeaderboard, - ThresholdBasedResultDiscardingRule resultDiscardingRule, RegattaRegistry regattaRegistry) { + private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName, + DBObject dbLeaderboard, ThresholdBasedResultDiscardingRule resultDiscardingRule, + RegattaRegistry regattaRegistry) { RegattaLeaderboard result = null; Regatta regatta = regattaRegistry.getRegatta(new RegattaName(regattaName)); if (regatta == null) { - logger.info("Couldn't find regatta "+regattaName+" for corresponding regatta leaderboard. Not loading regatta leaderboard."); + logger.info("Couldn't find regatta " + regattaName + + " for corresponding regatta leaderboard. Not loading regatta leaderboard."); } else { result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule); - result.setName(leaderboardName); // this will temporarily set the display name; it will be adjusted later if a display name is found + result.setName(leaderboardName); // this will temporarily set the display name; it will be adjusted later if + // a display name is found } return result; } - + private RaceLogStore getRaceLogStore() { - return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore( - new MongoObjectFactoryImpl(database, serviceFinderFactory), this); + return MongoRaceLogStoreFactory.INSTANCE + .getMongoRaceLogStore(new MongoObjectFactoryImpl(database, serviceFinderFactory), this); } - + private RegattaLogStore getRegattaLogStore() { - return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore( - new MongoObjectFactoryImpl(database, serviceFinderFactory), this); + return MongoRegattaLogStoreFactory.INSTANCE + .getMongoRegattaLogStore(new MongoObjectFactoryImpl(database, serviceFinderFactory), this); } private FlexibleLeaderboard loadFlexibleLeaderboard(DBObject dbLeaderboard, @@ -563,21 +588,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (dbRaceColumns == null) { // this was probably an orphaned overall leaderboard logger.warning("Probably found orphan overall leaderboard named " - + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name())+". Ignoring."); + + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()) + ". Ignoring."); result = null; } else { final ScoringScheme scoringScheme = loadScoringScheme(dbLeaderboard); - + Serializable courseAreaId = (Serializable) dbLeaderboard.get(FieldNames.COURSE_AREA_ID.name()); CourseArea courseArea = null; if (courseAreaId != null) { UUID courseAreaUuid = UUID.fromString(courseAreaId.toString()); courseArea = baseDomainFactory.getExistingCourseAreaById(courseAreaUuid); } - + result = new FlexibleLeaderboardImpl(getRaceLogStore(), getRegattaLogStore(), - (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()), - resultDiscardingRule, scoringScheme, courseArea); + (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()), resultDiscardingRule, scoringScheme, + courseArea); // For a FlexibleLeaderboard, there should be only the default fleet for any race column for (Object dbRaceColumnAsObject : dbRaceColumns) { BasicDBObject dbRaceColumn = (BasicDBObject) dbRaceColumnAsObject; @@ -618,11 +643,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private void loadLeaderboardCorrections(DBObject dbLeaderboard, DelayedLeaderboardCorrections correctionsToUpdate, SettableScoreCorrection scoreCorrectionToUpdate) { - BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name()); + BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard + .get(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name()); if (carriedPointsById != null) { for (Object o : carriedPointsById) { DBObject competitorIdAndCarriedPoints = (DBObject) o; - Serializable competitorId = (Serializable) competitorIdAndCarriedPoints.get(FieldNames.COMPETITOR_ID.name()); + Serializable competitorId = (Serializable) competitorIdAndCarriedPoints + .get(FieldNames.COMPETITOR_ID.name()); Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints .get(FieldNames.LEADERBOARD_CARRIED_POINTS.name())).doubleValue(); if (carriedPointsForCompetitor != null) { @@ -632,20 +659,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } DBObject dbScoreCorrection = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name()); if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name())) { - scoreCorrectionToUpdate.setTimePointOfLastCorrectionsValidity( - new MillisecondsTimePoint((Long) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()))); + scoreCorrectionToUpdate.setTimePointOfLastCorrectionsValidity(new MillisecondsTimePoint( + (Long) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()))); dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()); } if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())) { - scoreCorrectionToUpdate.setComment((String) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())); + scoreCorrectionToUpdate + .setComment((String) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())); dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name()); } for (String escapedRaceColumnName : dbScoreCorrection.keySet()) { // deprecated style: a DBObject per race where the keys are the escaped competitor names // new style: a BasicDBList per race where each entry is a DBObject with COMPETITOR_ID and - // LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON and LEADERBOARD_CORRECTED_SCORE fields each + // LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON and LEADERBOARD_CORRECTED_SCORE fields each DBObject dbScoreCorrectionForRace = (DBObject) dbScoreCorrection.get(escapedRaceColumnName); - final RaceColumn raceColumn = correctionsToUpdate.getLeaderboard().getRaceColumnByName(MongoUtils.unescapeDollarAndDot(escapedRaceColumnName)); + final RaceColumn raceColumn = correctionsToUpdate.getLeaderboard() + .getRaceColumnByName(MongoUtils.unescapeDollarAndDot(escapedRaceColumnName)); if (raceColumn != null) { for (Object o : (BasicDBList) dbScoreCorrectionForRace) { DBObject dbScoreCorrectionForCompetitorInRace = (DBObject) o; @@ -653,12 +682,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { .get(FieldNames.COMPETITOR_ID.name()); if (dbScoreCorrectionForCompetitorInRace .containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())) { - correctionsToUpdate.setMaxPointsReasonByID(competitorId, raceColumn, MaxPointsReason - .valueOf((String) dbScoreCorrectionForCompetitorInRace + correctionsToUpdate.setMaxPointsReasonByID(competitorId, raceColumn, + MaxPointsReason.valueOf((String) dbScoreCorrectionForCompetitorInRace .get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name()))); } - if (dbScoreCorrectionForCompetitorInRace.containsField(FieldNames.LEADERBOARD_CORRECTED_SCORE - .name())) { + if (dbScoreCorrectionForCompetitorInRace + .containsField(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())) { final Double leaderboardCorrectedScore = ((Number) dbScoreCorrectionForCompetitorInRace .get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())).doubleValue(); correctionsToUpdate.correctScoreByID(competitorId, raceColumn, @@ -670,22 +699,25 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { + " in leaderboard " + correctionsToUpdate.getLeaderboard().getName()); } } - DBObject competitorDisplayNames = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name()); + DBObject competitorDisplayNames = (DBObject) dbLeaderboard + .get(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name()); // deprecated style: a DBObject whose keys are the escaped competitor names // new style: a BasicDBList whose entries are DBObjects with COMPETITOR_ID and COMPETITOR_DISPLAY_NAME fields if (competitorDisplayNames != null) { if (competitorDisplayNames instanceof BasicDBList) { for (Object o : (BasicDBList) competitorDisplayNames) { DBObject competitorDisplayName = (DBObject) o; - final Serializable competitorId = (Serializable) competitorDisplayName.get(FieldNames.COMPETITOR_ID.name()); - final String displayName = (String) competitorDisplayName.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); + final Serializable competitorId = (Serializable) competitorDisplayName + .get(FieldNames.COMPETITOR_ID.name()); + final String displayName = (String) competitorDisplayName + .get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); correctionsToUpdate.setDisplayNameByID(competitorId, displayName); } } else { - logger.severe("Deprecated, now unreadable format of the "+FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name() - +" field for leaderboard "+dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name())+ - ". You will have to update the competitor display names manually: "+ - competitorDisplayNames); + logger.severe("Deprecated, now unreadable format of the " + + FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name() + " field for leaderboard " + + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()) + + ". You will have to update the competitor display names manually: " + competitorDisplayNames); } } } @@ -719,15 +751,17 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public LeaderboardGroup loadLeaderboardGroup(String name, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public LeaderboardGroup loadLeaderboardGroup(String name, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); LeaderboardGroup leaderboardGroup = null; try { BasicDBObject query = new BasicDBObject(); query.put(FieldNames.LEADERBOARD_GROUP_NAME.name(), name); - leaderboardGroup = loadLeaderboardGroup(leaderboardGroupCollection.findOne(query), regattaRegistry, leaderboardRegistry); + leaderboardGroup = loadLeaderboardGroup(leaderboardGroupCollection.findOne(query), regattaRegistry, + leaderboardRegistry); } catch (Exception e) { - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard group "+name+"."); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard group " + name + "."); logger.log(Level.SEVERE, "loadLeaderboardGroup", e); } @@ -735,7 +769,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public Iterable getAllLeaderboardGroups(RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Iterable getAllLeaderboardGroups(RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); Set leaderboardGroups = new HashSet(); try { @@ -744,8 +779,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final LeaderboardGroup leaderboardGroup = loadLeaderboardGroup(o, regattaRegistry, leaderboardRegistry); leaderboardGroups.add(leaderboardGroup); if (!hasUUID) { - // in an effort to migrate leaderboard groups without ID to such that have a UUID as their ID, we need - // to write a leaderboard group to the database again after it just received a UUID for the first time: + // in an effort to migrate leaderboard groups without ID to such that have a UUID as their ID, we + // need + // to write a leaderboard group to the database again after it just received a UUID for the first + // time: logger.info("Existing LeaderboardGroup " + leaderboardGroup.getName() + " received a UUID during migration; updating the leaderboard group in the database"); new MongoObjectFactoryImpl(database).storeLeaderboardGroup(leaderboardGroup); @@ -759,21 +796,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return leaderboardGroups; } - private LeaderboardGroup loadLeaderboardGroup(DBObject o, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + private LeaderboardGroup loadLeaderboardGroup(DBObject o, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); String name = (String) o.get(FieldNames.LEADERBOARD_GROUP_NAME.name()); UUID uuid = (UUID) o.get(FieldNames.LEADERBOARD_GROUP_UUID.name()); if (uuid == null) { uuid = UUID.randomUUID(); - logger.info("Leaderboard group "+name+" receives UUID "+uuid+" in a migration effort"); + logger.info("Leaderboard group " + name + " receives UUID " + uuid + " in a migration effort"); // migration: leaderboard groups that don't yet have a UUID receive a random one } String description = (String) o.get(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name()); String displayName = (String) o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name()); - boolean displayGroupsInReverseOrder = false; // default value + boolean displayGroupsInReverseOrder = false; // default value Object displayGroupsInReverseOrderObj = o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name()); if (displayGroupsInReverseOrderObj != null) { - displayGroupsInReverseOrder = (Boolean) displayGroupsInReverseOrderObj; + displayGroupsInReverseOrder = (Boolean) displayGroupsInReverseOrderObj; } ArrayList leaderboards = new ArrayList(); BasicDBList dbLeaderboardIds = (BasicDBList) o.get(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name()); @@ -787,11 +825,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { leaderboards.add(loadedLeaderboard); } } else { - logger.warning("couldn't find leaderboard with ID "+dbLeaderboardId+" referenced by leaderboard group "+name); + logger.warning("couldn't find leaderboard with ID " + dbLeaderboardId + + " referenced by leaderboard group " + name); } } - logger.info("loaded leaderboard group "+name); - LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayName, displayGroupsInReverseOrder, leaderboards); + logger.info("loaded leaderboard group " + name); + LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayName, + displayGroupsInReverseOrder, leaderboards); Object overallLeaderboardIdOrName = o.get(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name()); if (overallLeaderboardIdOrName != null) { final DBObject dbOverallLeaderboard; @@ -803,40 +843,50 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (dbOverallLeaderboard != null) { // the loadLeaderboard call adds the overall leaderboard to the leaderboard registry and sets it as the // overall leaderboard of the leaderboard group - loadLeaderboard(dbOverallLeaderboard, regattaRegistry, leaderboardRegistry, /* groupForMetaLeaderboard */ result); + loadLeaderboard(dbOverallLeaderboard, regattaRegistry, leaderboardRegistry, + /* groupForMetaLeaderboard */ result); } } return result; } @Override - public Iterable getLeaderboardsNotInGroup(RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Iterable getLeaderboardsNotInGroup(RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); Set result = new HashSet(); try { // For MongoDB 2.4 $where with refs to global objects no longer works // http://docs.mongodb.org/manual/reference/operator/where/#op._S_where // Also a single where leads to a table walk without using indexes. So avoid $where. - + // Don't change the query object, unless you know what you're doing. // It queries all leaderboards not referenced to be part of a leaderboard group // and in particular not being an overall leaderboard of a leaderboard group. DBCursor allLeaderboards = leaderboardCollection.find(); for (DBObject leaderboardFromDB : allLeaderboards) { DBObject inLeaderboardGroupsQuery = new BasicDBObject(); - inLeaderboardGroupsQuery.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), ((ObjectId)leaderboardFromDB.get("_id")).toString()); - boolean inLeaderboardGroups = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupsQuery).size()>0; + inLeaderboardGroupsQuery.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), + ((ObjectId) leaderboardFromDB.get("_id")).toString()); + boolean inLeaderboardGroups = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupsQuery).size() > 0; DBObject inLeaderboardGroupOverallQuery = new BasicDBObject(); - inLeaderboardGroupOverallQuery.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), ((ObjectId)leaderboardFromDB.get("_id")).toString()); - boolean inLeaderboardGroupOverall = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupOverallQuery).size()>0; - + inLeaderboardGroupOverallQuery.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), + ((ObjectId) leaderboardFromDB.get("_id")).toString()); + boolean inLeaderboardGroupOverall = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupOverallQuery).size() > 0; + DBObject inLeaderboardGroupOverallQueryName = new BasicDBObject(); - inLeaderboardGroupOverallQueryName.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), leaderboardFromDB.get(FieldNames.LEADERBOARD_NAME.name())); - boolean inLeaderboardGroupOverallName = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupOverallQueryName).size()>0; - + inLeaderboardGroupOverallQueryName.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), + leaderboardFromDB.get(FieldNames.LEADERBOARD_NAME.name())); + boolean inLeaderboardGroupOverallName = database + .getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupOverallQueryName).size() > 0; + if (!inLeaderboardGroups && !inLeaderboardGroupOverall && !inLeaderboardGroupOverallName) { - final Leaderboard loadedLeaderboard = loadLeaderboard(leaderboardFromDB, regattaRegistry, leaderboardRegistry, /* groupForMetaLeaderboard */ null); + final Leaderboard loadedLeaderboard = loadLeaderboard(leaderboardFromDB, regattaRegistry, + leaderboardRegistry, /* groupForMetaLeaderboard */ null); if (loadedLeaderboard != null) { result.add(loadedLeaderboard); } @@ -850,16 +900,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public WindTrack loadWindTrack(String regattaName, RaceDefinition race, WindSource windSource, long millisecondsOverWhichToAverage) { + public WindTrack loadWindTrack(String regattaName, RaceDefinition race, WindSource windSource, + long millisecondsOverWhichToAverage) { final WindTrack result; - Map resultMap = loadWindTracks(regattaName, race, windSource, millisecondsOverWhichToAverage); + Map resultMap = loadWindTracks(regattaName, race, windSource, + millisecondsOverWhichToAverage); if (resultMap.containsKey(windSource)) { result = resultMap.get(windSource); } else { // create an empty wind track as result if no fixes were found in store for the wind source requested result = new WindTrackImpl(millisecondsOverWhichToAverage, windSource.getType().getBaseConfidence(), - windSource.getType().useSpeed(), - /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName()+" for source "+windSource.toString()); + windSource.getType().useSpeed(), /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName() + + " for source " + windSource.toString()); } return result; } @@ -867,7 +919,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { @Override public Map loadWindTracks(String regattaName, RaceDefinition race, long millisecondsOverWhichToAverageWind) { - Map result = loadWindTracks(regattaName, race, /* constrain wind source */ null, millisecondsOverWhichToAverageWind); + Map result = loadWindTracks(regattaName, race, /* constrain wind source */ null, + millisecondsOverWhichToAverageWind); return result; } @@ -891,7 +944,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { for (DBObject dbWind : windTracks.find(queryById)) { loadWindFix(result, dbWind, millisecondsOverWhichToAverageWind); } - // Additionally check for legacy wind fixes stored with the old EVENT_NAME key; if any are found, migrate them + // Additionally check for legacy wind fixes stored with the old EVENT_NAME key; if any are found, migrate + // them BasicDBObject queryByName = new BasicDBObject(); queryByName.put(FieldNames.EVENT_NAME.name(), regattaName); queryByName.put(FieldNames.RACE_NAME.name(), race.getName()); @@ -907,35 +961,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { windFixesToMigrate.add(new MongoObjectFactoryImpl(database).storeWindTrackEntry(race, regattaName, wind.getB(), wind.getA())); } - logger.info("Migrating "+windFixesFoundByName.size()+" wind fixes of regatta "+regattaName+ - " and race "+race.getName()+" to ID-based keys"); + logger.info("Migrating " + windFixesFoundByName.size() + " wind fixes of regatta " + regattaName + + " and race " + race.getName() + " to ID-based keys"); windTracks.insert(windFixesToMigrate.toArray(new DBObject[windFixesToMigrate.size()])); - logger.info("Removing "+windFixesFoundByName.size()+" wind fixes that were keyed by the names of regatta "+regattaName+ - " and race "+race.getName()); + logger.info("Removing " + windFixesFoundByName.size() + + " wind fixes that were keyed by the names of regatta " + regattaName + " and race " + + race.getName()); windTracks.remove(queryByName); } } catch (Exception e) { // something went wrong during DB access; report, then use empty new wind track - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded wind data. Check MongoDB settings."); + logger.log(Level.SEVERE, + "Error connecting to MongoDB, unable to load recorded wind data. Check MongoDB settings."); logger.log(Level.SEVERE, "loadWindTrack", e); } return result; } - private Util.Pair loadWindFix(Map result, DBObject dbWind, long millisecondsOverWhichToAverageWind) { + private Util.Pair loadWindFix(Map result, DBObject dbWind, + long millisecondsOverWhichToAverageWind) { Wind wind = loadWind((DBObject) dbWind.get(FieldNames.WIND.name())); WindSourceType windSourceType = WindSourceType.valueOf((String) dbWind.get(FieldNames.WIND_SOURCE_NAME.name())); WindSource windSource; if (dbWind.containsField(FieldNames.WIND_SOURCE_ID.name())) { - windSource = new WindSourceWithAdditionalID(windSourceType, (String) dbWind.get(FieldNames.WIND_SOURCE_ID.name())); + windSource = new WindSourceWithAdditionalID(windSourceType, + (String) dbWind.get(FieldNames.WIND_SOURCE_ID.name())); } else { windSource = new WindSourceImpl(windSourceType); } WindTrack track = result.get(windSource); if (track == null) { track = new WindTrackImpl(millisecondsOverWhichToAverageWind, windSource.getType().getBaseConfidence(), - windSource.getType().useSpeed(), - /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName()+" for source "+windSource.toString()); + windSource.getType().useSpeed(), /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName() + + " for source " + windSource.toString()); result.put(windSource, track); } track.add(wind); @@ -951,12 +1009,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { UUID eventId = (UUID) dbLink.get(FieldNames.EVENT_ID.name()); Event event = eventResolver.getEvent(eventId); if (event == null) { - logger.info("Found leaderboard group IDs for event with ID "+eventId+" but couldn't find that event."); + logger.info( + "Found leaderboard group IDs for event with ID " + eventId + " but couldn't find that event."); } else { @SuppressWarnings("unchecked") List leaderboardGroupIDs = (List) dbLink.get(FieldNames.LEADERBOARD_GROUP_UUID.name()); for (UUID leaderboardGroupID : leaderboardGroupIDs) { - LeaderboardGroup leaderboardGroup = leaderboardGroupResolver.getLeaderboardGroupByID(leaderboardGroupID); + LeaderboardGroup leaderboardGroup = leaderboardGroupResolver + .getLeaderboardGroupByID(leaderboardGroupID); if (leaderboardGroup != null) { event.addLeaderboardGroup(leaderboardGroup); } @@ -1018,7 +1078,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { boolean isStandaloneServer = (Boolean) serverDBObject.get(FieldNames.SERVER_IS_STANDALONE.name()); return new SailingServerConfigurationImpl(isStandaloneServer); } - + private RemoteSailingServerReference loadRemoteSailingSever(DBObject serverDBObject) { RemoteSailingServerReference result = null; String name = (String) serverDBObject.get(FieldNames.SERVER_NAME.name()); @@ -1050,8 +1110,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } /** - * An event doesn't store its regattas; it's the regatta that stores a reference to its event; the regatta - * needs to add itself to the event when loaded or instantiated. + * An event doesn't store its regattas; it's the regatta that stores a reference to its event; the regatta needs to + * add itself to the event when loaded or instantiated. */ private Event loadEvent(DBObject eventDBObject) { String name = (String) eventDBObject.get(FieldNames.EVENT_NAME.name()); @@ -1059,7 +1119,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { UUID id = (UUID) eventDBObject.get(FieldNames.EVENT_ID.name()); TimePoint startDate = loadTimePoint(eventDBObject, FieldNames.EVENT_START_DATE); TimePoint endDate = loadTimePoint(eventDBObject, FieldNames.EVENT_END_DATE); - boolean isPublic = eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) != null ? (Boolean) eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) : false; + boolean isPublic = eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) != null + ? (Boolean) eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) : false; Venue venue = loadVenue((DBObject) eventDBObject.get(FieldNames.VENUE.name())); Event result = new EventImpl(name, startDate, endDate, venue, isPublic, id); result.setDescription(description); @@ -1068,7 +1129,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { result.setOfficialWebsiteURL(new URL(officialWebSiteURLAsString)); } catch (MalformedURLException e) { - logger.severe("Error parsing official website URL "+officialWebSiteURLAsString+" for event "+name+". Ignoring this URL."); + logger.severe("Error parsing official website URL " + officialWebSiteURLAsString + " for event " + name + + ". Ignoring this URL."); } } String baseURLAsString = (String) eventDBObject.get(FieldNames.EVENT_BASE_URL.name()); @@ -1076,7 +1138,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { result.setBaseURL(new URL(baseURLAsString)); } catch (MalformedURLException e) { - logger.severe("Error parsing base URL "+baseURLAsString+" for event "+name+". Ignoring this URL."); + logger.severe( + "Error parsing base URL " + baseURLAsString + " for event " + name + ". Ignoring this URL."); } } BasicDBList images = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGES.name()); @@ -1097,14 +1160,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } } - BasicDBList sailorsInfoWebsiteURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name()); + BasicDBList sailorsInfoWebsiteURLs = (BasicDBList) eventDBObject + .get(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name()); if (sailorsInfoWebsiteURLs != null) { for (Object sailorsInfoWebsiteObject : sailorsInfoWebsiteURLs) { DBObject sailorsInfoWebsiteDBObject = (DBObject) sailorsInfoWebsiteObject; URL url = loadURL(sailorsInfoWebsiteDBObject, FieldNames.SAILORS_INFO_URL); String localeRaw = (String) sailorsInfoWebsiteDBObject.get(FieldNames.SAILORS_INFO_LOCALE.name()); if (url != null) { - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; result.setSailorsInfoWebsiteURL(locale, url); } } @@ -1162,7 +1226,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } BoatClass boatClass = null; if (boatClassName != null) { - boolean typicallyStartsUpwind = (Boolean) dbRegatta.get(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name()); + boolean typicallyStartsUpwind = (Boolean) dbRegatta + .get(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name()); boatClass = baseDomainFactory.getOrCreateBoatClass(boatClassName, typicallyStartsUpwind); } BasicDBList dbSeries = (BasicDBList) dbRegatta.get(FieldNames.REGATTA_SERIES.name()); @@ -1176,30 +1241,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { RegattaConfiguration configuration = null; if (dbRegatta.containsField(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())) { try { - JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(dbRegatta.get(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())))); + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser() + .parse(JSON.serialize(dbRegatta.get(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())))); configuration = RegattaConfigurationJsonDeserializer.create().deserialize(json); - } catch (JsonDeserializationException|ParseException e) { + } catch (JsonDeserializationException | ParseException e) { logger.log(Level.WARNING, "Error loading racing procedure configration for regatta.", e); } } - final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta.get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name()); - final Boolean useStartTimeInference = (Boolean) dbRegatta.get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name()); - final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta.get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name()); - Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); + final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta + .get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name()); + final Boolean useStartTimeInference = (Boolean) dbRegatta + .get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name()); + final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta + .get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name()); + Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta + .get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); // for backward compatibility - if(canBoatsOfCompetitorsChangePerRace == null) { + if (canBoatsOfCompetitorsChangePerRace == null) { canBoatsOfCompetitorsChangePerRace = false; } final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta); - result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true, - loadScoringScheme(dbRegatta), id, courseArea, buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS : buoyZoneRadiusInHullLengths, useStartTimeInference == null ? true - : useStartTimeInference, controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes, - rankingMetricConstructor); + result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, + canBoatsOfCompetitorsChangePerRace, startDate, endDate, series, /* persistent */true, + loadScoringScheme(dbRegatta), id, courseArea, + buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS + : buoyZoneRadiusInHullLengths, + useStartTimeInference == null ? true : useStartTimeInference, + controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes, + rankingMetricConstructor); result.setRegattaConfiguration(configuration); } return result; } - + private RankingMetricConstructor loadRankingMetricConstructor(DBObject dbRegatta) { DBObject rankingMetricJson = (DBObject) dbRegatta.get(FieldNames.REGATTA_RANKING_METRIC.name()); // default is OneDesignRankingMetric @@ -1207,7 +1281,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (rankingMetricJson == null) { result = OneDesignRankingMetric::new; } else { - final String rankingMetricTypeName = (String) rankingMetricJson.get(FieldNames.REGATTA_RANKING_METRIC_TYPE.name()); + final String rankingMetricTypeName = (String) rankingMetricJson + .get(FieldNames.REGATTA_RANKING_METRIC_TYPE.name()); result = RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.valueOf(rankingMetricTypeName)); } return result; @@ -1225,7 +1300,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // can happen that the database contains a scoring scheme that // has not yet been implemented - fall back with a warning scoringSchemeType = ScoringSchemeType.LOW_POINT; - logger.warning("Could not find scoring scheme " + scoringSchemeTypeName + "! Most probably this has not yet been implemented or even been removed."); + logger.warning("Could not find scoring scheme " + scoringSchemeTypeName + + "! Most probably this has not yet been implemented or even been removed."); } } return scoringSchemeType; @@ -1250,17 +1326,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (isFleetCanRunInParallelObject != null) { isFleetsCanRunInParallel = (Boolean) dbSeries.get(FieldNames.SERIES_IS_FLEETS_CAN_RUN_IN_PARALLEL.name()); } - final Integer maximumNumberOfDiscards = (Integer) dbSeries.get(FieldNames.SERIES_MAXIMUM_NUMBER_OF_DISCARDS.name()); + final Integer maximumNumberOfDiscards = (Integer) dbSeries + .get(FieldNames.SERIES_MAXIMUM_NUMBER_OF_DISCARDS.name()); Boolean startsWithZeroScore = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name()); - Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries.get(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name()); - Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name()); + Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries + .get(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name()); + Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries + .get(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name()); final BasicDBList dbFleets = (BasicDBList) dbSeries.get(FieldNames.SERIES_FLEETS.name()); List fleets = loadFleets(dbFleets); BasicDBList dbRaceColumns = (BasicDBList) dbSeries.get(FieldNames.SERIES_RACE_COLUMNS.name()); Iterable raceColumnNames = loadRaceColumnNames(dbRaceColumns); - Series series = new SeriesImpl(name, isMedal, isFleetsCanRunInParallel, fleets, raceColumnNames, trackedRegattaRegistry); + Series series = new SeriesImpl(name, isMedal, isFleetsCanRunInParallel, fleets, raceColumnNames, + trackedRegattaRegistry); if (dbSeries.get(FieldNames.SERIES_DISCARDING_THRESHOLDS.name()) != null) { - ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbSeries, FieldNames.SERIES_DISCARDING_THRESHOLDS); + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbSeries, + FieldNames.SERIES_DISCARDING_THRESHOLDS); series.setResultDiscardingRule(resultDiscardingRule); } if (startsWithZeroScore != null) { @@ -1323,7 +1404,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Color color = null; if (colorAsInt != null) { int r = colorAsInt % 256; - int g = (colorAsInt / 256 ) % 256; + int g = (colorAsInt / 256) % 256; int b = (colorAsInt / 256 / 256) % 256; color = new RGBColor(r, g, b); } @@ -1356,7 +1437,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { loadRaceLogEvents(result, query); } catch (Throwable t) { // something went wrong during DB access; report, then use empty new race log - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded race log data. Check MongoDB settings."); + logger.log(Level.SEVERE, + "Error connecting to MongoDB, unable to load recorded race log data. Check MongoDB settings."); logger.log(Level.SEVERE, "loadRaceLog", t); } return result; @@ -1373,12 +1455,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { result.add(raceLogEvent); } } catch (IllegalStateException e) { - logger.log(Level.SEVERE, "Couldn't load race log event "+o+": "+e.getMessage(), e); + logger.log(Level.SEVERE, "Couldn't load race log event " + o + ": " + e.getMessage(), e); } } return result; } - + public RaceLogEvent loadRaceLogEvent(DBObject dbObject) { TimePoint logicalTimePoint = loadTimePoint(dbObject); TimePoint createdAt = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_CREATED_AT); @@ -1399,11 +1481,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (eventClass.equals(RaceLogStartTimeEvent.class.getSimpleName())) { return loadRaceLogStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogStartOfTrackingEvent.class.getSimpleName())) { - return loadRaceLogStartOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogEndOfTrackingEvent.class.getSimpleName())) { - return loadRaceLogEndOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogEndOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogDependentStartTimeEvent.class.getSimpleName())) { - return loadRaceLogDependentStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogDependentStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRaceStatusEvent.class.getSimpleName())) { return loadRaceLogRaceStatusEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogFlagEvent.class.getSimpleName())) { @@ -1411,119 +1496,152 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } else if (eventClass.equals(RaceLogPassChangeEvent.class.getSimpleName())) { return loadRaceLogPassChangeEvent(createdAt, author, logicalTimePoint, id, passId, competitors); } else if (eventClass.equals(RaceLogCourseAreaChangedEvent.class.getSimpleName())) { - return loadRaceLogCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogCourseDesignChangedEvent.class.getSimpleName())) { - return loadRaceLogCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogFinishPositioningListChangedEvent.class.getSimpleName())) { - return loadRaceLogFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogFinishPositioningConfirmedEvent.class.getSimpleName())) { - return loadRaceLogFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogPathfinderEvent.class.getSimpleName())) { return loadRaceLogPathfinderEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogGateLineOpeningTimeEvent.class.getSimpleName())) { - return loadRaceLogGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogStartProcedureChangedEvent.class.getSimpleName())) { - return loadRaceLogStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogProtestStartTimeEvent.class.getSimpleName())) { - return loadRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) { return loadRaceLogWindFixEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogDenoteForTrackingEvent.class.getSimpleName())) { - return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogStartTrackingEvent.class.getSimpleName())) { - return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRevokeEvent.class.getSimpleName())) { return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { - return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { - return loadRaceLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogAdditionalScoringInformationEvent.class.getSimpleName())) { - return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())){ - return loadRaceLogFixedMarkPassingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogSuppressedMarkPassingsEvent.class.getSimpleName())){ - return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())){ - return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName())){ - return loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); + } else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())) { + return loadRaceLogFixedMarkPassingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); + } else if (eventClass.equals(RaceLogSuppressedMarkPassingsEvent.class.getSimpleName())) { + return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); + } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())) { + return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); + } else if (eventClass.equals(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName())) { + return loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); } private RaceLogEvent loadRaceLogUseCompetitorsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogUseCompetitorsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } - private RaceLogEvent loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { return new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } - private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name())); Boolean isMagnetic = (Boolean) dbObject.get(FieldNames.IS_MAGNETIC.name()); - return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, isMagnetic == null ? true : isMagnetic); + return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, + isMagnetic == null ? true : isMagnetic); } - private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name()); - BoatClass boatClass = baseDomainFactory.getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name())); + BoatClass boatClass = baseDomainFactory + .getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name())); Serializable raceId = (Serializable) dbObject.get(FieldNames.RACE_ID.name()); - return new RaceLogDenoteForTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId, raceName, boatClass, raceId); + return new RaceLogDenoteForTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId, raceName, + boatClass, raceId); } - private RaceLogEvent loadRaceLogStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogStartTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Serializable revokedEventId = Helpers.tryUuidConversion( - (Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name())); + private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Serializable revokedEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name())); String revokedEventType = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_REASON.name()); - return new RaceLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, passId, - revokedEventId, revokedEventType, revokedEventShortInfo, reason); + return new RaceLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, passId, revokedEventId, + revokedEventType, revokedEventShortInfo, reason); } - private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); - Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); + private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); + CompetitorWithBoat comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); return new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, comp); } - private RaceLogEvent loadRaceLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); Serializable boatId = (Serializable) dbObject.get(FieldNames.RACE_LOG_BOAT_ID.name()); Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); - return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, comp, boat); + return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, comp, + boat); } - private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Object additionalScoringInformationTypeInfo = dbObject.get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); + private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { + Object additionalScoringInformationTypeInfo = dbObject + .get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); AdditionalScoringInformationType informationType = AdditionalScoringInformationType.UNKNOWN; if (additionalScoringInformationTypeInfo != null) { informationType = AdditionalScoringInformationType.valueOf(additionalScoringInformationTypeInfo.toString()); } else { - logger.warning("Could not find additional scoring information attached to db log for " + dbObject.toString()); + logger.warning( + "Could not find additional scoring information attached to db log for " + dbObject.toString()); } - return new RaceLogAdditionalScoringInformationEventImpl(createdAt, logicalTimePoint, author, id, passId, informationType); + return new RaceLogAdditionalScoringInformationEventImpl(createdAt, logicalTimePoint, author, id, passId, + informationType); } private RaceLogEvent loadRaceLogProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME); TimePoint protestEndTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_END_TIME); if (protestEndTime == null) { @@ -1535,78 +1653,101 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - RacingProcedureType type = RacingProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + RacingProcedureType type = RacingProcedureType + .valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); return new RaceLogStartProcedureChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, type); } - private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Number gateLaunchStopTime = (Number) dbObject.get(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name()); Number golfDownTime = 0; if (dbObject.containsField(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name())) { golfDownTime = (Number) dbObject.get(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name()); } - return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, author, id, - passId, gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue()); + return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, + gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue()); } - - private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + + private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { String pathfinderId = dbObject.get(FieldNames.RACE_LOG_PATHFINDER_ID.name()).toString(); return new RaceLogPathfinderEventImpl(createdAt, logicalTimePoint, author, id, passId, pathfinderId); } - + private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject + .get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); CompetitorResults positionedCompetitors = null; - //When a confirmation event is loaded that does not contain the positioned competitors (this is the case for the ESS events in - //Singapore and Quingdao) then null should be set for the positionedCompetitors, which is evaluated later on. + // When a confirmation event is loaded that does not contain the positioned competitors (this is the case for + // the ESS events in + // Singapore and Quingdao) then null should be set for the positionedCompetitors, which is evaluated later on. if (dbPositionedCompetitorList != null) { positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); } - - return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); + + return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, author, id, passId, + positionedCompetitors); } - private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); + private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { + BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject + .get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); CompetitorResults positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); - - return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); + + return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, + positionedCompetitors); } - private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors) { + private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors) { return new RaceLogPassChangeEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { String courseName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name()); - CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), courseName); + CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), + courseName); final String courseDesignerModeName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGNER_MODE.name()); - final CourseDesignerMode courseDesignerMode = courseDesignerModeName == null ? null : CourseDesignerMode.valueOf(courseDesignerModeName); - return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, courseData, courseDesignerMode); + final CourseDesignerMode courseDesignerMode = courseDesignerModeName == null ? null + : CourseDesignerMode.valueOf(courseDesignerModeName); + return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, courseData, + courseDesignerMode); } - private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { Serializable courseAreaId = (Serializable) dbObject.get(FieldNames.COURSE_AREA_ID.name()); return new RaceLogCourseAreaChangeEventImpl(createdAt, logicalTimePoint, author, id, passId, courseAreaId); } - - private RaceLogEvent loadRaceLogFixedMarkPassingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + + private RaceLogEvent loadRaceLogFixedMarkPassingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint ofFixedPassing = loadTimePoint(dbObject, FieldNames.TIMEPOINT_OF_FIXED_MARKPASSING); Integer zeroBasedIndexOfWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_PASSED_WAYPOINT.name()); - return new RaceLogFixedMarkPassingEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, ofFixedPassing, zeroBasedIndexOfWaypoint); + return new RaceLogFixedMarkPassingEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, + ofFixedPassing, zeroBasedIndexOfWaypoint); } - private RaceLogEvent loadRaceLogSuppressedMarkPassingsEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Integer zeroBasedIndexOfFirstSuppressedWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name()); - return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, zeroBasedIndexOfFirstSuppressedWaypoint); + private RaceLogEvent loadRaceLogSuppressedMarkPassingsEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Integer zeroBasedIndexOfFirstSuppressedWaypoint = (Integer) dbObject + .get(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name()); + return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, + zeroBasedIndexOfFirstSuppressedWaypoint); } private CompetitorResults loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) { @@ -1616,22 +1757,29 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbObject = (DBObject) object; final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()); String competitorDisplayName = (String) dbObject.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); - //The Competitor name is a new field in the list. Therefore the name might be null for existing events. In this case a standard name is set. + // The Competitor name is a new field in the list. Therefore the name might be null for existing events. In + // this case a standard name is set. if (competitorDisplayName == null) { competitorDisplayName = "loaded competitor"; } - //At this point we do not retrieve the competitor object since at any point in time, especially after a server restart, the DomainFactory and its competitor - //cache might be empty. But at this time the race log is loaded from database, so the competitor would be null. - //By not using the Competitor object retrieved from the DomainFactory we get completely independent from server restarts and the timepoint of loading - //competitors by tracking providers. + // At this point we do not retrieve the competitor object since at any point in time, especially after a + // server restart, the DomainFactory and its competitor + // cache might be empty. But at this time the race log is loaded from database, so the competitor would be + // null. + // By not using the Competitor object retrieved from the DomainFactory we get completely independent from + // server restarts and the timepoint of loading + // competitors by tracking providers. final Integer rank = (Integer) dbObject.get(FieldNames.LEADERBOARD_RANK.name()); - final MaxPointsReason maxPointsReason = MaxPointsReason.valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())); + final MaxPointsReason maxPointsReason = MaxPointsReason + .valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())); final Double score = (Double) dbObject.get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name()); - final Long finishingTimePointAsMillis = (Long) dbObject.get(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name()); - final TimePoint finishingTime = finishingTimePointAsMillis == null ? null : new MillisecondsTimePoint(finishingTimePointAsMillis); + final Long finishingTimePointAsMillis = (Long) dbObject + .get(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name()); + final TimePoint finishingTime = finishingTimePointAsMillis == null ? null + : new MillisecondsTimePoint(finishingTimePointAsMillis); final String comment = (String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name()); - CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl( - competitorId, competitorDisplayName, rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment); + CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl(competitorId, competitorDisplayName, + rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment); positionedCompetitors.add(positionedCompetitor); rankCounter++; } @@ -1648,7 +1796,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return competitors; } - private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Flags upperFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_UPPER.name())); Flags lowerFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_LOWER.name())); Boolean displayed = Boolean.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name())); @@ -1657,41 +1807,56 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return null; } - return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, author, id, passId, upperFlag, lowerFlag, displayed); + return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, author, id, passId, upperFlag, lowerFlag, + displayed); } - private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint startTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_START_TIME); - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); return new RaceLogStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, startTime, nextStatus); } - private RaceLogStartOfTrackingEvent loadRaceLogStartOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogStartOfTrackingEvent loadRaceLogStartOfTrackingEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { return new RaceLogStartOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogEndOfTrackingEvent loadRaceLogEndOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEndOfTrackingEvent loadRaceLogEndOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogEndOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogDependentStartTimeEvent loadRaceLogDependentStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogDependentStartTimeEvent loadRaceLogDependentStartTimeEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { final Object regattaLikeNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_REGATTALIKE.name()); final String regattaLikeName = regattaLikeNameObject == null ? null : regattaLikeNameObject.toString(); final Object raceColumnNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_RACECOLUMN.name()); final String raceColumnName = raceColumnNameObject == null ? null : raceColumnNameObject.toString(); final Object fleetNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_FLEET.name()); final String fleetName = fleetNameObject == null ? null : fleetNameObject.toString(); - final SimpleRaceLogIdentifier dependentRaceLog = new SimpleRaceLogIdentifierImpl(regattaLikeName, raceColumnName, fleetName); + final SimpleRaceLogIdentifier dependentRaceLog = new SimpleRaceLogIdentifierImpl(regattaLikeName, + raceColumnName, fleetName); final Object startTimeDifferenceObject = dbObject.get(FieldNames.RACE_LOG_START_TIME_DIFFERENCE_IN_MS.name()); - final Duration startTimeDifference = startTimeDifferenceObject == null ? null : - new MillisecondsDurationImpl(((Number) startTimeDifferenceObject).longValue()); - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); - return new RaceLogDependentStartTimeEventImpl(createdAt, logicalTimePoint, author, id, - passId, dependentRaceLog, startTimeDifference, nextStatus); + final Duration startTimeDifference = startTimeDifferenceObject == null ? null + : new MillisecondsDurationImpl(((Number) startTimeDifferenceObject).longValue()); + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + return new RaceLogDependentStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, dependentRaceLog, + startTimeDifference, nextStatus); } - private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); return new RaceLogRaceStatusEventImpl(createdAt, logicalTimePoint, author, id, passId, nextStatus); } @@ -1705,12 +1870,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { loadRegattaLogEvents(result, query, identifier); } catch (Throwable t) { // something went wrong during DB access; report, then use empty new regatta log - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded regatta log data for "+identifier+". Check MongoDB settings.", t); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded regatta log data for " + + identifier + ". Check MongoDB settings.", t); } return result; } - private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query, RegattaLikeIdentifier regattaLogIdentifier) { + private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query, + RegattaLikeIdentifier regattaLogIdentifier) { DBCollection collection = database.getCollection(CollectionNames.REGATTA_LOGS.name()); for (DBObject o : collection.find(query)) { try { @@ -1719,7 +1886,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { targetRegattaLog.load(event); } } catch (IllegalStateException e) { - logger.log(Level.SEVERE, "Couldn't load regatta log event "+o+": "+e.getMessage(), e); + logger.log(Level.SEVERE, "Couldn't load regatta log event " + o + ": " + e.getMessage(), e); } } } @@ -1733,27 +1900,33 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String authorName = (String) dbObject.get(FieldNames.REGATTA_LOG_EVENT_AUTHOR_NAME.name()); Number authorPriority = (Number) dbObject.get(FieldNames.REGATTA_LOG_EVENT_AUTHOR_PRIORITY.name()); author = new LogEventAuthorImpl(authorName, authorPriority.intValue()); - //CloseOpenEnded, DeviceCompMapping, DeviceMarkMapping, RegisterComp, Revoke + // CloseOpenEnded, DeviceCompMapping, DeviceMarkMapping, RegisterComp, Revoke String eventClass = (String) dbObject.get(FieldNames.REGATTA_LOG_EVENT_CLASS.name()); if (eventClass.equals(RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName())) { - return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); + return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, + regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogDeviceCompetitorBravoMappingEventImpl.class.getSimpleName())) { return loadRegattaLogDeviceCompetitorBravoMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogDeviceMarkMappingEvent.class.getSimpleName())) { - return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); + return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, + regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName())) { return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterBoatEvent.class.getSimpleName())) { return loadRegattaLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass.equals(RegattaLogRegisterEntryEvent.class.getSimpleName())) { + return loadRegattaLogRegisterEntryEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnTimeFactorEvent.class.getSimpleName())) { return loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(createdAt, author, logicalTimePoint, id, dbObject); - } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) { - return loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass + .equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) { + return loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(createdAt, author, + logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogDefineMarkEvent.class.getSimpleName())) { return loadRegattaLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRevokeEvent.class.getSimpleName())) { @@ -1768,6 +1941,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return comp; } + private CompetitorWithBoat getCompetitorWithBoatByID(DBObject dbObject) { + Serializable competitorId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()); + CompetitorWithBoat comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); + return comp; + } + private Boat getBoatByID(DBObject dbObject) { Serializable boatId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()); Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); @@ -1778,139 +1957,169 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); final Double timeOnTimeFactor = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_TIME_FACTOR.name()); - return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnTimeFactor); + return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, logicalTimePoint, author, id, comp, + timeOnTimeFactor); } private RegattaLogEvent loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); - final Double timeOnDistanceSecondsAllowancePerNauticalMile = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name()); - final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceSecondsAllowancePerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceSecondsAllowancePerNauticalMile*1000)); - return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnDistanceAllowancePerNauticalMile); + final Double timeOnDistanceSecondsAllowancePerNauticalMile = (Double) dbObject + .get(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name()); + final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceSecondsAllowancePerNauticalMile == null + ? null : new MillisecondsDurationImpl((long) (timeOnDistanceSecondsAllowancePerNauticalMile * 1000)); + return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, logicalTimePoint, + author, id, comp, timeOnDistanceAllowancePerNauticalMile); } private RegattaLogRevokeEvent loadRegattaLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Serializable revokedEventId = Helpers.tryUuidConversion( - (Serializable) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name())); + Serializable revokedEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name())); String revokedEventType = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_REASON.name()); - return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, - revokedEventId, revokedEventType, revokedEventShortInfo, reason); - } - - private RegattaLogEvent loadRegattaLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Mark mark = loadMark((DBObject) dbObject.get(FieldNames.REGATTA_LOG_MARK.name())); - return new RegattaLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, id, mark); + return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, revokedEventId, revokedEventType, + revokedEventShortInfo, reason); } - private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, + private RegattaLogEvent loadRegattaLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Competitor comp = getCompetitorByID(dbObject); + Mark mark = loadMark((DBObject) dbObject.get(FieldNames.REGATTA_LOG_MARK.name())); + return new RegattaLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, id, mark); + } + + private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + CompetitorWithBoat comp = getCompetitorWithBoatByID(dbObject); final RegattaLogRegisterCompetitorEvent result; if (comp == null) { result = null; - logger.log(Level.SEVERE, "Couldn't resolve competitor with ID "+dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, + "Couldn't resolve competitor with ID " + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); } else { result = new RegattaLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, comp); } return result; } - private RegattaLogRegisterBoatEvent loadRegattaLogRegisterBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + private RegattaLogRegisterBoatEvent loadRegattaLogRegisterBoatEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Boat boat = getBoatByID(dbObject); final RegattaLogRegisterBoatEvent result; if (boat == null) { result = null; - logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ - " from registration event with ID "+id+". Skipping this boat registration."); + logger.log(Level.SEVERE, + "Couldn't resolve boat with ID " + dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()) + + " from registration event with ID " + id + ". Skipping this boat registration."); } else { result = new RegattaLogRegisterBoatEventImpl(createdAt, logicalTimePoint, author, id, boat); } return result; } - private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + private RegattaLogRegisterEntryEvent loadRegattaLogRegisterEntryEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + Competitor comp = getCompetitorByID(dbObject); + final RegattaLogRegisterEntryEvent result; + if (comp == null) { + result = null; + logger.log(Level.SEVERE, + "Couldn't resolve competitor with ID " + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); + } else { + result = new RegattaLogRegisterEntryEventImpl(createdAt, logicalTimePoint, author, id, comp); + } + return result; + } + + private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Competitor comp = getCompetitorByID(dbObject); Boat boat = getBoatByID(dbObject); final RegattaLogRegisterCompetitorAndBoatEvent result; if (comp == null || boat == null) { result = null; if (comp == null) { - logger.log(Level.SEVERE, "Couldn't resolve competitor with ID "+dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, "Couldn't resolve competitor with ID " + + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); } if (boat == null) { - logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, + "Couldn't resolve boat with ID " + dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()) + + " from registration event with ID " + id + + ". Skipping this competitor registration."); } } else { - result = new RegattaLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, comp, boat); + result = new RegattaLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, comp, + boat); } return result; } - private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get( - FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name())); + private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent( + TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, + DBObject dbObject) { + Serializable deviceMappingEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name())); TimePoint closingTimePointInclusive = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_CLOSING_TIMEPOINT); return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(createdAt, author, logicalTimePoint, id, deviceMappingEventId, closingTimePointInclusive); } - private RegattaLogDeviceMarkMappingEvent loadRegattaLogDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject, RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { + private RegattaLogDeviceMarkMappingEvent loadRegattaLogDeviceMarkMappingEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject, + RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { DeviceIdentifier device = null; try { - device = loadDeviceId(deviceIdentifierServiceFinder, - (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); + device = loadDeviceId(deviceIdentifierServiceFinder, (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); } catch (Exception e) { logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e); e.printStackTrace(); } - //have to load complete mark, as no order is guaranteed for loading of racelog events + // have to load complete mark, as no order is guaranteed for loading of racelog events Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name())); @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO; - Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); + Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, + deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); final TimePoint from = times.getA(); final TimePoint to = times.getB(); - final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); + final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, + logicalTimePoint, author, id, mappedTo, device, from, to); final boolean needsMigration = times.getC(); if (needsMigration) { // remove old version of mapping event - WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject); + WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()) + .remove(outerDBObject); assert removeResult.getN() == 1; // and then insert using the fixed storage implementation - new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result); + new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, + result); } return result; } /** * Loads a from and a to time point from fromField and toField of dbObject. - * If the fromField is not found, the fromFieldDeprecated is attempted. If found, migration - * is deemed necessary, expressed by returning true in the {@link Triple#getC()} component of the result. - * Same for the to-field. + * If the fromField is not found, the fromFieldDeprecated is attempted. If found, + * migration is deemed necessary, expressed by returning true in the {@link Triple#getC()} component of + * the result. Same for the to-field. * - * @return the from-time in {@link Triple#getA()}, the to-time in {@link Triple#getB()} and whether or not migration is - * necessary because a value was only found in a deprecated field in {@link Triple#getC()}. + * @return the from-time in {@link Triple#getA()}, the to-time in {@link Triple#getB()} and whether or not migration + * is necessary because a value was only found in a deprecated field in {@link Triple#getC()}. */ - private Triple loadFromToTimePoint(final DBObject dbObject, FieldNames fromField, FieldNames fromFieldDeprecated, - FieldNames toField, FieldNames toFieldDeprecated) { + private Triple loadFromToTimePoint(final DBObject dbObject, FieldNames fromField, + FieldNames fromFieldDeprecated, FieldNames toField, FieldNames toFieldDeprecated) { boolean needsMigration = false; TimePoint from = loadTimePoint(dbObject, fromField); if (from == null) { - // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM + // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of + // REGATTA_LOG_FROM // If such a case is found here, migrate the record. from = loadTimePoint(dbObject, fromFieldDeprecated); if (from != null) { @@ -1919,7 +2128,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } TimePoint to = loadTimePoint(dbObject, toField); if (to == null) { - // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM + // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of + // REGATTA_LOG_FROM // If such a case is found here, migrate the record. to = loadTimePoint(dbObject, toFieldDeprecated); if (to != null) { @@ -1928,42 +2138,44 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return new Triple<>(from, to, needsMigration); } - + private RegattaLogDeviceCompetitorMappingEvent loadRegattaLogDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, final DBObject dbObject, RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { DeviceIdentifier device = null; try { - device = loadDeviceId(deviceIdentifierServiceFinder, - (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); + device = loadDeviceId(deviceIdentifierServiceFinder, (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); } catch (Exception e) { logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e); e.printStackTrace(); } final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()); - Competitor mappedTo = baseDomainFactory.getExistingCompetitorById( - competitorId); + Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(competitorId); final RegattaLogDeviceCompetitorMappingEventImpl result; if (mappedTo == null) { - logger.severe("Found a "+RegattaLogDeviceCompetitorMappingEventImpl.class.getName()+ - " event but couldn't find competitor with ID "+competitorId); + logger.severe("Found a " + RegattaLogDeviceCompetitorMappingEventImpl.class.getName() + + " event but couldn't find competitor with ID " + competitorId); result = null; } else { @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO; - Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); + Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, + deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); final TimePoint from = times.getA(); final TimePoint to = times.getB(); final boolean needsMigration = times.getC(); - result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); + result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, + device, from, to); if (needsMigration) { // remove old version of mapping event - WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject); + WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()) + .remove(outerDBObject); assert removeResult.getN() == 1; // and then insert using the fixed storage implementation - new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result); + new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, + result); } } return result; @@ -1979,8 +2191,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e); e.printStackTrace(); } - Competitor mappedTo = baseDomainFactory.getExistingCompetitorById((Serializable) dbObject - .get(FieldNames.COMPETITOR_ID.name())); + Competitor mappedTo = baseDomainFactory + .getExistingCompetitorById((Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name())); @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @@ -2020,15 +2232,17 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { CourseBase courseData = new CourseDataImpl(courseName); int i = 0; for (Object object : dbCourseList) { - DBObject dbObject = (DBObject) object; + DBObject dbObject = (DBObject) object; Waypoint waypoint = null; PassingInstruction passingInstructions = null; String waypointPassingInstruction = (String) dbObject.get(FieldNames.WAYPOINT_PASSINGINSTRUCTIONS.name()); if (waypointPassingInstruction == null) { waypointPassingInstruction = (String) dbObject.get(FieldNames.WAYPOINT_PASSINGSIDE.name()); - if(waypointPassingInstruction != null) { - logger.info("Migrating PassingInstruction "+waypointPassingInstruction+" to field name WAYPOINT_PASSINGINSTRUCTIONS"); - if((i==0||i==dbCourseList.size()-1)&&waypointPassingInstruction.toLowerCase().equals("gate")){ + if (waypointPassingInstruction != null) { + logger.info("Migrating PassingInstruction " + waypointPassingInstruction + + " to field name WAYPOINT_PASSINGINSTRUCTIONS"); + if ((i == 0 || i == dbCourseList.size() - 1) + && waypointPassingInstruction.toLowerCase().equals("gate")) { logger.warning("Changing PassingInstructions of first or last Waypoint from Gate to Line."); waypointPassingInstruction = "Line"; } @@ -2058,11 +2272,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Mark mark = loadMark((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); controlPoint = mark; } else if (controlPointClass.equals("Gate")) { - ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); + ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks( + (DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); dbObject.put(FieldNames.CONTROLPOINT_CLASS.name(), ControlPointWithTwoMarks.class.getSimpleName()); controlPoint = cpwtm; } else if (controlPointClass.equals(ControlPointWithTwoMarks.class.getSimpleName())) { - ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); + ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks( + (DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); controlPoint = cpwtm; } } @@ -2093,7 +2309,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbLeft = (DBObject) dbObject.get(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name()); if (dbLeft == null) { dbLeft = (DBObject) dbObject.get(FieldNames.GATE_LEFT.name()); - logger.info("Migrating left Mark of ControlPointWithTwoMarks " + controlPointName + " from old field GATE_LEFT to CONTROLPOINTWITHTWOMARKS_LEFT"); + logger.info("Migrating left Mark of ControlPointWithTwoMarks " + controlPointName + + " from old field GATE_LEFT to CONTROLPOINTWITHTWOMARKS_LEFT"); dbObject.put(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name(), dbLeft); dbObject.removeField(FieldNames.GATE_LEFT.name()); } @@ -2101,12 +2318,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbRight = (DBObject) dbObject.get(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name()); if (dbRight == null) { dbRight = (DBObject) dbObject.get(FieldNames.GATE_RIGHT.name()); - logger.info("Migrating right Mark of ControlPointWithTwoMarks " + controlPointName + " from old field GATE_RIGHT to CONTROLPOINTWITHTWOMARKS_RIGHT"); + logger.info("Migrating right Mark of ControlPointWithTwoMarks " + controlPointName + + " from old field GATE_RIGHT to CONTROLPOINTWITHTWOMARKS_RIGHT"); dbObject.put(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name(), dbRight); dbObject.removeField(FieldNames.GATE_RIGHT.name()); } Mark rightMark = loadMark(dbRight); - ControlPointWithTwoMarks gate = baseDomainFactory.createControlPointWithTwoMarks(controlPointId, leftMark, rightMark, controlPointName); + ControlPointWithTwoMarks gate = baseDomainFactory.createControlPointWithTwoMarks(controlPointId, leftMark, + rightMark, controlPointName); return gate; } @@ -2119,13 +2338,30 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String markShape = (String) dbObject.get(FieldNames.MARK_SHAPE.name()); Object markTypeRaw = dbObject.get(FieldNames.MARK_TYPE.name()); MarkType markType = markTypeRaw == null ? null : MarkType.valueOf((String) markTypeRaw); - + Mark mark = baseDomainFactory.getOrCreateMark(markId, markName, markType, markColor, markShape, markPattern); return mark; } @Override - public Collection loadAllCompetitors() { + public Collection loadAllCompetitors() { + ArrayList result = new ArrayList<>(); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); + try { + for (DBObject o : collection.find()) { + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o))); + Competitor c = competitorDeserializer.deserialize(json); + result.add(c); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors."); + logger.log(Level.SEVERE, "loadCompetitors", e); + } + return result; + } + + @Override + public Collection loadAllCompetitorsWithBoat() { ArrayList result = new ArrayList<>(); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); try { @@ -2162,7 +2398,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public Iterable> loadAllDeviceConfigurations() { Map result = new HashMap<>(); DBCollection configurationCollection = database.getCollection(CollectionNames.CONFIGURATIONS.name()); - + try { for (DBObject dbObject : configurationCollection.find()) { Util.Pair entry = loadConfigurationEntry(dbObject); @@ -2172,20 +2408,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load configurations."); logger.log(Level.SEVERE, "loadAllDeviceConfigurations", e); } - + return result.entrySet(); } private Util.Pair loadConfigurationEntry(DBObject dbObject) { DBObject matcherObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_MATCHER.name()); DBObject configObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_CONFIG.name()); - return new Util.Pair(loadConfigurationMatcher(matcherObject), + return new Util.Pair(loadConfigurationMatcher(matcherObject), loadConfiguration(configObject)); } private DeviceConfigurationMatcher loadConfigurationMatcher(DBObject matcherObject) { List clientIdentifiers = new ArrayList(); - BasicDBList clientIdentifiersObject = (BasicDBList) matcherObject.get(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name()); + BasicDBList clientIdentifiersObject = (BasicDBList) matcherObject + .get(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name()); if (clientIdentifiersObject != null) { for (Object clientIdentifier : clientIdentifiersObject) { clientIdentifiers.add(clientIdentifier.toString()); @@ -2201,25 +2438,27 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(configObject))); configuration = deserializer.deserialize(json); } catch (JsonDeserializationException | ParseException e) { - logger.log(Level.SEVERE, "Error parsing configuration object from MongoDB, falling back to empty configuration."); + logger.log(Level.SEVERE, + "Error parsing configuration object from MongoDB, falling back to empty configuration."); logger.log(Level.SEVERE, "loadConfiguration", e); configuration = new DeviceConfigurationImpl(new RegattaConfigurationImpl()); } return configuration; } - + private DeviceIdentifier loadDeviceId( TypeBasedServiceFinder deviceIdentifierServiceFinder, DBObject deviceId) - throws TransformationException, NoCorrespondingServiceRegisteredException { + throws TransformationException, NoCorrespondingServiceRegisteredException { String deviceType = (String) deviceId.get(FieldNames.DEVICE_TYPE.name()); Object deviceTypeId = deviceId.get(FieldNames.DEVICE_TYPE_SPECIFIC_ID.name()); String stringRepresentation = (String) deviceId.get(FieldNames.DEVICE_STRING_REPRESENTATION.name()); - + try { - return deviceIdentifierServiceFinder.findService(deviceType).deserialize(deviceTypeId, deviceType, stringRepresentation); + return deviceIdentifierServiceFinder.findService(deviceType).deserialize(deviceTypeId, deviceType, + stringRepresentation); } catch (TransformationException e) { - return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize( - stringRepresentation, deviceType, stringRepresentation); + return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize(stringRepresentation, deviceType, + stringRepresentation); } } @@ -2245,7 +2484,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return resultUrls; } - + private ImageDescriptor loadImage(DBObject dbObject) { ImageDescriptor image = null; URL imageURL = loadURL(dbObject, FieldNames.IMAGE_URL); @@ -2253,8 +2492,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String title = (String) dbObject.get(FieldNames.IMAGE_TITLE.name()); String subtitle = (String) dbObject.get(FieldNames.IMAGE_SUBTITLE.name()); String copyright = (String) dbObject.get(FieldNames.IMAGE_COPYRIGHT.name()); - String localeRaw = (String) dbObject.get(FieldNames.IMAGE_LOCALE.name()); - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + String localeRaw = (String) dbObject.get(FieldNames.IMAGE_LOCALE.name()); + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; Number imageWidth = (Number) dbObject.get(FieldNames.IMAGE_WIDTH_IN_PX.name()); Number imageHeight = (Number) dbObject.get(FieldNames.IMAGE_HEIGHT_IN_PX.name()); TimePoint createdAtDate = loadTimePoint(dbObject, FieldNames.IMAGE_CREATEDATDATE); @@ -2277,18 +2516,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return image; } - + private VideoDescriptor loadVideo(DBObject dbObject) { VideoDescriptor video = null; URL videoURL = loadURL(dbObject, FieldNames.VIDEO_URL); - if(videoURL != null) { + if (videoURL != null) { String title = (String) dbObject.get(FieldNames.VIDEO_TITLE.name()); String subtitle = (String) dbObject.get(FieldNames.VIDEO_SUBTITLE.name()); String copyright = (String) dbObject.get(FieldNames.VIDEO_COPYRIGHT.name()); Object mimeTypeRaw = dbObject.get(FieldNames.VIDEO_MIMETYPE.name()); MimeType mimeType = mimeTypeRaw == null ? null : MimeType.valueOf((String) mimeTypeRaw); - String localeRaw = (String) dbObject.get(FieldNames.VIDEO_LOCALE.name()); - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + String localeRaw = (String) dbObject.get(FieldNames.VIDEO_LOCALE.name()); + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; TimePoint createdAtDate = loadTimePoint(dbObject, FieldNames.VIDEO_CREATEDATDATE); BasicDBList tags = (BasicDBList) dbObject.get(FieldNames.VIDEO_TAGS.name()); Number lengthInSeconds = (Number) dbObject.get(FieldNames.VIDEO_LENGTH_IN_SECONDS.name()); @@ -2314,18 +2553,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private URL loadURL(DBObject dbObject, FieldNames field) { URL result = null; String urlAsString = (String) dbObject.get(field.name()); - if(urlAsString != null) { + if (urlAsString != null) { try { result = new URL(urlAsString); } catch (MalformedURLException e) { - logger.severe("Error parsing URL '"+urlAsString+"' in field "+field.name()+"."); + logger.severe("Error parsing URL '" + urlAsString + "' in field " + field.name() + "."); } } - return result; + return result; } - + /** - * Legacy code to support conversion of old image and video URLs + * Legacy code to support conversion of old image and video URLs + * * @param event * @param eventDBObject */ @@ -2334,22 +2574,24 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { List imageURLs = new ArrayList(); List sponsorImageURLs = new ArrayList(); List videoURLs = new ArrayList(); - + String logoImageURLAsString = (String) eventDBObject.get(FieldNames.EVENT_LOGO_IMAGE_URL.name()); if (logoImageURLAsString != null) { try { logoImageURL = new URL(logoImageURLAsString); } catch (MalformedURLException e) { - logger.severe("Error parsing logo image URL "+logoImageURLAsString+" for event "+event.getName()+". Ignoring this URL."); + logger.severe("Error parsing logo image URL " + logoImageURLAsString + " for event " + event.getName() + + ". Ignoring this URL."); } } BasicDBList imageURLsJson = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGE_URLS.name()); if (imageURLsJson != null) { for (Object imageURL : imageURLsJson) { try { - imageURLs.add(new URL((String) imageURL)); + imageURLs.add(new URL((String) imageURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing image URL "+imageURL+" for event "+event.getName()+". Ignoring this image URL."); + logger.severe("Error parsing image URL " + imageURL + " for event " + event.getName() + + ". Ignoring this image URL."); } } } @@ -2359,7 +2601,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { videoURLs.add(new URL((String) videoURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing video URL "+videoURL+" for event "+event.getName()+". Ignoring this video URL."); + logger.severe("Error parsing video URL " + videoURL + " for event " + event.getName() + + ". Ignoring this video URL."); } } } @@ -2369,7 +2612,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { sponsorImageURLs.add(new URL((String) sponsorImageURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing sponsor image URL "+sponsorImageURL+" for event "+event.getName()+". Ignoring this sponsor image URL."); + logger.severe("Error parsing sponsor image URL " + sponsorImageURL + " for event " + event.getName() + + ". Ignoring this sponsor image URL."); } } } @@ -2378,21 +2622,26 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private boolean loadLegacySailorsInfoWebsiteURL(Event event, DBObject eventDBObject) { final boolean modified; - final String sailorsInfoWebSiteURLAsString = (String) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name()); + final String sailorsInfoWebSiteURLAsString = (String) eventDBObject + .get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name()); if (sailorsInfoWebSiteURLAsString != null) { try { - // The legacy sailors info URL (only used at Kieler/Travemuender Woche events) used to have 2 localized versions: + // The legacy sailors info URL (only used at Kieler/Travemuender Woche events) used to have 2 localized + // versions: // The German version with no suffix (e.g. http://sailorsinfo.travemuender-woche.com) - // The English/international version with "/en" suffix (e.g. http://sailorsinfo.travemuender-woche.com/en) + // The English/international version with "/en" suffix (e.g. + // http://sailorsinfo.travemuender-woche.com/en) if (!event.hasSailorsInfoWebsiteURL(null)) { - final String englishURL = sailorsInfoWebSiteURLAsString + (sailorsInfoWebSiteURLAsString.endsWith("/") ? "" : "/") + "en"; + final String englishURL = sailorsInfoWebSiteURLAsString + + (sailorsInfoWebSiteURLAsString.endsWith("/") ? "" : "/") + "en"; event.setSailorsInfoWebsiteURL(null, new URL(englishURL)); } if (!event.hasSailorsInfoWebsiteURL(Locale.GERMAN)) { event.setSailorsInfoWebsiteURL(Locale.GERMAN, new URL(sailorsInfoWebSiteURLAsString)); } } catch (MalformedURLException e) { - logger.severe("Error parsing sailors info website URL "+sailorsInfoWebSiteURLAsString+" for event "+event.getName()+". Ignoring this URL."); + logger.severe("Error parsing sailors info website URL " + sailorsInfoWebSiteURLAsString + " for event " + + event.getName() + ". Ignoring this URL."); } modified = true; } else { @@ -2402,18 +2651,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public ConnectivityParametersLoadingResult loadConnectivityParametersForRacesToRestore(Consumer callback) { - final DBCollection collection = database.getCollection(CollectionNames.CONNECTIVITY_PARAMS_FOR_RACES_TO_BE_RESTORED.name()); + public ConnectivityParametersLoadingResult loadConnectivityParametersForRacesToRestore( + Consumer callback) { + final DBCollection collection = database + .getCollection(CollectionNames.CONNECTIVITY_PARAMS_FOR_RACES_TO_BE_RESTORED.name()); final DBCursor cursor = collection.find(); final int count = cursor.count(); - logger.info("Restoring "+count+" races"); + logger.info("Restoring " + count + " races"); final List restoreParameters = new ArrayList<>(); // consume all elements quickly to avoid cursor/DB timeouts while restoring many races; // MongoDB cursors by default time out after ten minutes if no more batch (of by default 100 elements) // has been requested during this time. Util.addAll(cursor, restoreParameters); - logger.info("Obtained "+restoreParameters.size()+" race parameters to restore"); - final ScheduledExecutorService backgroundExecutor = ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor(); + logger.info("Obtained " + restoreParameters.size() + " race parameters to restore"); + final ScheduledExecutorService backgroundExecutor = ThreadPoolUtil.INSTANCE + .getDefaultBackgroundTaskThreadPoolExecutor(); final Set> waiters = new HashSet<>(); logger.info("Starting to restore races"); final AtomicInteger i = new AtomicInteger(); @@ -2421,35 +2673,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final FutureTask waiter = new FutureTask<>(() -> { final String type = (String) o.get(TypeBasedServiceFinder.TYPE); final int finalI = i.incrementAndGet(); - logger.info("Applying to restore race #"+ finalI +"/"+count+" of type "+type); - raceTrackingConnectivityParamsServiceFinder.applyServiceWhenAvailable(type, connectivityParamsPersistenceService -> { - logger.info("Restoring race #"+ finalI +"/"+count+" of type "+type); - final Map map = new HashMap<>(); - for (final String key : o.keySet()) { - if (!key.equals(TypeBasedServiceFinder.TYPE)) { - map.put(key, o.get(key)); - } - } - try { - final RaceTrackingConnectivityParameters params = connectivityParamsPersistenceService.mapTo(map); - if (params != null) { - callback.accept(params); - logger.info("Done restoring race #"+ finalI +"/"+count+" of type "+type); - } else { - logger.warning("Couldn't restore race #"+ finalI +"/"+count+" of type "+type+ - " because the parameters loaded from the DB couldn't be mapped. Maybe the owning leaderboard was removed?"); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Exception trying to load race #"+ finalI +"/"+count+" of type "+type+ - " from restore connectivity parameters " - + o + " with handler " + connectivityParamsPersistenceService, e); - } - }); + logger.info("Applying to restore race #" + finalI + "/" + count + " of type " + type); + raceTrackingConnectivityParamsServiceFinder.applyServiceWhenAvailable(type, + connectivityParamsPersistenceService -> { + logger.info("Restoring race #" + finalI + "/" + count + " of type " + type); + final Map map = new HashMap<>(); + for (final String key : o.keySet()) { + if (!key.equals(TypeBasedServiceFinder.TYPE)) { + map.put(key, o.get(key)); + } + } + try { + final RaceTrackingConnectivityParameters params = connectivityParamsPersistenceService + .mapTo(map); + if (params != null) { + callback.accept(params); + logger.info("Done restoring race #" + finalI + "/" + count + " of type " + type); + } else { + logger.warning("Couldn't restore race #" + finalI + "/" + count + " of type " + type + + " because the parameters loaded from the DB couldn't be mapped. Maybe the owning leaderboard was removed?"); + } + } catch (Exception e) { + logger.log(Level.SEVERE, + "Exception trying to load race #" + finalI + "/" + count + " of type " + type + + " from restore connectivity parameters " + o + " with handler " + + connectivityParamsPersistenceService, + e); + } + }); }, /* void result */ null); waiters.add(waiter); backgroundExecutor.execute(waiter); } - logger.info("Done restoring races; restored "+i+" of "+count+" races"); + logger.info("Done restoring races; restored " + i + " of " + count + " races"); return new ConnectivityParametersLoadingResult() { @Override public int getNumberOfParametersToLoad() { diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 10ef00bba75..9300d8497a4 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -63,12 +63,14 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; @@ -121,6 +123,7 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; import com.sap.sse.common.Duration; @@ -138,6 +141,7 @@ import com.sap.sse.shared.media.VideoDescriptor; public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; + private final CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; @@ -1146,7 +1150,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT); result.put(FieldNames.RACE_LOG_EVENT_ID.name(), event.getId()); result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), event.getPassId()); - result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedBoats())); + result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedCompetitors())); storeRaceLogEventAuthor(result, event.getAuthor()); } @@ -1317,10 +1321,33 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } return passing; } - + + @Override + public void storeCompetitorWithBoat(CompetitorWithBoat competitor) { + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + JSONObject json = competitorWithBoatSerializer.serialize(competitor); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + DBObject entry = (DBObject) JSON.parse(json.toString()); + collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); + } + + @Override + public void storeCompetitorsWithBoat(Iterable competitors) { + if (competitors != null && !Util.isEmpty(competitors)) { + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + List competitorsDB = new ArrayList<>(); + for (CompetitorWithBoat competitor : competitors) { + JSONObject json = competitorWithBoatSerializer.serialize(competitor); + DBObject entry = (DBObject) JSON.parse(json.toString()); + competitorsDB.add(entry); + } + collection.insert(competitorsDB); + } + } + @Override public void storeCompetitor(Competitor competitor) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); JSONObject json = competitorSerializer.serialize(competitor); DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); DBObject entry = (DBObject) JSON.parse(json.toString()); @@ -1330,7 +1357,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeCompetitors(Iterable competitors) { if (competitors != null && !Util.isEmpty(competitors)) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); List competitorsDB = new ArrayList<>(); for (Competitor competitor : competitors) { JSONObject json = competitorSerializer.serialize(competitor); @@ -1343,6 +1370,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void removeAllCompetitors() { + logger.info("Removing all persistent competitors"); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); + collection.drop(); + } + + @Override + public void removeAllCompetitorsWithBoat() { logger.info("Removing all persistent competitors"); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); collection.drop(); @@ -1350,6 +1384,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void removeCompetitor(Competitor competitor) { + logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + collection.remove(query, WriteConcern.SAFE); + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId()); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); @@ -1564,6 +1606,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterEntryEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterEntryEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java index 2a3d97d0671..3de5346128d 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -59,6 +60,11 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index 598a3f69546..6d79312f710 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -22,17 +22,21 @@ import org.junit.rules.Timeout; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; +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.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.base.impl.SeriesImpl; @@ -64,7 +68,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { private RacingEventService service; - + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); private final Fleet fleet = new FleetImpl("fleet"); private final String columnName = "column"; private RegattaLeaderboard leaderboard; @@ -182,13 +186,14 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { assertFalse(raceLog.isEmpty()); // add a mapping and one fix in, one out of mapping + Boat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10))); addFixes0(dev1); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(t(), author, t(), UUID.randomUUID(), 0)); - raceLog.add(new RaceLogRegisterCompetitorEventImpl(t(), author, 0, comp1)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(t(), author, t(), UUID.randomUUID(), 0)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(t(), author, 0, comp1, boat1)); raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0)); // start tracking adapter.startTracking(service, leaderboard, column, fleet, /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false); @@ -261,13 +266,14 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race"); // add a mapping and one fix in, one out of mapping + Boat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c1", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, t(0), t(10))); addFixes0(dev1); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(t(), t(), author, UUID.randomUUID(), comp1)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(t(), t(), author, UUID.randomUUID(), comp1, boat1)); raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0)); // start tracking diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 00c3b5163bd..b52b445fbb2 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.logging.Level; @@ -43,7 +44,7 @@ import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; -import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorAndBoatRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; @@ -139,9 +140,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { RegattaLeaderboard rLeaderboard = (RegattaLeaderboard) leaderboard; boatClass = rLeaderboard.getRegatta().getBoatClass(); } else { - if (!Util.isEmpty(raceColumn.getAllCompetitors(fleet))) { + if (!Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values())) { boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values()); - } else if (!Util.isEmpty(raceColumn.getAllCompetitors())) { + } else if (!Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats().values())) { boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats().values()); } else if (!Util.isEmpty(leaderboard.getAllCompetitors())) { boatClass = leaderboard.getBoatClass(); @@ -223,18 +224,18 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { @Override public void copyCompetitors(final RaceColumn fromRaceColumn, final Fleet fromFleet, final Iterable> toRaces) { - Iterable competitorsToCopy = fromRaceColumn.getAllCompetitors(fromFleet); + Map competitorsAndBoatsToCopy = fromRaceColumn.getAllCompetitorsAndTheirBoats(fromFleet); for (Pair toRace : toRaces) { final RaceColumn toRaceColumn = toRace.getA(); final Fleet toFleet = toRace.getB(); try { - if (toRaceColumn.isCompetitorRegistrationInRacelogEnabled(toFleet)) { - toRaceColumn.registerCompetitors(competitorsToCopy, toFleet); + if (toRaceColumn.isCompetitorAndBoatRegistrationInRacelogEnabled(toFleet)) { + toRaceColumn.registerCompetitorsAndBoats(competitorsAndBoatsToCopy, toFleet); } else { - toRaceColumn.enableCompetitorRegistrationOnRaceLog(toFleet); - toRaceColumn.registerCompetitors(competitorsToCopy, toFleet); + toRaceColumn.enableCompetitorAndBoatRegistrationOnRaceLog(toFleet); + toRaceColumn.registerCompetitorsAndBoats(competitorsAndBoatsToCopy, toFleet); } - } catch (CompetitorRegistrationOnRaceLogDisabledException e1) { + } catch (CompetitorAndBoatRegistrationOnRaceLogDisabledException e1) { // cannot happen as we explicitly checked successfully before, or enabled it when the check failed; still produce a log documenting this strangeness: logger.log(Level.WARNING, "Internal error: race column "+toRaceColumn.getName()+" does not accept competitor registration although it should", e1); } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java index 3693a5abd42..9a24f11dee9 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java @@ -14,13 +14,20 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sse.common.impl.MillisecondsTimePoint; public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + private final static DynamicBoat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); + private final static DynamicBoat boat2 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); + private final CompetitorWithBoat competitor = new CompetitorWithBoatImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null, boat1); + private final CompetitorWithBoat competitor2 = new CompetitorWithBoatImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null, boat2); @Test public void testCompetitorDeregistration() { @@ -30,7 +37,7 @@ public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest Collections.singleton(competitor2), author); final Set events = deregistrator.analyze(); deregistrator.deregister(events); - final Set competitors = new CompetitorsInLogAnalyzer<>(log).analyze(); + final Set competitors = new CompetitorsInLogAnalyzer<>(log).analyze(); assertEquals(1, competitors.size()); assertSame(competitor, competitors.iterator().next()); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java index c715c3351d9..5b7ab1c3611 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java @@ -23,5 +23,5 @@ public interface RaceLogEventData extends Serializable { * A {@link RaceLogEventData} might be associated with a list of competitors, which are somehow relevant for this * kind of event. An example is a list of competitors who are marked for an individual recall. */ - List getInvolvedBoats(); + List getInvolvedCompetitors(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java index e5ead97f468..247811d4b65 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java @@ -23,11 +23,11 @@ public class MarkPassingDataFinder extends RaceLogAnalyzer(castedEvent.getInvolvedBoats().get(0), castedEvent + result.add(new Triple(castedEvent.getInvolvedCompetitors().get(0), castedEvent .getZeroBasedIndexOfPassedWaypoint(), castedEvent.getTimePointOfFixedPassing())); } else if (event instanceof RaceLogSuppressedMarkPassingsEvent){ RaceLogSuppressedMarkPassingsEvent castedEvent = (RaceLogSuppressedMarkPassingsEvent) event; - result.add(new Triple(castedEvent.getInvolvedBoats().get(0), castedEvent.getZeroBasedIndexOfFirstSuppressedWaypoint(), null)); + result.add(new Triple(castedEvent.getInvolvedCompetitors().get(0), castedEvent.getZeroBasedIndexOfFirstSuppressedWaypoint(), null)); } } return result; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java index d7f8737854d..00a84487785 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java @@ -6,17 +6,17 @@ import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; -public class RaceLogRegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { +public class RaceLogRegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { public RaceLogRegisteredCompetitorsAnalyzer(RaceLog raceLog) { super(raceLog); } @Override - protected Set performAnalysis() { - final Set result; + protected Set performAnalysis() { + final Set result; if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()){ // get Events from RaceLog result = new CompetitorsInLogAnalyzer<>(getLog()).analyze(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java new file mode 100644 index 00000000000..3199b98c703 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java @@ -0,0 +1,31 @@ +package com.sap.sailing.domain.abstractlog.race.analyzing.impl; + +import java.util.Collections; +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; + +public class RaceLogRegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer> { + + public RaceLogRegisteredCompetitorsAndBoatsAnalyzer(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected Map performAnalysis() { + final Map result; + if (new RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(getLog()).analyze()){ + // get Events from RaceLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); + } else { + // as we're explicitly only trying to find those registrations in the RaceLog, we won't + // return anything from the regatta log. + result = Collections.emptyMap(); + } + return result; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java index 68f1f88def4..45933ee3450 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java @@ -21,7 +21,7 @@ public class RaceLogEventDataImpl implements RaceLogEventData { } @Override - public List getInvolvedBoats() { + public List getInvolvedCompetitors() { return involvedBoats; } @@ -32,6 +32,6 @@ public class RaceLogEventDataImpl implements RaceLogEventData { @Override public String toString() { - return super.toString() + ", involvedBoats: " + getInvolvedBoats() + ", passId: " + getPassId(); + return super.toString() + ", involvedBoats: " + getInvolvedCompetitors() + ", passId: " + getPassId(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java index 2c4092a3130..ffd67eda973 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java @@ -36,8 +36,8 @@ public abstract class RaceLogEventImpl extends AbstractLogEventImpl getInvolvedBoats() { - return raceLogEventData.getInvolvedBoats(); + public List getInvolvedCompetitors() { + return raceLogEventData.getInvolvedCompetitors(); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java index ebd95a0a6fe..c3ef632647b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java @@ -49,8 +49,8 @@ public class RaceLogFixedMarkPassingEventImpl extends RaceLogEventImpl implement @Override public String getShortInfo() { - return (getInvolvedBoats() == null || getInvolvedBoats().get(0) == null ? "Unknown" : - getInvolvedBoats().get(0).getName()) + " at mark " + getZeroBasedIndexOfPassedWaypoint() + " at " + return (getInvolvedCompetitors() == null || getInvolvedCompetitors().get(0) == null ? "Unknown" : + getInvolvedCompetitors().get(0).getName()) + " at mark " + getZeroBasedIndexOfPassedWaypoint() + " at " + getTimePointOfFixedPassing(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java index 8f5d7560275..ab7dd407aef 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java @@ -35,8 +35,8 @@ public class RaceLogRevokeEventImpl extends RevokeEventImpl } @Override - public List getInvolvedBoats() { - return raceLogEventData.getInvolvedBoats(); + public List getInvolvedCompetitors() { + return raceLogEventData.getInvolvedCompetitors(); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java index f3eb85c285a..941515811f9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java @@ -42,6 +42,6 @@ public class RaceLogSuppressedMarkPassingsEventImpl extends RaceLogEventImpl imp @Override public String getShortInfo() { - return getInvolvedBoats().get(0).getName() + " at mark " + getZeroBasedIndexOfFirstSuppressedWaypoint(); + return getInvolvedCompetitors().get(0).getName() + " at mark " + getZeroBasedIndexOfFirstSuppressedWaypoint(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java index 185a9f226a8..5d526694b96 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java @@ -4,7 +4,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -public interface RaceLogRegisterCompetitorEvent extends RaceLogEvent, -RegisterCompetitorEvent { +/** + * ATTENTION: This is the old legacy race log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + */ +public interface RaceLogRegisterCompetitorEvent extends RaceLogEvent, RegisterCompetitorEvent { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java index 460c633d444..fe7e83f5f55 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java @@ -8,9 +8,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; * This is a marker event, which marks a {@link RaceLog} for using it's own boat registrations. When present, * boats are not registered on the RegattaLog corresponding to the RaceLog, but on the RaceLog itself. * - * See bug2851. - * - * @see RaceLogUsesOwnBoatsAnalyzer * @author Frank Mittag * */ diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java index 95ff17e1784..084d9c7a97a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java @@ -6,7 +6,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; /** * Used to find competitors of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the @@ -20,7 +20,7 @@ import com.sap.sailing.domain.base.Competitor; * @author Jan Bross (D056848) * */ -public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { +public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { private RegattaLog regattaLog; public RegisteredCompetitorsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) { @@ -29,8 +29,8 @@ public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer performAnalysis() { - final Set result; + protected Set performAnalysis() { + final Set result; if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { // get Events from RaceLog result = new CompetitorsInLogAnalyzer<>(getLog()).analyze(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java index a6606a2aae7..c3757c679f5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java @@ -32,7 +32,7 @@ public class RegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer performAnalysis() { final Map result; - if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { + if (new RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(getLog()).analyze()) { // get Events from RaceLog result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); } else { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java index 50daed3a0cd..e001d693a51 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java @@ -46,7 +46,7 @@ public class RaceLogRegisterCompetitorAndBoatEventImpl extends BaseRegisterCompe } @Override - public List getInvolvedBoats() { + public List getInvolvedCompetitors() { return Collections.singletonList(getCompetitor()); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java index 1c84b6b429b..9d854e9c160 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEventImpl implements @@ -23,7 +24,7 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv * if {@code competitor} is null */ public RaceLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, int passId, Competitor competitor) + AbstractLogEventAuthor author, Serializable id, int passId, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, id, competitor); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); @@ -34,7 +35,7 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv * if {@code competitor} is null */ public RaceLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, Competitor competitor) + AbstractLogEventAuthor author, int passId, CompetitorWithBoat competitor) throws IllegalArgumentException { this(now(), logicalTimePoint, author, randId(), passId, competitor); } @@ -45,8 +46,8 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv } @Override - public List getInvolvedBoats() { - return Collections.singletonList(getCompetitor()); + public List getInvolvedCompetitors() { + return Collections.singletonList((Competitor) getCompetitor()); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index 86d9f917ecc..6246c0f05d7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -25,6 +26,8 @@ public interface RegattaLogEventVisitor { void visit(RegattaLogRegisterBoatEvent event); + void visit(RegattaLogRegisterEntryEvent event); + void visit(RegattaLogRegisterCompetitorEvent event); void visit(RegattaLogRegisterCompetitorAndBoatEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java index 2a14d08cf9f..5135c57e4ea 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java @@ -1,10 +1,9 @@ package com.sap.sailing.domain.abstractlog.regatta.events; +import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; - -public interface RegattaLogRegisterBoatEvent extends RegattaLogEvent, -RegisterBoatEvent { +import com.sap.sailing.domain.base.Boat; +public interface RegattaLogRegisterBoatEvent extends RegattaLogEvent, Revokable { + Boat getBoat(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java index 9c39e217079..0f9ba9f3e91 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java @@ -1,9 +1,15 @@ package com.sap.sailing.domain.abstractlog.regatta.events; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; +/** + * Registers a competitor together with a boat for {@link RegattaLog} tracked regattas. + * @author Frank Mittag + * + */ public interface RegattaLogRegisterCompetitorAndBoatEvent extends RegattaLogEvent, RegisterCompetitorAndBoatEvent { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java index 4362da82dd3..29374f85624 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java @@ -4,7 +4,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -public interface RegattaLogRegisterCompetitorEvent extends RegattaLogEvent, -RegisterCompetitorEvent { +/** + * ATTENTION: This is the old legacy regatta log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + */ +public interface RegattaLogRegisterCompetitorEvent + extends RegattaLogEvent, RegisterCompetitorEvent { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java new file mode 100644 index 00000000000..c5eee3fe6d7 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.abstractlog.regatta.events; + +import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.base.Competitor; + +/** + * Registers a single entry for the regatta, the entry can be is used as a competitor for all races or the + * regatta or only for single races + * @author Frank Mittag + * + */ +public interface RegattaLogRegisterEntryEvent extends RegattaLogEvent, Revokable { + Competitor getCompetitor(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java index 69e959e8b19..20b5c649900 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java @@ -3,15 +3,16 @@ package com.sap.sailing.domain.abstractlog.regatta.events.impl; import java.io.Serializable; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sse.common.TimePoint; -public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl +public class RegattaLogRegisterBoatEventImpl extends AbstractLogEventImpl implements RegattaLogRegisterBoatEvent { private static final long serialVersionUID = -4531928509653259811L; + private final Boat boat; /** * @throws IllegalArgumentException @@ -19,7 +20,9 @@ public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl @@ -18,7 +18,7 @@ public class RegattaLogRegisterCompetitorEventImpl extends BaseRegisterCompetito * if {@code competitor} is null */ public RegattaLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, Serializable id, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, id, competitor); } @@ -27,7 +27,7 @@ public class RegattaLogRegisterCompetitorEventImpl extends BaseRegisterCompetito * if {@code competitor} is null */ public RegattaLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, CompetitorWithBoat competitor) throws IllegalArgumentException { super(logicalTimePoint, author, competitor); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java new file mode 100644 index 00000000000..2a3434d6172 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java @@ -0,0 +1,60 @@ +package com.sap.sailing.domain.abstractlog.regatta.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sse.common.TimePoint; + +public class RegattaLogRegisterEntryEventImpl extends AbstractLogEventImpl + implements RegattaLogRegisterEntryEvent { + + private static final long serialVersionUID = 2759139058776278902L; + private Competitor competitor; + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterEntryEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id); + checkCompetitor(competitor); + this.competitor = competitor; + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterEntryEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), competitor); + } + + @Override + public void accept(RegattaLogEventVisitor visitor) { + visitor.visit(this); + } + + private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { + if (competitor == null) { + throw new IllegalArgumentException("Competitor may not be null"); + } + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + + @Override + public String getShortInfo() { + return "competitor: " + getCompetitor().toString(); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java index 409064f0827..22b4cc9e599 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -39,6 +40,10 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor { public void visit(RegattaLogRegisterBoatEvent event) { } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java index 7f4ae3f34ca..3a91f6c3e5b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -42,6 +43,11 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor eventAdded(event); } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + eventAdded(event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { eventAdded(event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java similarity index 77% rename from java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java index 6c66f7e9d86..33cb57dbad8 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java @@ -1,4 +1,4 @@ -package com.sap.sailing.domain.abstractlog.shared.analyzing; +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; import java.util.HashSet; import java.util.Set; @@ -9,7 +9,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sse.common.Util; @@ -28,14 +28,14 @@ import com.sap.sse.common.Util; * @author Frank Mittag * */ -public class BoatDeregistrator, EventT extends AbstractLogEvent, VisitorT> +public class RegattaLogBoatDeregistrator, EventT extends AbstractLogEvent, VisitorT> extends BaseLogAnalyzer> { - private static final Logger logger = Logger.getLogger(BoatDeregistrator.class.getName()); + private static final Logger logger = Logger.getLogger(RegattaLogBoatDeregistrator.class.getName()); protected final Iterable boatsToDeregister; private AbstractLogEventAuthor eventAuthor; - public BoatDeregistrator(LogT log, Iterable boatsToDeregister, AbstractLogEventAuthor eventAuthor) { + public RegattaLogBoatDeregistrator(LogT log, Iterable boatsToDeregister, AbstractLogEventAuthor eventAuthor) { super(log); this.boatsToDeregister = boatsToDeregister; this.eventAuthor = eventAuthor; @@ -47,8 +47,8 @@ extends BaseLogAnalyzer> { final HashSet boatSet = new HashSet(); Util.addAll(boatsToDeregister, boatSet); for (EventT event : log.getUnrevokedEventsDescending()) { - if (event instanceof RegisterBoatEvent) { - RegisterBoatEvent registerEvent = (RegisterBoatEvent) event; + if (event instanceof RegattaLogRegisterBoatEvent) { + RegattaLogRegisterBoatEvent registerEvent = (RegattaLogRegisterBoatEvent) event; if (boatSet.contains(registerEvent.getBoat())) { result.add(event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java new file mode 100644 index 00000000000..6969d84ffe3 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java @@ -0,0 +1,38 @@ +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; +import com.sap.sailing.domain.base.Boat; + +/** + * This class searches for RegisterBoat events in the given log. + * + * Boats alone in a regatta log are not enough to be used in a real race. + * Instead a competitor and a boat together must be registered through a {@link RegisterCompetitorAndBoat} event. + * + */ +public class RegattaLogBoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public RegattaLogBoatsInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Set performAnalysis() { + Set result = new HashSet(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegattaLogRegisterBoatEvent) { + result.add(((RegattaLogRegisterBoatEvent) event).getBoat()); + } + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java new file mode 100644 index 00000000000..66e7d7cc1b9 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java @@ -0,0 +1,38 @@ +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; +import com.sap.sailing.domain.base.Competitor; + +/** + * This class searches for RegisterEntry events in the given log. + * + * Entries alone in a regatta log are not enough to be used in a real race. + * Instead an entry (competitor) and a boat together must be registered through a {@link RegisterCompetitorAndBoat} event. + * + */ +public class RegattaLogEntriesInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public RegattaLogEntriesInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Set performAnalysis() { + Set result = new HashSet(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegattaLogRegisterEntryEvent) { + result.add(((RegattaLogRegisterEntryEvent) event).getCompetitor()); + } + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java deleted file mode 100644 index cc6ff4cebbf..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.analyzing; - -import java.util.HashSet; -import java.util.Set; - -import com.sap.sailing.domain.abstractlog.AbstractLog; -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Boat; - -/** - * This class searches for RegisterBoatsEvents in the given log. - * - * TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredBoatsAnalyzer} or {@link RaceLogRegisteredBoatsAnalyzer} - * - * Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered boats for the race - * corresponding to the RaceLog/the races corresponding to the RegattaLog. - * - * This is the case as by default the boats registered on the RegattaLog are used for each race of the regatta - * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the - * {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}. Is an event of this type present, the boats written into the - * RaceLog are used instead of the boats in the RegattaLog. - * - */ -public class BoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> - extends BaseLogAnalyzer> { - - public BoatsInLogAnalyzer(LogT log) { - super(log); - } - - @Override - protected Set performAnalysis() { - Set result = new HashSet(); - - for (EventT event : getLog().getUnrevokedEvents()) { - if (event instanceof RegisterBoatEvent) { - result.add(((RegisterBoatEvent) event).getBoat()); - } - } - - return result; - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java index 7001fda0406..cbf3c02a0a4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredC import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; /** * This class searches for RegisterCompetitorEvents in the given log. @@ -27,15 +27,15 @@ import com.sap.sailing.domain.base.Competitor; * */ public class CompetitorsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> - extends BaseLogAnalyzer> { + extends BaseLogAnalyzer> { public CompetitorsInLogAnalyzer(LogT log) { super(log); } @Override - protected Set performAnalysis() { - Set result = new HashSet(); + protected Set performAnalysis() { + Set result = new HashSet<>(); for (EventT event : getLog().getUnrevokedEvents()) { if (event instanceof RegisterCompetitorEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java deleted file mode 100644 index 094a20c5d8d..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.events; - -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.Revokable; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Boat; -import com.sap.sse.common.IsManagedByCache; - -/** - * Register a boat for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. - * - * A dummy {@link Boat} implementation with only an {@link Boat#getId() id} may be used, - * if the boat is known to already exist on the server, as it is - * {@link IsManagedByCache#resolve(com.sap.sailing.domain.base.SharedDomainFactory) resolved} - * on arrival. - * @author Frank Mittag - * - */ -public interface RegisterBoatEvent extends AbstractLogEvent, Revokable { - Boat getBoat(); -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java index f1fb754ec8b..31fddb958a3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java @@ -1,12 +1,15 @@ package com.sap.sailing.domain.abstractlog.shared.events; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.IsManagedByCache; /** - * Register a competitor together with a boat for {@link RaceLog} and {@link RegattaLog} trackeds race and regattas. + * Register a competitor together with a boat for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, * if the competitor is known to already exist on the server, as it is @@ -15,5 +18,8 @@ import com.sap.sse.common.IsManagedByCache; * @author Frank Mittag * */ -public interface RegisterCompetitorAndBoatEvent extends RegisterBoatEvent, RegisterCompetitorEvent { +public interface RegisterCompetitorAndBoatEvent extends AbstractLogEvent, Revokable { + Competitor getCompetitor(); + + Boat getBoat(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java index 95897699c6c..66f6de6c905 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java @@ -5,9 +5,13 @@ import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.IsManagedByCache; /** + * ATTENTION: This is the old legacy log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + * * Register a competitor for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, @@ -18,5 +22,5 @@ import com.sap.sse.common.IsManagedByCache; * */ public interface RegisterCompetitorEvent extends AbstractLogEvent, Revokable { - Competitor getCompetitor(); + CompetitorWithBoat getCompetitor(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java deleted file mode 100644 index 8e57146971f..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.events.impl; - -import java.io.Serializable; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Boat; -import com.sap.sse.common.TimePoint; - -public abstract class BaseRegisterBoatEventImpl extends AbstractLogEventImpl implements - RegisterBoatEvent { - private static final long serialVersionUID = -224096196692372694L; - private final Boat boat; - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public BaseRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, Boat boat) throws IllegalArgumentException { - super(createdAt, logicalTimePoint, author, pId); - checkBoat(boat); - this.boat = boat; - } - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public BaseRegisterBoatEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Boat boat) throws IllegalArgumentException { - this(now(), logicalTimePoint, author, randId(), boat); - } - - private static void checkBoat(Boat boat) throws IllegalArgumentException { - if (boat == null) { - throw new IllegalArgumentException("Boat may not be null"); - } - } - - @Override - public Boat getBoat() { - return boat; - } - - @Override - public String getShortInfo() { - return "boat: " + getBoat().toString(); - } -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java index ac71017500e..d317da64a5e 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java @@ -5,20 +5,20 @@ import java.io.Serializable; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.TimePoint; public abstract class BaseRegisterCompetitorEventImpl extends AbstractLogEventImpl implements RegisterCompetitorEvent { private static final long serialVersionUID = -30864810737555657L; - private final Competitor competitor; + private final CompetitorWithBoat competitor; /** * @throws IllegalArgumentException * if {@code competitor} is null */ public BaseRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, Serializable pId, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, pId); checkCompetitor(competitor); this.competitor = competitor; @@ -29,18 +29,21 @@ public abstract class BaseRegisterCompetitorEventImpl extends Abstract * if {@code competitor} is null */ public BaseRegisterCompetitorEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Competitor competitor) throws IllegalArgumentException { + CompetitorWithBoat competitor) throws IllegalArgumentException { this(now(), logicalTimePoint, author, randId(), competitor); } - private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { + private static void checkCompetitor(CompetitorWithBoat competitor) throws IllegalArgumentException { if (competitor == null) { throw new IllegalArgumentException("Competitor may not be null"); } + if (competitor.getBoat() == null) { + throw new IllegalArgumentException("BoaCompetitor may not be null"); + } } @Override - public Competitor getCompetitor() { + public CompetitorWithBoat getCompetitor() { return competitor; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 47e24499e51..b6ccfbe10ed 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -12,17 +12,21 @@ import com.sap.sse.common.Color; import com.sap.sse.common.Duration; /** - * Manages a set of {@link Competitor} and {@link Boat} objects. There may be a transient implementation based on a simple cache, + * Manages a set of {@link Competitor}, {@link CompetitorWithBoat} and {@link Boat} objects. There may be a transient implementation based on a simple cache, * and there may be persistent implementations. * * @author Axel Uhl (d043530) * */ -public interface CompetitorStore extends CompetitorFactory, BoatFactory { +public interface CompetitorStore extends CompetitorFactory, BoatFactory, CompetitorWithBoatFactory { public interface CompetitorUpdateListener { void competitorUpdated(Competitor competitor); } + public interface CompetitorWithBoatUpdateListener { + void competitorWithBoatUpdated(CompetitorWithBoat competitorWithBoat); + } + public interface BoatUpdateListener { void boatUpdated(Boat boat); } @@ -36,14 +40,14 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { Competitor getExistingCompetitorByIdAsString(String idAsString); /** - * When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} + * When a competitor is queried using {@link #getOrCreateCompetitor()} * , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This * method can be used to reset a competitor object to what a tracking provider or an external system supplies to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the - * next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with + * {@link #getOrCreateCompetitor()}. After calling this method, the + * next call to {@link #getOrCreateCompetitor()} with * competitor's {@link Competitor#getId() ID} will - * {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as + * {@link #updateCompetitor()} the competitor in its updatable properties such as * the name, the sail ID and the nationality. */ void allowCompetitorResetToDefaults(Competitor competitor); @@ -78,8 +82,6 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); - CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); - CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); /** @@ -90,6 +92,63 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { void removeCompetitorUpdateListener(CompetitorUpdateListener listener); + /** + * If a valid competitor is returned and the caller has information available that could be used to update the competitor, + * the caller must check the result of {@link #isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat)}, and if true, + * must call {@link #getOrCreateCompetitorWithBoat()} to cause an update of the competitor's values. + */ + CompetitorWithBoat getExistingCompetitorWithBoatByIdAsString(String idAsString); + + /** + * When a competitor is queried using {@link #getOrCreateCompetitorWithBoat()} + * and the competitorWithBoat object for that ID already exists, it is generally returned unchanged, and the name, team + * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This + * method can be used to reset a competitorWithBoat object to what a tracking provider or an external system supplies to + * {@link #getOrCreateCompetitorWithBoat()}. After calling this method, the + * next call to {@link #getOrCreateCompetitorWithBoat()} with competitor's {@link CompetitorWithBoat#getId() ID} will + * {@link #updateCompetitorWithBoat()} the competitorWithBoat in its updatable properties such as + * the name, the sail ID and the nationality. + */ + void allowCompetitorWithBoatResetToDefaults(CompetitorWithBoat competitor); + + int getCompetitorsWithBoatCount(); + + /** + * Removes all competitors from this store. Use with due care. + */ + void clearCompetitorsWithBoat(); + + /** + * Obtains a non-live snapshot of the list of competitors managed by this store. + */ + Iterable getCompetitorsWithBoat(); + + void removeCompetitorWithBoat(CompetitorWithBoat competitor); + + /** + * Updates the competitor with {@link Competitor#getId() ID} id by setting the name, sail ID and nationality to + * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. + * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will + * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

      + * + * If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. + */ + CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); + + void addCompetitorsWithBoat(Iterable competitors); + + CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); + + /** + * Listeners added here are notified whenever {@link #updateCompetitorWithBoat()} is called + * for any competitor in this store. + */ + void addCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener); + + void removeCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener); + /** * If a valid boat is returned and the caller has information available that could be used to update the boat, * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, @@ -122,6 +181,8 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { void removeBoat(Boat boat); + void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat); + /** * Updates the boat with {@link Boat#getId() ID} id by setting the name, sail ID, etc. to * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java new file mode 100644 index 00000000000..7fcf35461af --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java @@ -0,0 +1,33 @@ +package com.sap.sailing.domain.base; + +import java.io.Serializable; +import java.net.URI; + +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Base interface for classes managing a set of {@link Competitor} objects which contain a {@link Boat} object belonging to the competitor. + */ +public interface CompetitorWithBoatFactory { + /** + * If a valid competitor is returned and the caller has information available that could be used to update the competitor, + * the caller must check the result of {@link #isCompetitorWithBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, + * must call {@link #getOrCreateCompetitorWithBoat(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the + * competitor's values. + */ + CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorWithBoatId); + + /** + * Checks if the competitor shall be updated from the default provided by, e.g., a tracking infrastructure. + * Callers of {@link #getExistingCompetitorWithBoatById(Serializable)} or {@link #getExistingCompetitorWithBoatByIdAsString(String)} + * must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update + * the competitor. + */ + boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat result); + + CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, Color displayColor, String email, + URI flagImageURI, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java index f2c9fa6aeaf..e0c3f5ca9d7 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sse.common.Color; -public interface SharedDomainFactory extends CompetitorFactory, BoatFactory { +public interface SharedDomainFactory extends CompetitorFactory, CompetitorWithBoatFactory, BoatFactory { /** * Looks up or, if not found, creates a {@link Nationality} object and re-uses threeLetterIOCCode also as the diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java index e137a34e322..37412b9d057 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java @@ -3,32 +3,30 @@ package com.sap.sailing.domain.base.impl; import java.io.Serializable; import java.net.URI; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; -public class CompetitorWithBoatImpl extends CompetitorImpl implements CompetitorWithBoat { +public class CompetitorWithBoatImpl extends CompetitorImpl implements DynamicCompetitorWithBoat { private static final long serialVersionUID = 22679449208503264L; - private final Boat boat; + private final DynamicBoat boat; public CompetitorWithBoatImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, - String searchTag, Boat boat) { + String searchTag, DynamicBoat boat) { super(id, name, shortName, color, email, flagImage, team, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); this.boat = boat; } - public CompetitorWithBoatImpl(Competitor competitor, Boat boat) { + public CompetitorWithBoatImpl(Competitor competitor, DynamicBoat boat) { this(competitor.getId(), competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), competitor.getFlagImage(), (DynamicTeam) competitor.getTeam(), competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), boat); } @Override - public Boat getBoat() { + public DynamicBoat getBoat() { return boat; } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java new file mode 100644 index 00000000000..4771f8b6067 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java @@ -0,0 +1,7 @@ +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.CompetitorWithBoat; + +public interface DynamicCompetitorWithBoat extends DynamicCompetitor, CompetitorWithBoat { + DynamicBoat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 6721043876d..429a06a965d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; @@ -342,6 +343,11 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { return getCompetitorStore().getExistingCompetitorById(competitorId); } + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorId) { + return getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); + } + @Override public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(competitor); @@ -358,6 +364,17 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } + @Override + public CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, + Color displayColor, String email, URI flagImageURI, DynamicTeam team, Double timeOnTimeFactor, + Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this); + } + return getCompetitorStore().getOrCreateCompetitorWithBoat(competitorId, name, shortName, displayColor, email, flagImageURI, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + } + @Override public Boat getExistingBoatById(Serializable boatId) { return getCompetitorStore().getExistingBoatById(boatId); @@ -368,6 +385,11 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { return getCompetitorStore().isBoatToUpdateDuringGetOrCreate(boat); } + @Override + public boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + return getCompetitorStore().isCompetitorWithBoatToUpdateDuringGetOrCreate(competitor); + } + @Override public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { return getCompetitorStore().getOrCreateBoat(id, name, boatClass, sailId, color); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 7b12a82791e..d9ffd133122 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -36,22 +36,35 @@ import com.sap.sse.concurrent.NamedReentrantReadWriteLock; public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable { private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName()); private static final long serialVersionUID = -4198298775476586931L; + private final Map competitorCache; private final Map competitorsByIdAsString; private transient Set competitorUpdateListeners; + + private final Map competitorWithBoatCache; + private final Map competitorsWithBoatByIdAsString; + private transient Set competitorWithBoatUpdateListeners; + private final Map boatCache; private final Map boatsByIdAsString; private transient Set boatUpdateListeners; /** * The competitors contained in this map will have their changeable properties - * {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID. + * {@link #updateCompetitor() updated} upon the next call to {@link #getOrCreateCompetitor()} for their ID. */ private final Set competitorsToUpdateDuringGetOrCreate; private transient WeakHashMap weakCompetitorDTOCache; + /** + * The competitors contained in this map will have their changeable properties + * {@link #updateCompetitor() updated} upon the next call to {@link #getOrCreateCompetitor()} for their ID. + */ + private final Set competitorsWithBoatToUpdateDuringGetOrCreate; + + private transient WeakHashMap weakCompetitorWithBoatDTOCache; + private final Set boatsToUpdateDuringGetOrCreate; private transient WeakHashMap weakBoatDTOCache; @@ -65,6 +78,13 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitorsToUpdateDuringGetOrCreate = new HashSet(); weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + + competitorWithBoatCache = new HashMap(); + competitorsWithBoatByIdAsString = new HashMap(); + competitorsWithBoatToUpdateDuringGetOrCreate = new HashSet(); + weakCompetitorWithBoatDTOCache = new WeakHashMap(); + competitorWithBoatUpdateListeners = Collections.synchronizedSet(new HashSet()); + boatCache = new HashMap(); boatsByIdAsString = new HashMap(); boatsToUpdateDuringGetOrCreate = new HashSet(); @@ -76,6 +96,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab ois.defaultReadObject(); weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + weakCompetitorWithBoatDTOCache = new WeakHashMap(); + competitorWithBoatUpdateListeners = Collections.synchronizedSet(new HashSet()); weakBoatDTOCache = new WeakHashMap(); boatUpdateListeners = Collections.synchronizedSet(new HashSet()); } @@ -101,6 +123,11 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab return result; } + @Override + public void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat) { + addNewBoat(separateBoat.getId(), separateBoat); + } + /** * Adds the competitor to this transient competitor collection so that it is available in * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional @@ -281,11 +308,6 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } } } - - @Override - public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { - return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); - } @Override public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { @@ -328,6 +350,204 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } } + /** CompetitorWithBoat stuff starts here */ + + @Override + public void addCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener) { + competitorWithBoatUpdateListeners.add(listener); + } + + @Override + public void removeCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener) { + competitorWithBoatUpdateListeners.remove(listener); + } + + private CompetitorWithBoat createCompetitorWithBoat(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, + DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + CompetitorWithBoat result = new CompetitorWithBoatImpl(id, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + addNewCompetitorWithBoat(id, result); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened")); + } + return result; + } + + /** + * Adds the competitor to this transient competitor collection so that it is available in + * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional + * measures such as durably storing the competitor. Overriding implementations must call this implementation. + */ + protected void addNewCompetitorWithBoat(Serializable id, CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + competitorWithBoatCache.put(id, competitor); + competitorsWithBoatByIdAsString.put(id.toString(), competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, Color displayColor, String email, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, + Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + CompetitorWithBoat result = getExistingCompetitorWithBoatById(competitorId); // avoid synchronization for successful read access + if (result == null) { + LockUtil.lockForWrite(lock); + try { + result = getExistingCompetitorWithBoatById(competitorId); // try again, now while holding the write lock + if (result == null) { + result = createCompetitorWithBoat(competitorId, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } else if (isCompetitorWithBoatToUpdateDuringGetOrCreate(result)) { + updateCompetitorWithBoat(result.getId().toString(), name, shortName, displayColor, email, team.getNationality(), + team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + competitorWithBoatNoLongerToUpdateDuringGetOrCreate(result); + } + return result; + } + + private void competitorWithBoatNoLongerToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + competitorsWithBoatToUpdateDuringGetOrCreate.remove(competitor); + } + + @Override + public boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + return competitorsWithBoatToUpdateDuringGetOrCreate.contains(competitor); + } + + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorWithBoatId) { + LockUtil.lockForRead(lock); + try { + return competitorWithBoatCache.get(competitorWithBoatId); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatByIdAsString(String competitorWithBoatIdAsString) { + LockUtil.lockForRead(lock); + try { + return competitorsWithBoatByIdAsString.get(competitorWithBoatIdAsString); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public int getCompetitorsWithBoatCount() { + LockUtil.lockForRead(lock); + try { + return competitorWithBoatCache.size(); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void clearCompetitorsWithBoat() { + LockUtil.lockForWrite(lock); + try { + competitorWithBoatCache.clear(); + competitorsWithBoatByIdAsString.clear(); + competitorsWithBoatToUpdateDuringGetOrCreate.clear(); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Clearing competitorWithBoat store "+this, new Exception("here is where it happened")); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Iterable getCompetitorsWithBoat() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(competitorWithBoatCache.values()); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + logger.fine("removing competitor "+competitor+" from competitor store "+this); + competitorWithBoatCache.remove(competitor.getId()); + competitorsWithBoatByIdAsString.remove(competitor.getId().toString()); + weakCompetitorWithBoatDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { + DynamicCompetitorWithBoat competitor = (DynamicCompetitorWithBoat) getExistingCompetitorWithBoatByIdAsString(idAsString); + if (competitor != null) { + LockUtil.lockForWrite(lock); + try { + competitor.setName(newName); + competitor.setShortName(newShortName); + competitor.setColor(newDisplayColor); + competitor.setEmail(newEmail); + competitor.setFlagImage(newFlagImageUri); + competitor.getTeam().setNationality(newNationality); + competitor.getTeam().setImage(newTeamImageUri); + competitor.setTimeOnTimeFactor(timeOnTimeFactor); + competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile); + competitor.setSearchTag(newSearchTag); + weakCompetitorDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + synchronized (competitorUpdateListeners) { + for (CompetitorUpdateListener listener : competitorUpdateListeners) { + listener.competitorUpdated(competitor); + } + } + return (CompetitorWithBoat) competitor; + } + + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { + return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); + } + + @Override + public void allowCompetitorWithBoatResetToDefaults(CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + competitorsWithBoatToUpdateDuringGetOrCreate.add(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public void addCompetitorsWithBoat(Iterable competitors) { + LockUtil.lockForWrite(lock); + try { + for (CompetitorWithBoat competitor: competitors) { + competitorWithBoatCache.put(competitor.getId(), competitor); + competitorsWithBoatByIdAsString.put(competitor.getId().toString(), competitor); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + /** Boat stuff starts here */ @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 3e84daed991..303a1649001 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -1,17 +1,18 @@ package com.sap.sailing.domain.test; -import java.io.Serializable; import java.util.Collections; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorFactory; import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -21,35 +22,29 @@ public abstract class AbstractLeaderboardTest { private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); public static CompetitorAndBoat createCompetitorAndBoat(String competitorName) { - Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + return new CompetitorAndBoatImpl(createCompetitor(competitorName), createBoat(competitorName)); + } + + public static Competitor createCompetitor(String competitorName) { + return new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, /* searchTag */ null); } - public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, CompetitorFactory competitorFactory) { - Competitor c = competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + public static Boat createBoat(String competitorName) { + return new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); } - public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, Serializable id) { - Competitor c = new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + public static CompetitorWithBoat createCompetitorWithBoat(String competitorName) { + DynamicBoat b = (DynamicBoat) createBoat(competitorName); + return new CompetitorWithBoatImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, /* searchTag */ null, b); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index 63bddb6eee3..964f1b1a615 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -19,12 +19,14 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.impl.BoatClassImpl; @@ -49,7 +51,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; /** * Tests the behavior of the class {@link CompetitorProviderFromRaceColumnsAndRegattaLike}, paying particular - * attention to its caching and cache invalidation logic. When competitors are added to regatta logs or race logs + * attention to its caching and cache invalidation logic. When competitors and their boats are added to regatta logs or race logs * or when a tracked race is attached to a column or a column is added or removed, its caches need to be * invalidated and re-calculated accordingly. * @@ -65,6 +67,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final int NUMBER_OF_COMP_LISTS = 4; @SuppressWarnings("unchecked") private List[] compLists = (List[]) new List[NUMBER_OF_COMP_LISTS]; + private Map boats = new HashMap<>(); @Before public void setUp() { @@ -84,7 +87,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard for (int l = 0; l < NUMBER_OF_COMP_LISTS; l++) { compLists[l] = new ArrayList(); for (int i = 0; i < 10; i++) { - compLists[l].add(createCompetitorAndBoat("" + l + "/" + i).getCompetitor()); + Competitor c = createCompetitor("" + l + "/" + i); + compLists[l].add(c); + boats.put(c, createBoat("" + l + "/" + i)); } } competitorProviderRegattaLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard); @@ -100,10 +105,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard regatta.removeSeries(seriesToRemove); } RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); - final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); + final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c); + final RegattaLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c)); regattaLog.add(registerCompetitorEvent); competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -137,10 +142,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME); final int passId = 1; final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); - final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[0]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), author, passId, c, boats.get(c)); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -180,7 +185,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c, boats.get(c))); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -198,15 +203,15 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c, boats.get(c))); } RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); int passId = 1; - final RaceLogUseCompetitorsFromRaceLogEventImpl usesCompetitorsFromRaceLogEvent = new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId); + final RaceLogUseCompetitorsAndBoatsFromRaceLogEvent usesCompetitorsFromRaceLogEvent = new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId); raceLog.add(usesCompetitorsFromRaceLogEvent); for (Competitor c : compLists[1]) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c, boats.get(c))); } // expected are only the competitors in the RaceLog, because only one RaceColumn is // registered, which has the competitors registered in the RaceLog. @@ -217,7 +222,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard raceLog.revokeEvent(author, usesCompetitorsFromRaceLogEvent); assertRegattaAndRaceCompetitors(new HashSet<>(compLists[0])); // And now re-introduce per-race competitors and validate again that the cache adjusts properly: - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); assertRegattaAndRaceCompetitors(new HashSet<>(compLists[1])); } @@ -302,9 +307,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); int passId = 1; - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); for (Competitor c : compLists[0]) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c, boats.get(c))); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -319,10 +324,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard @Test public void testSimpleCompetitorListOnRegattaLogInRegattaLeaderboard() throws NotRevokableException { RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); - final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); + final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c); + final RegattaLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c)); regattaLog.add(registerCompetitorEvent); competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -355,14 +360,14 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c))); } final RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); final int passId = 1; - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); - final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[passId]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), author, passId, c, boats.get(c)); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index f8c4a107633..499e115a5be 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -15,7 +15,9 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumnListener; @@ -74,7 +76,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); leaderboard.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -96,14 +98,14 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedLeaderboard.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } - private RegattaLogRegisterCompetitorEventImpl createRegattaLogEvent() { - final RegattaLogRegisterCompetitorEventImpl event = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), /* author */ null, - AbstractTracTracLiveTest.createCompetitorAndBoat("Someone").getCompetitor()); + private RegattaLogRegisterCompetitorAndBoatEvent createRegattaLogEvent() { + final RegattaLogRegisterCompetitorAndBoatEvent event = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), /* author */ null, + AbstractLeaderboardTest.createCompetitor("Someone"), AbstractLeaderboardTest.createBoat("Some boat")); return event; } @@ -129,7 +131,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); regatta.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -151,7 +153,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedRegatta.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -165,7 +167,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa LeaderboardDTO dto = leaderboard.getLeaderboardDTO(now.plus(10), Collections.emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); assertTrue(dto.competitors.isEmpty()); - final RegattaLogRegisterCompetitorEvent event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); regatta.getRegattaLog().add(event); LeaderboardDTO dto2 = leaderboard.computeDTO(now.plus(20), Collections.emptySet(), /* addOverallDetails */ false, /* waitForLatestAnalyses */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); @@ -197,7 +199,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa LeaderboardDTO dto = deserializedLeaderboard.getLeaderboardDTO(now.plus(10), Collections.emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); assertTrue(dto.competitors.isEmpty()); - final RegattaLogRegisterCompetitorEvent event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedLeaderboard.getRegatta().getRegattaLog().add(event); LeaderboardDTO dto2 = deserializedLeaderboard.computeDTO(now.plus(20), Collections.emptySet(), /* addOverallDetails */ false, /* waitForLatestAnalyses */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); 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 3719ae66517..0601e8b343f 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 @@ -31,8 +31,8 @@ import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseImpl; 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 9c5c12ebf3d..51ef72b3212 100644 --- 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 @@ -46,7 +46,6 @@ import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.SensorFix; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; @@ -556,11 +555,6 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - return null; - } - @Override public Iterable getBoatsRegisteredInRegattaLog() { return null; 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 75dfcd195d1..4b6d60826f7 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 @@ -678,6 +678,9 @@ public class DomainFactoryImpl implements DomainFactory { if (isSeparateBoat && existingCompetitor.getShortName() != rc.getCompetitor().getShortName()) { // in case we find a boat info we only want to update the shortName field of the competitor (instead of using sailID) CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); + + competitorStore.migrateCompetitorToHaveASeparateBoat(existingCompetitor, boatOfCompetitor); + boolean isOldCompetitorToUpdateDuringGetOrCreate = competitorStore.isCompetitorToUpdateDuringGetOrCreate(existingCompetitor); competitorStore.allowCompetitorResetToDefaults(existingCompetitor); existingCompetitor = competitorStore.getOrCreateCompetitor(existingCompetitor.getId(), existingCompetitor.getName(), diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index 147bfd81995..fcac2fac31d 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -309,26 +309,15 @@ public interface RaceColumn extends Named { Iterable getAvailableMarks(Fleet fleet); /** - * Returns the competitor set registered in the race column's race log associated to the passed fleet. If competitor - * registration in RaceLog is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or in case of a + * Returns the competitor and their boats registered in the race column's race log associated to the passed fleet. If competitor + * registration in RaceLog is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} or in case of a * MetaLeaderboardColumn an empty set is returned. * - * @return competitors in RaceLog if registration {@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabled} or - * empty set in case registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or this + * @return competitors and boats in RaceLog if registration {@link #enableCompetitorAndBoatRegistrationOnRaceLog(Fleet) enabled} or + * empty set in case registration is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} or this * column belongs to a {@link MetaLeaderboard} */ - Iterable getCompetitorsRegisteredInRacelog(Fleet fleet); - - /** - * Checks whether competitor registration on RaceLog is enabled. - * - * @return boolean if competitor registration on the RaceLog is enabled, false in case this column belongs to a - * {@link MetaLeaderboard} - * - * @see #enableCompetitorRegistrationOnRaceLog(Fleet) - * @see #disableCompetitorRegistrationOnRaceLog(Fleet) - */ - boolean isCompetitorRegistrationInRacelogEnabled(Fleet fleet); + Map getCompetitorsAndBoatsRegisteredInRacelog(Fleet fleet); /** * Checks whether competitor and boat registration on RaceLog is enabled. @@ -340,28 +329,7 @@ public interface RaceColumn extends Named { * @see #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) */ boolean isCompetitorAndBoatRegistrationInRacelogEnabled(Fleet fleet); - - /** - * Activates competitor registration on the race column's race log associated to the passed fleet. As a result, - * competitor registrations that were added to the race log before this was disabled by - * {@link #disableCompetitorRegistrationOnRaceLog(Fleet)} will again be honored.

      - * - * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. - */ - void enableCompetitorRegistrationOnRaceLog(Fleet fleet); - /** - * Disables competitor registration on the race column's race log associated to the passed fleet. Performs nothing - * in case this column belongs to a {@link MetaLeaderboard}. If there are already competitor registrations on the - * race log, those will not be removed from the log but they will be ignored, and the regatta log's competitor - * registrations will be used instead. Re-{@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabling} competitor - * registrations in the race log will cause such existing registrations to be honored again. - *

      - * - * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. - */ - void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; - /** * Activates competitor and boat registration on the race column's race log associated to the passed fleet. As a result, * competitor and boat registrations that were added to the race log before this was disabled by @@ -384,22 +352,22 @@ public interface RaceColumn extends Named { void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; /** - * Registers a competitor on the the race column's race log associated to the passed fleet. + * Registers a competitor and his boat on the the race column's race log associated to the passed fleet. * - * @throws CompetitorRegistrationOnRaceLogDisabledException - * thrown if competitor registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} + * @throws CompetitorAndBoatRegistrationOnRaceLogDisabledException + * thrown if competitor registration is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} * on racelog as well as if RaceColumn belongs to a {@link MetaLeaderboard} */ - void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; + void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; /** - * Registers competitors on the the race column's race log associated to the passed fleet. + * Registers competitors and their boats on the the race column's race log associated to the passed fleet. * - * @throws CompetitorRegistrationOnRaceLogDisabledException + * @throws CompetitorAndBoatRegistrationOnRaceLogDisabledException * thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a * {@link MetaLeaderboard} */ - void registerCompetitors(Iterable competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; + void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; /** * Deregisters a competitor on the the race column's race log associated to the passed fleet. @@ -418,7 +386,4 @@ public interface RaceColumn extends Named { * {@link MetaLeaderboard} */ void deregisterCompetitors(Iterable currentlyRegisteredCompetitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; - - void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; - void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index b4ebbf1e361..93d63e4c6d6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -21,13 +21,9 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; @@ -264,19 +260,8 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public Iterable getAllCompetitors(final Fleet fleet) { - final Iterable result; - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - result = trackedRace.getRace().getCompetitors(); - } else { - // if no tracked race is found, use competitors from race/regatta log depending on whether - // the mapping event is present or not; this assumes that if a tracked - // race exists, its competitors set takes precedence over what's in the race log. Usually, - // the tracked race will have the same competitors as those in the race log, or more because - // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze(); - result = viaRaceLog; - } + Set result = new HashSet<>(); + Util.addAll(getAllCompetitorsAndTheirBoats(fleet).keySet(), result); return result; } @@ -306,26 +291,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem return result; } - @Override - public void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { - registerCompetitors(Collections.singleton(competitor), fleet); - } - - @Override - public void registerCompetitors(Iterable competitors, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - if (!isCompetitorRegistrationInRacelogEnabled(fleet)) { - throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); - } - TimePoint now = MillisecondsTimePoint.now(); - RaceLog raceLog = getRaceLog(fleet); - int passId = raceLog.getCurrentPassId(); - for (Competitor competitor : competitors) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(now, now, raceLogEventAuthorForRaceColumn, - UUID.randomUUID(), passId, competitor)); - } - } - @Override public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { Map competitorsAndBoats = new HashMap<>(); @@ -337,7 +302,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem public void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { if (!isCompetitorAndBoatRegistrationInRacelogEnabled(fleet)) { - throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException("Competitor and boat registration not allowed for fleet "+fleet+" in column "+this); + throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); } TimePoint now = MillisecondsTimePoint.now(); RaceLog raceLog = getRaceLog(fleet); @@ -357,7 +322,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public void deregisterCompetitors(Iterable competitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { - if (!isCompetitorRegistrationInRacelogEnabled(fleet)) { + if (!isCompetitorAndBoatRegistrationInRacelogEnabled(fleet)) { throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); } HashSet competitorSet = new HashSet(); @@ -436,31 +401,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem return result; } - @Override - public void enableCompetitorRegistrationOnRaceLog(Fleet fleet) { - TimePoint now = MillisecondsTimePoint.now(); - RaceLog raceLog = getRaceLog(fleet); - int passId = raceLog.getCurrentPassId(); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(now, raceLogEventAuthorForRaceColumn, now, UUID.randomUUID(), passId)); - } - - @Override - public void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException { - RaceLog raceLog = getRaceLog(fleet); - List events = new AllEventsOfTypeFinder<>(raceLog, true, RaceLogUseCompetitorsFromRaceLogEvent.class).analyze(); - for (RaceLogEvent event : events) { - raceLog.lockForRead(); - try { - event = raceLog.getEventById(event.getId()); - } finally { - raceLog.unlockAfterRead(); - } - if (event != null) { - raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event, "revoke triggered by GWT user action"); - } - } - } - @Override public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) { TimePoint now = MillisecondsTimePoint.now(); 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 e90c18cc3c4..12830773095 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 @@ -26,11 +26,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -54,7 +54,6 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.AbstractLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -159,7 +158,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene private boolean useStartTimeInference; private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; - private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; + private AbstractLogEventAuthor regattaLogEventAuthorForRegatta = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -425,14 +424,6 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return competitorsProvider; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - if (boatsProvider == null) { - boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); - } - return boatsProvider; - } - @Override public Iterable getAllCompetitors() { Set result = new HashSet(); @@ -865,7 +856,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public Iterable getCompetitorsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLog(); - CompetitorsInLogAnalyzer analyzer = new CompetitorsInLogAnalyzer<>( + RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -881,7 +872,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene TimePoint now = MillisecondsTimePoint.now(); for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForRegatta, + regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForRegatta, UUID.randomUUID(), competitor)); } } @@ -902,7 +893,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public Iterable getBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLog(); - BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + RegattaLogBoatsInLogAnalyzer analyzer = new RegattaLogBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -931,7 +922,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public void deregisterBoats(Iterable boats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForRegatta); + RegattaLogBoatDeregistrator deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForRegatta); deregisterer.deregister(deregisterer.analyze()); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java index c4cd3aa8feb..05b6811c87e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java @@ -1,11 +1,12 @@ package com.sap.sailing.domain.base.impl; import java.util.Collections; +import java.util.Map; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -122,23 +123,12 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn { } @Override - public Iterable getCompetitorsRegisteredInRacelog(final Fleet fleet) { + public Map getCompetitorsAndBoatsRegisteredInRacelog(final Fleet fleet) { RaceLog raceLog = getRaceLog(fleet); if (raceLog == null) { - return Collections.emptySet(); + return Collections.emptyMap(); } else { - RaceLogRegisteredCompetitorsAnalyzer analyzer = new RaceLogRegisteredCompetitorsAnalyzer(raceLog); - return analyzer.analyze(); - } - } - - @Override - public boolean isCompetitorRegistrationInRacelogEnabled(final Fleet fleet) { - RaceLog raceLog = getRaceLog(fleet); - if (raceLog == null) { - return false; - } else { - RaceLogUsesOwnCompetitorsAnalyzer analyzer = new RaceLogUsesOwnCompetitorsAnalyzer(raceLog); + RaceLogRegisteredCompetitorsAndBoatsAnalyzer analyzer = new RaceLogRegisteredCompetitorsAndBoatsAnalyzer(raceLog); return analyzer.analyze(); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java index f67e9ae5fc4..29d5b5ee948 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java @@ -1,12 +1,9 @@ package com.sap.sailing.domain.leaderboard; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.regattalike.HasRegattaLike; public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceColumns { CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider(); - - BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 3be2500817a..f1492ae4fce 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -14,11 +14,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; @@ -53,12 +53,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI */ private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; - /** - * Cache for the combined boats of this leaderboard; taken from the {@link TrackedRace#getRace() races of the - * tracked races} associated with this leaderboard. Updated when the set of tracked races changes. - */ - private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; - private final AbstractLogEventAuthor regattaLogEventAuthorForAbstractLeaderboard = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -126,14 +120,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return competitorsProvider; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - if (boatsProvider == null) { - boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); - } - return boatsProvider; - } - @Override public Competitor getCompetitorByIdAsString(String idAsString) { for (Competitor competitor : getAllCompetitors()) { @@ -221,7 +207,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI @Override public Iterable getCompetitorsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - CompetitorsInLogAnalyzer analyzer = new CompetitorsInLogAnalyzer<>( + RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -237,7 +223,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI TimePoint now = MillisecondsTimePoint.now(); for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, + regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, UUID.randomUUID(), competitor)); } } @@ -261,14 +247,14 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI */ @Override public Iterable getAllBoats() { - return getOrCreateBoatsProvider().getAllBoats(); + return getBoatsRegisteredInRegattaLog(); } @Override public Iterable getBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + RegattaLogBoatsInLogAnalyzer analyzer = new RegattaLogBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -297,7 +283,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI @Override public void deregisterBoats(Iterable boats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); + RegattaLogBoatDeregistrator deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); deregisterer.deregister(deregisterer.analyze()); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java deleted file mode 100644 index 8d3414e002c..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.sap.sailing.domain.leaderboard.impl; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -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.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction; -import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; - -/** - * A caching provider of a boat set, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of - * a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been - * provided, it is cached. The cache is invalidated when one of the following events occurs: - *

        - *
      • a boat is registered with or unregistered from a race log of any of the race columns or the regatta log
      • - *
      • a race column is added or removed
      • - *
      • a tracked race is linked to or unlinked from any of the race columns
      • - *
      • the racelog is marked as providing it's own boats via the {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
      • - *
      • the racelog is marked as no longer providing it's own boats by revoking an event of type {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
      • - *
      - * - * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient - * fields if they want to be serializable themselves. - * - * @author Frank Mittag - * - */ -public class BoatProviderFromRaceColumnsAndRegattaLike { - private static final Logger logger = Logger.getLogger(BoatProviderFromRaceColumnsAndRegattaLike.class - .getName()); - - private final HasRaceColumnsAndRegattaLike provider; - - private final RegattaLogEventVisitor regattaLogBoatsCacheInvalidationListener; - - private final RaceLogEventVisitor raceLogBoatsCacheInvalidationListener; - - private final RaceColumnListener raceColumnListener; - - private Iterable allBoatsCache; - - private final ConcurrentMap, Iterable> allBoatsCacheByRace; - - public BoatProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) { - super(); - this.provider = provider; - this.allBoatsCacheByRace = new ConcurrentHashMap<>(); - // A note regarding listener serializability: RaceLogListener and RegattaLogListener objects - // don't need to be serializable as the log listeners are a transient structure. The race column - // listeners, however, need to explicitly declare that they are transient. - // This enclosing object is intended not to be serialized and shall be re-constructed by - // its users after de-serialization. Therefore, the transient-ness of the log listeners works - // as intended, and the race column listener explicitly returns true from its isTransient() - // method. - regattaLogBoatsCacheInvalidationListener = new BaseRegattaLogEventVisitor() { - @Override - public void visit(RegattaLogRegisterBoatEvent event) { - invalidateAllBoatsCaches(); - } - - @Override - public void visit(RegattaLogRevokeEvent event) { - try { - if (RegattaLogRegisterBoatEvent.class.isAssignableFrom(Class.forName(event - .getRevokedEventType()))) { - invalidateAllBoatsCaches(); - } - } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, - "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); - } - } - }; - raceLogBoatsCacheInvalidationListener = new BaseRaceLogEventVisitor() { - - @Override - public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { - invalidateAllBoatsCaches(); - } - - @Override - public void visit(RaceLogRevokeEvent event) { - try { - final Class revokedEventClass = Class.forName(event.getRevokedEventType()); - // - if (RaceLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(revokedEventClass) || - RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { - invalidateAllBoatsCaches(); - } - } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, - "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); - } - } - }; - raceColumnListener = new RaceColumnListenerWithDefaultAction() { - private static final long serialVersionUID = -8678230058730043052L; - - @Override - public void defaultAction() { - } - - /** - * As the entire provider object is considered transient, its listeners are so, too. - */ - @Override - public boolean isTransient() { - return true; - } - - @Override - public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - invalidateAllBoatsCaches(); - } - - @Override - public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - invalidateAllBoatsCaches(); - } - - @Override - public void raceColumnAddedToContainer(RaceColumn raceColumn) { - invalidateAllBoatsCaches(); - } - - @Override - public void raceColumnRemovedFromContainer(RaceColumn raceColumn) { - invalidateAllBoatsCaches(); - } - }; - } - - public Iterable getAllBoats() { - if (allBoatsCache == null) { - final Set result = new HashSet<>(); - boolean hasRaceColumns = false; - for (RaceColumn rc : provider.getRaceColumns()) { - hasRaceColumns = true; - Util.addAll(rc.getAllCompetitorsAndTheirBoats().values(), result); - for (final Fleet fleet : rc.getFleets()) { - rc.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); - } - } - final RegattaLog regattaLog = provider.getRegattaLike().getRegattaLog(); - if (!hasRaceColumns) { - // If no race exists, the regatta log-provided boat registrations will not have - // been considered yet; add them: - final Set regattaLogProvidedBoats = new BoatsInLogAnalyzer<>(regattaLog).analyze(); - result.addAll(regattaLogProvidedBoats); - } - // else, don't add regatta log boats because they have been added in each column already. - // The boats are collected from the races. Those, however, will be the regatta log - // boats if the race does not define its own. - // Note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's - // listeners set - provider.addRaceColumnListener(raceColumnListener); - // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there - regattaLog.addListener(regattaLogBoatsCacheInvalidationListener); - allBoatsCache = result; - } - return allBoatsCache; - } - - /** - * Obtains boats from the regatta log and adds those from the tracked race for the raceColumn/fleet - * combination or the race log, if no tracked race is attached for this combination. - */ - public Iterable getAllBoats(final RaceColumn raceColumn, final Fleet fleet) { - Pair key = new Pair<>(raceColumn, fleet); - Iterable result = allBoatsCacheByRace.get(key); - if (result == null) { - final Set resultSet = new HashSet<>(); - // raceColumn already considers trackedRace, RaceLog and RegattaLog - Util.addAll(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values(), resultSet); - // note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's - // listeners set - raceColumn.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); - provider.addRaceColumnListener(raceColumnListener); - // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there - provider.getRegattaLike().getRegattaLog().addListener(regattaLogBoatsCacheInvalidationListener); - result = resultSet; - allBoatsCacheByRace.put(key, result); - } - return result; - } - - private void invalidateAllBoatsCaches() { - allBoatsCache = null; - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's - // listeners set - provider.getRegattaLike().getRegattaLog().removeListener(regattaLogBoatsCacheInvalidationListener); - for (final RaceColumn rc : provider.getRaceColumns()) { - for (final Fleet fleet : rc.getFleets()) { - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race - // log's listeners set - rc.getRaceLog(fleet).removeListener(raceLogBoatsCacheInvalidationListener); - } - } - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column - // listeners set - provider.removeRaceColumnListener(raceColumnListener); - allBoatsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it - // should be good enough. - // The change frequency of boats lists on individual races is much lower than the access frequency to this - // structure. - } - -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java index a508ec868eb..9e7b0d27cfa 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -11,14 +12,18 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -37,8 +42,8 @@ import com.sap.sse.common.Util.Pair; *
    21. a competitor is registered with or unregistered from a race log of any of the race columns or the regatta log
    22. *
    23. a race column is added or removed
    24. *
    25. a tracked race is linked to or unlinked from any of the race columns
    26. - *
    27. the racelog is marked as providing it's own competitors via the {@link RaceLogUseCompetitorsFromRaceLogEvent}
    28. - *
    29. the racelog is marked as no longer providing it's own competitors by revoking an event of type {@link RaceLogUseCompetitorsFromRaceLogEvent}
    30. + *
    31. the racelog is marked as providing it's own competitors via the {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
    32. + *
    33. the racelog is marked as no longer providing it's own competitors by revoking an event of type {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
    34. * * * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient @@ -80,11 +85,15 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { invalidateAllCompetitorsCaches(); } + public void visit(RegattaLogRegisterCompetitorAndBoatEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RegattaLogRevokeEvent event) { try { - if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event - .getRevokedEventType()))) { + if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType())) || + RegattaLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) { invalidateAllCompetitorsCaches(); } } catch (ClassNotFoundException e) { @@ -99,18 +108,30 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { invalidateAllCompetitorsCaches(); } + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { invalidateAllCompetitorsCaches(); } + @Override + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RaceLogRevokeEvent event) { try { final Class revokedEventClass = Class.forName(event.getRevokedEventType()); // if (RaceLogRegisterCompetitorEvent.class.isAssignableFrom(revokedEventClass) || - RaceLogUseCompetitorsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { + RaceLogUseCompetitorsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { invalidateAllCompetitorsCaches(); } } catch (ClassNotFoundException e) { @@ -171,8 +192,8 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { if (!hasRaceColumns) { // If no race exists, the regatta log-provided competitor registrations will not have // been considered yet; add them: - final Set regattaLogProvidedCompetitors = new CompetitorsInLogAnalyzer<>(regattaLog).analyze(); - result.addAll(regattaLogProvidedCompetitors); + final Map regattaLogProvidedCompetitors = new CompetitorsAndBoatsInLogAnalyzer<>(regattaLog).analyze(); + result.addAll(regattaLogProvidedCompetitors.keySet()); } // else, don't add regatta log competitors because they have been added in each column already. // The competitors are collected from the races. Those, however, will be the regatta log diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java index d55d72bd7e0..d0ddd1f8497 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java @@ -185,10 +185,6 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr return getFullLeaderboard().getOrCreateCompetitorsProvider(); } - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - return getFullLeaderboard().getOrCreateBoatsProvider(); - } - public Regatta getRegatta() { return getFullLeaderboard().getRegatta(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 13356340de0..f9766d2bb45 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -238,6 +238,18 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R return result; } + @Override + public Map getAllCompetitorsAndTheirBoats() { + // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + + @Override + public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { + // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + @Override public RegattaLog getRegattaLog() { return null; @@ -263,19 +275,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R return Collections.emptySet(); } - @Override - public void registerCompetitor(Competitor competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void registerCompetitors(Iterable competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { @@ -300,14 +299,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R throw new CompetitorRegistrationOnRaceLogDisabledException(); } - @Override - public void enableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - - @Override - public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - @Override public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { } @@ -316,18 +307,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R public void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { } - @Override - public Map getAllCompetitorsAndTheirBoats() { - // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } - - @Override - public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { - // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } - /** * When the leaderboard name changes, notify this to this object's {@link RaceColumnListener}s as a * change of this race column's name, but only if no {@link Leaderboard#getDisplayName() display name} 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 2547b155557..aaa83b444ec 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 @@ -296,7 +296,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { @Override public void visit(RaceLogFixedMarkPassingEvent event) { if (markPassingUpdateListener != null) { - markPassingUpdateListener.addFixedPassing(event.getInvolvedBoats().get(0), event.getZeroBasedIndexOfPassedWaypoint(), + markPassingUpdateListener.addFixedPassing(event.getInvolvedCompetitors().get(0), event.getZeroBasedIndexOfPassedWaypoint(), event.getTimePointOfFixedPassing()); } } @@ -304,7 +304,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { @Override public void visit(RaceLogSuppressedMarkPassingsEvent event) { if (markPassingUpdateListener != null) { - markPassingUpdateListener.addSuppressedPassing(event.getInvolvedBoats().get(0), + markPassingUpdateListener.addSuppressedPassing(event.getInvolvedCompetitors().get(0), event.getZeroBasedIndexOfFirstSuppressedWaypoint()); } } @@ -326,10 +326,10 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { } if (revokedEvent instanceof RaceLogSuppressedMarkPassingsEvent) { - markPassingUpdateListener.removeSuppressedPassing(revokedEvent.getInvolvedBoats().get(0)); + markPassingUpdateListener.removeSuppressedPassing(revokedEvent.getInvolvedCompetitors().get(0)); } if (revokedEvent instanceof RaceLogFixedMarkPassingEvent) { - markPassingUpdateListener.removeFixedPassing(revokedEvent.getInvolvedBoats().get(0), + markPassingUpdateListener.removeFixedPassing(revokedEvent.getInvolvedCompetitors().get(0), ((RaceLogFixedMarkPassingEvent) revokedEvent).getZeroBasedIndexOfPassedWaypoint()); } } 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 d7cbe012138..fc2b634b982 100644 --- 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 @@ -1086,6 +1086,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** + * TODO: bug 2822 Is this still required? * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. * The iteration order in the result matches that of the {@code iterable} passed. */ @@ -1098,6 +1099,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } + /** + * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. + * The iteration order in the result matches that of the {@code iterable} passed. + */ + private List convertToCompetitorDTOs(Map competitorsAndBoats) { + List result = new ArrayList(); + for (Entry competitorAndBoatEntry : competitorsAndBoats.entrySet()) { + CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue()); + result.add(competitorDTO); + } + return result; + } + private List convertToBoatDTOs(Iterable iterable) { List result = new ArrayList(); for (Boat b : iterable) { @@ -2524,7 +2538,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final RaceLogTrackingState raceLogTrackingState = raceLog == null ? RaceLogTrackingState.NOT_A_RACELOG_TRACKED_RACE : new RaceLogTrackingStateAnalyzer(raceLog).analyze(); final boolean raceLogTrackerExists = raceLog == null ? false : getService().getRaceTrackerById(raceLog.getId()) != null; - final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitors(fleet)); + final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); final boolean courseExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getCourseMarks(fleet)); final RaceLogTrackingInfoDTO raceLogTrackingInfo = new RaceLogTrackingInfoDTO(raceLogTrackerExists, competitorRegistrationsExist, courseExist, raceLogTrackingState); @@ -5466,7 +5480,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private Competitor getCompetitor(CompetitorDTO dto) { return getService().getCompetitorStore().getExistingCompetitorByIdAsString(dto.getIdAsString()); } - + @Override public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, Set competitorDTOs) throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { @@ -5477,13 +5491,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - Iterable competitorsToRemove = raceColumn.getCompetitorsRegisteredInRacelog(fleet); + Map competitorsToRemove = raceColumn.getCompetitorsAndBoatsRegisteredInRacelog(fleet); HashSet competitorSetToRemove = new HashSet<>(); - Util.addAll(competitorsToRemove, competitorSetToRemove); + Util.addAll(competitorsToRemove.keySet(), competitorSetToRemove); filterDuplicates(competitorsToRegister, competitorSetToRemove); raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); - raceColumn.registerCompetitors(competitorsToRegister, fleet); + + // TODO bug 2822: temporary commented out -> needs first cleanup of CompetitorDTO and BoatDTO passing + // raceColumn.registerCompetitors(competitorsToRegister, fleet); } @Override @@ -6053,7 +6069,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = getCompetitor(competitorDTO); RaceLogFixedMarkPassingEvent oldFixedMarkPassingEvent = null; for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { - if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedBoats().contains(competitor)) { + if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedCompetitors().contains(competitor)) { RaceLogFixedMarkPassingEvent fixedEvent = (RaceLogFixedMarkPassingEvent) event; if (Util.equalsWithNull(fixedEvent.getZeroBasedIndexOfPassedWaypoint(), indexOfWaypoint)) { oldFixedMarkPassingEvent = fixedEvent; @@ -6082,7 +6098,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = getCompetitor(competitorDTO); NavigableSet unrevokedEvents = raceLog.getUnrevokedEvents(); for (RaceLogEvent event : unrevokedEvents) { - if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedBoats().contains(competitor)) { + if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedCompetitors().contains(competitor)) { oldSuppressedMarkPassingEvent = (RaceLogSuppressedMarkPassingsEvent) event; break; } @@ -6357,7 +6373,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return convertToCompetitorDTOs(raceColumn.getAllCompetitors(fleet)); + return convertToCompetitorDTOs(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); } @Override @@ -6381,7 +6397,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return convertToCompetitorDTOs(raceColumn.getCompetitorsRegisteredInRacelog(fleet)); + return convertToCompetitorDTOs(raceColumn.getCompetitorsAndBoatsRegisteredInRacelog(fleet)); } @Override @@ -6389,7 +6405,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return raceColumn.isCompetitorRegistrationInRacelogEnabled(fleet); + return raceColumn.isCompetitorAndBoatRegistrationInRacelogEnabled(fleet); } private Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException{ @@ -6424,7 +6440,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotRevokableException, NotFoundException { if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.disableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + raceColumn.disableCompetitorAndBoatRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } } @@ -6432,7 +6448,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws IllegalArgumentException, NotFoundException { if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.enableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + raceColumn.enableCompetitorAndBoatRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java index c02a07b0145..0228ccd345d 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java @@ -2,10 +2,12 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import org.junit.Before; @@ -15,20 +17,51 @@ import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.MongoException; import com.mongodb.WriteConcern; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.impl.CollectionNames; -import com.sap.sailing.domain.test.AbstractLeaderboardTest; +import com.sap.sse.common.Color; import com.sap.sse.common.Util; public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { private DomainFactory domainFactory; + + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + public static Competitor createCompetitor(String competitorName) { + return createCompetitor(competitorName, competitorName); + } + + public static Competitor createCompetitor(String competitorName, Serializable id) { + return new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + } + + public static CompetitorWithBoat createCompetitorWithBoat(String competitorName) { + Competitor c = createCompetitor(competitorName); + DynamicBoat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); + return new CompetitorWithBoatImpl(c, b); + } + public StoreAndLoadCompetitorsTest() throws UnknownHostException, MongoException { super(); } @@ -59,12 +92,12 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat(competitorName1).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor(competitorName1); c.setShortName(competitorShortName1); c.setFlagImage(flagImageURI1); mongoObjectFactory.storeCompetitor(c); - Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); + Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); assertEquals(1, Util.size(allCompetitors)); DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next(); assertEquals(flagImageURI1, loadedCompetitor.getFlagImage()); @@ -90,7 +123,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); c.setName("Hasso Plattner"); @@ -104,7 +137,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso").getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso"); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); @@ -118,7 +151,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index b6c821f6d23..b9951252e07 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -34,12 +34,13 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; 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.impl.BoatClassImpl; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.persistence.PersistenceFactory; @@ -53,6 +54,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); protected MongoObjectFactoryImpl mongoFactory = (MongoObjectFactoryImpl) PersistenceFactory.INSTANCE .getMongoObjectFactory(getMongoService(), new MockSmartphoneImeiServiceFinderFactory()); @@ -84,7 +86,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { assertEquals(expectedEvent.getCreatedAt(), actualEvent.getCreatedAt()); assertEquals(expectedEvent.getLogicalTimePoint(), actualEvent.getLogicalTimePoint()); assertEquals(expectedEvent.getId(), actualEvent.getId()); - assertEquals(expectedEvent.getInvolvedBoats().size(), Util.size(actualEvent.getInvolvedBoats())); + assertEquals(expectedEvent.getInvolvedCompetitors().size(), Util.size(actualEvent.getInvolvedCompetitors())); assertEquals(expectedEvent.getPassId(), actualEvent.getPassId()); } @@ -209,14 +211,15 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { } @Test - public void testStoreAndLoadRegisterCompetitorEvent() { - RaceLogRegisterCompetitorEvent expectedEvent = new RaceLogRegisterCompetitorEventImpl(expectedEventTime, + public void testStoreAndLoadRegisterCompetitorAndBoatEvent() { + RaceLogRegisterCompetitorAndBoatEvent expectedEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, DomainFactory.INSTANCE.getOrCreateCompetitor( "comp", "comp", "c", null, null, null, null, - /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null)); + /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null), + DomainFactory.INSTANCE.getOrCreateBoat("boat", "b", boatClass, null, null)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); - RaceLogRegisterCompetitorEvent actualEvent = loadEvent(dbObject); + RaceLogRegisterCompetitorAndBoatEvent actualEvent = loadEvent(dbObject); assertBaseFields(expectedEvent, actualEvent); assertEquals(expectedEvent.getCompetitor(), actualEvent.getCompetitor()); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 5ee3ee1f088..6186725cb1b 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -27,9 +27,9 @@ import java.util.logging.Logger; import org.junit.Test; import com.mongodb.MongoException; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorAndBoat; @@ -418,18 +418,18 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), /* defaultCourseAreaId */ null, /*buoyZoneRadiusInHullLengths*/ 2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); - CompetitorAndBoat competitorAndBoat1 = AbstractLeaderboardTest.createCompetitorAndBoat("Humba1"); - CompetitorAndBoat competitorAndBoat2 = AbstractLeaderboardTest.createCompetitorAndBoat("Humba2"); - res.getCompetitorStore().addCompetitors(Arrays.asList(competitorAndBoat1.getCompetitor(), competitorAndBoat2.getCompetitor())); - regatta.getRegattaLog().add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitorAndBoat1.getCompetitor())); - regatta.getRegattaLog().add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitorAndBoat2.getCompetitor())); - assertTrue(Util.contains(regatta.getAllCompetitors(), competitorAndBoat1)); - assertTrue(Util.contains(regatta.getAllCompetitors(), competitorAndBoat2)); + Competitor competitor1 = AbstractLeaderboardTest.createCompetitor("Humba1"); + Competitor competitor2 = AbstractLeaderboardTest.createCompetitor("Humba2"); + res.getCompetitorStore().addCompetitors(Arrays.asList(competitor1, competitor2)); + regatta.getRegattaLog().add(new RegattaLogRegisterEntryEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitor1)); + regatta.getRegattaLog().add(new RegattaLogRegisterEntryEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitor2)); + assertTrue(Util.contains(regatta.getAllCompetitors(), competitor1)); + assertTrue(Util.contains(regatta.getAllCompetitors(), competitor2)); addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); RegattaLeaderboard fullLeaderboard = res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); // use the set-up and add a regatta leaderboard with eliminations that wraps the regatta leaderboard RegattaLeaderboardWithEliminations withEliminations = res.addRegattaLeaderboardWithEliminations("U16", /* leaderboardDisplayName */ "Display Name", fullLeaderboard); - res.apply(new UpdateEliminatedCompetitorsInLeaderboard(withEliminations.getName(), Collections.singleton(competitorAndBoat1.getCompetitor()))); + res.apply(new UpdateEliminatedCompetitorsInLeaderboard(withEliminations.getName(), Collections.singleton(competitor1))); DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); @@ -451,8 +451,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest assertTrue(loadedLeaderboardWithEliminations instanceof RegattaLeaderboardWithEliminations); assertEquals("Display Name", loadedLeaderboardWithEliminations.getDisplayName()); assertEquals(withEliminations.getAllCompetitors(), loadedLeaderboardWithEliminations.getAllCompetitors()); - assertTrue(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitorAndBoat1.getCompetitor())); - assertFalse(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitorAndBoat2.getCompetitor())); + assertTrue(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitor1)); + assertFalse(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitor2)); } @Test diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index d9defb4a071..86416afe3bd 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -369,7 +369,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; assertEquals(now, loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); - assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(0, loadedConfirmedEvent.getInvolvedCompetitors().size()); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); @@ -419,7 +419,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD assertEquals(event.getLogicalTimePoint(), loadedPositioningEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedPositioningEvent.getInvolvedCompetitors().size()); final CompetitorResults expectedCompetiorResults = event.getPositionedCompetitorsIDsNamesMaxPointsReasons(); final CompetitorResults loadedCompetitorResults = loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons(); assertCompetitorResultsEqual(expectedCompetiorResults, loadedCompetitorResults); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index d6b8207c8fe..73b0f572cf3 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -221,7 +221,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin assertEquals(event.getLogicalTimePoint(), loadedPositioningEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedPositioningEvent.getInvolvedCompetitors().size()); assertCompetitorResultsEqual(event.getPositionedCompetitorsIDsNamesMaxPointsReasons(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { @@ -245,7 +245,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin assertEquals(event.getLogicalTimePoint(), loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedConfirmedEvent.getPassId()); assertEquals(event.getId(), loadedConfirmedEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedConfirmedEvent.getInvolvedCompetitors().size()); assertCompetitorResultsEqual(event.getPositionedCompetitorsIDsNamesMaxPointsReasons(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { @@ -267,7 +267,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; assertEquals(now, loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); - assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(0, loadedConfirmedEvent.getInvolvedCompetitors().size()); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java index 663514ab034..946693834b7 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java @@ -8,11 +8,9 @@ import java.util.logging.Logger; import org.json.simple.JSONObject; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorFactory; import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorWithBoatFactory; import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; @@ -24,7 +22,7 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.RGBColor; public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { - protected final CompetitorFactory competitorFactory; + protected final CompetitorWithBoatFactory competitorWithBoatFactory; protected final JsonDeserializer teamJsonDeserializer; protected final JsonDeserializer boatJsonDeserializer; private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); @@ -34,12 +32,12 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorFactory = competitorFactory; + public CompetitorWithBoatJsonDeserializer(CompetitorWithBoatFactory competitorWithBoatFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorWithBoatFactory = competitorWithBoatFactory; this.teamJsonDeserializer = teamJsonDeserializer; this.boatJsonDeserializer = boatDeserializer; } @@ -92,12 +90,12 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer public static RaceLogEventDeserializer create(SharedDomainFactory domainFactory, JsonDeserializer deviceDeserializer) { JsonDeserializer competitorDeserializer = CompetitorJsonDeserializer.create(domainFactory); + JsonDeserializer competitorWithBoatDeserializer = CompetitorWithBoatJsonDeserializer.create(domainFactory); return new RaceLogEventDeserializer( new RaceLogFlagEventDeserializer(competitorDeserializer), new RaceLogStartTimeEventDeserializer(competitorDeserializer), @@ -81,7 +84,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogDenoteForTrackingEventDeserializer(competitorDeserializer, domainFactory), new RaceLogStartTrackingEventDeserializer(competitorDeserializer), new RaceLogRevokeEventDeserializer(competitorDeserializer), - new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer), + new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer, competitorWithBoatDeserializer), new RaceLogRegisterCompetitorAndBoatEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogAdditionalScoringInformationEventDeserializer(competitorDeserializer), new RaceLogFixedMarkPassingEventDeserializer(competitorDeserializer), diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java index ba85cdddb62..b5e86ef052a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java @@ -25,7 +25,7 @@ public class RaceLogRegisterCompetitorAndBoatEventDeserializer extends BaseRaceL @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; + assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorAndBoatEvent"; Boat boat = boatDeserializer.deserialize(object); return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0), boat); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java index 6272c1e5dbb..14a58db69ae 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java @@ -9,19 +9,24 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorEventDeserializer extends BaseRaceLogEventDeserializer { + private final JsonDeserializer competitorWithBoatDeserializer; - public RaceLogRegisterCompetitorEventDeserializer(JsonDeserializer competitorDeserializer) { + public RaceLogRegisterCompetitorEventDeserializer(JsonDeserializer competitorDeserializer, JsonDeserializer competitorWithBoatDeserializer) { super(competitorDeserializer); + this.competitorWithBoatDeserializer = competitorWithBoatDeserializer; } @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; - return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0)); + CompetitorWithBoat competitorWithBoat = competitorWithBoatDeserializer.deserialize(object); + return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitorWithBoat); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java similarity index 51% rename from java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java rename to java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java index 1494ca5d317..585480a153a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java @@ -4,35 +4,35 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -public class CompetitorAndBoatJsonSerializer implements JsonSerializer { +public class CompetitorWithBoatJsonSerializer implements JsonSerializer { private final JsonSerializer boatJsonSerializer; private final JsonSerializer competitorJsonSerializer; - public static CompetitorAndBoatJsonSerializer create() { - return new CompetitorAndBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); + public static CompetitorWithBoatJsonSerializer create() { + return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); } - public CompetitorAndBoatJsonSerializer() { + public CompetitorWithBoatJsonSerializer() { this(null, null); } - public CompetitorAndBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { + public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { this.competitorJsonSerializer = competitorJsonSerializer; this.boatJsonSerializer = boatJsonSerializer; } @Override - public JSONObject serialize(CompetitorAndBoat competitorAndBoat) { - JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getCompetitor()); + public JSONObject serialize(CompetitorWithBoat competitor) { + JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitor); - serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitorAndBoat.getBoat() == null ? "" : competitorAndBoat.getBoat().getSailID()); + serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID()); - if (boatJsonSerializer != null) { - serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitorAndBoat.getBoat())); + if (boatJsonSerializer != null && competitor.getBoat() != null) { + serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitor.getBoat())); } return serializedCompetitor; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java index 04b0f436ecb..6ac4fb4accd 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java @@ -37,7 +37,7 @@ public abstract class BaseRaceLogEventSerializer implements JsonSerializer, Rac new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), new RaceLogStartTrackingEventSerializer(competitorSerializer), new RaceLogRevokeEventSerializer(competitorSerializer), - new RaceLogRegisterBoatEventSerializer(competitorSerializer), new RaceLogRegisterCompetitorEventSerializer(competitorSerializer), new RaceLogRegisterCompetitorAndBoatEventSerializer(competitorSerializer), new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), @@ -136,7 +135,6 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac JsonSerializer denoteForTrackingSerializer, JsonSerializer createRaceSerializer, JsonSerializer revokeSerializer, - JsonSerializer registerBoatSerializer, JsonSerializer registerCompetitorSerializer, JsonSerializer registerCompetitorAndBoatSerializer, JsonSerializer additionalScoringInformationSerializer, diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java deleted file mode 100644 index 7729f67d5ee..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.racelog.impl; - -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; - -public class RaceLogRegisterBoatEventSerializer extends BaseRaceLogEventSerializer { - - public static final String VALUE_CLASS = RegisterBoatEvent.class.getSimpleName(); - - public RaceLogRegisterBoatEventSerializer( - JsonSerializer competitorSerializer) { - super(competitorSerializer); - } - - @Override - protected String getClassFieldValue() { - return VALUE_CLASS; - } -} diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java index 1f9d5c80c20..9d3b6f72e38 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java @@ -54,7 +54,7 @@ public abstract class AbstractEventSerializerTest emptyList()); + when(event.getInvolvedCompetitors()).thenReturn(Collections. emptyList()); when(event.getAuthor()).thenReturn(author); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java index fb3d55fd8da..9e365d43ca4 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java @@ -78,8 +78,8 @@ public class RaceLogCourseDesignChangedEventSerializerTest { assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); assertEquals(event.getCourseDesignerMode(), deserializedEvent.getCourseDesignerMode()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); compareCourseData(event.getCourseDesign(), deserializedEvent.getCourseDesign()); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 007975c5c36..3e1653b065d 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -26,9 +26,12 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChanged import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; @@ -57,7 +60,6 @@ public class RaceLogEventSerializerTest { private JsonSerializer denoteForTrackingEventSerializer; private JsonSerializer startTrackingEventSerializer; private JsonSerializer revokeEventSerializer; - private JsonSerializer registerBoatEventSerializer; private JsonSerializer registerCompetitorEventSerializer; private JsonSerializer registerCompetitorAndBoatEventSerializer; private JsonSerializer additionalScoringInformationSerializer; @@ -90,7 +92,6 @@ public class RaceLogEventSerializerTest { denoteForTrackingEventSerializer = mock(JsonSerializer.class); startTrackingEventSerializer = mock(JsonSerializer.class); revokeEventSerializer = mock(JsonSerializer.class); - registerBoatEventSerializer = mock(JsonSerializer.class); registerCompetitorEventSerializer = mock(JsonSerializer.class); registerCompetitorAndBoatEventSerializer = mock(JsonSerializer.class); additionalScoringInformationSerializer = mock(JsonSerializer.class); @@ -108,7 +109,7 @@ public class RaceLogEventSerializerTest { pathfinderEventSerializer, gateLineOpeningTimeEventSerializer, startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer, denoteForTrackingEventSerializer, startTrackingEventSerializer, revokeEventSerializer, - registerBoatEventSerializer, registerCompetitorEventSerializer, registerCompetitorAndBoatEventSerializer, + registerCompetitorEventSerializer, registerCompetitorAndBoatEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, additionalScoringInformationSerializer, dependentStartTimeEventSerializer, startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer, useBoatsFromRaceLogEventSerializer, @@ -245,13 +246,14 @@ public class RaceLogEventSerializerTest { } @Test - public void testRegisterCompetitorEventSerializer() { + public void testRegisterCompetitorAndBoatEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0, - DomainFactory.INSTANCE - .getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ - null, null)); + Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ + null, null); + Boat b = DomainFactory.INSTANCE.getOrCreateBoat("boat", "b", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null, null); + + RaceLogEvent event = new RaceLogRegisterCompetitorAndBoatEventImpl(null, author, 0, c, b); serializer.serialize(event); - verify(registerCompetitorEventSerializer).serialize(event); + verify(registerCompetitorAndBoatEventSerializer).serialize(event); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java index 39ecdf518d3..49a50da94e1 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -76,8 +76,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); @@ -95,8 +95,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertTrue(Util.isEmpty(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); @@ -113,8 +113,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertTrue(Util.isEmpty(event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java index 3ee5c285332..6b2e7f8abc4 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java @@ -67,8 +67,8 @@ public class RaceLogWindFixEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); compareWind(event.getWindFix(), deserializedEvent.getWindFix()); } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java index 748c11f7608..c4bb45d2071 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java @@ -7,7 +7,8 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; @@ -16,10 +17,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public final static String MANEUVERS = "maneuvers"; - private final CompetitorAndBoatJsonSerializer competitorSerializer; + private final CompetitorWithBoatJsonSerializer competitorSerializer; private final ManeuverJsonSerializer maneuverSerializer; - public ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { super(); this.competitorSerializer = competitorSerializer; this.maneuverSerializer = maneuverSerializer; @@ -35,7 +36,7 @@ public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializ Boat boat = competitorAndBoatEntry.getValue(); final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); + forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); final JSONArray maneuvers = new JSONArray(); forCompetitorJson.put(MANEUVERS, maneuvers); for (final Maneuver maneuver : getManeuversDuringRace(trackedRace, competitor)) { diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java index c9bf8b687eb..7e656c4fcc3 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java @@ -11,7 +11,8 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; @@ -26,7 +27,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria public JSONObject serialize(TrackedRace trackedRace) { final Course course = trackedRace.getRace().getCourse(); JSONObject result = new JSONObject(); - CompetitorAndBoatJsonSerializer competitorWithBoatSerializer = CompetitorAndBoatJsonSerializer.create(); + CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); @@ -35,7 +36,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria Boat boat = competitorAndBoatEntry.getValue(); JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); + forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); final NavigableSet markPassingsForCompetitor = trackedRace.getMarkPassings(competitor); JSONArray markPassingsForCompetitorJson = new JSONArray(); forCompetitorJson.put(MARKPASSINGS, markPassingsForCompetitorJson); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java index 859140b0d90..231fbec82a3 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java @@ -7,33 +7,34 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.server.gateway.serialization.JsonSerializer; public class RaceEntriesJsonSerializer implements JsonSerializer { public static final String FIELD_NAME = "name"; public static final String FIELD_COMPETITORS = "competitors"; - private final JsonSerializer competitorAndBoatSerializer; + private final JsonSerializer competitorWithBoatSerializer; public RaceEntriesJsonSerializer() { this(null); } - public RaceEntriesJsonSerializer(JsonSerializer competitorAndBoatSerializer) { - this.competitorAndBoatSerializer = competitorAndBoatSerializer; + public RaceEntriesJsonSerializer(JsonSerializer competitorWithBoatSerializer) { + this.competitorWithBoatSerializer = competitorWithBoatSerializer; } public JSONObject serialize(RaceDefinition race) { JSONObject result = new JSONObject(); result.put(FIELD_NAME, race.getName()); - if(competitorAndBoatSerializer != null) { + if(competitorWithBoatSerializer != null) { JSONArray competitorsJson = new JSONArray(); for (Entry competitorAndBoatEntry: race.getCompetitorsAndTheirBoats().entrySet()) { - competitorsJson.add(competitorAndBoatSerializer.serialize(new CompetitorAndBoatImpl(competitorAndBoatEntry.getKey(), - competitorAndBoatEntry.getValue()))); + competitorsJson.add(competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitorAndBoatEntry.getKey(), + (DynamicBoat) competitorAndBoatEntry.getValue()))); } result.put(FIELD_COMPETITORS, competitorsJson); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index 510a5a14bcc..1079f29b343 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.UUID; import javax.ws.rs.core.Response; @@ -20,7 +19,8 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.BoatClassImpl; @@ -75,7 +75,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest Response response = resource.postCheckin(json.toString(), leaderboard.getName()); assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); - Set registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze(); + Map registeredCompetitors = new CompetitorsAndBoatsInLogAnalyzer<>(log).analyze(); Map>> mappings = new RegattaLogDeviceCompetitorMappingFinder( log).analyze(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index aef98773eb3..df847b8830e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -36,7 +36,8 @@ 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.Waypoint; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Position; @@ -67,7 +68,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJson import com.sap.sailing.server.gateway.serialization.impl.AbstractTrackedRaceDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DefaultWindTrackJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DistanceJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer; @@ -211,7 +212,7 @@ public class RegattasResource extends AbstractSailingServerResource { if (race == null) { response = getBadRaceErrorResponse(regattaName, raceName); } else { - CompetitorAndBoatJsonSerializer competitorJsonSerializer = CompetitorAndBoatJsonSerializer.create(); + CompetitorWithBoatJsonSerializer competitorJsonSerializer = CompetitorWithBoatJsonSerializer.create(); JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorJsonSerializer); JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race); @@ -861,7 +862,7 @@ public class RegattasResource extends AbstractSailingServerResource { .build(); } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); - ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorAndBoatJsonSerializer(), + ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorWithBoatJsonSerializer(), new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer())); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); @@ -930,11 +931,11 @@ public class RegattasResource extends AbstractSailingServerResource { return result; }); } - CompetitorAndBoatJsonSerializer serializer = new CompetitorAndBoatJsonSerializer(); + CompetitorWithBoatJsonSerializer serializer = new CompetitorWithBoatJsonSerializer(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { Boat boat = trackedRace.getBoatOfCompetitor(c); - JSONObject jsonCompetitor = serializer.serialize(new CompetitorAndBoatImpl(c, boat)); + JSONObject jsonCompetitor = serializer.serialize(new CompetitorWithBoatImpl(c, (DynamicBoat) boat)); result.add(jsonCompetitor); } String json = result.toJSONString(); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java index 395f020fb01..c489a1a89bf 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java @@ -181,7 +181,7 @@ public class RaceLogReplicationTest extends AbstractLogReplicationTestnull); - DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitor("Test Competitor"); Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); @@ -72,7 +75,7 @@ public class CompetitorStoreTest { assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); - DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ @@ -89,7 +92,43 @@ public class CompetitorStoreTest { assertSame(competitor2, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); } - + + @Test + public void testPersistentCompetitorWithBoatStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicCompetitorWithBoat template = (DynamicCompetitorWithBoat) AbstractLeaderboardTest.createCompetitorWithBoat("Test Competitor"); + CompetitorWithBoat competitor = persistentStore1.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null, template.getBoat()); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + CompetitorWithBoat competitor2 = persistentStore2.getExistingCompetitorWithBoatById(template.getId()); + assertNotSame(competitor2, template); // the new store loads new instances from the database + assertEquals(template.getId(), competitor2.getId()); + assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); + assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); + assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); + + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorWithBoat("Test Competitor").getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + CompetitorWithBoat competitor3 = persistentStore2.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null, template.getBoat()); + assertSame(competitor2, competitor3); // use existing competitor despite the different team + assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged + assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality + // expected to remain unchanged + // now mark the competitor as to update from defaults + persistentStore2.allowCompetitorWithBoatResetToDefaults(competitor2); + CompetitorWithBoat competitor4 = persistentStore2.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null, template.getBoat()); + assertSame(competitor2, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } + @Test public void testPersistentBoatStore() { CompetitorStore persistentStore1 = new PersistentCompetitorStore( diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 70bbfd900bc..5d805358e28 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -52,9 +52,10 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -292,7 +293,7 @@ public class MasterDataImportTest { // Set RegattaLog event TimePoint regattaLogTimepoint = new MillisecondsTimePoint(84392048L); - RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl( + RegattaLogRegisterEntryEvent registerEvent = new RegattaLogRegisterEntryEventImpl( regattaLogTimepoint, regattaLogTimepoint, author, UUID.randomUUID(), competitor); regatta.getRegattaLog().add(registerEvent); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java index 3bee1d8a5e3..730de4a79e5 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/PersistentCompetitorStore.java @@ -51,14 +51,19 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory); this.storeTo = storeTo; if (clearCompetitorsAndBaots) { + storeTo.removeAllCompetitorsWithBoat(); storeTo.removeAllCompetitors(); storeTo.removeAllBoats(); } else { // TODO bug2822: How to migrate the competitors with contained boats to competitors with separate boat - Collection allCompetitors = loadFrom.loadAllCompetitors(); - for (CompetitorWithBoat competitor : allCompetitors) { + Collection allCompetitors = loadFrom.loadAllCompetitors(); + for (Competitor competitor : allCompetitors) { addCompetitorToTransientStore(competitor.getId(), competitor); } + Collection allCompetitorsWithBoat = loadFrom.loadAllCompetitorsWithBoat(); + for (CompetitorWithBoat competitor : allCompetitorsWithBoat) { + addCompetitorWithBoatToTransientStore(competitor.getId(), competitor); + } Collection allBoats = loadFrom.loadAllBoats(); for (Boat boat: allBoats) { addBoatToTransientStore(boat.getId(), boat); @@ -86,8 +91,15 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl ois.defaultReadObject(); storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); } - - private void addCompetitorToTransientStore(Serializable id, CompetitorWithBoat competitor) { + + @Override + public void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat) { + storeTo.storeCompetitor(existingCompetitor); + storeTo.storeBoat(separateBoat); + super.addNewBoat(separateBoat.getId(), separateBoat); + } + + private void addCompetitorToTransientStore(Serializable id, Competitor competitor) { super.addNewCompetitor(id, competitor); } @@ -124,6 +136,46 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo.storeCompetitors(competitors); super.addCompetitors(competitors); } + + ///////////// + private void addCompetitorWithBoatToTransientStore(Serializable id, CompetitorWithBoat competitor) { + super.addNewCompetitorWithBoat(id, competitor); + } + + @Override + protected void addNewCompetitorWithBoat(Serializable id, CompetitorWithBoat competitor) { + storeTo.storeCompetitorWithBoat(competitor); + super.addNewCompetitorWithBoat(id, competitor); + } + + @Override + public void clearCompetitorsWithBoat() { + storeTo.removeAllCompetitorsWithBoat(); + super.clearCompetitorsWithBoat(); + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { + storeTo.removeCompetitorWithBoat(competitor); + super.removeCompetitorWithBoat(competitor); + } + + @Override + public CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newRgbDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, + String searchTag) { + CompetitorWithBoat result = super.updateCompetitorWithBoat(idAsString, newName, newShortName, newRgbDisplayColor, newEmail, newNationality, + newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + storeTo.storeCompetitorWithBoat(result); + return result; + } + + @Override + public void addCompetitorsWithBoat(Iterable competitors) { + storeTo.storeCompetitorsWithBoat(competitors); + super.addCompetitorsWithBoat(competitors); + } + private void addBoatToTransientStore(Serializable id, Boat boat) { super.addNewBoat(id, boat); 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 2acd7a366ef..7b7e4b43771 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 @@ -471,18 +471,18 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes /** * Constructs a {@link DomainFactory base domain factory} that uses this object's {@link #competitorStore competitor - * store} for competitor management. This base domain factory is then also used for the construction of the - * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor collection, - * hence removes all previously persistent competitors. This is the default for testing and for backward - * compatibility with prior releases that did not support a persistent competitor collection. + * store} for competitor and boat management. This base domain factory is then also used for the construction of the + * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor and boat collections, + * hence removes all previously persistent competitors and boats. This is the default for testing and for backward + * compatibility with prior releases that did not support a persistent competitor and boat collection. */ public RacingEventServiceImpl() { - this(/* clearPersistentCompetitorStore */ true, /* serviceFinderFactory */ null, /* restoreTrackedRaces */ false); + this(/* clearPersistentCompetitorAndBoatStore */ true, /* serviceFinderFactory */ null, /* restoreTrackedRaces */ false); } public RacingEventServiceImpl(WindStore windStore, SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) { - this(/* clearPersistentCompetitorStore */ true, windStore, sensorFixStore, serviceFinderFactory, + this(/* clearPersistentCompetitorAndBoatStore */ true, windStore, sensorFixStore, serviceFinderFactory, /* sailingNotificationService */ null, /* restoreTrackedRaces */ false); } @@ -490,8 +490,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes this.bundleContext = bundleContext; } - public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) { - this(clearPersistentCompetitorStore, serviceFinderFactory, null, /* sailingNotificationService */ null, restoreTrackedRaces); + public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) { + this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null, restoreTrackedRaces); } /** @@ -506,14 +506,14 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes * a notification service to call upon events worth notifying users about, or {@code null} if no * notification service is available, e.g., in test set-ups */ - public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, + public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener, SailingNotificationService sailingNotificationService, boolean restoreTrackedRaces) { this((final RaceLogResolver raceLogResolver)-> { return new ConstructorParameters() { private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory), - clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); + clearPersistentCompetitorAndBoatStore, serviceFinderFactory, raceLogResolver); @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } From c5f08e3dfa8d5ea092281dc447314ad7eb646f46 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 28 Aug 2017 16:57:22 +0200 Subject: [PATCH 053/271] Fixed compile errors after lastest master merge (caused my Competitor/Boat separation related issues) --- .../mining/GPSFixMovingWithOriginInfo.java | 7 +++++++ .../sailing/polars/mining/PolarDataMiner.java | 2 +- .../gateway/jaxrs/api/EventsResource.java | 7 ++++--- .../gateway/jaxrs/api/RegattasResource.java | 18 ++++++++++-------- .../server/statistics/StatisticsTest.java | 14 ++++++++++---- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithOriginInfo.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithOriginInfo.java index 69a0671379d..1c376b468d6 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithOriginInfo.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/GPSFixMovingWithOriginInfo.java @@ -1,5 +1,6 @@ package com.sap.sailing.polars.mining; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.TrackedRace; @@ -14,11 +15,13 @@ public class GPSFixMovingWithOriginInfo { private final GPSFixMoving fix; private final TrackedRace trackedRace; private final Competitor competitor; + private final Boat boat; public GPSFixMovingWithOriginInfo(GPSFixMoving fix, TrackedRace trackedRace, Competitor competitor) { this.fix = fix; this.trackedRace = trackedRace; this.competitor = competitor; + this.boat = trackedRace.getBoatOfCompetitor(competitor); } public GPSFixMoving getFix() { @@ -32,4 +35,8 @@ public class GPSFixMovingWithOriginInfo { public Competitor getCompetitor() { return competitor; } + + public Boat getBoat() { + return boat; + } } diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java index 36f870a3ed9..4b56065ffad 100755 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java @@ -197,7 +197,7 @@ public class PolarDataMiner { element.getCompetitor(), backendPolarSheetGenerationSettings.getPctOfLeadingCompetitorsToInclude())) { result = true; - final BoatClass boatClass = element.getCompetitor().getBoat().getBoatClass(); + final BoatClass boatClass = element.getBoat().getBoatClass(); AtomicInteger count = stats.get(boatClass); if (count == null) { count = new AtomicInteger(1); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java index d109cdb1d1c..ac10eefdf6f 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java @@ -276,7 +276,8 @@ public class EventsResource extends AbstractSailingServerResource { RegattaCreationParametersDTO regattaCreationParametersDTO = new RegattaCreationParametersDTO( createDefaultSeriesCreationParameters(regattaName, numberOfRaces)); UUID regattaId = UUID.randomUUID(); - addRegatta(regattaName, controlTrackingFromStartAndFinishTimes, useStartTimeInterference, + boolean canBoatsOfCompetitorsChangePerRace = false; + addRegatta(regattaName, canBoatsOfCompetitorsChangePerRace, controlTrackingFromStartAndFinishTimes, useStartTimeInterference, buoyZoneRadiusInHullLengths, courseAreaId, boatClassName, /* startDate */ null, /* endDate */ null, scoringScheme, rankingMetric, regattaId, regattaCreationParametersDTO, leaderboardDiscardThresholds, numberOfRaces); final RegattaLeaderboard leaderboard = addLeaderboard(regattaName, leaderboardDiscardThresholds); @@ -454,7 +455,7 @@ public class EventsResource extends AbstractSailingServerResource { return getService().apply(new AddCourseAreas(eventId, courseAreaNames, courseAreaIds))[0]; } - private Regatta addRegatta(String regattaName, boolean controlTrackingFromStartAndFinishTimes, boolean useStartTimeInterference, + private Regatta addRegatta(String regattaName, boolean canBoatsOfCompetitorsChangePerRace, boolean controlTrackingFromStartAndFinishTimes, boolean useStartTimeInterference, double buoyZoneRadiusInHullLengths, UUID courseAreaId, String boatClassName, MillisecondsTimePoint startDate, MillisecondsTimePoint endDate, ScoringScheme scoringScheme, RankingMetrics rankingMetric, UUID regattaId, RegattaCreationParametersDTO regattaCreationParametersDTO, @@ -462,7 +463,7 @@ public class EventsResource extends AbstractSailingServerResource { if (enforceSecurityChecks) { SecurityUtils.getSubject().checkPermission(Permission.REGATTA.getStringPermissionForObjects(Mode.CREATE, regattaName)); } - Regatta regatta = getService().apply(new AddSpecificRegatta(regattaName, boatClassName, startDate, endDate, regattaId, + Regatta regatta = getService().apply(new AddSpecificRegatta(regattaName, boatClassName, canBoatsOfCompetitorsChangePerRace, startDate, endDate, regattaId, regattaCreationParametersDTO, /* isPersistent */ true, scoringScheme, courseAreaId, buoyZoneRadiusInHullLengths, useStartTimeInterference, controlTrackingFromStartAndFinishTimes, rankingMetric)); return regatta; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index af7c5c8935d..f0dd9a955d7 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -37,6 +37,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.datamining.SailingPredefinedQueries; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumnInSeries; @@ -44,9 +45,9 @@ import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.common.Distance; @@ -325,19 +326,20 @@ public class RegattasResource extends AbstractSailingServerResource { response = getBadBoatClassResponse(boatClassName); } else { final User user = getService(SecurityService.class).getCurrentUser(); - final Competitor competitor = getService().getCompetitorStore().getOrCreateCompetitor(UUID.randomUUID(), - user.getFullName() == null ? user.getName() : user.getFullName(), + final Boat boat = new BoatImpl(UUID.randomUUID(), user.getName(), + getService().getBaseDomainFactory().getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), + sailId); + final CompetitorWithBoat competitor = getService().getCompetitorStore().getOrCreateCompetitorWithBoat(UUID.randomUUID(), + user.getFullName() == null ? user.getName() : user.getFullName(), /* shortName */ null, /* displayColor */ null, user.getEmail(), /* flagImageURI */ null, new TeamImpl(user.getName(), Collections.singleton(new PersonImpl(user.getFullName() == null ? user.getName() : user.getFullName(), getService().getBaseDomainFactory().getOrCreateNationality(nationalityThreeLetterIOCCode), /* dateOfBirth */ null, /* description */ null)), - /* coach */ null), new BoatImpl(user.getName(), - getService().getBaseDomainFactory().getOrCreateBoatClass(boatClassName, /* typicallyStartsUpwind */ true), - sailId), timeOnTimeFactor, + /* coach */ null), timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMileAsMillis == null ? null : new MillisecondsDurationImpl(timeOnDistanceAllowancePerNauticalMileAsMillis), - searchTag); + searchTag, (DynamicBoat) boat); regatta.registerCompetitor(competitor); - response = Response.ok(CompetitorJsonSerializer.create().serialize(competitor).toJSONString()). + response = Response.ok(CompetitorWithBoatJsonSerializer.create().serialize(competitor).toJSONString()). header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } return response; diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java index b23212f6999..77400742011 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/statistics/StatisticsTest.java @@ -7,12 +7,15 @@ import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -49,9 +52,10 @@ public class StatisticsTest { private static final long START_OF_RACE = 200; private static final long END_OF_TRACKING = 400; private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); - private final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, - new BoatImpl("boat", boatClass, "DE 12345"), /* timeOnTimeFactor */ null, + private final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); + private final Boat boat = new BoatImpl("boat", "b", boatClass, "DE 12345"); private final Mark mark1 = DomainFactory.INSTANCE.getOrCreateMark("mark1"); private final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2"); private final Mark mark3 = DomainFactory.INSTANCE.getOrCreateMark("mark3"); @@ -65,12 +69,14 @@ public class StatisticsTest { @Before public void setUp() { regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE, - EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, + EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass, false, /* startDate */ null, /* endDate */null, null, null, "a", null)); final Course course = new CourseImpl("course", Arrays.asList(new Waypoint[] { waypoint1, waypoint2, waypoint3 })); - RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp)); + Map competitors = new HashMap<>(); + competitors.put(comp, boat); + RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, competitors); trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections.emptyList(), EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new, From db1d11eb6e8969d526a6d6fd87b1a5c2c78f1094 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Mon, 28 Aug 2017 17:18:12 +0200 Subject: [PATCH 054/271] removed some 'unused imports' warnings --- .../regatta/events/impl/RegattaLogRegisterEntryEventImpl.java | 1 - .../domain/test/RegattaLogEventNotificationForwardingTest.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java index 2a3434d6172..a12ead59dfe 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java @@ -7,7 +7,6 @@ import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.TimePoint; public class RegattaLogRegisterEntryEventImpl extends AbstractLogEventImpl diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index 499e115a5be..56601d39313 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -16,9 +16,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.Regatta; From ae0514671252ed9c7bd85082d379bcb09fe7fbc7 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 30 Aug 2017 11:55:47 +0200 Subject: [PATCH 055/271] first step to use only CompetitorDTO instead of mixture of CompetitorDTO and CompetitorWithoutBoatDTO --- .../GetCompetitorInLeaderboardAction.java | 4 +-- .../CompetitorSelectionListener.java | 4 +-- .../CompetitorSelectionPopup.java | 10 +++---- .../table/CompetitorTable.java | 18 ++++++------- .../CompetitorTableRowSelectionListener.java | 4 +-- .../startanalysis/StartAnalysisWidget.java | 3 +-- .../shared/dto/LeaderboardCompetitorsDTO.java | 8 +++--- .../sailing/domain/base/DomainFactory.java | 14 +++++----- .../domain/base/impl/DomainFactoryImpl.java | 26 ++++++++----------- .../impl/AbstractLeaderboardWithCache.java | 21 +++++++++++++-- 10 files changed, 61 insertions(+), 51 deletions(-) diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java index 2d5583674f1..00b89b38845 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/actions/GetCompetitorInLeaderboardAction.java @@ -7,7 +7,7 @@ import com.sap.sailing.dashboards.gwt.shared.dispatch.DashboardAction; import com.sap.sailing.dashboards.gwt.shared.dispatch.DashboardDispatchContext; import com.sap.sailing.dashboards.gwt.shared.dto.LeaderboardCompetitorsDTO; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.dispatch.shared.exceptions.DispatchException; @@ -34,7 +34,7 @@ public class GetCompetitorInLeaderboardAction implements DashboardAction competitorsFromBestToWorst = lb.getCompetitorsFromBestToWorst(MillisecondsTimePoint.now()); - List competitorDTOs = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorWithoutBoatDTOListTemp(competitorsFromBestToWorst); + List competitorDTOs = dashboardDispatchContext.getRacingEventService().getBaseDomainFactory().getCompetitorDTOList(competitorsFromBestToWorst); result.setCompetitors(competitorDTOs); return result; } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java index 5e281844e23..b4ec20fdf25 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionListener.java @@ -1,8 +1,8 @@ package com.sap.sailing.dashboards.gwt.client.popups.competitorselection; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; public interface CompetitorSelectionListener { - public void didClickOKWithSelectedCompetitor(CompetitorWithoutBoatDTO competitor); + public void didClickOKWithSelectedCompetitor(CompetitorDTO competitor); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java index 84a1612c221..743eb998187 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/CompetitorSelectionPopup.java @@ -16,7 +16,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table.CompetitorTable; import com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table.CompetitorTableRowSelectionListener; import com.sap.sailing.dashboards.gwt.client.widgets.ActionPanel; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; public class CompetitorSelectionPopup extends Composite implements HasWidgets, CompetitorTableRowSelectionListener { @@ -38,7 +38,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C @UiField(provided = true) ActionPanel okButton; - private CompetitorWithoutBoatDTO currentCompetitorSelected; + private CompetitorDTO currentCompetitorSelected; private boolean isVisible; private CompetitorSelectionPopupResources competitorSelectionPopupResources = CompetitorSelectionPopupResources.INSTANCE; @@ -63,7 +63,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C okButton.getElement().setInnerText("OK"); } - public void show(List competitorList) { + public void show(List competitorList) { competitortable.setTableContent(competitorList); RootLayoutPanel.get().add(this); competitorselectionpopup.addStyleName(competitorSelectionPopupResources.gss().popupshow()); @@ -88,7 +88,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C this.competitorSelectionPopupListener.remove(o); } - public void notifyListenerAboutOKButtonClickedWithSelectedCompetitorName(CompetitorWithoutBoatDTO competitor) { + public void notifyListenerAboutOKButtonClickedWithSelectedCompetitorName(CompetitorDTO competitor) { for (CompetitorSelectionListener newStartAnalysisListener : competitorSelectionPopupListener) { newStartAnalysisListener.didClickOKWithSelectedCompetitor(competitor); } @@ -127,7 +127,7 @@ public class CompetitorSelectionPopup extends Composite implements HasWidgets, C } @Override - public void didSelectedRowWithCompetitorName(CompetitorWithoutBoatDTO competitor) { + public void didSelectedRowWithCompetitorName(CompetitorDTO competitor) { currentCompetitorSelected = competitor; } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java index cf23b175868..56ae2e648c1 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTable.java @@ -10,46 +10,46 @@ import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sse.gwt.client.celltable.BaseCelltable; public class CompetitorTable extends AbsolutePanel { - private CellTable table; + private CellTable table; private CompetitorTableRowSelectionListener competitorTableRowSelectionListener; public CompetitorTable(CompetitorTableRowSelectionListener competitorTableRowSelectionListener) { this.competitorTableRowSelectionListener = competitorTableRowSelectionListener; } - public void setTableContent(List competitorNames) { + public void setTableContent(List competitorNames) { if (table == null) { initTable(competitorNames); } } - private void initTable(List competitorNames) { + private void initTable(List competitorNames) { CellTable.Resources tableRes = GWT.create(CompetitorTableStyleResource.class); - table = new BaseCelltable(15, tableRes); + table = new BaseCelltable(15, tableRes); table.getElement().getStyle().setWidth(100, Unit.PCT); table.setSkipRowHoverStyleUpdate(true); table.setSkipRowHoverCheck(true); table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED); - final SingleSelectionModel selectionModel = new SingleSelectionModel(); + final SingleSelectionModel selectionModel = new SingleSelectionModel(); table.setSelectionModel(selectionModel); selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { public void onSelectionChange(SelectionChangeEvent event) { - CompetitorWithoutBoatDTO selected = selectionModel.getSelectedObject(); + CompetitorDTO selected = selectionModel.getSelectedObject(); if (selected != null) { competitorTableRowSelectionListener.didSelectedRowWithCompetitorName(selected); } } }); - TextColumn competitorNameCollumn = new TextColumn() { + TextColumn competitorNameCollumn = new TextColumn() { @Override - public String getValue(CompetitorWithoutBoatDTO competitor) { + public String getValue(CompetitorDTO competitor) { return competitor.getName(); } }; diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java index c2d3907f45e..3087d8745b4 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/popups/competitorselection/table/CompetitorTableRowSelectionListener.java @@ -1,8 +1,8 @@ package com.sap.sailing.dashboards.gwt.client.popups.competitorselection.table; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; public interface CompetitorTableRowSelectionListener { - public void didSelectedRowWithCompetitorName(CompetitorWithoutBoatDTO competitor); + public void didSelectedRowWithCompetitorName(CompetitorDTO competitor); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java index c3952e6b90c..b808797b761 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/widgets/startanalysis/StartAnalysisWidget.java @@ -41,7 +41,6 @@ import com.sap.sailing.dashboards.gwt.shared.dto.LeaderboardCompetitorsDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysesDTO; import com.sap.sailing.dashboards.gwt.shared.dto.StartAnalysisDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapResources; @@ -241,7 +240,7 @@ public class StartAnalysisWidget extends Composite implements HasWidgets, PollsL competitorSelectionPopup.addListener(new CompetitorSelectionListener() { @Override - public void didClickOKWithSelectedCompetitor(CompetitorWithoutBoatDTO competitor) { + public void didClickOKWithSelectedCompetitor(CompetitorDTO competitor) { if (competitor != null) { Cookies.removeCookie(cookieKeyForSelectedCompetitorInLeaderboard); Cookies.setCookie(cookieKeyForSelectedCompetitorInLeaderboard, competitor.getIdAsString(), new Date(new Date().getTime()+SELECTED_COMPETITOR_ID_COOKIE_KEY_EXPIRE_TIME_IN_MILLIS)); diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java index 24470dfa69f..f402d3031eb 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/shared/dto/LeaderboardCompetitorsDTO.java @@ -2,7 +2,7 @@ package com.sap.sailing.dashboards.gwt.shared.dto; import java.util.List; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sse.gwt.dispatch.shared.commands.Result; /** @@ -11,15 +11,15 @@ import com.sap.sse.gwt.dispatch.shared.commands.Result; */ public class LeaderboardCompetitorsDTO implements Result { - private List competitors; + private List competitors; public LeaderboardCompetitorsDTO() {} - public List getCompetitors() { + public List getCompetitors() { return competitors; } - public void setCompetitors(List competitors) { + public void setCompetitors(List competitors) { this.competitors = competitors; } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java index 767d68daf16..c4c11031896 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.base; import java.io.IOException; import java.io.InputStream; import java.util.List; +import java.util.Map; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.common.Placemark; @@ -10,7 +11,6 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; import com.sap.sailing.domain.common.dto.RaceDTO; @@ -24,6 +24,7 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sse.common.IsManagedByCache; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; public interface DomainFactory extends SharedDomainFactory { @@ -63,8 +64,6 @@ public interface DomainFactory extends SharedDomainFactory { CompetitorDTO convertToCompetitorDTO(Competitor c); CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); - - CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); BoatDTO convertToBoatDTO(Boat boat); @@ -77,13 +76,12 @@ public interface DomainFactory extends SharedDomainFactory { PlacemarkDTO convertToPlacemarkDTO(Placemark placemark); - List getCompetitorDTOList(Iterable competitors); + List getCompetitorDTOList(Map competitors); - /** Temporary function -> REMOVE later on */ - List getCompetitorWithoutBoatDTOListTemp(Iterable competitors); - - List getCompetitorDTOListTemp(Iterable competitors); + List getCompetitorDTOList(Iterable competitors); + List getCompetitorDTOList(List> competitors); + TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 5c9bddaa1fb..5d8f268b931 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -5,6 +5,8 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; @@ -27,7 +29,6 @@ import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.dto.CompetitorWithoutBoatDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; import com.sap.sailing.domain.common.dto.PlacemarkOrderDTO; @@ -70,6 +71,7 @@ import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; import com.sap.sailing.geocoding.ReverseGeocoder; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; @@ -159,11 +161,6 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return competitorAndBoatStore.convertToCompetitorDTO(c); } - @Override - public CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c) { - return competitorAndBoatStore.convertToCompetitorWithoutBoatDTO(c); - } - @Override public BoatDTO convertToBoatDTO(Boat boat) { return competitorAndBoatStore.convertToBoatDTO(boat); @@ -367,16 +364,16 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain } @Override - public List getCompetitorDTOList(Iterable competitors) { + public List getCompetitorDTOList(Map competitors) { List result = new ArrayList(); - for (CompetitorWithBoat competitor : competitors) { - result.add(convertToCompetitorDTO(competitor)); + for (Entry competitorAndBoatEntry : competitors.entrySet()) { + result.add(convertToCompetitorDTO(competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue())); } return result; } @Override - public List getCompetitorDTOListTemp(Iterable competitors) { + public List getCompetitorDTOList(Iterable competitors) { List result = new ArrayList(); for (Competitor competitor : competitors) { result.add(convertToCompetitorDTO(competitor)); @@ -384,11 +381,10 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return result; } - @Override - public List getCompetitorWithoutBoatDTOListTemp(Iterable competitors) { - List result = new ArrayList(); - for (Competitor competitor : competitors) { - result.add(convertToCompetitorWithoutBoatDTO(competitor)); + public List getCompetitorDTOList(List> competitors) { + List result = new ArrayList(); + for (Pair competitorAndBoat : competitors) { + result.add(convertToCompetitorDTO(competitorAndBoat.getA(), competitorAndBoat.getB())); } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java index f9d49f74fa1..950ba5a76bd 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java @@ -25,6 +25,7 @@ import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.InvalidatesLeaderboardCache; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.DomainFactory; @@ -78,6 +79,7 @@ import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; import com.sap.sse.util.ThreadPoolUtil; import com.sap.sse.util.impl.FutureTaskWithTracingGet; @@ -389,8 +391,23 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null, fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race, isMetaLeaderboardColumn); } - Future> task = executor.submit( - () -> baseDomainFactory.getCompetitorDTOListTemp(AbstractLeaderboardWithCache.this.getCompetitorsFromBestToWorst(raceColumn, timePoint))); + Future> task = executor.submit(new Callable>() { + public List call() throws NoWindException { + Iterable competitorsFromBestToWorst = AbstractLeaderboardWithCache.this.getCompetitorsFromBestToWorst(raceColumn, timePoint); + List> orderedeCompetitorsWithBoats = new ArrayList<>(); + Map allCompetitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(); + for (Competitor c: competitorsFromBestToWorst) { + Boat boat = null; + if (!isMetaLeaderboardColumn) { + boat = allCompetitorsAndTheirBoats.get(c); + } + orderedeCompetitorsWithBoats.add(new Pair(c, boat)); + } + return baseDomainFactory.getCompetitorDTOList(orderedeCompetitorsWithBoats); + } + }); +// Future> task = executor.submit( +// () -> baseDomainFactory.getCompetitorDTOList(AbstractLeaderboardWithCache.this.getCompetitorsFromBestToWorst(raceColumn, timePoint))); competitorsFromBestToWorstTasks.put(raceColumn, task); } // wait for the competitor orderings to have been computed for all race columns before continuing; subsequent tasks may depend on these data From ecc51c05ba61f38f45c987adc1dd92ebfde4c2f2 Mon Sep 17 00:00:00 2001 From: Frank Mittag Date: Wed, 30 Aug 2017 17:01:01 +0200 Subject: [PATCH 056/271] Removed the idea of a RegattaLogEntryEvent Refactored CompetitorProviderFromRaceColumnsAndRegattaLike to be a CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike to cache also the boats of the competitors --- .../impl/DomainObjectFactoryImpl.java | 19 --- .../impl/MongoObjectFactoryImpl.java | 8 -- .../impl/MongoRegattaLogStoreVisitor.java | 6 - .../regatta/RegattaLogEventVisitor.java | 3 - .../events/RegattaLogRegisterEntryEvent.java | 15 -- .../RegattaLogRegisterEntryEventImpl.java | 59 -------- .../impl/BaseRegattaLogEventVisitor.java | 5 - .../regatta/impl/RegattaLogEventListener.java | 6 - .../impl/RegattaLogEntriesInLogAnalyzer.java | 38 ----- ...mpetitorProviderCacheInvalidationTest.java | 10 +- .../domain/test/mock/MockedTrackedRace.java | 17 +-- .../sap/sailing/domain/base/RaceColumn.java | 8 -- .../com/sap/sailing/domain/base/Regatta.java | 8 -- .../domain/base/impl/AbstractRaceColumn.java | 54 ++----- .../sailing/domain/base/impl/RegattaImpl.java | 66 +++------ .../HasRaceColumnsAndRegattaLike.java | 4 +- .../domain/leaderboard/Leaderboard.java | 8 -- .../impl/AbstractLeaderboardImpl.java | 57 ++++---- .../impl/AbstractLeaderboardWithCache.java | 5 - ...roviderFromRaceColumnsAndRegattaLike.java} | 134 +++++++----------- ...aLeaderboardWithCompetitorElimination.java | 22 ++- .../impl/RegattaLeaderboardImpl.java | 17 +-- .../meta/AbstractMetaLeaderboard.java | 15 +- .../meta/MetaLeaderboardColumn.java | 9 +- .../domain/regattalike/HasRegattaLike.java | 56 ++++---- .../LeaderboardThatHasRegattaLike.java | 5 +- .../gwt/ui/server/SailingServiceImpl.java | 6 +- ...estStoringAndLoadingEventsAndRegattas.java | 9 +- ...LeaderboardsResourceCheckinAndOutTest.java | 9 +- .../jaxrs/api/LeaderboardsResource.java | 2 +- .../gateway/jaxrs/api/RegattasResource.java | 6 +- .../test/RegattaLogReplicationTest.java | 4 +- .../server/test/MasterDataImportTest.java | 14 +- 33 files changed, 211 insertions(+), 493 deletions(-) delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java delete mode 100644 java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java rename java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/{CompetitorProviderFromRaceColumnsAndRegattaLike.java => CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike.java} (66%) diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 866be5c3518..8b823df8b34 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -109,7 +109,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -121,7 +120,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnTimeFactorEventImpl; @@ -1915,8 +1913,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterBoatEvent.class.getSimpleName())) { return loadRegattaLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); - } else if (eventClass.equals(RegattaLogRegisterEntryEvent.class.getSimpleName())) { - return loadRegattaLogRegisterEntryEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { @@ -2019,21 +2015,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return result; } - private RegattaLogRegisterEntryEvent loadRegattaLogRegisterEntryEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Competitor comp = getCompetitorByID(dbObject); - final RegattaLogRegisterEntryEvent result; - if (comp == null) { - result = null; - logger.log(Level.SEVERE, - "Couldn't resolve competitor with ID " + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) - + " from registration event with ID " + id + ". Skipping this competitor registration."); - } else { - result = new RegattaLogRegisterEntryEventImpl(createdAt, logicalTimePoint, author, id, comp); - } - return result; - } - private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Competitor comp = getCompetitorByID(dbObject); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index 8c021575039..042455d57ab 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -67,7 +67,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -1629,13 +1628,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterEntryEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterEntryEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - storeRegattaLogEvent(regattaLikeId, result); - } - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java index 3de5346128d..2a3d97d0671 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java @@ -11,7 +11,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -60,11 +59,6 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); } - @Override - public void visit(RegattaLogRegisterEntryEvent event) { - mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); - } - @Override public void visit(RegattaLogRegisterCompetitorEvent event) { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index 6246c0f05d7..86d9f917ecc 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -8,7 +8,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -26,8 +25,6 @@ public interface RegattaLogEventVisitor { void visit(RegattaLogRegisterBoatEvent event); - void visit(RegattaLogRegisterEntryEvent event); - void visit(RegattaLogRegisterCompetitorEvent event); void visit(RegattaLogRegisterCompetitorAndBoatEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java deleted file mode 100644 index c5eee3fe6d7..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sap.sailing.domain.abstractlog.regatta.events; - -import com.sap.sailing.domain.abstractlog.Revokable; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.base.Competitor; - -/** - * Registers a single entry for the regatta, the entry can be is used as a competitor for all races or the - * regatta or only for single races - * @author Frank Mittag - * - */ -public interface RegattaLogRegisterEntryEvent extends RegattaLogEvent, Revokable { - Competitor getCompetitor(); -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java deleted file mode 100644 index a12ead59dfe..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.sap.sailing.domain.abstractlog.regatta.events.impl; - -import java.io.Serializable; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sse.common.TimePoint; - -public class RegattaLogRegisterEntryEventImpl extends AbstractLogEventImpl - implements RegattaLogRegisterEntryEvent { - - private static final long serialVersionUID = 2759139058776278902L; - private Competitor competitor; - - /** - * @throws IllegalArgumentException - * if {@code competitor} is null - */ - public RegattaLogRegisterEntryEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { - super(createdAt, logicalTimePoint, author, id); - checkCompetitor(competitor); - this.competitor = competitor; - } - - /** - * @throws IllegalArgumentException - * if {@code competitor} is null - */ - public RegattaLogRegisterEntryEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { - this(now(), logicalTimePoint, author, randId(), competitor); - } - - @Override - public void accept(RegattaLogEventVisitor visitor) { - visitor.visit(this); - } - - private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { - if (competitor == null) { - throw new IllegalArgumentException("Competitor may not be null"); - } - } - - @Override - public Competitor getCompetitor() { - return competitor; - } - - @Override - public String getShortInfo() { - return "competitor: " + getCompetitor().toString(); - } - -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java index 22b4cc9e599..409064f0827 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java @@ -9,7 +9,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -40,10 +39,6 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor { public void visit(RegattaLogRegisterBoatEvent event) { } - @Override - public void visit(RegattaLogRegisterEntryEvent event) { - } - @Override public void visit(RegattaLogRegisterCompetitorEvent event) { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java index 3a91f6c3e5b..7f4ae3f34ca 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java @@ -10,7 +10,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -43,11 +42,6 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor eventAdded(event); } - @Override - public void visit(RegattaLogRegisterEntryEvent event) { - eventAdded(event); - } - @Override public void visit(RegattaLogRegisterCompetitorEvent event) { eventAdded(event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java deleted file mode 100644 index 66e7d7cc1b9..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; - -import java.util.HashSet; -import java.util.Set; - -import com.sap.sailing.domain.abstractlog.AbstractLog; -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; -import com.sap.sailing.domain.base.Competitor; - -/** - * This class searches for RegisterEntry events in the given log. - * - * Entries alone in a regatta log are not enough to be used in a real race. - * Instead an entry (competitor) and a boat together must be registered through a {@link RegisterCompetitorAndBoat} event. - * - */ -public class RegattaLogEntriesInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> - extends BaseLogAnalyzer> { - - public RegattaLogEntriesInLogAnalyzer(LogT log) { - super(log); - } - - @Override - protected Set performAnalysis() { - Set result = new HashSet(); - - for (EventT event : getLog().getUnrevokedEvents()) { - if (event instanceof RegattaLogRegisterEntryEvent) { - result.add(((RegattaLogRegisterEntryEvent) event).getCompetitor()); - } - } - - return result; - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index 964f1b1a615..a039f1d8632 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -37,7 +37,7 @@ import com.sap.sailing.domain.base.impl.SeriesImpl; import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; -import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; +import com.sap.sailing.domain.leaderboard.impl.CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; @@ -59,8 +59,8 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; * */ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboardTest { - private CompetitorProviderFromRaceColumnsAndRegattaLike competitorProviderFlexibleLeaderboard; - private CompetitorProviderFromRaceColumnsAndRegattaLike competitorProviderRegattaLeaderboard; + private CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike competitorProviderFlexibleLeaderboard; + private CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike competitorProviderRegattaLeaderboard; private FlexibleLeaderboardImpl flexibleLeaderboard; private RegattaLeaderboardImpl regattaLeaderboard; private RegattaImpl regatta; @@ -75,7 +75,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard "Test Course Area", UUID.randomUUID()); flexibleLeaderboard = new FlexibleLeaderboardImpl("Test Flexible Leaderboard", new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(), courseArea); - competitorProviderFlexibleLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(flexibleLeaderboard); + competitorProviderFlexibleLeaderboard = new CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike(flexibleLeaderboard); regatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, "Test Regatta", new BoatClassImpl("49er", BoatClassMasterdata._49ER), /* canBoatsOfCompetitorsChangePerRace */ true, /* startDate */ null, /* endDate */null, @@ -92,7 +92,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard boats.put(c, createBoat("" + l + "/" + i)); } } - competitorProviderRegattaLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard); + competitorProviderRegattaLeaderboard = new CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard); } /** 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 75e68929150..569d862c186 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.NavigableSet; import java.util.Set; import java.util.TreeSet; @@ -46,7 +47,7 @@ import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.SensorFix; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; +import com.sap.sailing.domain.leaderboard.impl.CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; import com.sap.sailing.domain.ranking.RankingMetric; @@ -88,7 +89,6 @@ import com.sap.sse.common.Duration; import com.sap.sse.common.IsManagedByCache; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; public class MockedTrackedRace implements DynamicTrackedRace { private static final long serialVersionUID = 5827912985564121181L; @@ -327,11 +327,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Iterable getAllBoats() { + public Map getAllCompetitorsAndBoats() { return null; } - public Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered() { + @Override + public Iterable getAllBoats() { return null; } @@ -535,16 +536,16 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Iterable getCompetitorsRegisteredInRegattaLog() { + public Map getCompetitorsAndBoatsRegisteredInRegattaLog() { return null; } @Override - public void registerCompetitor(Competitor competitor) { + public void registerCompetitorAndBoat(Competitor competitor, Boat boat) { } @Override - public void registerCompetitors(Iterable competitor) { + public void registerCompetitorsAndBoats(Map competitorsAndBoats) { } @Override @@ -556,7 +557,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { + public CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { return null; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index c82fb37af8c..fcac2fac31d 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -20,7 +20,6 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.util.impl.RaceColumnListeners; import com.sap.sse.common.Named; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; /** * One or more races that would be noted together in a single column in a {@link Leaderboard}. If the number of @@ -255,13 +254,6 @@ public interface RaceColumn extends Named { */ Iterable getAllCompetitors(); - /** - * Same as {@link #getAllCompetitors()}, but the {@link RaceDefinition}s whose {@link RaceDefinition#getCompetitors() competitors} - * were considered while computing the results are returned as the first element of the pair. The second element are the competitors - * as they are returned by {@link #getAllCompetitors()}. - */ - Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered(); - /** * Same as {@link #getAllCompetitors()}, but restricted to the single race identified by the fleet parameter. */ diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index 7c18c4064ee..9e8587b50d7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -16,7 +16,6 @@ import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.util.RegattaUtil; import com.sap.sse.common.NamedWithID; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; /** * The name shall be unique across all regattas tracked concurrently. In particular, if you want to keep apart regattas @@ -123,13 +122,6 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe Iterable getAllBoats(); - /** - * Same as {@link #getAllCompetitors()}, only that additionally the method returns as a first element of a pair - * which {@link RaceDefinition}s' {@link RaceDefinition#getCompetitors() competitors} were used in assembling the - * result. - */ - Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered(); - /** * Will remove the series from this regatta. Will also call {@link RaceColumn#removeRaceIdentifier(Fleet)} to make * sure that all raceLogs and race associations get removed for all race columns in this series. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index 37e0e11c7d1..6665af9f53e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -33,7 +33,6 @@ import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; @@ -46,7 +45,6 @@ import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn { @@ -253,54 +251,20 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public Iterable getAllCompetitors() { - return getAllCompetitorsWithRaceDefinitionsConsidered().getB(); + Set result = new HashSet<>(); + for (Fleet fleet : getFleets()) { + Util.addAll(getAllCompetitors(fleet), result); + } + return result; } @Override public Iterable getAllCompetitors(final Fleet fleet) { - return getAllCompetitorsWithRaceDefinitionsConsidered(fleet).getB(); + Set result = new HashSet<>(); + Util.addAll(getAllCompetitorsAndTheirBoats(fleet).keySet(), result); + return result; } - - @Override - public Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered() { - Set competitors = new HashSet<>(); - Set raceDefinitionsConsidered = new HashSet<>(); - for (Fleet fleet : getFleets()) { - final Pair> allCompetitorsWithRaceDefinitionsConsidered = getAllCompetitorsWithRaceDefinitionsConsidered(fleet); - Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getB(), competitors); - if (allCompetitorsWithRaceDefinitionsConsidered.getA() != null) { - raceDefinitionsConsidered.add(allCompetitorsWithRaceDefinitionsConsidered.getA()); - } - } - return new Pair<>(raceDefinitionsConsidered, competitors); - } - - /** - * Same as {@link #getAllCompetitors(Fleet)}, but also returns the {@link RaceDefinition} as the first - * component of a pair if it contributed its {@link RaceDefinition#getCompetitors()}. If the resulting - * iterable of competitors did not consider a {@link RaceDefinition}'s competitor set, {@code null} - * is returned as the first component of the pair. - */ - private Pair> getAllCompetitorsWithRaceDefinitionsConsidered(final Fleet fleet) { - final Iterable competitors; - final RaceDefinition raceDefinition; - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - raceDefinition = trackedRace.getRace(); - competitors = raceDefinition.getCompetitors(); - } else { - raceDefinition = null; - // if no tracked race is found, use competitors from race/regatta log depending on whether - // the mapping event is present or not; this assumes that if a tracked - // race exists, its competitors set takes precedence over what's in the race log. Usually, - // the tracked race will have the same competitors as those in the race log, or more because - // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAndBoatsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze().keySet(); - competitors = viaRaceLog; - } - return new Pair<>(raceDefinition, competitors); - } - + @Override public Map getAllCompetitorsAndTheirBoats() { Map result = new HashMap<>(); 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 1805595c9d5..c070efcc7a6 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 @@ -5,6 +5,7 @@ import java.io.ObjectInputStream; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.HashMap; @@ -26,11 +27,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; -import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -54,7 +55,7 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.AbstractLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; +import com.sap.sailing.domain.leaderboard.impl.CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -77,7 +78,6 @@ import com.sap.sailing.util.impl.RaceColumnListeners; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.NamedImpl; @@ -158,7 +158,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene */ private boolean useStartTimeInference; - private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; + private transient CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike competitorsProvider; private AbstractLogEventAuthor regattaLogEventAuthorForRegatta = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -418,53 +418,29 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } @Override - public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { + public CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { if (competitorsProvider == null) { - competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this); + competitorsProvider = new CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike(this); } return competitorsProvider; } @Override - public Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered() { - if (competitorsProvider == null) { - competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this); - } - final Pair, Iterable> allCompetitorsWithRaceDefinitionsConsidered = competitorsProvider.getAllCompetitorsWithRaceDefinitionsConsidered(); - Set newResult = null; - Set newRaceDefinitions = null; - final Iterable racesConsideredSoFar = allCompetitorsWithRaceDefinitionsConsidered.getA(); - for (final RaceDefinition race : getAllRaces()) { - if (!Util.contains(racesConsideredSoFar, race)) { - if (newResult == null) { - newRaceDefinitions = new HashSet<>(); - Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getA(), newRaceDefinitions); - newResult = new HashSet<>(); - Util.addAll(allCompetitorsWithRaceDefinitionsConsidered.getB(), newResult); - } - Util.addAll(race.getCompetitors(), newResult); - newRaceDefinitions.add(race); - } - } - return newResult == null ? allCompetitorsWithRaceDefinitionsConsidered : new Pair<>(newRaceDefinitions, newResult); + public Map getAllCompetitorsAndBoats() { + return getOrCreateCompetitorsProvider().getAllCompetitorsAndBoats(); } @Override public Iterable getAllCompetitors() { - return getAllCompetitorsWithRaceDefinitionsConsidered().getB(); + return getOrCreateCompetitorsProvider().getAllCompetitors(); } @Override public Iterable getAllBoats() { Set result = new HashSet(); -// if (boatsProvider == null) { -// boatsProvider = new BoatsProviderFromRaceColumnsAndRegattaLike(this); -// } -// Util.addAll(boatsProvider.getAllBoats(), result); - for (RaceDefinition race : getAllRaces()) { - for (Boat b: race.getBoats()) { - result.add(b); - } + Collection allBoatsOfAllRaces = getOrCreateCompetitorsProvider().getAllCompetitorsAndBoats().values(); + for (Boat boat: allBoatsOfAllRaces) { + result.add(boat); } return result; } @@ -869,26 +845,26 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } @Override - public Iterable getCompetitorsRegisteredInRegattaLog() { + public Map getCompetitorsAndBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLog(); - RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( + CompetitorsAndBoatsInLogAnalyzer analyzer = new CompetitorsAndBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @Override - public void registerCompetitor(Competitor competitor) { - registerCompetitors(Collections.singleton(competitor)); + public void registerCompetitorAndBoat(Competitor competitor, Boat boat) { + registerCompetitorsAndBoats(Collections.singletonMap(competitor, boat)); } @Override - public void registerCompetitors(Iterable competitors) { + public void registerCompetitorsAndBoats(Map competitorsAndBoats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); TimePoint now = MillisecondsTimePoint.now(); - for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForRegatta, - UUID.randomUUID(), competitor)); + for (Map.Entry competitorAndBoatEntry : competitorsAndBoats.entrySet()) { + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(now, now, regattaLogEventAuthorForRegatta, + UUID.randomUUID(), competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue())); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java index 29d5b5ee948..0ca027354d0 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java @@ -1,9 +1,9 @@ package com.sap.sailing.domain.leaderboard; -import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; +import com.sap.sailing.domain.leaderboard.impl.CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.regattalike.HasRegattaLike; public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceColumns { - CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider(); + CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index 352db41ddb9..11984a97b33 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -15,7 +15,6 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardBase; 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; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.common.Distance; @@ -100,13 +99,6 @@ public interface Leaderboard extends LeaderboardBase, HasRaceColumns { */ Iterable getAllCompetitors(); - /** - * Same as {@link #getAllCompetitors()}, only that additionally the method returns as a first element in a pair - * which {@link RaceDefinition}s were used in order to fetch their {@link RaceDefinition#getCompetitors()} to - * assemble the results. - */ - Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered(); - /** * Retrieves all competitors expected to race in the fleet and column specified. * When a {@link TrackedRace} is {@link RaceColumn#getTrackedRace(Fleet) attached} to the race diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 0aca9b9c81f..6841798682f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -14,24 +15,22 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; -import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; 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.common.MaxPointsReason; import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.ScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; /** @@ -52,7 +51,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI * Cache for the combined competitors of this leaderboard; taken from the {@link TrackedRace#getRace() races of the * tracked races} associated with this leaderboard. Updated when the set of tracked races changes. */ - private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; + private transient CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike competitorsProvider; private final AbstractLogEventAuthor regattaLogEventAuthorForAbstractLeaderboard = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -93,30 +92,30 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return Collections.unmodifiableSet(trackedRaces); } - /** - * This default implementation collects all competitors by visiting all {@link TrackedRace}s associated with this - * leaderboard's columns (see {@link #getTrackedRaces()}) and considering the race and regatta logs. - */ - @Override - public Pair, Iterable> getAllCompetitorsWithRaceDefinitionsConsidered() { - return getOrCreateCompetitorsProvider().getAllCompetitorsWithRaceDefinitionsConsidered(); - } - @Override public Iterable getAllCompetitors(RaceColumn raceColumn, Fleet fleet) { return getOrCreateCompetitorsProvider().getAllCompetitors(raceColumn, fleet); } @Override - public Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet) { - RaceDefinition race = raceColumn.getRaceDefinition(fleet); - return race.getBoatOfCompetitorById(competitor.getId()); + public Iterable getAllCompetitors() { + return getOrCreateCompetitorsProvider().getAllCompetitors(); } @Override - public CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { + public Map getAllCompetitorsAndBoats() { + return getOrCreateCompetitorsProvider().getAllCompetitorsAndBoats(); + } + + @Override + public Boat getBoatOfCompetitor(Competitor competitor, RaceColumn raceColumn, Fleet fleet) { + return getAllCompetitorsAndBoats().get(competitor); + } + + @Override + public CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider() { if (competitorsProvider == null) { - competitorsProvider = new CompetitorProviderFromRaceColumnsAndRegattaLike(this); + competitorsProvider = new CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike(this); } return competitorsProvider; } @@ -206,26 +205,26 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI } @Override - public Iterable getCompetitorsRegisteredInRegattaLog() { + public Map getCompetitorsAndBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( + CompetitorsAndBoatsInLogAnalyzer analyzer = new CompetitorsAndBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @Override - public void registerCompetitor(Competitor competitor) { - registerCompetitors(Collections.singleton(competitor)); + public void registerCompetitorAndBoat(Competitor competitor, Boat boat) { + registerCompetitorsAndBoats(Collections.singletonMap(competitor, boat)); } @Override - public void registerCompetitors(Iterable competitors) { + public void registerCompetitorsAndBoats(Map competitorsAndBoats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); TimePoint now = MillisecondsTimePoint.now(); - for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, - UUID.randomUUID(), competitor)); + for (Map.Entry competitorAndBoatEntry : competitorsAndBoats.entrySet()) { + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, + UUID.randomUUID(), competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue())); } } @@ -243,7 +242,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI // boat functions /** - * This default implementation collects all boats by visiting all {@link TrackedRace}s associated with this + * This collects all boats by visiting all {@link TrackedRace}s associated with this * leaderboard's columns (see {@link #getTrackedRaces()}). */ @Override @@ -251,7 +250,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return getBoatsRegisteredInRegattaLog(); } - @Override public Iterable getBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); @@ -287,4 +285,5 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI RegattaLogBoatDeregistrator deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); deregisterer.deregister(deregisterer.analyze()); } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java index 950ba5a76bd..abfaf65b65a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java @@ -1122,11 +1122,6 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { } return result; } - - @Override - public Iterable getAllCompetitors() { - return getAllCompetitorsWithRaceDefinitionsConsidered().getB(); - } @Override public void destroy() { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike.java similarity index 66% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java rename to java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike.java index a16aaf43315..d513ec74a08 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorAndBoatProviderFromRaceColumnsAndRegattaLike.java @@ -1,9 +1,7 @@ package com.sap.sailing.domain.leaderboard.impl; -import java.util.Collection; -import java.util.HashSet; +import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.logging.Level; @@ -29,19 +27,17 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; 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.impl.RaceColumnListenerWithDefaultAction; import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; /** - * A caching provider of a competitor set, based on the {@link TrackedRace TrackedRaces} and {@link RaceLog}s of the {@link RaceColumn}s of + * A caching provider of a competitor and boat map, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of * a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been * provided, it is cached. The cache is invalidated when one of the following events occurs: *