diff --git a/.gitignore b/.gitignore index 00de9eb7a46..fa2035fc9ee 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ sailing_debug0* /java/com.sap.sailing.server.gateway.serialization.test/.settings/*.prefs .DS_Store java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml +/mobile/google-play-services_lib/bin/* + +/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml diff --git a/configuration/buildAndUpdateProduct.sh b/configuration/buildAndUpdateProduct.sh index ac1cc21b32f..438b327b63e 100755 --- a/configuration/buildAndUpdateProduct.sh +++ b/configuration/buildAndUpdateProduct.sh @@ -379,7 +379,7 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then # make sure to save the information from env.sh . $ACDIR/env.sh - echo "$VERSION_INFO-$MONGDB_PORT-$MEMORY-$REPLICATION_CHANNEL" > $ACDIR/configuration/jetty/version.txt + echo "$VERSION_INFO-$MONGODB_PORT-$MEMORY-$REPLICATION_CHANNEL" > $ACDIR/configuration/jetty/version.txt sed -i "s/mongo.port=.*$/mongo.port=$MONGODB_PORT/g" $ACDIR/configuration/config.ini sed -i "s/expedition.udp.port=.*$/expedition.udp.port=$EXPEDITION_PORT/g" $ACDIR/configuration/config.ini diff --git a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF index 37de5a111b9..f2de8aac085 100755 --- a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF @@ -13,4 +13,5 @@ Export-Package: com.sap.sailing.domain.common, com.sap.sailing.domain.common.quadtree, com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test", com.sap.sailing.domain.common.racelog, + com.sap.sailing.domain.common.racelog.utils, com.sap.sailing.domain.common.dto diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/MarkType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/MarkType.java index 11e361cd195..aef826d30e3 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/MarkType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/MarkType.java @@ -1,3 +1,3 @@ package com.sap.sailing.domain.common; -public enum MarkType { BUOY, CAMERABOAT, STARTBOAT, UMPIREBOAT, LANDMARK } \ No newline at end of file +public enum MarkType { BUOY, CAMERABOAT, STARTBOAT, UMPIREBOAT, LANDMARK, FINISHBOAT } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/RaceLogRaceStatus.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/RaceLogRaceStatus.java index 84dbfc45378..c0ba3da7a37 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/RaceLogRaceStatus.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/RaceLogRaceStatus.java @@ -2,8 +2,17 @@ package com.sap.sailing.domain.common.racelog; /** * @author D053502 - * + * */ public enum RaceLogRaceStatus { - UNKNOWN, UNSCHEDULED, SCHEDULED, STARTPHASE, RUNNING, FINISHING, FINISHED + UNKNOWN, UNSCHEDULED, SCHEDULED, STARTPHASE, RUNNING, FINISHING, FINISHED; + + public static boolean isActive(RaceLogRaceStatus status) { + if (status == null) { + return false; + } + + return status.equals(SCHEDULED) || status.equals(STARTPHASE) || status.equals(RUNNING) + || status.equals(FINISHING); + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/StartProcedureType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/StartProcedureType.java index b39fbb39d43..0bd82f959ba 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/StartProcedureType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/StartProcedureType.java @@ -1,18 +1,18 @@ package com.sap.sailing.domain.common.racelog; public enum StartProcedureType { - //RRS26("Fix Line Start (RRS26)"), + RRS26("Fix Line Start (RRS26)"), GateStart("Gate Start"), ESS("\"Extreme Sailing Series\"-Start"); private String displayName; - private StartProcedureType(String displayName){ + private StartProcedureType(String displayName) { this.displayName = displayName; } @Override - public String toString(){ + public String toString() { return displayName; } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/FlagAlphabetInterpretationTemplate.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/FlagAlphabetInterpretationTemplate.java new file mode 100644 index 00000000000..ed86ebb1309 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/FlagAlphabetInterpretationTemplate.java @@ -0,0 +1,74 @@ +package com.sap.sailing.domain.common.racelog.utils; + +import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; + +public abstract class FlagAlphabetInterpretationTemplate { + + public String getMeaningOfRaceStateAndFlags(RaceLogRaceStatus status, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) { + String statusText = ""; + if (status.equals(RaceLogRaceStatus.RUNNING) && upperFlag.equals(Flags.XRAY) && isDisplayed) { + statusText = getTextForRunningRaceWithEarlyStarter(); + } else if (status.equals(RaceLogRaceStatus.RUNNING) && upperFlag.equals(Flags.XRAY) && !isDisplayed) { + statusText = getTextForRunningRace(); + } else if (status.equals(RaceLogRaceStatus.RUNNING)) { + statusText = getTextForRunningRace(); + } else if (status.equals(RaceLogRaceStatus.FINISHING)) { + statusText = getTextForFinishingRace(); + } else if (status.equals(RaceLogRaceStatus.FINISHED)) { + statusText = getTextForFinishedRace(); + } else if (status.equals(RaceLogRaceStatus.SCHEDULED)) { + statusText = getTextForScheduledRace(); + } else if (status.equals(RaceLogRaceStatus.STARTPHASE)) { + statusText = getTextForRaceInStartphase(); + } else if (status.equals(RaceLogRaceStatus.UNSCHEDULED)) { + statusText = getTextForUnscheduledRace(); + if (upperFlag != null) { + if (upperFlag.equals(Flags.FIRSTSUBSTITUTE)) { + statusText = getTextForFirstSubstituteFlag(); + } else if (upperFlag.equals(Flags.AP) && lowerFlag.equals(Flags.ALPHA) && isDisplayed) { + statusText = getTextForAnsweringPennantWithAlphaFlags(); + } else if (upperFlag.equals(Flags.AP) && lowerFlag.equals(Flags.HOTEL) && isDisplayed) { + statusText = getTextForAnsweringPennantWithHotelFlags(); + } else if (upperFlag.equals(Flags.AP) && isDisplayed) { + statusText = getTextForAnsweringPennantFlag(); + } else if (upperFlag.equals(Flags.NOVEMBER) && lowerFlag.equals(Flags.ALPHA) && isDisplayed) { + statusText = getTextForNovemberWithAlphaFlags(); + } else if (upperFlag.equals(Flags.NOVEMBER) && lowerFlag.equals(Flags.HOTEL) && isDisplayed) { + statusText = getTextForNovemberWithHotelFlags(); + } else if (upperFlag.equals(Flags.NOVEMBER) && isDisplayed) { + statusText = getTextForNovemberFlag(); + } + } + } + return statusText; + } + + protected abstract String getTextForRunningRace(); + + protected abstract String getTextForRunningRaceWithEarlyStarter(); + + protected abstract String getTextForFinishingRace(); + + protected abstract String getTextForFinishedRace(); + + protected abstract String getTextForScheduledRace(); + + protected abstract String getTextForRaceInStartphase(); + + protected abstract String getTextForUnscheduledRace(); + + protected abstract String getTextForFirstSubstituteFlag(); + + protected abstract String getTextForAnsweringPennantFlag(); + + protected abstract String getTextForAnsweringPennantWithAlphaFlags(); + + protected abstract String getTextForAnsweringPennantWithHotelFlags(); + + protected abstract String getTextForNovemberFlag(); + + protected abstract String getTextForNovemberWithAlphaFlags(); + + protected abstract String getTextForNovemberWithHotelFlags(); +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/RaceStateOfSameDayHelper.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/RaceStateOfSameDayHelper.java new file mode 100644 index 00000000000..4e3c37a8d41 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/racelog/utils/RaceStateOfSameDayHelper.java @@ -0,0 +1,47 @@ +package com.sap.sailing.domain.common.racelog.utils; + +import java.util.Calendar; +import java.util.Date; + +import com.sap.sailing.domain.common.TimePoint; + +public class RaceStateOfSameDayHelper { + + public static boolean isRaceStateOfSameDay(TimePoint raceStartTimePoint, TimePoint raceFinishedTimePoint, Calendar now) { + Date raceStartTime = null; + Date raceFinishedTime = null; + + if (raceStartTimePoint != null) { + raceStartTime = raceStartTimePoint.asDate(); + } + if (raceFinishedTimePoint != null) { + raceFinishedTime = raceFinishedTimePoint.asDate(); + } + + return isRaceStateOfSameDay(raceStartTime, raceFinishedTime, now); + } + + public static boolean isRaceStateOfSameDay(Date raceStartTime, Date raceFinishedTime, Calendar now) { + boolean result = false; + if (raceFinishedTime != null) { + Calendar finishedTimeCal = Calendar.getInstance(); + finishedTimeCal.setTime(raceFinishedTime); + if(isSameDay(now, finishedTimeCal)) { + result = true; + } + } else if (raceStartTime != null) { + Calendar startTimeCal = Calendar.getInstance(); + startTimeCal.setTime(raceStartTime); + if(isSameDay(now, startTimeCal)) { + result = true; + } + } + return result; + } + + private static boolean isSameDay(Calendar cal1, Calendar cal2) { + return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && + cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); + } + +} 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 d9089de27d0..931fd011d15 100755 --- 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 @@ -38,7 +38,6 @@ import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.SpeedWithBearing; import com.sap.sailing.domain.base.Venue; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.EventImpl; import com.sap.sailing.domain.base.impl.FleetImpl; @@ -83,8 +82,8 @@ import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; +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.MongoRaceLogStoreFactory; @@ -100,10 +99,12 @@ import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; import com.sap.sailing.domain.racelog.impl.RaceLogImpl; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sailing.domain.tracking.Wind; @@ -333,26 +334,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return result; } - private CourseArea loadCourseAreaFromEvents(DBObject dbObject) { - Serializable courseAreaId = (Serializable) dbObject.get(FieldNames.COURSE_AREA_ID.name()); - CourseArea result; - if (courseAreaId == null) { - result = null; - } else { - UUID courseAreaUuid = UUID.fromString(courseAreaId.toString()); - Iterable allEvents = loadAllEvents(); - result = null; - for (Event event : allEvents) { - for (CourseArea courseArea : event.getVenue().getCourseAreas()) { - if (courseArea.getId().equals(courseAreaUuid)) { - result = courseArea; - } - } - } - } - return result; - } - /** * @return null if the regatta cannot be resolved; otherwise the leaderboard for the regatta specified */ @@ -382,7 +363,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final ScoringScheme scoringScheme = loadScoringScheme(dbLeaderboard); RaceLogStore raceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore( new MongoObjectFactoryImpl(database), this); - CourseArea courseArea = loadCourseAreaFromEvents(dbLeaderboard); + + Serializable courseAreaId = (Serializable) dbLeaderboard.get(FieldNames.COURSE_AREA_ID.name()); + CourseArea courseArea = null; + if (courseAreaId != null) { + UUID courseAreaUuid = UUID.fromString(courseAreaId.toString()); + courseArea = DomainFactory.INSTANCE.getExistingCourseAreaById(courseAreaUuid); + } + result = new FlexibleLeaderboardImpl(raceLogStore, (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME .name()), scoreCorrection, resultDiscardingRule, scoringScheme, courseArea); // For a FlexibleLeaderboard, fleets are owned by the leaderboard's RaceColumn objects. We need to manage @@ -839,7 +827,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private CourseArea loadCourseArea(DBObject courseAreaDBObject) { String name = (String) courseAreaDBObject.get(FieldNames.COURSE_AREA_NAME.name()); Serializable id = (Serializable) courseAreaDBObject.get(FieldNames.COURSE_AREA_ID.name()); - return new CourseAreaImpl(name, id); + return DomainFactory.INSTANCE.getOrCreateCourseArea(id, name); } @Override @@ -881,7 +869,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { RaceLogStore raceLogStore = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore( new MongoObjectFactoryImpl(database), this); - CourseArea courseArea = loadCourseAreaFromEvents(dbRegatta); + + Serializable courseAreaId = (Serializable) dbRegatta.get(FieldNames.COURSE_AREA_ID.name()); + CourseArea courseArea = null; + if (courseAreaId != null) { + UUID courseAreaUuid = UUID.fromString(courseAreaId.toString()); + courseArea = DomainFactory.INSTANCE.getExistingCourseAreaById(courseAreaUuid); + } + result = new RegattaImpl(raceLogStore, baseName, boatClass, series, /* persistent */ true, loadScoringScheme(dbRegatta), id, courseArea); } return result; @@ -1058,11 +1053,27 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogGateLineOpeningTimeEvent(createdAt, timePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogStartProcedureChangedEvent.class.getSimpleName())) { return loadRaceLogStartProcedureChangedEvent(createdAt, timePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogProtestStartTimeEvent.class.getSimpleName())) { + return loadRaceLogRaceLogProtestStartTimeEvent(createdAt, timePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) { + return loadRaceLogRaceLogWindFixEvent(createdAt, timePoint, id, passId, competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); } + private RaceLogEvent loadRaceLogRaceLogWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, + Integer passId, List competitors, DBObject dbObject) { + Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name())); + return raceLogEventFactory.createWindFixEvent(createdAt, timePoint, id, competitors, passId, wind); + } + + private RaceLogEvent loadRaceLogRaceLogProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint, + Serializable id, Integer passId, List competitors, DBObject dbObject) { + TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME); + return raceLogEventFactory.createProtestStartTimeEvent(createdAt, timePoint, id, competitors, passId, protestStartTime); + } + private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { StartProcedureType type = StartProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); @@ -1084,7 +1095,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - return raceLogEventFactory.createFinishPositioningConfirmedEvent(createdAt, timePoint, id, competitors, passId); + BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); + List> 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. + if (dbPositionedCompetitorList != null) { + positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); + } + + return raceLogEventFactory.createFinishPositioningConfirmedEvent(createdAt, timePoint, id, competitors, passId, positionedCompetitors); } private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, TimePoint timePoint, @@ -1101,7 +1120,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name())); + 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); return raceLogEventFactory.createCourseDesignChangedEvent(createdAt, timePoint, id, competitors, passId, courseData); } @@ -1168,8 +1188,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return raceLogEventFactory.createRaceStatusEvent(createdAt, timePoint, id, competitors, passId, nextStatus); } - private CourseBase loadCourseData(BasicDBList dbCourseList) { - CourseBase courseData = new CourseDataImpl("TemplateCourse"); + private CourseBase loadCourseData(BasicDBList dbCourseList, String courseName) { + if (courseName == null) { + courseName = "Course template"; + } + CourseBase courseData = new CourseDataImpl(courseName); int i = 0; for (Object object : dbCourseList) { DBObject dbObject = (DBObject) object; 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 5b9853889f6..1ccaf2b5a3d 100755 --- 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 @@ -72,5 +72,6 @@ public enum FieldNames { RACE_LOG_EVENT, RACE_LOG_EVENT_PASS_ID, RACE_LOG_EVENT_ID, RACE_LOG_EVENT_CREATED_AT, 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, WAYPOINT_ID, WAYPOINT_NAME, WAYPOINT_PASSINGSIDE, CONTROLPOINT, CONTROLPOINT_CLASS, MARK_ID, MARK_COLOR, MARK_NAME, MARK_PATTERN, MARK_SHAPE, MARK_TYPE, - CONTROLPOINT_VALUE, GATE_ID, GATE_NAME, GATE_LEFT, GATE_RIGHT, RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, RACE_LOG_START_PROCEDURE_TYPE; + CONTROLPOINT_VALUE, GATE_ID, GATE_NAME, GATE_LEFT, GATE_RIGHT, RACE_LOG_POSITIONED_COMPETITORS, RACE_LOG_PATHFINDER_ID, RACE_LOG_GATE_LINE_OPENING_TIME, + RACE_LOG_START_PROCEDURE_TYPE, RACE_LOG_PROTEST_START_TIME, RACE_LOG_COURSE_DESIGN_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 f175862a823..f38d50af98b 100755 --- 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 @@ -55,9 +55,11 @@ import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; import com.sap.sailing.domain.tracking.Positioned; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegatta; @@ -605,8 +607,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogGateLineOpeningTimeEvent(gateLineOpeningTimeEvent)); return result; } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartProcedureChangedEvent event) { DBObject result = new BasicDBObject(); @@ -614,7 +614,39 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartProcedureChangedEvent(event)); return result; } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogProtestStartTimeEvent event) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.RACE_LOG_IDENTIFIER.name(), MongoUtils.escapeDollarAndDot(raceLogIdentifier.getIdentifier().toString())); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogProtestStartTimeEvent(event)); + return result; + } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogWindFixEvent event) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.RACE_LOG_IDENTIFIER.name(), MongoUtils.escapeDollarAndDot(raceLogIdentifier.getIdentifier().toString())); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogWindFix(event)); + return result; + } + + private Object storeRaceLogWindFix(RaceLogWindFixEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogWindFixEvent.class.getSimpleName()); + result.put(FieldNames.WIND.name(), storeWind(event.getWindFix())); + return result; + } + + private Object storeRaceLogProtestStartTimeEvent(RaceLogProtestStartTimeEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogProtestStartTimeEvent.class.getSimpleName()); + storeTimePoint(event.getProtestStartTime(), result, FieldNames.RACE_LOG_PROTEST_START_TIME); + return result; + } + private Object storeRaceLogStartProcedureChangedEvent(RaceLogStartProcedureChangedEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); @@ -656,7 +688,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { result.put(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name(), String.valueOf(flagEvent.isDisplayed())); return result; } - + private void storeRaceLogEventProperties(RaceLogEvent event, DBObject result) { storeTimed(event, result); storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT); @@ -707,7 +739,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRaceLogEventProperties(courseDesignChangedEvent, result); result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCourseDesignChangedEvent.class.getSimpleName()); - + + result.put(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name(), courseDesignChangedEvent.getCourseDesign().getName()); result.put(FieldNames.RACE_LOG_COURSE_DESIGN.name(), storeCourseBase(courseDesignChangedEvent.getCourseDesign())); return result; } @@ -728,6 +761,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRaceLogEventProperties(finishPositioningConfirmedEvent, result); result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); + + result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitors())); return result; } @@ -745,10 +780,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { private BasicDBList storePositionedCompetitors(List> positionedCompetitors) { BasicDBList dbList = new BasicDBList(); - for (Triple competitorPair : positionedCompetitors) { - dbList.add(storePositionedCompetitor(competitorPair)); + if (positionedCompetitors != null) { + for (Triple competitorPair : positionedCompetitors) { + dbList.add(storePositionedCompetitor(competitorPair)); + } } - + return dbList; } @@ -817,4 +854,5 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } return passing; } + } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogListener.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogListener.java index c91a5c5ec4c..55493b47612 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogListener.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogListener.java @@ -14,9 +14,11 @@ import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; public class MongoRaceLogListener implements RaceLogEventVisitor { @@ -79,20 +81,20 @@ public class MongoRaceLogListener implements RaceLogEventVisitor { @Override public void visit(RaceLogFinishPositioningConfirmedEvent event) { - DBObject finishPositioningConfirmedEventTrackEntry = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); - storeEventInCollection(finishPositioningConfirmedEventTrackEntry); + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + storeEventInCollection(object); } @Override public void visit(RaceLogPathfinderEvent event) { - DBObject pathfinderEventTrackEntry = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); - storeEventInCollection(pathfinderEventTrackEntry); + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + storeEventInCollection(object); } @Override public void visit(RaceLogGateLineOpeningTimeEvent event) { - DBObject gateLineOpeningTimeEventTrackEntry = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); - storeEventInCollection(gateLineOpeningTimeEventTrackEntry); + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + storeEventInCollection(object); } @Override @@ -101,4 +103,16 @@ public class MongoRaceLogListener implements RaceLogEventVisitor { storeEventInCollection(object); } + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + storeEventInCollection(object); + } + + @Override + public void visit(RaceLogWindFixEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + storeEventInCollection(object); + } + } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/AbortingFlagFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/AbortingFlagFinderTest.java new file mode 100644 index 00000000000..7128fd9300b --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/AbortingFlagFinderTest.java @@ -0,0 +1,122 @@ +package com.sap.sailing.domain.racelog.analyzing.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.when; + +import java.util.UUID; + +import org.junit.Test; + +import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; +import com.sap.sailing.domain.racelog.analyzing.impl.AbortingFlagFinder; + +public class AbortingFlagFinderTest extends RaceLogAnalyzerTest { + + @Override + protected AbortingFlagFinder createAnalyzer(RaceLog raceLog) { + return new AbortingFlagFinder(raceLog); + } + + @Test + public void testNullOnEmpty() { + assertNull(analyzer.analyze()); + } + + @Test + public void testNullOnNoPreviousPass() { + int passId = 0; + RaceLogFlagEvent event1 = createAbortingEvent(passId); + + raceLog.add(event1); + + assertNull(analyzer.analyze()); + } + + @Test + public void testNullOnPreviousPassNotAborted() { + int passId = 0; + RaceLogFlagEvent event1 = createNonAbortingEvent(passId); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 1, passId + 1, UUID.randomUUID()); + + raceLog.add(event1); + raceLog.add(event2); + + assertNull(analyzer.analyze()); + } + + @Test + public void testNullOnPassBeforePreviousAborted() { + int passId = 0; + RaceLogFlagEvent event1 = createAbortingEvent(passId); + RaceLogFlagEvent event2 = createNonAbortingEvent(passId + 1); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 1, passId + 2, UUID.randomUUID()); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + assertNull(analyzer.analyze()); + } + + @Test + public void testPreviousPassAborted() { + int passId = 0; + RaceLogFlagEvent event1 = createAbortingEvent(passId); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 1, passId + 1, UUID.randomUUID()); + + raceLog.add(event1); + raceLog.add(event2); + + assertEquals(event1, analyzer.analyze()); + } + + @Test + public void testPreviousPassAbortedReturnsMostRecentAbortEvent() { + int passId = 0; + RaceLogFlagEvent event1 = createAbortingEvent(passId, 1); + RaceLogFlagEvent event2 = createAbortingEvent(passId, 2); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 1, passId + 1, UUID.randomUUID()); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + assertEquals(event2, analyzer.analyze()); + } + + @Test + public void testPreviousPassAndPassBeforePreviousAborted() { + int passId = 0; + RaceLogFlagEvent event1 = createAbortingEvent(passId); + RaceLogFlagEvent event2 = createAbortingEvent(passId + 1); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 1, passId + 2, UUID.randomUUID()); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + assertEquals(event2, analyzer.analyze()); + } + + private static RaceLogFlagEvent createAbortingEvent(int passId) { + return createAbortingEvent(passId, 1); + } + + private static RaceLogFlagEvent createAbortingEvent(int passId, int time) { + RaceLogFlagEvent event = createEvent(RaceLogFlagEvent.class, time, passId, UUID.randomUUID()); + when(event.getUpperFlag()).thenReturn(Flags.AP); + when(event.isDisplayed()).thenReturn(true); + return event; + } + + private static RaceLogFlagEvent createNonAbortingEvent(int passId) { + RaceLogFlagEvent event = createEvent(RaceLogFlagEvent.class, 1, passId, UUID.randomUUID()); + when(event.getUpperFlag()).thenReturn(Flags.AP); + when(event.isDisplayed()).thenReturn(false); + return event; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastFlagsFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastFlagsFinderTest.java new file mode 100644 index 00000000000..c5f84c32151 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastFlagsFinderTest.java @@ -0,0 +1,172 @@ +package com.sap.sailing.domain.racelog.analyzing.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; + +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; +import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagsFinder; + +public class LastFlagsFinderTest extends RaceLogAnalyzerTest { + + @Override + protected LastFlagsFinder createAnalyzer(RaceLog raceLog) { + return new LastFlagsFinder(raceLog); + } + + @Test + public void testNullForNoFlag() { + RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1); + raceLog.add(event1); + + assertNull(analyzer.analyze()); + } + + @Test + public void testSingleLast() { + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2); + + raceLog.add(event1); + raceLog.add(event2); + + List result = analyzer.analyze(); + assertEquals(1, result.size()); + assertEquals(event2, result.get(0)); + } + + @Test + public void testSingleInBetween() { + RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2); + RaceLogEvent event3 = createEvent(RaceLogEvent.class, 3); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + List result = analyzer.analyze(); + assertEquals(1, result.size()); + assertEquals(event2, result.get(0)); + } + + @Test + public void testTwoLast() { + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2, "a"); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 2, "b"); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + List result = analyzer.analyze(); + assertEquals(2, result.size()); + assertEquals(event3, result.get(0)); + assertEquals(event2, result.get(1)); + } + + @Test + public void testTwoLastWithInBetween() { + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2, "a"); + RaceLogEvent event3 = createEvent(RaceLogEvent.class, 2, "b"); + RaceLogFlagEvent event4 = createEvent(RaceLogFlagEvent.class, 2, "c"); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + raceLog.add(event4); + + List result = analyzer.analyze(); + assertEquals(2, result.size()); + assertEquals(event4, result.get(0)); + assertEquals(event2, result.get(1)); + } + + @Test + public void testMoreThanTwoLast() { + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 2, "a"); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 2, "b"); + RaceLogFlagEvent event4 = createEvent(RaceLogFlagEvent.class, 2, "c"); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + raceLog.add(event4); + + List result = analyzer.analyze(); + assertEquals(3, result.size()); + assertEquals(event4, result.get(0)); + assertEquals(event3, result.get(1)); + assertEquals(event2, result.get(2)); + } + + @Test + public void testGetMostRecentDisplayedNullOnNull() { + assertNull(LastFlagsFinder.getMostRecent(null)); + } + + @Test + public void testGetMostRecentDisplayedNullOnEmpty() { + assertNull(LastFlagsFinder.getMostRecent(new ArrayList())); + } + + @Test + public void testGetMostRecentDisplayedDisplayedOverRemoved() { + List events = new ArrayList(); + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + when(event1.isDisplayed()).thenReturn(false); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 1); + when(event2.isDisplayed()).thenReturn(true); + + events.add(event1); + events.add(event2); + + assertEquals(event2, LastFlagsFinder.getMostRecent(events)); + + // order independent? + Collections.reverse(events); + assertEquals(event2, LastFlagsFinder.getMostRecent(events)); + } + + @Test + public void testGetMostRecentDisplayedMultipleDisplayedOverRemoved() { + List events = new ArrayList(); + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1); + when(event1.isDisplayed()).thenReturn(false); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 1, "a"); + when(event2.isDisplayed()).thenReturn(true); + RaceLogFlagEvent event3 = createEvent(RaceLogFlagEvent.class, 1, "b"); + when(event3.isDisplayed()).thenReturn(true); + + events.add(event1); + events.add(event2); + events.add(event3); + + assertEquals(event3, LastFlagsFinder.getMostRecent(events)); + } + + @Test + public void testGetMostRecentDisplayedMultipleRemoved() { + List events = new ArrayList(); + RaceLogFlagEvent event1 = createEvent(RaceLogFlagEvent.class, 1, "a"); + when(event1.isDisplayed()).thenReturn(false); + RaceLogFlagEvent event2 = createEvent(RaceLogFlagEvent.class, 1, "b"); + when(event2.isDisplayed()).thenReturn(false); + + events.add(event1); + events.add(event2); + + assertEquals(event2, LastFlagsFinder.getMostRecent(events)); + } +} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastWindFixFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastWindFixFinderTest.java new file mode 100644 index 00000000000..7a3296b986c --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/LastWindFixFinderTest.java @@ -0,0 +1,42 @@ +package com.sap.sailing.domain.racelog.analyzing.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.racelog.analyzing.impl.LastWindFixFinder; +import com.sap.sailing.domain.tracking.Wind; + +public class LastWindFixFinderTest extends RaceLogAnalyzerTest { + + @Override + protected LastWindFixFinder createAnalyzer(RaceLog raceLog) { + return new LastWindFixFinder(raceLog); + } + + @Test + public void testNullForNone() { + RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1); + raceLog.add(event1); + assertNull(analyzer.analyze()); + } + + @Test + public void testMostRecent() { + RaceLogWindFixEvent event1 = createEvent(RaceLogWindFixEvent.class, 1); + RaceLogWindFixEvent event2 = createEvent(RaceLogWindFixEvent.class, 2); + when(event2.getWindFix()).thenReturn(mock(Wind.class)); + + raceLog.add(event1); + raceLog.add(event2); + + raceLog.lockForRead(); + assertEquals(event2.getWindFix(), analyzer.analyze()); + } +} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ProtestStartTmeFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ProtestStartTmeFinderTest.java new file mode 100644 index 00000000000..577620d82ca --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/ProtestStartTmeFinderTest.java @@ -0,0 +1,42 @@ +package com.sap.sailing.domain.racelog.analyzing.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; +import com.sap.sailing.domain.racelog.analyzing.impl.ProtestStartTimeFinder; + +public class ProtestStartTmeFinderTest extends RaceLogAnalyzerTest { + + @Override + protected ProtestStartTimeFinder createAnalyzer(RaceLog raceLog) { + return new ProtestStartTimeFinder(raceLog); + } + + @Test + public void testNullForNone() { + RaceLogEvent event1 = createEvent(RaceLogEvent.class, 1); + raceLog.add(event1); + assertNull(analyzer.analyze()); + } + + @Test + public void testMostRecent() { + RaceLogProtestStartTimeEvent event1 = createEvent(RaceLogProtestStartTimeEvent.class, 1); + RaceLogProtestStartTimeEvent event2 = createEvent(RaceLogProtestStartTimeEvent.class, 2); + when(event2.getProtestStartTime()).thenReturn(mock(TimePoint.class)); + + raceLog.add(event1); + raceLog.add(event2); + + raceLog.lockForRead(); + assertEquals(event2.getProtestStartTime(), analyzer.analyze()); + } +} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/RaceLogAnalyzerTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/RaceLogAnalyzerTest.java new file mode 100644 index 00000000000..2b1a0ea7265 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/RaceLogAnalyzerTest.java @@ -0,0 +1,44 @@ +package com.sap.sailing.domain.racelog.analyzing.test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.Serializable; + +import org.junit.Before; + +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.impl.RaceLogImpl; + +public abstract class RaceLogAnalyzerTest { + + protected AnalyzerType analyzer; + protected RaceLog raceLog; + + @Before + public void setUpBase() { + raceLog = new RaceLogImpl("RaceLogTest", "test-identifier"); + analyzer = createAnalyzer(raceLog); + } + + protected abstract AnalyzerType createAnalyzer(RaceLog raceLog); + + protected static T createEvent(Class type, long milliseconds) { + return createEvent(type, milliseconds, 0, ""); + } + + protected static T createEvent(Class type, long milliseconds, Serializable id) { + return createEvent(type, milliseconds, 0, id); + } + + protected static T createEvent(Class type, long milliseconds, int passId, Serializable id) { + T event = mock(type); + when(event.getPassId()).thenReturn(passId); + when(event.getTimePoint()).thenReturn(new MillisecondsTimePoint(milliseconds)); + when(event.getId()).thenReturn(id); + return event; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogAnalyzerTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogAnalyzerTest.java deleted file mode 100644 index 4aa979513bb..00000000000 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogAnalyzerTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.sap.sailing.domain.racelog.test; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; -import com.sap.sailing.domain.common.TimePoint; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.racelog.RaceLog; -import com.sap.sailing.domain.racelog.RaceLogEventFactory; -import com.sap.sailing.domain.racelog.RaceLogFlagEvent; -import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagFinder; -import com.sap.sailing.domain.racelog.impl.RaceLogImpl; - -public class RaceLogAnalyzerTest { - - @Test - public void testLastFlagFinder() { - RaceLog raceLog = new RaceLogImpl("RaceLogTest", "test-identifier"); - TimePoint t1 = MillisecondsTimePoint.now(); - int passId = 0; - boolean isDisplayed = true; - RaceLogFlagEvent rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, passId, Flags.XRAY, Flags.NONE, - isDisplayed); - raceLog.add(rcEvent); - rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(t1.plus(1), passId, Flags.PAPA, Flags.NONE, - isDisplayed); - raceLog.add(rcEvent); - - raceLog.lockForRead(); - try { - LastFlagFinder lff = new LastFlagFinder(raceLog); - assertEquals(rcEvent, lff.getLastFlagEvent()); - - } finally { - raceLog.unlockAfterRead(); - } - } - -} diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java index 0ceea5a6e87..447ceb59b99 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java @@ -146,6 +146,50 @@ public class RaceLogTest { verify(listener, never()).visit(event); } + @Test + public void testRawFixesDescending() { + RaceLogEvent event1 = mock(RaceLogEvent.class); + RaceLogEvent event2 = mock(RaceLogEvent.class); + RaceLogEvent event3 = mock(RaceLogEvent.class); + + when(event1.getTimePoint()).thenReturn(new MillisecondsTimePoint(1)); + when(event2.getTimePoint()).thenReturn(new MillisecondsTimePoint(2)); + when(event3.getTimePoint()).thenReturn(new MillisecondsTimePoint(3)); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + raceLog.lockForRead(); + assertEquals(event3, Util.get(raceLog.getRawFixesDescending(), 0)); + assertEquals(event2, Util.get(raceLog.getRawFixesDescending(), 1)); + assertEquals(event1, Util.get(raceLog.getRawFixesDescending(), 2)); + raceLog.unlockAfterRead(); + } + + @Test + public void testFixesDescending() { + RaceLogEvent event1 = mock(RaceLogEvent.class); + RaceLogEvent event2 = mock(RaceLogEvent.class); + RaceLogEvent event3 = mock(RaceLogEvent.class); + + when(event1.getPassId()).thenReturn(1); + when(event1.getTimePoint()).thenReturn(new MillisecondsTimePoint(1)); + when(event2.getPassId()).thenReturn(1); + when(event2.getTimePoint()).thenReturn(new MillisecondsTimePoint(2)); + when(event3.getPassId()).thenReturn(0); + when(event3.getTimePoint()).thenReturn(new MillisecondsTimePoint(3)); + + raceLog.add(event1); + raceLog.add(event2); + raceLog.add(event3); + + raceLog.lockForRead(); + assertEquals(event2, Util.get(raceLog.getFixesDescending(), 0)); + assertEquals(event1, Util.get(raceLog.getFixesDescending(), 1)); + raceLog.unlockAfterRead(); + } + private class VisitFlagEventAnswer implements Answer { @Override public Object answer(InvocationOnMock invocation) throws Throwable { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseArea.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseArea.java index 5dcab51d8b5..bd90d7a8be7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseArea.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseArea.java @@ -10,6 +10,6 @@ import com.sap.sailing.domain.common.WithID; * @author Axel Uhl (D043530) * */ -public interface CourseArea extends Named, WithID { +public interface CourseArea extends Named, WithID, IsManagedBySharedDomainFactory { } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/CourseChange.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseChange.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/CourseChange.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CourseChange.java 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 d5ef24aefe7..03d08f83a2f 100644 --- 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 @@ -77,6 +77,10 @@ public interface SharedDomainFactory { Competitor createCompetitor(Serializable id, String name, Team team, Boat boat); Competitor getOrCreateCompetitor(Serializable competitorId, String name, Team team, Boat boat); + + CourseArea getOrCreateCourseArea(Serializable courseAreaId, String name); + + CourseArea getExistingCourseAreaById(Serializable courseAreaId); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/SpeedWithBearing.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SpeedWithBearing.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/SpeedWithBearing.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SpeedWithBearing.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithAbstractBearingImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithAbstractBearingImpl.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithAbstractBearingImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithAbstractBearingImpl.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/AbstractSpeedWithBearingImpl.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseAreaImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseAreaImpl.java index 93201d7aeda..62581d234a1 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseAreaImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseAreaImpl.java @@ -3,6 +3,8 @@ package com.sap.sailing.domain.base.impl; import java.io.Serializable; import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.IsManagedBySharedDomainFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.common.impl.NamedImpl; public class CourseAreaImpl extends NamedImpl implements CourseArea { @@ -21,14 +23,7 @@ public class CourseAreaImpl extends NamedImpl implements CourseArea { } @Override - public boolean equals(Object obj) { - if (obj instanceof CourseArea) { - CourseArea courseArea = (CourseArea) obj; - if (this.id.equals(courseArea.getId())) { - return true; - } - return false; - } - return super.equals(obj); + public IsManagedBySharedDomainFactory resolve(SharedDomainFactory domainFactory) { + return domainFactory.getOrCreateCourseArea(id, getName()); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseChangeImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseChangeImpl.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseChangeImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CourseChangeImpl.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KnotSpeedWithBearingImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/KnotSpeedWithBearingImpl.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/KnotSpeedWithBearingImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/KnotSpeedWithBearingImpl.java diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/racegroup/SeriesWithRows.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/racegroup/SeriesWithRows.java index 22dab07e17d..2e1604bf79a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/racegroup/SeriesWithRows.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/racegroup/SeriesWithRows.java @@ -7,5 +7,9 @@ import com.sap.sailing.domain.base.SeriesBase; * between Leaderboards and Regattas for any app since Leaderboards do not have any series, but Regattas. */ public interface SeriesWithRows extends SeriesBase { + + /** + * All {@link RaceRow}s of this series. + */ public Iterable getRaceRows(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java index 3a665056e7b..ea6348cf621 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLog.java @@ -17,6 +17,9 @@ import com.sap.sailing.domain.tracking.Track; *

*/ public interface RaceLog extends Track, WithID { + + public static final int DefaultPassId = 0; + /** * Gets the current pass id. * @@ -47,4 +50,8 @@ public interface RaceLog extends Track, WithID { * Checks if the race log is empty. */ boolean isEmpty(); + + Iterable getRawFixesDescending(); + + Iterable getFixesDescending(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventFactory.java index 33f5e3c5a11..a0b8c3860b3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventFactory.java @@ -12,59 +12,82 @@ import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.StartProcedureType; import com.sap.sailing.domain.racelog.impl.RaceLogEventFactoryImpl; +import com.sap.sailing.domain.tracking.Wind; public interface RaceLogEventFactory { RaceLogEventFactory INSTANCE = new RaceLogEventFactoryImpl(); RaceLogFlagEvent createFlagEvent(TimePoint timePoint, Serializable id, List involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed); + RaceLogFlagEvent createFlagEvent(TimePoint timePoint, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed); RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, Serializable id, List involvedBoats, int passId, TimePoint startTime); + RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, int passId, TimePoint startTime); RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, Serializable id, List competitors, int passId, RaceLogRaceStatus nextStatus); + RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, int passId, RaceLogRaceStatus nextStatus); RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, Serializable id, List competitors, int passId); + RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, int passId); RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, Serializable courseAreaId); + RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, int passId, Serializable courseAreaId); RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, CourseBase courseData); + RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, int passId, CourseBase courseData); RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, List> positionedCompetitors); + RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint timePoint, int passId, List> positionedCompetitors); RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, Serializable id, - List competitors, int passId); - RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId); + List competitors, int passId, List> positionedCompetitors); + + RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId, + List> positionedCompetitors); RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, Serializable id, List competitors, int passId, String pathfinderId); + RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, int passId, String pathfinderId); RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, Serializable id, List competitors, int passId, Long gateLineOpeningTimeInMillis); + RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, int passId, Long gateLineOpeningTimeInMillis); RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, StartProcedureType type); + RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, int passId, StartProcedureType type); + RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, Serializable id, + List competitors, int passId, TimePoint protestStartTime); + + RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, int passId, TimePoint protestStartTime); + + RaceLogWindFixEvent createWindFixEvent(TimePoint eventTime, int currentPassId, Wind wind); + + RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, Serializable id, + List competitors, int passId, Wind wind); + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventRestoreFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventRestoreFactory.java index 7639e9a7b72..9094f945cf1 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventRestoreFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventRestoreFactory.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.StartProcedureType; import com.sap.sailing.domain.racelog.impl.RaceLogEventRestoreFactoryImpl; +import com.sap.sailing.domain.tracking.Wind; public interface RaceLogEventRestoreFactory extends RaceLogEventFactory { RaceLogEventRestoreFactory INSTANCE = new RaceLogEventRestoreFactoryImpl(); @@ -39,7 +40,8 @@ public interface RaceLogEventRestoreFactory extends RaceLogEventFactory { List> positionedCompetitors); RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId); + TimePoint logicalTimePoint, Serializable id, List competitors, int passId, + List> positionedCompetitors); RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, TimePoint logicalTimePoint, Serializable id, List competitors, int passId, String pathfinderId); @@ -49,4 +51,10 @@ public interface RaceLogEventRestoreFactory extends RaceLogEventFactory { RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, List competitors, int passId, StartProcedureType type); + + RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint, + Serializable id, List competitors, int passId, TimePoint protestStartTime); + + RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, + List competitors, Integer passId, Wind wind); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventVisitor.java index bcecedd3d47..45f58b5f642 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogEventVisitor.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.racelog; + public interface RaceLogEventVisitor { public void visit(RaceLogFlagEvent event); @@ -22,4 +23,8 @@ public interface RaceLogEventVisitor { public void visit(RaceLogGateLineOpeningTimeEvent event); public void visit(RaceLogStartProcedureChangedEvent event); + + public void visit(RaceLogProtestStartTimeEvent event); + + public void visit(RaceLogWindFixEvent event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningConfirmedEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningConfirmedEvent.java index aff470f3651..69f35dd2244 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningConfirmedEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningConfirmedEvent.java @@ -1,5 +1,12 @@ package com.sap.sailing.domain.racelog; -public interface RaceLogFinishPositioningConfirmedEvent extends RaceLogEvent { +/** + * This RaceLog evet type confirms the entered positioning list. Since we do not guarantee the order of incoming events from the app (due to possible + * connectivity issues), this event type contains the the confirmed positioning list again. Although this racelog event type contains the same information + * such as {@link RaceLogFinishPositioningListChangedEvent} we keep it for backwards compatibility reasons. + * + */ +public interface RaceLogFinishPositioningConfirmedEvent extends RaceLogFinishPositioningEvent { + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java new file mode 100644 index 00000000000..5c92d3e9a9b --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningEvent.java @@ -0,0 +1,12 @@ +package com.sap.sailing.domain.racelog; + +import java.io.Serializable; +import java.util.List; + +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.impl.Util.Triple; + +public abstract interface RaceLogFinishPositioningEvent extends RaceLogEvent { + + List> getPositionedCompetitors(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningListChangedEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningListChangedEvent.java index ea5c8513178..7eeb1265a60 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningListChangedEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogFinishPositioningListChangedEvent.java @@ -1,12 +1,6 @@ package com.sap.sailing.domain.racelog; -import java.io.Serializable; -import java.util.List; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.impl.Util.Triple; - -public interface RaceLogFinishPositioningListChangedEvent extends RaceLogEvent { +public interface RaceLogFinishPositioningListChangedEvent extends RaceLogFinishPositioningEvent { - List> getPositionedCompetitors(); -} +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogProtestStartTimeEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogProtestStartTimeEvent.java new file mode 100644 index 00000000000..bce44018dda --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogProtestStartTimeEvent.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.racelog; + +import com.sap.sailing.domain.common.TimePoint; + +/** + * Indicates that the protest start time for the related race has changed. + * + */ +public interface RaceLogProtestStartTimeEvent extends RaceLogEvent { + + /** + * Returns the start time of the race's protest time. + */ + TimePoint getProtestStartTime(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogWindFixEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogWindFixEvent.java new file mode 100644 index 00000000000..b4815a71177 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/RaceLogWindFixEvent.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.racelog; + +import com.sap.sailing.domain.tracking.Wind; + +/** + * Contains a wind fix that the race officers documented in the Race Committee App ashore + * + */ +public interface RaceLogWindFixEvent extends RaceLogEvent { + + /** + * Returns the wind fix entered by the race committee + */ + Wind getWindFix(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java index d61cecfcba6..c3e606f939f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AbortingFlagFinder.java @@ -5,47 +5,32 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogFlagEvent; -public class AbortingFlagFinder extends RaceLogAnalyzer { +public class AbortingFlagFinder extends RaceLogAnalyzer { public AbortingFlagFinder(RaceLog raceLog) { super(raceLog); } - public RaceLogFlagEvent getAbortingFlagEvent() { - - RaceLogFlagEvent newFlagEvent = null; - - this.raceLog.lockForRead(); - try { - newFlagEvent = searchForAbortingFlagEvent(); - } finally { - this.raceLog.unlockAfterRead(); + @Override + protected RaceLogFlagEvent performAnalyzation() { + if (raceLog.getCurrentPassId() <= RaceLog.DefaultPassId) { + return null; } - - return newFlagEvent; - } - private RaceLogFlagEvent searchForAbortingFlagEvent() { - RaceLogFlagEvent newFlagEvent = null; - - if (raceLog.getCurrentPassId() > 0) { - int relevantPassId = raceLog.getCurrentPassId() - 1; - for (RaceLogEvent event : getAllEvents()) { - if (event.getPassId() == relevantPassId) { - if (event instanceof RaceLogFlagEvent) { - RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event; - if (isAbortingFlag(flagEvent)) { - newFlagEvent = flagEvent; - } - } + int lastButOnePass = raceLog.getCurrentPassId() - 1; + for (RaceLogEvent event : getAllEventsDescending()) { + if (event.getPassId() == lastButOnePass && event instanceof RaceLogFlagEvent) { + RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event; + if (isDisplayedAbortingFlag(flagEvent)) { + return flagEvent; } } } - - return newFlagEvent; + + return null; } - - private boolean isAbortingFlag(RaceLogFlagEvent flagEvent) { + + private static boolean isDisplayedAbortingFlag(RaceLogFlagEvent flagEvent) { return (flagEvent.getUpperFlag().equals(Flags.AP) && flagEvent.isDisplayed()) || (flagEvent.getUpperFlag().equals(Flags.NOVEMBER) && flagEvent.isDisplayed()) || (flagEvent.getUpperFlag().equals(Flags.FIRSTSUBSTITUTE) && flagEvent.isDisplayed()); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java new file mode 100644 index 00000000000..bceb0a085b4 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ConfirmedFinishPositioningListFinder.java @@ -0,0 +1,31 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import java.io.Serializable; +import java.util.List; + +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.impl.Util.Triple; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; + +public class ConfirmedFinishPositioningListFinder extends RaceLogAnalyzer>> { + + public ConfirmedFinishPositioningListFinder(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected List> performAnalyzation() { + List> lastFinishPositioningList = null; + + for (RaceLogEvent event : getPassEvents()) { + if (event instanceof RaceLogFinishPositioningConfirmedEvent) { + RaceLogFinishPositioningConfirmedEvent finishPositioningEvent = (RaceLogFinishPositioningConfirmedEvent) event; + lastFinishPositioningList = finishPositioningEvent.getPositionedCompetitors(); + } + } + + return lastFinishPositioningList; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java index 97cf66bf0ff..e7ec923ff7b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishPositioningListFinder.java @@ -9,26 +9,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent; -public class FinishPositioningListFinder extends RaceLogAnalyzer { +public class FinishPositioningListFinder extends RaceLogAnalyzer>> { public FinishPositioningListFinder(RaceLog raceLog) { super(raceLog); } - - public List> getFinishPositioningList() { - List> lastFinishPositioningList = null; - this.raceLog.lockForRead(); - try { - lastFinishPositioningList = searchForLastFinishPositioningList(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return lastFinishPositioningList; - } - - private List> searchForLastFinishPositioningList() { + @Override + protected List> performAnalyzation() { List> lastFinishPositioningList = null; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java index 2664356eed2..eacb45ac001 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishedTimeFinder.java @@ -6,26 +6,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; -public class FinishedTimeFinder extends RaceLogAnalyzer { +public class FinishedTimeFinder extends RaceLogAnalyzer { public FinishedTimeFinder(RaceLog raceLog) { super(raceLog); } - public TimePoint getFinishedTime() { - TimePoint finishedTime = null; - - this.raceLog.lockForRead(); - try { - finishedTime = searchForFinishedTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return finishedTime; - } - - private TimePoint searchForFinishedTime() { + @Override + protected TimePoint performAnalyzation() { TimePoint finishedTime = null; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java index b74c1dede26..2071cd9e2d6 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/FinishingTimeFinder.java @@ -6,26 +6,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; -public class FinishingTimeFinder extends RaceLogAnalyzer { +public class FinishingTimeFinder extends RaceLogAnalyzer { public FinishingTimeFinder(RaceLog raceLog) { super(raceLog); } - public TimePoint getFinishingTime() { - TimePoint finishingTime = null; - - this.raceLog.lockForRead(); - try { - finishingTime = searchForFinishingTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return finishingTime; - } - - private TimePoint searchForFinishingTime() { + @Override + protected TimePoint performAnalyzation() { TimePoint finishingTime = null; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java index f2033952b22..06355605087 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/GateLineOpeningTimeFinder.java @@ -4,25 +4,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; -public class GateLineOpeningTimeFinder extends RaceLogAnalyzer { +public class GateLineOpeningTimeFinder extends RaceLogAnalyzer { public GateLineOpeningTimeFinder(RaceLog raceLog) { super(raceLog); } - public Long getGateLineOpeningTime() { - Long gateLineOpeningTime; - this.raceLog.lockForRead(); - try { - gateLineOpeningTime = searchForGateLineOpeningTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return gateLineOpeningTime; - } - - private Long searchForGateLineOpeningTime() { + @Override + protected Long performAnalyzation() { Long gateLineOpeningTime = null; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallDisplayedFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallDisplayedFinder.java new file mode 100644 index 00000000000..de3ed99ca6d --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallDisplayedFinder.java @@ -0,0 +1,17 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; + +public class IndividualRecallDisplayedFinder extends IndividualRecallFinder { + + public IndividualRecallDisplayedFinder(RaceLog raceLog) { + super(raceLog); + } + + protected boolean isRelevant(RaceLogFlagEvent flagEvent) { + return flagEvent.getUpperFlag().equals(Flags.XRAY) && flagEvent.isDisplayed(); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java index 7bc24f0825f..5994b6e43a7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallFinder.java @@ -1,50 +1,26 @@ package com.sap.sailing.domain.racelog.analyzing.impl; import com.sap.sailing.domain.common.TimePoint; -import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogFlagEvent; -public class IndividualRecallFinder extends RaceLogAnalyzer { +public abstract class IndividualRecallFinder extends RaceLogAnalyzer { public IndividualRecallFinder(RaceLog raceLog) { super(raceLog); } - - public TimePoint getIndividualRecallDisplayedTime() { - TimePoint displayedTime = null; - - this.raceLog.lockForRead(); - try { - displayedTime = searchForIndividualRecallDisplayedTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return displayedTime; - } - public TimePoint getIndividualRecallDisplayedRemovalTime() { - TimePoint removalTime = null; - - this.raceLog.lockForRead(); - try { - removalTime = searchForIndividualRecallRemovalTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return removalTime; - } - - private TimePoint searchForIndividualRecallDisplayedTime() { + protected abstract boolean isRelevant(RaceLogFlagEvent flagEvent); + + @Override + protected TimePoint performAnalyzation() { TimePoint displayedTime = null; for (RaceLogEvent event : getPassEvents()) { if (event instanceof RaceLogFlagEvent) { RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event; - if (flagEvent.getUpperFlag().equals(Flags.XRAY) && flagEvent.isDisplayed()) { + if (isRelevant(flagEvent)) { displayedTime = flagEvent.getTimePoint(); } } @@ -52,21 +28,5 @@ public class IndividualRecallFinder extends RaceLogAnalyzer { return displayedTime; } - - private TimePoint searchForIndividualRecallRemovalTime() { - TimePoint removalTime = null; - - for (RaceLogEvent event : getPassEvents()) { - if (event instanceof RaceLogFlagEvent) { - RaceLogFlagEvent flagEvent = (RaceLogFlagEvent) event; - if (flagEvent.getUpperFlag().equals(Flags.XRAY) && !flagEvent.isDisplayed()) { - removalTime = flagEvent.getTimePoint(); - } - } - } - - return removalTime; - } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallRemovedFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallRemovedFinder.java new file mode 100644 index 00000000000..76ce775ea48 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/IndividualRecallRemovedFinder.java @@ -0,0 +1,17 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import com.sap.sailing.domain.common.racelog.Flags; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; + +public class IndividualRecallRemovedFinder extends IndividualRecallFinder { + + public IndividualRecallRemovedFinder(RaceLog raceLog) { + super(raceLog); + } + + protected boolean isRelevant(RaceLogFlagEvent flagEvent) { + return flagEvent.getUpperFlag().equals(Flags.XRAY) && !flagEvent.isDisplayed(); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagFinder.java deleted file mode 100644 index 598067f1aa3..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagFinder.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sap.sailing.domain.racelog.analyzing.impl; - -import com.sap.sailing.domain.racelog.RaceLog; -import com.sap.sailing.domain.racelog.RaceLogEvent; -import com.sap.sailing.domain.racelog.RaceLogFlagEvent; - -public class LastFlagFinder extends RaceLogAnalyzer { - - public LastFlagFinder(RaceLog raceLog) { - super(raceLog); - } - - public RaceLogFlagEvent getLastFlagEvent() { - RaceLogFlagEvent lastFlagEvent = null; - - this.raceLog.lockForRead(); - try { - lastFlagEvent = searchForLastFlagEvent(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return lastFlagEvent; - } - - private RaceLogFlagEvent searchForLastFlagEvent() { - RaceLogFlagEvent lastFlagEvent = null; - - for (RaceLogEvent event : getPassEvents()) { - if (event instanceof RaceLogFlagEvent) { - lastFlagEvent = (RaceLogFlagEvent) event; - } - } - - return lastFlagEvent; - } - -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java new file mode 100644 index 00000000000..30748e187a1 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastFlagsFinder.java @@ -0,0 +1,99 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; + +/** + * Analyzation returns the most recent {@link RaceLogFlagEvent}s. + * + * If there is no {@link RaceLogFlagEvent} in the current pass, null is returned. Otherwise a {@link List} + * of {@link RaceLogFlagEvent} is returned containing all {@link RaceLogEvent}s with the most recent {@link TimePoint}. + * + */ +public class LastFlagsFinder extends RaceLogAnalyzer> { + + public LastFlagsFinder(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected List performAnalyzation() { + + Iterator iterator = getPassEventsDescending().iterator(); + RaceLogFlagEvent flagEvent = getNextFlagEvent(iterator); + if (flagEvent != null) { + return collectAllWithSameTimePoint(iterator, flagEvent); + } + return null; + } + + private List collectAllWithSameTimePoint(Iterator iterator, + RaceLogFlagEvent flagEvent) { + List result = new ArrayList(); + TimePoint lastFlagsTime = flagEvent.getTimePoint(); + + while (flagEvent.getTimePoint().equals(lastFlagsTime)) { + result.add(flagEvent); + flagEvent = getNextFlagEvent(iterator); + if (flagEvent == null) { + break; + } + } + + return result; + } + + private RaceLogFlagEvent getNextFlagEvent(Iterator iterator) { + while (iterator.hasNext()) { + RaceLogEvent event = iterator.next(); + if (event instanceof RaceLogFlagEvent) { + return (RaceLogFlagEvent) event; + } + } + return null; + } + + /** + * Use this method the obtain the most "interesting" {@link RaceLogFlagEvent} of the {@link LastFlagsFinder}'s + * analyzation result. + * + * If an empty list or null is passed, this method returns null. Otherwise the (most + * recent) {@link RaceLogFlagEvent} with the highest ID is returned favoring events with + * {@link RaceLogFlagEvent#isDisplayed()} returning true. + * + * @param events + * result of {@link LastFlagsFinder#analyze()}. + * @return {@link RaceLogFlagEvent} or null. + */ + public static RaceLogFlagEvent getMostRecent(List events) { + if (events == null || events.isEmpty()) { + return null; + } + + List sortedEvents = new ArrayList(events); + Collections.sort(sortedEvents, new Comparator() { + @Override + public int compare(RaceLogFlagEvent left, RaceLogFlagEvent right) { + int result = right.getTimePoint().compareTo(left.getTimePoint()); + if (result == 0) { + result = Boolean.valueOf(right.isDisplayed()).compareTo(left.isDisplayed()); + if (result == 0) { + result = right.getId().toString().compareTo(left.getId().toString()); + } + } + return result; + } + }); + + return sortedEvents.get(0); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java index 06fa8fc1e20..b242fee2862 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastPublishedCourseDesignFinder.java @@ -6,26 +6,14 @@ import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.analyzing.impl.RaceLogAnalyzer; -public class LastPublishedCourseDesignFinder extends RaceLogAnalyzer { +public class LastPublishedCourseDesignFinder extends RaceLogAnalyzer { public LastPublishedCourseDesignFinder(RaceLog raceLog) { super(raceLog); } - public CourseBase getLastCourseDesign() { - CourseBase lastCourseData = null; - - this.raceLog.lockForRead(); - try { - lastCourseData = searchForLastCourseData(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return lastCourseData; - } - - private CourseBase searchForLastCourseData() { + @Override + protected CourseBase performAnalyzation() { CourseBase lastCourseData = null; for (RaceLogEvent event : getAllEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java new file mode 100644 index 00000000000..37d97a9c808 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/LastWindFixFinder.java @@ -0,0 +1,28 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; + +public class LastWindFixFinder extends RaceLogAnalyzer { + + public LastWindFixFinder(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected Wind performAnalyzation() { + Wind lastWind = null; + + for (RaceLogEvent event : getAllEvents()) { + if (event instanceof RaceLogWindFixEvent) { + RaceLogWindFixEvent windFixEvent = (RaceLogWindFixEvent) event; + lastWind = windFixEvent.getWindFix(); + } + } + + return lastWind; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java index 1516f27ba12..b7ed1ac5946 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/PathfinderFinder.java @@ -4,24 +4,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; -public class PathfinderFinder extends RaceLogAnalyzer { +public class PathfinderFinder extends RaceLogAnalyzer { public PathfinderFinder(RaceLog raceLog) { super(raceLog); } - public String getPathfinderId() { - String pathfinderId; - this.raceLog.lockForRead(); - try { - pathfinderId = searchForPathfinderId(); - } finally { - this.raceLog.unlockAfterRead(); - } - return pathfinderId; - } - - private String searchForPathfinderId() { + @Override + protected String performAnalyzation() { String pathfinderId = null; for (RaceLogEvent event : getPassEvents()) { if (event instanceof RaceLogPathfinderEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java new file mode 100644 index 00000000000..38a3aa48248 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/ProtestStartTimeFinder.java @@ -0,0 +1,24 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; + +public class ProtestStartTimeFinder extends RaceLogAnalyzer { + + public ProtestStartTimeFinder(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected TimePoint performAnalyzation() { + for (RaceLogEvent event : getPassEventsDescending()) { + if (event instanceof RaceLogProtestStartTimeEvent) { + return ((RaceLogProtestStartTimeEvent) event).getProtestStartTime(); + } + } + return null; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java index 3b21248fe0e..96bab9fd0e7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceLogAnalyzer.java @@ -3,7 +3,13 @@ package com.sap.sailing.domain.racelog.analyzing.impl; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; -public abstract class RaceLogAnalyzer { +/** + * Analyzer to perform a query over a given {@link RaceLog}. Each subclass defines its ResultType. + * + * @param + * type of analyzation's result. + */ +public abstract class RaceLogAnalyzer { protected RaceLog raceLog; @@ -11,6 +17,17 @@ public abstract class RaceLogAnalyzer { this.raceLog = raceLog; } + public ResultType analyze() { + raceLog.lockForRead(); + try { + return performAnalyzation(); + } finally { + raceLog.unlockAfterRead(); + } + } + + protected abstract ResultType performAnalyzation(); + protected Iterable getPassEvents() { return raceLog.getFixes(); } @@ -18,4 +35,12 @@ public abstract class RaceLogAnalyzer { protected Iterable getAllEvents() { return raceLog.getRawFixes(); } + + protected Iterable getPassEventsDescending() { + return raceLog.getFixesDescending(); + } + + protected Iterable getAllEventsDescending() { + return raceLog.getRawFixesDescending(); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java index a9857a00635..2baf3b1e683 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/RaceStatusAnalyzer.java @@ -5,27 +5,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; -public class RaceStatusAnalyzer extends RaceLogAnalyzer { +public class RaceStatusAnalyzer extends RaceLogAnalyzer { public RaceStatusAnalyzer(RaceLog raceLog) { super(raceLog); } - public RaceLogRaceStatus getStatus() { - - RaceLogRaceStatus newStatus = RaceLogRaceStatus.UNSCHEDULED; - - this.raceLog.lockForRead(); - try { - newStatus = searchForRaceStatus(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return newStatus; - } - - private RaceLogRaceStatus searchForRaceStatus() { + @Override + protected RaceLogRaceStatus performAnalyzation() { RaceLogRaceStatus newStatus = RaceLogRaceStatus.UNSCHEDULED; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java index f5d3047b514..a7ce9a802da 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartProcedureTypeAnalyzer.java @@ -5,24 +5,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; -public class StartProcedureTypeAnalyzer extends RaceLogAnalyzer { +public class StartProcedureTypeAnalyzer extends RaceLogAnalyzer { public StartProcedureTypeAnalyzer(RaceLog raceLog) { super(raceLog); } - - public StartProcedureType getActiveStartProcedureType() { - StartProcedureType result = null; - raceLog.lockForRead(); - try { - result = searchLog(); - } finally { - raceLog.unlockAfterRead(); - } - return result; - } - private StartProcedureType searchLog() { + @Override + protected StartProcedureType performAnalyzation() { StartProcedureType result = null; for (RaceLogEvent event : getAllEvents()) { if (event instanceof RaceLogStartProcedureChangedEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartTimeFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartTimeFinder.java index 6905f598e7f..fc24491c803 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartTimeFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/StartTimeFinder.java @@ -5,26 +5,14 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; -public class StartTimeFinder extends RaceLogAnalyzer { +public class StartTimeFinder extends RaceLogAnalyzer { public StartTimeFinder(RaceLog raceLog) { super(raceLog); } - public TimePoint getStartTime() { - TimePoint startTime = null; - - this.raceLog.lockForRead(); - try { - startTime = searchForStartTime(); - } finally { - this.raceLog.unlockAfterRead(); - } - - return startTime; - } - - private TimePoint searchForStartTime() { + @Override + protected TimePoint performAnalyzation() { TimePoint startTime = null; for (RaceLogEvent event : getPassEvents()) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventFactoryImpl.java index 5e0f21b51fa..3bb354693e4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventFactoryImpl.java @@ -22,28 +22,34 @@ import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; public class RaceLogEventFactoryImpl implements RaceLogEventFactory { @Override - public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, Serializable id, List involvedBoats, int passId, - Flags upperFlag, Flags lowerFlag, boolean isDisplayed) { - return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId, upperFlag, lowerFlag, isDisplayed); - } - - @Override - public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, + public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, Serializable id, List involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) { - return createFlagEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, upperFlag, lowerFlag, isDisplayed); + return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId, upperFlag, + lowerFlag, isDisplayed); } @Override - public RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, Serializable id, List involvedBoats, int passId, - TimePoint startTime) { - return new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId, startTime); + public RaceLogFlagEvent createFlagEvent(TimePoint timePoint, int passId, Flags upperFlag, Flags lowerFlag, + boolean isDisplayed) { + return createFlagEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, upperFlag, lowerFlag, + isDisplayed); + } + + @Override + public RaceLogStartTimeEvent createStartTimeEvent(TimePoint timePoint, Serializable id, + List involvedBoats, int passId, TimePoint startTime) { + return new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, involvedBoats, passId, + startTime); } @Override @@ -52,20 +58,20 @@ public class RaceLogEventFactoryImpl implements RaceLogEventFactory { } @Override - public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint,Serializable id, List competitors, int passId, - RaceLogRaceStatus nextStatus) { - return new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, nextStatus); + public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, Serializable id, + List competitors, int passId, RaceLogRaceStatus nextStatus) { + return new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, + nextStatus); } @Override - public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, - int passId, RaceLogRaceStatus nextStatus) { + public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint timePoint, int passId, RaceLogRaceStatus nextStatus) { return createRaceStatusEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, nextStatus); } @Override - public RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, Serializable id, List competitors, - int passId) { + public RaceLogPassChangeEvent createPassChangeEvent(TimePoint timePoint, Serializable id, + List competitors, int passId) { return new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId); } @@ -75,55 +81,66 @@ public class RaceLogEventFactoryImpl implements RaceLogEventFactory { } @Override - public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, Serializable id, List competitors, - int passId, Serializable courseAreaId) { - return new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, courseAreaId); + public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, Serializable id, + List competitors, int passId, Serializable courseAreaId) { + return new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, + courseAreaId); } @Override - public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent( - TimePoint timePoint, int passId, Serializable courseAreaId) { - return createCourseAreaChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, courseAreaId); + public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint timePoint, int passId, + Serializable courseAreaId) { + return createCourseAreaChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, + courseAreaId); } @Override public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, CourseBase courseData) { - return new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, courseData); + return new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, + courseData); } @Override - public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, int passId, CourseBase courseData) { - return createCourseDesignChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, courseData); + public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint timePoint, int passId, + CourseBase courseData) { + return createCourseDesignChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, + courseData); } @Override - public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent( - TimePoint timePoint, Serializable id, List competitors, int passId, List> positionedCompetitors) { - return new RaceLogFinishPositioningListChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, positionedCompetitors); + public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint timePoint, + Serializable id, List competitors, int passId, + List> positionedCompetitors) { + return new RaceLogFinishPositioningListChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, + competitors, passId, positionedCompetitors); } @Override - public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent( - TimePoint timePoint, int passId, List> positionedCompetitors) { - return createFinishPositioningListChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, positionedCompetitors); + public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint timePoint, + int passId, List> positionedCompetitors) { + return createFinishPositioningListChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), + passId, positionedCompetitors); } @Override public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, - Serializable id, List competitors, int passId) { - return new RaceLogFinishPositioningConfirmedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId); + Serializable id, List competitors, int passId, List> positionedCompetitors) { + return new RaceLogFinishPositioningConfirmedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, + passId, positionedCompetitors); } @Override - public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId) { - return createFinishPositioningConfirmedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId); + public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint timePoint, int passId, + List> positionedCompetitors) { + return createFinishPositioningConfirmedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, positionedCompetitors); } @Override public RaceLogPathfinderEvent createPathfinderEvent(TimePoint timePoint, Serializable id, List competitors, int passId, String pathfinderId) { - return new RaceLogPathfinderEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, pathfinderId); + return new RaceLogPathfinderEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, + pathfinderId); } @Override @@ -134,19 +151,22 @@ public class RaceLogEventFactoryImpl implements RaceLogEventFactory { @Override public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, Serializable id, List competitors, int passId, Long gateLineOpeningTimeInMillis) { - return new RaceLogGateLineOpeningTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, gateLineOpeningTimeInMillis); + return new RaceLogGateLineOpeningTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, + gateLineOpeningTimeInMillis); } @Override public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint timePoint, int passId, Long gateLineOpeningTimeInMillis) { - return createGateLineOpeningTimeEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, gateLineOpeningTimeInMillis); + return createGateLineOpeningTimeEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, + gateLineOpeningTimeInMillis); } @Override public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint timePoint, Serializable id, List competitors, int passId, StartProcedureType type) { - return new RaceLogStartProcedureChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, type); + return new RaceLogStartProcedureChangedEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, + passId, type); } @Override @@ -155,4 +175,29 @@ public class RaceLogEventFactoryImpl implements RaceLogEventFactory { return createStartProcedureChangedEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, type); } + @Override + public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, Serializable id, + List competitors, int passId, TimePoint protestStartTime) { + return new RaceLogProtestStartTimeEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, + passId, protestStartTime); + } + + @Override + public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint timePoint, int passId, + TimePoint protestStartTime) { + return createProtestStartTimeEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, + protestStartTime); + } + + @Override + public RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, int passId, Wind wind) { + return createWindFixEvent(timePoint, UUID.randomUUID(), new ArrayList(), passId, wind); + } + + @Override + public RaceLogWindFixEvent createWindFixEvent(TimePoint timePoint, Serializable id, List competitors, + int passId, Wind wind) { + return new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), timePoint, id, competitors, passId, wind); + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventImpl.java index 2e0283688aa..9af8367e157 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventImpl.java @@ -51,12 +51,4 @@ public abstract class RaceLogEventImpl implements RaceLogEvent { return passId; } - @Override - public boolean equals(Object object) { - return object instanceof RaceLogEvent && logicalTimePoint.equals(((RaceLogEvent) object).getTimePoint()) - && id.equals(((RaceLogEvent) object).getId()) - && involvedBoats.equals(((RaceLogEvent) object).getInvolvedBoats()) - && passId == ((RaceLogEvent) object).getPassId(); - } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventRestoreFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventRestoreFactoryImpl.java index a7f92e13e22..3f793d6037d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventRestoreFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogEventRestoreFactoryImpl.java @@ -20,9 +20,12 @@ import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl implements RaceLogEventRestoreFactory { @@ -70,8 +73,8 @@ public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl impl @Override public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId) { - return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, id, competitors, passId); + TimePoint logicalTimePoint, Serializable id, List competitors, int passId, List> positionedCompetitors) { + return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, id, competitors, passId, positionedCompetitors); } @Override @@ -92,5 +95,17 @@ public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl impl return new RaceLogStartProcedureChangedEventImpl(createdAt, timePoint, id, competitors, passId, type); } + @Override + public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, TimePoint timePoint, + Serializable id, List competitors, int passId, TimePoint protestStartTime) { + return new RaceLogProtestStartTimeEventImpl(createdAt, timePoint, id, competitors, passId, protestStartTime); + } + + @Override + public RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, TimePoint timePoint, Serializable id, + List competitors, Integer passId, Wind wind) { + return new RaceLogWindFixEventImpl(createdAt, timePoint, id, competitors, passId, wind); + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningConfirmedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningConfirmedEventImpl.java index e0e5ff4a5e7..b57b8a28e23 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningConfirmedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningConfirmedEventImpl.java @@ -4,22 +4,23 @@ import java.io.Serializable; import java.util.List; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.racelog.RaceLogEventVisitor; import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; -public class RaceLogFinishPositioningConfirmedEventImpl extends RaceLogEventImpl implements RaceLogFinishPositioningConfirmedEvent { +public class RaceLogFinishPositioningConfirmedEventImpl extends RaceLogFinishPositioningEventImpl implements RaceLogFinishPositioningConfirmedEvent { private static final long serialVersionUID = 5028181339200048499L; - + public RaceLogFinishPositioningConfirmedEventImpl(TimePoint createdAt, - TimePoint pTimePoint, Serializable pId, List pCompetitors, int pPassId) { - super(createdAt, pTimePoint, pId, pCompetitors, pPassId); + TimePoint pTimePoint, Serializable pId, List pCompetitors, int pPassId, List> positionedCompetitors) { + super(createdAt, pTimePoint, pId, pCompetitors, pPassId, positionedCompetitors); } @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java new file mode 100644 index 00000000000..cb7e21d9453 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningEventImpl.java @@ -0,0 +1,29 @@ +package com.sap.sailing.domain.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.Util.Triple; +import com.sap.sailing.domain.racelog.RaceLogFinishPositioningEvent; + +public abstract class RaceLogFinishPositioningEventImpl extends RaceLogEventImpl implements RaceLogFinishPositioningEvent { + + private static final long serialVersionUID = -8168584588697908309L; + + protected List> positionedCompetitors; + + public RaceLogFinishPositioningEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId, + List pInvolvedBoats, int pPassId, List> positionedCompetitors) { + super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId); + this.positionedCompetitors = positionedCompetitors; + } + + @Override + public List> getPositionedCompetitors() { + return positionedCompetitors; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningListChangedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningListChangedEventImpl.java index a5c502a54d2..266a3d72e9f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningListChangedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFinishPositioningListChangedEventImpl.java @@ -10,26 +10,17 @@ import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.racelog.RaceLogEventVisitor; import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent; -public class RaceLogFinishPositioningListChangedEventImpl extends RaceLogEventImpl implements RaceLogFinishPositioningListChangedEvent { +public class RaceLogFinishPositioningListChangedEventImpl extends RaceLogFinishPositioningEventImpl implements RaceLogFinishPositioningListChangedEvent { private static final long serialVersionUID = -8167472925561954739L; - private List> positionedCompetitors; - public RaceLogFinishPositioningListChangedEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId, List competitors, int pPassId, List> positionedCompetitors) { - super(createdAt, pTimePoint, pId, competitors, pPassId); - this.positionedCompetitors = positionedCompetitors; + super(createdAt, pTimePoint, pId, competitors, pPassId, positionedCompetitors); } @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } - - @Override - public List> getPositionedCompetitors() { - return positionedCompetitors; - } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFlagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFlagEventImpl.java index 51668f54513..d43cc2eb86c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFlagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogFlagEventImpl.java @@ -43,13 +43,4 @@ public class RaceLogFlagEventImpl extends RaceLogEventImpl implements RaceLogFla visitor.visit(this); } - @Override - public boolean equals(Object object) { - return super.equals(object) - && object instanceof RaceLogFlagEvent - && upperFlag.equals(((RaceLogFlagEvent) object).getUpperFlag()) - && lowerFlag.equals(((RaceLogFlagEvent) object).getLowerFlag()) - && isDisplayed == ((RaceLogFlagEvent) object).isDisplayed(); - } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java index 59741fdaebf..3343ed59d7b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogImpl.java @@ -29,8 +29,6 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { private transient Set listeners; private int currentPassId; - public static final int DefaultPassId = 0; - /** * Initializes a new {@link RaceLogImpl} with the default lock name. */ @@ -141,4 +139,14 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { listeners = new HashSet(); } + @Override + public Iterable getRawFixesDescending() { + return getRawFixes().descendingSet(); + } + + @Override + public Iterable getFixesDescending() { + return getFixes().descendingSet(); + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogProtestStartTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogProtestStartTimeEventImpl.java new file mode 100644 index 00000000000..775fe9bfd91 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogProtestStartTimeEventImpl.java @@ -0,0 +1,32 @@ +package com.sap.sailing.domain.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; + +public class RaceLogProtestStartTimeEventImpl extends RaceLogEventImpl implements RaceLogProtestStartTimeEvent { + private static final long serialVersionUID = -1800827552916395996L; + + private TimePoint protestStartTime; + + public RaceLogProtestStartTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId, + List pInvolvedBoats, int pPassId, TimePoint protestStartTime) { + super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId); + this.protestStartTime = protestStartTime; + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } + + @Override + public TimePoint getProtestStartTime() { + return protestStartTime; + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogStartTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogStartTimeEventImpl.java index 510d22a9520..ae69e2e4d0d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogStartTimeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogStartTimeEventImpl.java @@ -30,11 +30,4 @@ public class RaceLogStartTimeEventImpl extends RaceLogRaceStatusEventImpl implem visitor.visit(this); } - @Override - public boolean equals(Object object) { - // / TODO: please check the implementation of this method... why is this needed? - return super.equals(object) && object instanceof RaceLogStartTimeEvent - && startTime.equals(((RaceLogStartTimeEvent) object).getStartTime()); - } - } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogWindFixEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogWindFixEventImpl.java new file mode 100644 index 00000000000..44defb957d9 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogWindFixEventImpl.java @@ -0,0 +1,33 @@ +package com.sap.sailing.domain.racelog.impl; + +import java.io.Serializable; +import java.util.List; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; + +public class RaceLogWindFixEventImpl extends RaceLogEventImpl implements RaceLogWindFixEvent { + private static final long serialVersionUID = 7879094280634905183L; + + private final Wind windFix; + + public RaceLogWindFixEventImpl(TimePoint createdAt, TimePoint pTimePoint, Serializable pId, + List pInvolvedBoats, int pPassId, Wind windFix) { + super(createdAt, pTimePoint, pId, pInvolvedBoats, pPassId); + this.windFix = windFix; + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } + + @Override + public Wind getWindFix() { + return windFix; + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Positioned.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/Positioned.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Positioned.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/Positioned.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Wind.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/Wind.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/Wind.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/Wind.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/WindImpl.java similarity index 100% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindImpl.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/WindImpl.java diff --git a/java/com.sap.sailing.domain.test/SailingDomainTest (No Proxy).launch b/java/com.sap.sailing.domain.test/SailingDomainTest (No Proxy).launch index 3b3dbe049f1..4929fbc0fde 100755 --- a/java/com.sap.sailing.domain.test/SailingDomainTest (No Proxy).launch +++ b/java/com.sap.sailing.domain.test/SailingDomainTest (No Proxy).launch @@ -7,6 +7,7 @@ + diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogEventTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogEventTest.java deleted file mode 100644 index 920444fb7a9..00000000000 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceLogEventTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.sap.sailing.domain.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; - -import java.util.ArrayList; -import java.util.UUID; - -import org.junit.Test; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; -import com.sap.sailing.domain.common.TimePoint; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.racelog.RaceLogEventFactory; -import com.sap.sailing.domain.racelog.RaceLogFlagEvent; - -public class RaceLogEventTest { - - @Test - public void testEqualityOfTwoNotSameEvents() { - TimePoint t1 = MillisecondsTimePoint.now(); - int passId = 0; - UUID randomUUID = UUID.randomUUID(); - RaceLogFlagEvent rcEvent1 = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, randomUUID, new ArrayList(), passId, Flags.CLASS, Flags.NONE, false); - RaceLogFlagEvent rcEvent2 = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, randomUUID, new ArrayList(), passId, Flags.CLASS, Flags.NONE, false); - assertNotSame(rcEvent1, rcEvent2); - assertEquals(rcEvent1, rcEvent2); - } - -} diff --git a/java/com.sap.sailing.domain/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.domain/.settings/org.eclipse.core.resources.prefs index 5dfd5763bfd..a75e8e21989 100755 --- a/java/com.sap.sailing.domain/.settings/org.eclipse.core.resources.prefs +++ b/java/com.sap.sailing.domain/.settings/org.eclipse.core.resources.prefs @@ -1,3 +1,2 @@ eclipse.preferences.version=1 -encoding//src/com/sap/sailing/domain/base/impl/AbstractSpeedWithAbstractBearingImpl.java=UTF-8 encoding//src/com/sap/sailing/domain/tracking/impl/CompactGPSFixMovingImpl.java=UTF-8 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 25ebfecb5c7..8947625b32f 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 @@ -22,6 +22,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.ControlPoint; +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.Gate; @@ -88,6 +89,8 @@ public class DomainFactoryImpl implements DomainFactory { private final Map competitorCache; + private final Map courseAreaCache; + /** * Weakly references the waypoints. If a waypoint is no longer strongly referenced, the corresponding reference contained * as value will have its referred object be null. In this case, the methods reading from this cache will purge @@ -134,6 +137,7 @@ public class DomainFactoryImpl implements DomainFactory { competitorCache = new HashMap(); waypointCache = new ConcurrentHashMap(); mayStartWithNoUpwindLeg = new HashSet(Arrays.asList(new String[] { "extreme40", "ess", "ess40" })); + courseAreaCache = new HashMap<>(); } @Override @@ -452,4 +456,19 @@ public class DomainFactoryImpl implements DomainFactory { return result; } + @Override + public CourseArea getOrCreateCourseArea(Serializable courseAreaId, String name) { + CourseArea result = getExistingCourseAreaById(courseAreaId); + if (result == null) { + result = new CourseAreaImpl(name, courseAreaId); + courseAreaCache.put(courseAreaId, result); + } + return result; + } + + @Override + public CourseArea getExistingCourseAreaById(Serializable courseAreaId) { + return courseAreaCache.get(courseAreaId); + } + } 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 675e440456b..2f343bdf068 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 @@ -14,9 +14,11 @@ import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Serializable { private static final long serialVersionUID = 4752330236765192592L; @@ -90,4 +92,14 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali public void visit(RaceLogStartProcedureChangedEvent event) { notifyOnAdd(event); } + + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + notifyOnAdd(event); + } + + @Override + public void visit(RaceLogWindFixEvent event) { + notifyOnAdd(event); + } } 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 39fd82a7aeb..a2598aea6b1 100644 --- 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 @@ -11,9 +11,11 @@ import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; import com.sap.sailing.domain.racelog.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer; import com.sap.sailing.domain.tracking.DynamicTrackedRace; @@ -58,13 +60,13 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor { } private void analyzeStatus() { - /* RaceLogRaceStatus newStatus = */statusAnalyzer.getStatus(); + /* RaceLogRaceStatus newStatus = */statusAnalyzer.analyze(); // TODO: What can we do with the status? Should we use DynamicTrackedRace.setStatus? } private void analyzeCourseDesign() { - CourseBase courseDesign = courseDesignFinder.getLastCourseDesign(); + CourseBase courseDesign = courseDesignFinder.analyze(); // On the initial analyze step after attaching the RaceLog there might be no course design. if (courseDesign != null) { @@ -129,4 +131,15 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor { } + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + + } + + @Override + public void visit(RaceLogWindFixEvent event) { + // TODO handle a new wind fix entered by the race committee + // add the wind fix to the race committee WindTrack + } + } 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 f1051db69e5..edf3978e336 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -479,7 +479,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { public TimePoint getStartOfRace() { if (startTime == null) { for (RaceLog raceLog : attachedRaceLogs.values()) { - startTime = new StartTimeFinder(raceLog).getStartTime(); + startTime = new StartTimeFinder(raceLog).analyze(); if (startTime != null) { break; } diff --git a/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/down.png b/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/down.png index ad7d485a7e0..ebf713b5c6f 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/down.png and b/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/down.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/up.png b/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/up.png index 800755d59cc..a7a5e25ef6a 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/up.png and b/java/com.sap.sailing.gwt.ui/images/flags/flagsRacecommittee/up.png differ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java index d739bf01100..e64241fb1f1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventConfigImagesBarCell.java @@ -25,7 +25,9 @@ public class EventConfigImagesBarCell extends ImagesBarCell { @Override protected Iterable getImageSpecs() { - return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + return Arrays.asList( + new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), + new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())) + ); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AnchorCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AnchorCell.java new file mode 100644 index 00000000000..1afc4648b98 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AnchorCell.java @@ -0,0 +1,26 @@ +package com.sap.sailing.gwt.ui.client; + +import com.google.gwt.cell.client.AbstractCell; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.client.ui.Anchor; + +/** + * A GWT cell rendering a simple anchor. + * @author C5163874 + * + */ +public class AnchorCell extends AbstractCell { + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, Anchor a, SafeHtmlBuilder sb) { + if (a.getHref() != null && a.getHref().trim().length() > 0 && a.isEnabled()) { + sb.append(SafeHtmlUtils.fromTrustedString("")); + sb.append(SafeHtmlUtils.fromTrustedString(a.getText())); + sb.append(SafeHtmlUtils.fromTrustedString("")); + } else { + sb.append(SafeHtmlUtils.fromTrustedString(a.getText())); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EntryPointLinkFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EntryPointLinkFactory.java new file mode 100644 index 00000000000..0aefc686e46 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/EntryPointLinkFactory.java @@ -0,0 +1,32 @@ +package com.sap.sailing.gwt.ui.client; + +import java.util.Map; +import java.util.Map.Entry; + +import com.google.gwt.user.client.Window; + +public class EntryPointLinkFactory { + public static String createRaceBoardLink(Map parameters) { + return createEntryPointLink("/gwt/RaceBoard.html", parameters); + } + + public static String createLeaderboardLink(Map parameters) { + return createEntryPointLink("/gwt/Leaderboard.html", parameters); + } + + private static String createEntryPointLink(String baseLink, Map parameters) { + String debugParam = Window.Location.getParameter("gwt.codesvr"); + String link = baseLink; + int i = 1; + for(Entry entry: parameters.entrySet()) { + link += i == 1 ? "?" : "&"; + link += entry.getKey() + "=" + entry.getValue(); + i++; + } + if (debugParam != null && !debugParam.isEmpty()) { + link += i == 1 ? "?" : "&"; + link += "gwt.codesvr=" + debugParam; + } + return URLEncoder.encode(link); + } +} 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 894c26a01a6..8b3e4d5a30e 100644 --- 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 @@ -38,6 +38,7 @@ import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -300,9 +301,12 @@ public interface SailingService extends RemoteService { CourseAreaDTO createCourseArea(String eventIdAsString, String courseAreaName); - List getRegattaOverviewEntriesForEvent(String eventIdAsString); - EventDTO getEventByIdAsString(String eventIdAsString); + List getRegattaStructureForEvent(String eventIdAsString); + + List getRaceStateEntriesForRaceGroup(String eventIdAsString, List visibleCourseAreas, + List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay); + String getBuildVersion(); } 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 431ff2b5707..4cde9a5ab70 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 @@ -38,6 +38,7 @@ import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -417,13 +418,17 @@ public interface SailingServiceAsync { void getPolarSheetData(String polarSheetId, int angle, int windSpeedLevel, AsyncCallback wrapperCallback); - void getRegattaOverviewEntriesForEvent(String eventIdAsString, AsyncCallback> asyncCallback); - void getEventByIdAsString(String eventIdAsString, AsyncCallback asyncCallback); void updateRegatta(RegattaIdentifier regattaIdentifier, String defaultCourseAreaId, AsyncCallback callback); void getBuildVersion(AsyncCallback callback); + void getRegattaStructureForEvent(String eventIdAsString, AsyncCallback> asyncCallback); + + void getRaceStateEntriesForRaceGroup(String eventIdAsString, List visibleCourseAreas, + List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, + AsyncCallback> markedAsyncCallback); + } 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 b4ffdeede8b..dff732ad46a 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 @@ -654,5 +654,20 @@ public interface StringMessages extends Messages { String addSeries(); String regattaDefinesResultDiscardingRules(); String startsWithZeroScore(); + String regattaOverviewConfiguration(); String firstRaceIsNonDiscardableCarryForward(); + String asLink(); + String raceIsRunning(); + String raceIsRunningWithEarlyStarters(); + String raceIsFinishing(); + String raceIsFinished(); + String raceIsScheduled(); + String raceIsInStartphase(); + String generalRecall(); + String startPostponed(); + String startPostponedNoMoreRacingToday(); + String startPostponedFurtherSignalsAshore(); + String raceAbandoned(); + String raceAbandonedNoMoreRacingToday(); + String raceAbandonedFurtherSignalsAshore(); } 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 c22daf76e08..f8e93c1beca 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 @@ -646,5 +646,20 @@ showOnlyCurrentlyRunningRaces=Show currently running races seriesDefinesResultDiscardingRule=Series defines result discarding rules addSeries=Add series regattaDefinesResultDiscardingRules=Regatta defines result discarding rules -startsWithZeroScore=Series starts with zero score -firstRaceIsNonDiscardableCarryForward=Starts with non-discardable carry-forward \ No newline at end of file +startsWithZeroScore=Series starts with zero score +regattaOverviewConfiguration=Regatta Overview Configuration +firstRaceIsNonDiscardableCarryForward=Starts with non-discardable carry-forward +asLink=As link +raceIsRunning=Race is running +raceIsRunningWithEarlyStarters=Race is running (had early starters) +raceIsFinishing=Race is finishing +raceIsFinished=Race is finished +raceIsScheduled=Race is scheduled +raceIsInStartphase=Race in start phase +generalRecall=General recall +startPostponed=Start postponed +startPostponedNoMoreRacingToday=Start postponed - No more racing today +startPostponedFurtherSignalsAshore=Start postponed - Further signals ashore +raceAbandoned=Race abandoned +raceAbandonedNoMoreRacingToday=Race abandoned - No more racing today +raceAbandonedFurtherSignalsAshore=Race abandoned - Further signals ashore \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index fcadc0c299b..e4c5c040825 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 @@ -585,7 +585,7 @@ disableRaceFilter=Deaktiviere Filter enableRaceFilter=Aktiviere Filter raceStatusColumn=Renn-Status loading=Lade... -showHiddenRaces=Rennen im Status HIDDEN anzeigen +showHiddenRaces=Rennen im Status HIDDEN anzeigen selectedCompetitors=Ausgewählte Teilnehmer filterNothing=Nichts filtern topNCompetitorsByRaceRank=Wettfahrt Top {0} @@ -645,4 +645,19 @@ seriesDefinesResultDiscardingRule=Serie legt Streichregel fest addSeries=Serie hinzufügen regattaDefinesResultDiscardingRules=Streichergebnisse werden von der Regatta festgelegt startsWithZeroScore=Serie beginnt mit auf 0 gesetzten Ergebnissen -firstRaceIsNonDiscardableCarryForward=Beginnt mit nicht streichbarem Übertrag \ No newline at end of file +regattaOverviewConfiguration=Regattaübersicht-Konfiguration +firstRaceIsNonDiscardableCarryForward=Beginnt mit nicht streichbarem Übertrag +asLink=Als Link +raceIsRunning=Rennen läuft +raceIsRunningWithEarlyStarters=Rennen läuft (es gab Frühstarter) +raceIsFinishing=Rennen am beenden +raceIsFinished=Rennen beendet +raceIsScheduled=Startzeit angesetzt +raceIsInStartphase=Rennen in der Startphase +generalRecall=Gesamtrückruf +startPostponed=Startverschiebung +startPostponedNoMoreRacingToday=Startverschiebung - heute keine Rennen mehr +startPostponedFurtherSignalsAshore=Startverschiebung - weitere Signale an Land +raceAbandoned=Rennabbruch +raceAbandonedNoMoreRacingToday=Rennabbruch - heute keine Rennen mehr +raceAbandonedFurtherSignalsAshore=Rennabbruch - weitere Signale an Land \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventAndRaceGroupAvailabilityListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventAndRaceGroupAvailabilityListener.java new file mode 100644 index 00000000000..e17b08375f7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventAndRaceGroupAvailabilityListener.java @@ -0,0 +1,11 @@ +package com.sap.sailing.gwt.ui.regattaoverview; + +import java.util.List; + +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; + +public interface EventAndRaceGroupAvailabilityListener { + void onEventUpdated(EventDTO event); + void onRaceGroupsUpdated(List raceGroups); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventProvider.java deleted file mode 100644 index 9c8b5ab5230..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/EventProvider.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import com.sap.sailing.gwt.ui.shared.EventDTO; - -public interface EventProvider { - - EventDTO getEvent(); - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagAlphabetInterpreter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagAlphabetInterpreter.java new file mode 100644 index 00000000000..d8be735a6c3 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagAlphabetInterpreter.java @@ -0,0 +1,84 @@ +package com.sap.sailing.gwt.ui.regattaoverview; + +import com.sap.sailing.domain.common.racelog.utils.FlagAlphabetInterpretationTemplate; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public class FlagAlphabetInterpreter extends FlagAlphabetInterpretationTemplate { + + private StringMessages stringMessages; + + public FlagAlphabetInterpreter(StringMessages stringMessages) { + this.stringMessages = stringMessages; + } + + @Override + protected String getTextForRunningRace() { + return stringMessages.raceIsRunning(); + } + + @Override + protected String getTextForRunningRaceWithEarlyStarter() { + return stringMessages.raceIsRunningWithEarlyStarters(); + } + + @Override + protected String getTextForFinishingRace() { + return stringMessages.raceIsFinishing(); + } + + @Override + protected String getTextForFinishedRace() { + return stringMessages.raceIsFinished(); + } + + @Override + protected String getTextForScheduledRace() { + return stringMessages.raceIsScheduled(); + } + + @Override + protected String getTextForRaceInStartphase() { + return stringMessages.raceIsInStartphase(); + } + + @Override + protected String getTextForUnscheduledRace() { + return stringMessages.noStarttimeAnnouncedYet(); + } + + @Override + protected String getTextForFirstSubstituteFlag() { + return stringMessages.generalRecall(); + } + + @Override + protected String getTextForAnsweringPennantFlag() { + return stringMessages.startPostponed(); + } + + @Override + protected String getTextForAnsweringPennantWithAlphaFlags() { + return stringMessages.startPostponedNoMoreRacingToday(); + } + + @Override + protected String getTextForAnsweringPennantWithHotelFlags() { + return stringMessages.startPostponedFurtherSignalsAshore(); + } + + @Override + protected String getTextForNovemberFlag() { + return stringMessages.raceAbandoned(); + } + + @Override + protected String getTextForNovemberWithAlphaFlags() { + return stringMessages.raceAbandonedNoMoreRacingToday(); + } + + @Override + protected String getTextForNovemberWithHotelFlags() { + return stringMessages.raceAbandonedFurtherSignalsAshore(); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageCell.java index b8ea1eb4a9c..25b4eb2fb56 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageCell.java @@ -10,7 +10,7 @@ import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; public class FlagImageCell extends ImagesBarCell { static final String ACTION_EDIT = "ACTION_EDIT"; private final StringMessages stringMessages; - private static RegattaOverviewResources resources = GWT.create(RegattaOverviewResources.class); + private static RegattaRaceStatesFlagsResources resources = GWT.create(RegattaRaceStatesFlagsResources.class); public FlagImageCell(StringMessages stringConstants) { super(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageResolver.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageResolver.java index e1d6ceae760..c6c7435217a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageResolver.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/FlagImageResolver.java @@ -11,7 +11,7 @@ public class FlagImageResolver { private Map flagImageMap; - private static RegattaOverviewResources resources = GWT.create(RegattaOverviewResources.class); + private static RegattaRaceStatesFlagsResources resources = GWT.create(RegattaRaceStatesFlagsResources.class); public FlagImageResolver() { this.flagImageMap = new HashMap(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RaceCourseComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RaceCourseComposite.java deleted file mode 100644 index b801c2fac20..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RaceCourseComposite.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.user.cellview.client.CellTable; -import com.google.gwt.user.cellview.client.TextColumn; -import com.google.gwt.user.client.ui.Composite; -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.sap.sailing.domain.common.NauticalSide; -import com.sap.sailing.gwt.ui.client.ErrorReporter; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; -import com.sap.sailing.gwt.ui.shared.WaypointDTO; - -public class RaceCourseComposite extends Composite { - - private final CellTable waypointTable; - private ListDataProvider waypointDataProvider; - private final SimplePanel mainPanel; - - @SuppressWarnings("unused") - private final SailingServiceAsync sailingService; - private final StringMessages stringMessages; - - private RegattaOverviewEntryDTO race; - - private static RegattaRaceStatesTableResources tableRes = GWT.create(RegattaRaceStatesTableResources.class); - - private static final String STYLE_NAME_PREFIX = "RegattaOverview-"; - private static final String STYLE_WORD_WRAP = STYLE_NAME_PREFIX + "wordWrap"; - - public RaceCourseComposite(final SailingServiceAsync sailingService, ErrorReporter errorReporter, - final StringMessages stringMessages) { - this.sailingService = sailingService; - this.stringMessages = stringMessages; - - this.race = null; - - mainPanel = new SimplePanel(); - VerticalPanel panel = new VerticalPanel(); - mainPanel.setWidget(panel); - panel.setWidth("100%"); - - waypointDataProvider = new ListDataProvider(); - waypointTable = createCourseDesignTable(); - - panel.add(waypointTable); - - initWidget(mainPanel); - - } - - private CellTable createCourseDesignTable() { - CellTable table = new CellTable(/* pageSize */10000, tableRes); - waypointDataProvider.addDataDisplay(table); - table.setWidth("100%"); - - TextColumn waypointNameColumn = new TextColumn() { - @Override - public String getValue(WaypointDTO waypointDTO) { - String result = waypointDTO.getName(); - result += (waypointDTO.passingSide == null) ? "" : ", to " + getNauticalSideAsText(waypointDTO.passingSide); - return result; - } - }; - - table.addColumn(waypointNameColumn, stringMessages.waypoints()); - waypointNameColumn.setCellStyleNames(STYLE_WORD_WRAP); - - return table; - } - - public void setRace(RegattaOverviewEntryDTO regattaOverviewEntryDTO) { - this.race = regattaOverviewEntryDTO; - updateCourseDetails(); - } - - private void updateCourseDetails() { - if (this.race != null && this.race.raceInfo.lastCourseDesign != null) { - waypointDataProvider.getList().clear(); - waypointDataProvider.getList().addAll(this.race.raceInfo.lastCourseDesign.waypoints); - } - } - - private String getNauticalSideAsText(NauticalSide passingSide) { - switch (passingSide) { - case PORT: - return stringMessages.portSide(); - case STARBOARD: - return stringMessages.starboardSide(); - default: - return ""; - } - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewEntryPoint.java index e5d61d9cf04..57c5c7fe26d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewEntryPoint.java @@ -1,13 +1,23 @@ package com.sap.sailing.gwt.ui.regattaoverview; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.RootPanel; import com.sap.sailing.gwt.ui.client.AbstractEntryPoint; import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel; +import com.sap.sailing.gwt.ui.client.URLEncoder; public class RegattaOverviewEntryPoint extends AbstractEntryPoint { - + + private final static String PARAM_EVENT = "event"; + private final static String PARAM_ONLY_RUNNING_RACES = "onlyrunningraces"; + private final static String PARAM_ONLY_RACES_OF_SAME_DAY = "onlyracesofsameday"; + private final static String PARAM_REGATTA = "regatta"; + private final static String PARAM_COURSE_AREA = "coursearea"; + @Override public void doOnModuleLoad() { super.doOnModuleLoad(); @@ -23,10 +33,66 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint { RootPanel.getBodyElement().getStyle().setPadding(0, Unit.PX); RootPanel.getBodyElement().getStyle().setPaddingTop(20, Unit.PX); } - String eventIdAsString = Window.Location.getParameter("event"); - RegattaOverviewPanel regattaOverviewPanel = new RegattaOverviewPanel(sailingService, this, stringMessages, eventIdAsString); + String eventIdAsString = Window.Location.getParameter(PARAM_EVENT); + + RegattaRaceStatesSettings settings = createRegattaRaceStatesSettingsFromURL(); + + RegattaOverviewPanel regattaOverviewPanel = new RegattaOverviewPanel(sailingService, this, stringMessages, eventIdAsString, settings); rootPanel.add(regattaOverviewPanel); } - -} + + public static RegattaRaceStatesSettings createRegattaRaceStatesSettingsFromURL() { + List visibleCourseAreas = new ArrayList(); + List visibleRegattas = new ArrayList(); + + boolean showOnlyCurrentlyRunningRaces = Window.Location.getParameter(PARAM_ONLY_RUNNING_RACES) == null + || !Window.Location.getParameter(PARAM_ONLY_RUNNING_RACES).equalsIgnoreCase("false"); + + boolean showOnlyRacesOfSameDay = Window.Location.getParameter(PARAM_ONLY_RACES_OF_SAME_DAY) != null + && Window.Location.getParameter(PARAM_ONLY_RACES_OF_SAME_DAY).equalsIgnoreCase("true"); + + if (Window.Location.getParameterMap().containsKey(PARAM_COURSE_AREA)) { + visibleCourseAreas.addAll(Window.Location.getParameterMap().get(PARAM_COURSE_AREA)); + } + + if (Window.Location.getParameterMap().containsKey(PARAM_REGATTA)) { + visibleRegattas.addAll(Window.Location.getParameterMap().get(PARAM_REGATTA)); + } + + return new RegattaRaceStatesSettings(visibleCourseAreas, visibleRegattas, showOnlyRacesOfSameDay, showOnlyCurrentlyRunningRaces); + } + + public static String getUrl(String eventIdAsString, RegattaRaceStatesSettings settings, + boolean isSetVisibleCourseAreasInUrl, boolean isSetVisibleRegattasInUrl) { + String debugParam = Window.Location.getParameter("gwt.codesvr"); + String showOnlyCurrentlyRunningRaces = "&" + PARAM_ONLY_RUNNING_RACES + "=" + (settings.isShowOnlyCurrentlyRunningRaces() ? "true" : "false"); + String showOnlyRacesOfSameDay = "&" + PARAM_ONLY_RACES_OF_SAME_DAY + "=" + (settings.isShowOnlyRacesOfSameDay() ? "true" : "false"); + + StringBuilder visibleCourseAreas = new StringBuilder(); + if (isSetVisibleCourseAreasInUrl) { + for (String visibleCourseArea : settings.getVisibleCourseAreas()) { + visibleCourseAreas.append('&'); + visibleCourseAreas.append(PARAM_COURSE_AREA); + visibleCourseAreas.append('='); + visibleCourseAreas.append(visibleCourseArea); + } + } + StringBuilder visibleRegattas = new StringBuilder(); + if (isSetVisibleRegattasInUrl) { + for (String visibleRegatta : settings.getVisibleRegattas()) { + visibleRegattas.append('&'); + visibleRegattas.append(PARAM_REGATTA); + visibleRegattas.append('='); + visibleRegattas.append(visibleRegatta); + } + } + String link = URLEncoder.encode("/gwt/RegattaOverview.html?" + PARAM_EVENT+ "=" + eventIdAsString + + visibleCourseAreas.toString() + + visibleRegattas.toString() + + showOnlyCurrentlyRunningRaces + + showOnlyRacesOfSameDay + + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); + return link; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java index 21742edc7f3..965a153e962 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewPanel.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.regattaoverview; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -25,9 +26,9 @@ import com.sap.sailing.gwt.ui.client.Timer.PlayModes; import com.sap.sailing.gwt.ui.client.Timer.PlayStates; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialog; import com.sap.sailing.gwt.ui.shared.EventDTO; -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; -public class RegattaOverviewPanel extends SimplePanel implements RegattaOverviewRaceSelectionChangeListener, EventProvider { +public class RegattaOverviewPanel extends SimplePanel { private final long serverUpdateRateInMs = 10000; private final long uiUpdateRateInMs = 1000; @@ -37,14 +38,14 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview private final SailingServiceAsync sailingService; protected final StringMessages stringMessages; + protected final ErrorReporter errorReporter; private final String eventIdAsString; private EventDTO eventDTO; - - private RegattaOverviewRaceSelectionModel raceSelectionProvider; + private List raceGroupDTOs; + private List eventRaceGroupListeners; private RegattaRaceStatesComponent regattaRaceStatesComponent; - private RaceCourseComposite raceCourseComposite; private final Label eventNameLabel; private final Label venueNameLabel; @@ -64,47 +65,27 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview private static final String STYLE_VENUE_LABEL = STYLE_NAME_PREFIX + "VenueLabel"; private static final String STYLE_CLOCK_LABEL = STYLE_NAME_PREFIX + "ClockLabel"; - public RegattaOverviewPanel(SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages, String eventIdAsString) { + public RegattaOverviewPanel(SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages, + String eventIdAsString, RegattaRaceStatesSettings settings) { this.sailingService = sailingService; this.stringMessages = stringMessages; + this.errorReporter = errorReporter; this.eventIdAsString = eventIdAsString; this.eventDTO = null; + this.raceGroupDTOs = new ArrayList(); + this.eventRaceGroupListeners = new ArrayList(); retrieveEvent(); + retrieveRegattaStructure(); VerticalPanel mainPanel = new VerticalPanel(); setWidget(mainPanel); mainPanel.setWidth("100%"); mainPanel.addStyleName(STYLE_CONTENT_WRAPPER); - Grid grid = new Grid(2, 2); - grid.setWidth("100%"); - - Label raceOverviewLabel = new Label(stringMessages.courseAreaOverview()); - raceOverviewLabel.addStyleName(STYLE_TITLE_LABEL); - - Label courseDesignOverviewLabel = new Label(stringMessages.courseDesignOverview()); - courseDesignOverviewLabel.addStyleName(STYLE_TITLE_LABEL); - - grid.setWidget(0, 0, raceOverviewLabel); - grid.setWidget(0, 1, courseDesignOverviewLabel); - - raceSelectionProvider = new RegattaOverviewRaceSelectionModel(false); - raceSelectionProvider.addRegattaOverviewRaceSelectionChangeListener(this); - - regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventIdAsString, - raceSelectionProvider, this); - grid.setWidget(1, 0, regattaRaceStatesComponent); - - raceCourseComposite = new RaceCourseComposite(sailingService, errorReporter, stringMessages); - grid.setWidget(1, 1, raceCourseComposite); - - grid.getRowFormatter().setVerticalAlign(0, HasVerticalAlignment.ALIGN_TOP); - grid.getRowFormatter().setVerticalAlign(1, HasVerticalAlignment.ALIGN_TOP); - grid.getColumnFormatter().setWidth(0, "80%"); - grid.getColumnFormatter().setWidth(1, "20%"); - grid.getColumnFormatter().getElement(1).getStyle().setPaddingTop(2.0, Unit.EM); - grid.getColumnFormatter().getElement(1).getStyle().setPaddingLeft(20.0, Unit.PX); + regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventIdAsString, settings); + this.eventRaceGroupListeners.add(regattaRaceStatesComponent); + regattaRaceStatesComponent.setWidth("100%"); refreshNowButton = new Button(stringMessages.refreshNow()); refreshNowButton.addClickHandler(new ClickHandler() { @@ -194,7 +175,7 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview flexTable.setWidget(0, 1, refreshStartStopClockPanel); mainPanel.add(flexTable); - mainPanel.add(grid); + mainPanel.add(regattaRaceStatesComponent); onUpdateUI(new Date()); } @@ -215,32 +196,15 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview public void onUpdateUI(Date time) { timeLabel.setText(timeFormatter.format(time)); } - - @Override - public void onRegattaOverviewEntrySelectionChange(List selectedRegattaOverviewEntries) { - final RegattaOverviewEntryDTO selectedRegattaOverviewEntry; - if (selectedRegattaOverviewEntries.iterator().hasNext()) { - selectedRegattaOverviewEntry = selectedRegattaOverviewEntries.iterator().next(); - if (selectedRegattaOverviewEntry != null && regattaRaceStatesComponent.getAllRaces() != null) { - for(RegattaOverviewEntryDTO regattaOverviewEntryDTO: regattaRaceStatesComponent.getAllRaces()) { - if(regattaOverviewEntryDTO.equals(selectedRegattaOverviewEntry)) { - raceCourseComposite.setRace(regattaOverviewEntryDTO); - break; - } - } - } - } else { - raceCourseComposite.setRace(null); - } - } private void retrieveEvent() { sailingService.getEventByIdAsString(eventIdAsString, new MarkedAsyncCallback() { @Override protected void handleFailure(Throwable cause) { - //Show a (friendly) error message settingsButton.setEnabled(false); + errorReporter.reportError("Error trying to load event with id " + eventIdAsString + " : " + + cause.getMessage()); } @Override @@ -257,11 +221,6 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview venueNameLabel.setText(eventDTO.venue.getName()); } - @Override - public EventDTO getEvent() { - return eventDTO; - } - protected void setEvent(EventDTO event) { eventDTO = event; onEventUpdated(); @@ -269,9 +228,50 @@ public class RegattaOverviewPanel extends SimplePanel implements RegattaOverview private void onEventUpdated() { fillEventAndVenueName(); - settingsButton.setEnabled(true); + + for (EventAndRaceGroupAvailabilityListener listener : this.eventRaceGroupListeners) { + listener.onEventUpdated(eventDTO); + } + + checkToEnableSettingsButton(); } - + private void retrieveRegattaStructure() { + sailingService.getRegattaStructureForEvent(eventIdAsString, new MarkedAsyncCallback>() { + + @Override + protected void handleFailure(Throwable cause) { + errorReporter.reportError("Error trying to load regattas for event with id " + eventIdAsString + " : " + + cause.getMessage()); + } + + @Override + protected void handleSuccess(List result) { + if (result != null) { + setRaceGroups(result); + } + } + + }); + } + + protected void setRaceGroups(List result) { + raceGroupDTOs.clear(); + raceGroupDTOs.addAll(result); + onRaceGroupsUpdated(); + } + + private void onRaceGroupsUpdated() { + for (EventAndRaceGroupAvailabilityListener listener : this.eventRaceGroupListeners) { + listener.onRaceGroupsUpdated(raceGroupDTOs); + } + checkToEnableSettingsButton(); + } + + private void checkToEnableSettingsButton() { + if (eventDTO != null && raceGroupDTOs.size() > 0) { + settingsButton.setEnabled(true); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionChangeListener.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionChangeListener.java deleted file mode 100644 index 116cbf029f4..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionChangeListener.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import java.util.List; - -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; - -public interface RegattaOverviewRaceSelectionChangeListener { - /** - * The first element is the first one selected - * - * @param selectedRegattaOverviewEntries a non-null list which is empty if nothing is selected - */ - void onRegattaOverviewEntrySelectionChange(List selectedRegattaOverviewEntries); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionModel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionModel.java deleted file mode 100644 index 36274cb3789..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionModel.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; - -public class RegattaOverviewRaceSelectionModel implements RegattaOverviewRaceSelectionProvider { - - private final List selection; - - private final List allRegattaOverviewRaces; - - private final Set listeners; - - private final boolean hasMultiSelection; - - public RegattaOverviewRaceSelectionModel(boolean hasMultiSelection) { - this.hasMultiSelection = hasMultiSelection; - this.selection = new ArrayList(); - this.allRegattaOverviewRaces = new ArrayList(); - listeners = new HashSet(); - } - - @Override - public List getSelectedEntries() { - return Collections.unmodifiableList(selection); - } - - @Override - public void addRegattaOverviewRaceSelectionChangeListener(RegattaOverviewRaceSelectionChangeListener listener) { - listeners.add(listener); - } - - @Override - public void removeRegattaOverviewRaceSelectionChangeListener(RegattaOverviewRaceSelectionChangeListener listener) { - listeners.remove(listener); - } - - @Override - public void setSelection(List newSelection, RegattaOverviewRaceSelectionChangeListener... listenersNotToNotify) { - boolean notify = !selection.equals(newSelection); - selection.clear(); - selection.addAll(newSelection); - if (notify) { - notifyListeners(listenersNotToNotify); - } - } - - private void notifyListeners(RegattaOverviewRaceSelectionChangeListener[] listenersNotToNotify) { - List selectedRegattaOverviewEntries = getSelectedEntries(); - for (RegattaOverviewRaceSelectionChangeListener listener : listeners) { - if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) { - listener.onRegattaOverviewEntrySelectionChange(selectedRegattaOverviewEntries); - } - } - } - - @Override - public boolean hasMultiSelection() { - return hasMultiSelection; - } - - @Override - public List getAllRegattaOverviewEntries() { - return Collections.unmodifiableList(allRegattaOverviewRaces); - } - - @Override - public void setAllRegattaOverviewEntries(List newAllRegattaOverviewEntries, - RegattaOverviewRaceSelectionChangeListener... listenersNotToNotify) { - allRegattaOverviewRaces.clear(); - for (RegattaOverviewEntryDTO r : newAllRegattaOverviewEntries) { - allRegattaOverviewRaces.add(r); - } - for (Iterator i=selection.iterator(); i.hasNext(); ) { - RegattaOverviewEntryDTO selectedRegattaOverviewEntry = i.next(); - if (!allRegattaOverviewRaces.contains(selectedRegattaOverviewEntry)) { - i.remove(); - } - } - // when setting all regatta overview entries, the actual RegattaOverviewEntryDTOs will usually have changed their identity and maybe also their state; - // so notifying the selection listeners is necessary anyhow - notifyListeners(listenersNotToNotify); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionProvider.java deleted file mode 100644 index 709a9fee027..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewRaceSelectionProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import java.util.List; - -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; - -public interface RegattaOverviewRaceSelectionProvider { - /** - * @return a non-null list which may be empty - */ - List getSelectedEntries(); - - void addRegattaOverviewRaceSelectionChangeListener(RegattaOverviewRaceSelectionChangeListener listener); - - void removeRegattaOverviewRaceSelectionChangeListener(RegattaOverviewRaceSelectionChangeListener listener); - - void setSelection(List newSelection, RegattaOverviewRaceSelectionChangeListener... listenersNotToNotify); - - boolean hasMultiSelection(); - - /** - * @return a non-null list which may be empty - */ - List getAllRegattaOverviewEntries(); - - void setAllRegattaOverviewEntries(List newAllRegattaOverviewEntries, RegattaOverviewRaceSelectionChangeListener... listenersNotToNotify); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComparator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComparator.java deleted file mode 100644 index 6d9fd0f2b55..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComparator.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import java.util.Comparator; - -import com.sap.sailing.domain.common.impl.NaturalComparator; -import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; - -public class RegattaRaceStatesComparator implements Comparator { - - @Override - public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - int result = left.courseAreaName.compareTo(right.courseAreaName); - if (result == 0) { - if (left.regattaName != null && right.regattaName != null) { - result = new NaturalComparator().compare(left.regattaName, right.regattaName); - } - if (result == 0) { - //TODO Caution: Series is missing!!! - result = Integer.valueOf(left.raceInfo.fleetOrdering).compareTo(Integer.valueOf(right.raceInfo.fleetOrdering)); - if (result == 0) { - result = (-1) * new NaturalComparator().compare(right.raceInfo.raceName, left.raceInfo.raceName); - //the naturalComparator sorts the other way round R30 < R29 < R28 etc., therefore the (-1) multiplication - } - } - } - return result; - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java index b8e1b90054c..cf0c4f8616a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesComponent.java @@ -4,46 +4,66 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.google.gwt.cell.client.ClickableTextCell; +import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.cell.client.ImageResourceCell; import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONParser; +import com.google.gwt.json.client.JSONValue; import com.google.gwt.resources.client.ImageResource; +import com.google.gwt.storage.client.Storage; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.ColumnSortEvent; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.DialogBox; +import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.ListDataProvider; -import com.google.gwt.view.client.SelectionChangeEvent; -import com.google.gwt.view.client.SelectionModel; -import com.google.gwt.view.client.SingleSelectionModel; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.LeaderboardNameConstants; +import com.sap.sailing.domain.common.NauticalSide; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.gwt.ui.client.AnchorCell; +import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; import com.sap.sailing.gwt.ui.client.ErrorReporter; +import com.sap.sailing.gwt.ui.client.GwtJsonDeSerializer; import com.sap.sailing.gwt.ui.client.MarkedAsyncCallback; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.Component; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent; +import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; import com.sap.sailing.gwt.ui.shared.RaceInfoDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; +import com.sap.sailing.gwt.ui.shared.WaypointDTO; /** * This component shows a table displaying the current state of races for a given event. * Which races are shown depends on the setting {@link RegattaRaceStatesSettings}. * Each entry shows what flags are currently displayed, what start time the race has and additional information, e.g. for Gate start. */ -public class RegattaRaceStatesComponent extends SimplePanel implements Component { +public class RegattaRaceStatesComponent extends SimplePanel implements Component, EventAndRaceGroupAvailabilityListener { private List allEntries; - private final SelectionModel raceSelectionModel; private final CellTable regattaOverviewTable; private ListDataProvider regattaOverviewDataProvider; private final VerticalPanel mainPanel; @@ -52,61 +72,56 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component private final SailingServiceAsync sailingService; private final StringMessages stringMessages; private final String eventIdAsString; - private final RegattaOverviewRaceSelectionProvider raceSelectionProvider; - private final EventProvider eventProvider; - private final FlagImageResolver flagImageResolver; - private RegattaRaceStatesSettings settings; + private EventDTO eventDTO; + private List raceGroupDTOs; + private TextColumn seriesNameColumn; + private TextColumn fleetNameColumn; + + private final RegattaRaceStatesSettings settings; + private final FlagAlphabetInterpreter flagInterpreter; + private final String localStorageRegattaOverviewEventKey; + private static RegattaRaceStatesTableResources tableRes = GWT.create(RegattaRaceStatesTableResources.class); + private final static String LOCAL_STORAGE_REGATTA_OVERVIEW_KEY = "sailingAnalytics.regattaOverview.settings."; + public RegattaRaceStatesComponent(final SailingServiceAsync sailingService, ErrorReporter errorReporter, - final StringMessages stringMessages, final String eventIdAsString, final RegattaOverviewRaceSelectionProvider raceSelectionProvider, - final EventProvider eventProvider) { + final StringMessages stringMessages, final String eventIdAsString, RegattaRaceStatesSettings settings) { this.sailingService = sailingService; this.stringMessages = stringMessages; this.eventIdAsString = eventIdAsString; - this.raceSelectionProvider = raceSelectionProvider; - this.eventProvider = eventProvider; this.flagImageResolver = new FlagImageResolver(); + this.allEntries = new ArrayList(); - settings = new RegattaRaceStatesSettings();//TODO initialize settings properly + this.eventDTO = null; + this.raceGroupDTOs = null; + this.localStorageRegattaOverviewEventKey = LOCAL_STORAGE_REGATTA_OVERVIEW_KEY + eventIdAsString; + + this.flagInterpreter = new FlagAlphabetInterpreter(stringMessages); + + this.settings = new RegattaRaceStatesSettings(); + loadAndSetSettings(settings); + mainPanel = new VerticalPanel(); setWidth("100%"); regattaOverviewDataProvider = new ListDataProvider(); regattaOverviewTable = createRegattaTable(); - raceSelectionModel = new SingleSelectionModel(); - raceSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { - - @Override - public void onSelectionChange(SelectionChangeEvent event) { - showSelectedRaces(); - } - - }); - - regattaOverviewTable.setSelectionModel(raceSelectionModel); - mainPanel.add(regattaOverviewTable); setWidget(mainPanel); - - loadAndUpdateEventLog(); } - protected List getSelectedRaces() { - List result = new ArrayList(); - if (regattaOverviewDataProvider != null) { - for (RegattaOverviewEntryDTO race : regattaOverviewDataProvider.getList()) { - if (raceSelectionModel.isSelected(race)) { - result.add(race); - } - } + private void loadAndSetSettings(RegattaRaceStatesSettings settings) { + RegattaRaceStatesSettings loadedSettings = loadRegattaRaceStatesSettings(); + if (loadedSettings != null) { + settings = loadedSettings; } - return result; + updateSettings(settings); } public void onUpdateServer(Date time) { @@ -115,86 +130,31 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component private void updateTable(List newEntries) { allEntries = newEntries; - List filteredRegattaRaces = getFilteredRegattaRaces(allEntries); - Collections.sort(filteredRegattaRaces, new RegattaRaceStatesComparator()); //sort entries after filtering - List racesToBeShown = getRacesToBeShown(filteredRegattaRaces); - //TODO group races by same day + regattaOverviewDataProvider.getList().clear(); - regattaOverviewDataProvider.getList().addAll(racesToBeShown); + regattaOverviewDataProvider.getList().addAll(allEntries); // now sort again according to selected criterion ColumnSortEvent.fire(regattaOverviewTable, regattaOverviewTable.getColumnSortList()); } - private List getRacesToBeShown(List filteredEntries) { - List racesToBeShown = new ArrayList(filteredEntries); - if (settings.isShowOnlyCurrentlyRunningRaces()) { - String currentRegattaName = ""; - String currentFleetName = ""; - int numberOfFinishedRacesOfCurrentRegattaFleet = 0; - for (RegattaOverviewEntryDTO entry : filteredEntries) { - if (!currentRegattaName.equals(entry.regattaName) || !currentFleetName.equals(entry.raceInfo.fleetName)) { - currentRegattaName = entry.regattaName; - currentFleetName = entry.raceInfo.fleetName; - numberOfFinishedRacesOfCurrentRegattaFleet = 0; - } - if (!isRaceActive(entry.raceInfo.lastStatus)) { - if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { - if (numberOfFinishedRacesOfCurrentRegattaFleet > 0) { - racesToBeShown.remove(entry); - } - numberOfFinishedRacesOfCurrentRegattaFleet++; - } else if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED)) { - //don't filter when the race is unscheduled and aborted before - if (!entry.raceInfo.isRaceAbortedInPassBefore) { - racesToBeShown.remove(entry); - } - - } - } - } - } - return racesToBeShown; - } - - private List getFilteredRegattaRaces(List raceList) { - List filteredEntries = new ArrayList(raceList); - - for (RegattaOverviewEntryDTO entry : raceList) { - if (!settings.getVisibleCourseAreas().contains(entry.courseAreaIdAsString)) { - filteredEntries.remove(entry); - continue; - } - if (!settings.getVisibleRegattas().contains(entry.regattaName)) { - filteredEntries.remove(entry); - continue; - } - } - - return filteredEntries; - } - - private boolean isRaceActive(RaceLogRaceStatus status) { - return status.equals(RaceLogRaceStatus.SCHEDULED) || status.equals(RaceLogRaceStatus.STARTPHASE) - || status.equals(RaceLogRaceStatus.RUNNING) || status.equals(RaceLogRaceStatus.FINISHING); - } - protected void loadAndUpdateEventLog() { - if (eventIdAsString == null) { + if (eventIdAsString == null || eventDTO == null || raceGroupDTOs == null) { return; } - sailingService.getRegattaOverviewEntriesForEvent(eventIdAsString, - new MarkedAsyncCallback>() { + sailingService.getRaceStateEntriesForRaceGroup(eventIdAsString, settings.getVisibleCourseAreas(), settings.getVisibleRegattas(), + settings.isShowOnlyCurrentlyRunningRaces(), settings.isShowOnlyRacesOfSameDay(), new MarkedAsyncCallback>() { - @Override - protected void handleFailure(Throwable cause) { + @Override + protected void handleFailure(Throwable cause) { - } + } - @Override - protected void handleSuccess(List result) { - updateTable(result); - } - }); + @Override + protected void handleSuccess(List result) { + updateTable(result); + } + + }); } private CellTable createRegattaTable() { @@ -221,10 +181,17 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component }); - TextColumn regattaNameColumn = new TextColumn() { + AnchorCell leaderboardAnchorCell = new AnchorCell(); + Column regattaNameColumn = new Column(leaderboardAnchorCell) { @Override - public String getValue(RegattaOverviewEntryDTO entryDTO) { - return entryDTO.regattaName; + public Anchor getValue(RegattaOverviewEntryDTO entryDTO) { + Map leaderboardLinkParameters = new HashMap(); + leaderboardLinkParameters.put("name", entryDTO.regattaName); + leaderboardLinkParameters.put("showRaceDetails", String.valueOf(true)); + leaderboardLinkParameters.put("displayName", entryDTO.regattaDisplayName); + String leaderboardLink = EntryPointLinkFactory.createLeaderboardLink(leaderboardLinkParameters); + Anchor result = new Anchor(entryDTO.regattaDisplayName, leaderboardLink); + return result; } }; regattaNameColumn.setSortable(true); @@ -232,44 +199,47 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component @Override public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - return left.regattaName.compareTo(right.regattaName); + return left.regattaDisplayName.compareTo(right.regattaDisplayName); } }); - TextColumn fleetNameColumn = new TextColumn() { + seriesNameColumn = new TextColumn() { @Override public String getValue(RegattaOverviewEntryDTO entryDTO) { - //TODO Fleet column shall be not shown when the races of this event have no fleets - return entryDTO.raceInfo.fleetName.equals("Default") ? "-" : entryDTO.raceInfo.fleetName; + return entryDTO.raceInfo.seriesName.equals(LeaderboardNameConstants.DEFAULT_SERIES_NAME) ? "-" : entryDTO.raceInfo.seriesName; + } + }; + seriesNameColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); + + fleetNameColumn = new TextColumn() { + @Override + public String getValue(RegattaOverviewEntryDTO entryDTO) { + return entryDTO.raceInfo.fleetName.equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME) ? "-" : entryDTO.raceInfo.fleetName; } }; fleetNameColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - fleetNameColumn.setSortable(true); - regattaOverviewListHandler.setComparator(fleetNameColumn, new Comparator() { + AnchorCell raceCell = new AnchorCell(); + Column raceNameColumn = new Column(raceCell) { @Override - public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - return left.raceInfo.fleetName.compareTo(right.raceInfo.fleetName); - } - - }); - - TextColumn raceNameColumn = new TextColumn() { - @Override - public String getValue(RegattaOverviewEntryDTO entryDTO) { - return entryDTO.raceInfo.raceName; + public Anchor getValue(RegattaOverviewEntryDTO entryDTO) { + Anchor result = null; + if (entryDTO.raceInfo.raceIdentifier != null && entryDTO.raceInfo.isTracked) { + Map raceLinkParameters = new HashMap(); + raceLinkParameters.put("leaderboardName", entryDTO.regattaName); + raceLinkParameters.put("raceName", entryDTO.raceInfo.raceIdentifier.getRaceName()); + raceLinkParameters.put("canReplayDuringLiveRaces", "true"); + raceLinkParameters.put("regattaName", entryDTO.regattaName); + String raceBoardLink = EntryPointLinkFactory.createRaceBoardLink(raceLinkParameters); + result = new Anchor(entryDTO.raceInfo.raceName, raceBoardLink); + } else { + result = new Anchor(entryDTO.raceInfo.raceName); + result.setEnabled(false); + } + return result; } }; - raceNameColumn.setSortable(true); - regattaOverviewListHandler.setComparator(raceNameColumn, new Comparator() { - - @Override - public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - return right.raceInfo.raceName.compareTo(left.raceInfo.raceName); - } - - }); TextColumn raceStartTimeColumn = new TextColumn() { @Override @@ -282,43 +252,40 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component } }; raceStartTimeColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); - raceStartTimeColumn.setSortable(true); - regattaOverviewListHandler.setComparator(raceStartTimeColumn, new Comparator() { - - @Override - public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - int result = 0; - if (left.raceInfo.startTime != null && right.raceInfo.startTime != null) { - result = left.raceInfo.startTime.compareTo(right.raceInfo.startTime); - } else if (left.raceInfo.startTime == null && right.raceInfo.startTime == null) { - result = 0; - } else if (left.raceInfo.startTime == null) { - result = 1; - } else if (right.raceInfo.startTime == null) { - result = -1; - } else { - result = 0; - } - return result; - } - - }); TextColumn raceStatusColumn = new TextColumn() { @Override public String getValue(RegattaOverviewEntryDTO entryDTO) { - return getStatusText(entryDTO.raceInfo); + return flagInterpreter.getMeaningOfRaceStateAndFlags(entryDTO.raceInfo.lastStatus, entryDTO.raceInfo.lastUpperFlag, + entryDTO.raceInfo.lastLowerFlag, entryDTO.raceInfo.isLastFlagDisplayed); } }; - raceStatusColumn.setSortable(true); - regattaOverviewListHandler.setComparator(raceStatusColumn, new Comparator() { + + Column raceCourseColumn = new Column(new ClickableTextCell()) { + @Override + public String getValue(RegattaOverviewEntryDTO entryDTO) { + String courseName = "-"; + if (entryDTO.raceInfo.lastCourseName != null) { + courseName = entryDTO.raceInfo.lastCourseName; + } + return courseName; + } + }; + raceCourseColumn.setFieldUpdater(new FieldUpdater() { @Override - public int compare(RegattaOverviewEntryDTO left, RegattaOverviewEntryDTO right) { - return left.raceInfo.lastStatus.compareTo(right.raceInfo.lastStatus); + public void update(int index, RegattaOverviewEntryDTO object, String value) { + if (object.raceInfo.lastCourseDesign.waypoints.size() > 0) { + DialogBox courseViewDialogBox = createCourseViewDialogBox(object.raceInfo); + courseViewDialogBox.center(); + courseViewDialogBox.setGlassEnabled(true); + courseViewDialogBox.setAnimationEnabled(true); + courseViewDialogBox.show(); + } } }); + raceCourseColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); Column lastUpperFlagColumn = new Column( new ImageResourceCell()) { @@ -365,18 +332,15 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component return additionalInformation.toString(); } }; - - //TODO add a link to a raceboard when a trackedrace is available for a given race column table.addColumn(courseAreaColumn, stringMessages.courseArea()); - table.addColumn(regattaNameColumn, stringMessages.regatta()); // For sailors the boat class also contains - // additional infos such as woman/man, e.g. - // Laser Radial Woman or Laser Radial Men - //TODO Show Series when available + table.addColumn(regattaNameColumn, stringMessages.regatta()); + table.addColumn(seriesNameColumn, stringMessages.series()); table.addColumn(fleetNameColumn, stringMessages.fleet()); table.addColumn(raceNameColumn, stringMessages.race()); table.addColumn(raceStartTimeColumn, stringMessages.startTime()); table.addColumn(raceStatusColumn, stringMessages.status()); + table.addColumn(raceCourseColumn, stringMessages.course()); table.addColumn(lastUpperFlagColumn, stringMessages.lastUpperFlag()); table.addColumn(lastLowerFlagColumn, stringMessages.lastLowerFlag()); table.addColumn(lastFlagDirectionColumn, stringMessages.flagStatus()); @@ -389,52 +353,37 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component public List getAllRaces() { return allEntries; } - - public List getRegattaNames() { - List regattaNames = new ArrayList(); - for (RegattaOverviewEntryDTO entry : allEntries) { - if (!regattaNames.contains(entry.regattaName)) { - regattaNames.add(entry.regattaName); + + private boolean hasAnyRaceGroupASeries() { + boolean result = false; + if (raceGroupDTOs != null) { + for (RaceGroupDTO raceGroup : raceGroupDTOs) { + for (RaceGroupSeriesDTO series : raceGroup.getSeries()) { + if (!series.getName().equals(LeaderboardNameConstants.DEFAULT_SERIES_NAME)) { + result = true; + break; + } + } } } - return regattaNames; - } - - private void showSelectedRaces() { - List selectedRaces = getSelectedRaces(); - RegattaRaceStatesComponent.this.raceSelectionProvider.setSelection(selectedRaces); + return result; } - private String getStatusText(RaceInfoDTO raceInfo) { - String statusText = ""; - if (raceInfo.lastStatus.equals(RaceLogRaceStatus.RUNNING) && raceInfo.lastUpperFlag.equals(Flags.XRAY) - && raceInfo.isLastFlagDisplayed) { - statusText = "Race is running (had early starters)"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.RUNNING) && raceInfo.lastUpperFlag.equals(Flags.XRAY) - && !raceInfo.isLastFlagDisplayed) { - statusText = "Race is running"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.RUNNING)) { - statusText = "Race is running"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHING)) { - statusText = "Race is finishing"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { - statusText = "Race is finished"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.SCHEDULED)) { - statusText = "Race is scheduled"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.STARTPHASE)) { - statusText = "Race in start phase"; - } else if (raceInfo.lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED)) { - statusText = stringMessages.noStarttimeAnnouncedYet(); - } else if (raceInfo.lastUpperFlag == null) { - statusText = ""; - } else if (raceInfo.lastUpperFlag.equals(Flags.FIRSTSUBSTITUTE)) { - statusText = "General recall"; - } else if (raceInfo.lastUpperFlag.equals(Flags.AP) && raceInfo.isLastFlagDisplayed) { - statusText = "Start postponed"; - } else if (raceInfo.lastUpperFlag.equals(Flags.NOVEMBER) && raceInfo.isLastFlagDisplayed) { - statusText = "Start abandoned"; + private boolean hasAnyRaceGroupAFleet() { + boolean result = false; + if (raceGroupDTOs != null) { + for (RaceGroupDTO raceGroup : raceGroupDTOs) { + for (RaceGroupSeriesDTO series : raceGroup.getSeries()) { + for (FleetDTO fleet : series.getFleets()) { + if (!fleet.getName().equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) { + result = true; + break; + } + } + } + } } - return statusText; + return result; } @Override @@ -444,31 +393,59 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component @Override public SettingsDialogComponent getSettingsDialogComponent() { - return new RegattaRaceStatesSettingsDialogComponent(settings, stringMessages, - Collections.unmodifiableList(eventProvider.getEvent().venue.getCourseAreas()), - Collections.unmodifiableList(getRegattaNames())); + return new RegattaRaceStatesSettingsDialogComponent(settings, stringMessages, eventIdAsString, + Collections.unmodifiableList(eventDTO.venue.getCourseAreas()), + Collections.unmodifiableList(raceGroupDTOs)); } @Override public void updateSettings(RegattaRaceStatesSettings newSettings) { - if (!settings.getVisibleCourseAreas().equals(newSettings.getVisibleCourseAreas())) { + if (settings.getVisibleCourseAreas().isEmpty() || !settings.getVisibleCourseAreas().equals(newSettings.getVisibleCourseAreas())) { settings.getVisibleCourseAreas().clear(); settings.getVisibleCourseAreas().addAll(newSettings.getVisibleCourseAreas()); + + fillVisibleCourseAreasInSettingsIfEmpty(); } - - if (!settings.getVisibleRegattas().equals(newSettings.getVisibleRegattas())) { + + if (settings.getVisibleRegattas().isEmpty() || !settings.getVisibleRegattas().equals(newSettings.getVisibleRegattas())) { settings.getVisibleRegattas().clear(); settings.getVisibleRegattas().addAll(newSettings.getVisibleRegattas()); + + fillVisibleRegattasInSettingsIfEmpty(); } - + if (settings.isShowOnlyRacesOfSameDay() != newSettings.isShowOnlyRacesOfSameDay()) { settings.setShowOnlyRaceOfSameDay(newSettings.isShowOnlyRacesOfSameDay()); } - + if (settings.isShowOnlyCurrentlyRunningRaces() != newSettings.isShowOnlyCurrentlyRunningRaces()) { settings.setShowOnlyCurrentlyRunningRaces(newSettings.isShowOnlyCurrentlyRunningRaces()); } - updateTable(allEntries); + + refreshTableWithNewSettings(); + storeRegattaRaceStatesSettings(settings); + } + + private void refreshTableWithNewSettings() { + if (eventDTO != null && raceGroupDTOs != null) { + loadAndUpdateEventLog(); + } + } + + private void fillVisibleRegattasInSettingsIfEmpty() { + if (settings.getVisibleRegattas().isEmpty() && raceGroupDTOs != null) { + for (RaceGroupDTO raceGroup : raceGroupDTOs) { + settings.getVisibleRegattas().add(raceGroup.getName()); + } + } + } + + private void fillVisibleCourseAreasInSettingsIfEmpty() { + if (settings.getVisibleCourseAreas().isEmpty() && eventDTO != null) { + for (CourseAreaDTO courseArea : eventDTO.venue.getCourseAreas()) { + settings.getVisibleCourseAreas().add(courseArea.id); + } + } } @Override @@ -480,4 +457,105 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component public Widget getEntryWidget() { return this; } + + @Override + public void onEventUpdated(EventDTO event) { + eventDTO = event; + fillVisibleCourseAreasInSettingsIfEmpty(); + refreshTableWithNewSettings(); + } + + @Override + public void onRaceGroupsUpdated(List raceGroups) { + raceGroupDTOs = raceGroups; + + if (!hasAnyRaceGroupASeries()) { + regattaOverviewTable.removeColumn(seriesNameColumn); + } + if (!hasAnyRaceGroupAFleet()) { + regattaOverviewTable.removeColumn(fleetNameColumn); + } + fillVisibleRegattasInSettingsIfEmpty(); + refreshTableWithNewSettings(); + } + + private void storeRegattaRaceStatesSettings(RegattaRaceStatesSettings settings) { + Storage localStorage = Storage.getLocalStorageIfSupported(); + if (localStorage != null) { + // delete old value + localStorage.removeItem(localStorageRegattaOverviewEventKey); + + //store settings + GwtJsonDeSerializer serializer = new RegattaRaceStatesSettingsJsonDeSerializer(); + JSONObject settingsAsJson = serializer.serialize(settings); + localStorage.setItem(localStorageRegattaOverviewEventKey, settingsAsJson.toString()); + } + } + + private RegattaRaceStatesSettings loadRegattaRaceStatesSettings() { + RegattaRaceStatesSettings loadedSettings = null; + Storage localStorage = Storage.getLocalStorageIfSupported(); + + if (localStorage != null) { + String jsonAsLocalStore = localStorage.getItem(localStorageRegattaOverviewEventKey); + if (jsonAsLocalStore != null && !jsonAsLocalStore.isEmpty()) { + GwtJsonDeSerializer deserializer = new RegattaRaceStatesSettingsJsonDeSerializer(); + JSONValue value = JSONParser.parseStrict(jsonAsLocalStore); + if(value.isObject() != null) { + loadedSettings = deserializer.deserialize((JSONObject) value); + } + + } + } + return loadedSettings; + } + + private DialogBox createCourseViewDialogBox(RaceInfoDTO raceInfoDTO) { + final DialogBox dialogBox = new DialogBox(); + dialogBox.setText(stringMessages.courseLayout()); + + // Create a table to layout the content + VerticalPanel dialogContents = new VerticalPanel(); + dialogContents.setSpacing(4); + dialogBox.setWidget(dialogContents); + + Label courseNameLabel = new Label(raceInfoDTO.lastCourseName); + dialogContents.add(courseNameLabel); + + Grid waypointGrid = new Grid(raceInfoDTO.lastCourseDesign.waypoints.size(), 1); + dialogContents.add(waypointGrid); + for (int i = 0; i < raceInfoDTO.lastCourseDesign.waypoints.size(); i++) { + WaypointDTO waypoint = raceInfoDTO.lastCourseDesign.waypoints.get(i); + waypointGrid.setText(i, 0, getWaypointNameLabel(waypoint)); + } + + Button closeButton = new Button(stringMessages.ok()); + closeButton.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + dialogBox.hide(); + } + }); + dialogContents.add(closeButton); + dialogContents.setCellHorizontalAlignment( + closeButton, HasHorizontalAlignment.ALIGN_CENTER); + + return dialogBox; + } + + private String getWaypointNameLabel(WaypointDTO waypointDTO) { + String result = waypointDTO.getName(); + result += (waypointDTO.passingSide == null) ? "" : ", to " + getNauticalSideAsText(waypointDTO.passingSide); + return result; + } + + private String getNauticalSideAsText(NauticalSide passingSide) { + switch (passingSide) { + case PORT: + return stringMessages.portSide(); + case STARBOARD: + return stringMessages.starboardSide(); + default: + return ""; + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesFlagsResources.java similarity index 95% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewResources.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesFlagsResources.java index 1a0ed1882c0..953b67741f1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaOverviewResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesFlagsResources.java @@ -1,66 +1,66 @@ -package com.sap.sailing.gwt.ui.regattaoverview; - -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.ImageResource; - -interface RegattaOverviewResources extends ClientBundle { - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/ap.png") - ImageResource flagAP(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/alpha.png") - ImageResource flagAlpha(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/black.png") - ImageResource flagBlack(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/blue.png") - ImageResource flagBlue(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/bravo.png") - ImageResource flagBravo(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/class.png") - ImageResource flagClass(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/essone.png") - ImageResource flagEssOne(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/esstwo.png") - ImageResource flagEssTwo(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/essthree.png") - ImageResource flagEssThree(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/firstsubstitute.png") - ImageResource flagFirstSubstitute(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/golf.png") - ImageResource flagGolf(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/hotel.png") - ImageResource flagHotel(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/india.png") - ImageResource flagIndia(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/november.png") - ImageResource flagNovember(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/papa.png") - ImageResource flagPapa(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/whiskey.png") - ImageResource flagWhiskey(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/xray.png") - ImageResource flagXray(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/zulu.png") - ImageResource flagZulu(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png") - ImageResource arrowUp(); - - @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png") - ImageResource arrowDown(); +package com.sap.sailing.gwt.ui.regattaoverview; + +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +interface RegattaRaceStatesFlagsResources extends ClientBundle { + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/ap.png") + ImageResource flagAP(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/alpha.png") + ImageResource flagAlpha(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/black.png") + ImageResource flagBlack(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/blue.png") + ImageResource flagBlue(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/bravo.png") + ImageResource flagBravo(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/class.png") + ImageResource flagClass(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/essone.png") + ImageResource flagEssOne(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/esstwo.png") + ImageResource flagEssTwo(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/essthree.png") + ImageResource flagEssThree(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/firstsubstitute.png") + ImageResource flagFirstSubstitute(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/golf.png") + ImageResource flagGolf(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/hotel.png") + ImageResource flagHotel(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/india.png") + ImageResource flagIndia(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/november.png") + ImageResource flagNovember(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/papa.png") + ImageResource flagPapa(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/whiskey.png") + ImageResource flagWhiskey(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/xray.png") + ImageResource flagXray(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/zulu.png") + ImageResource flagZulu(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png") + ImageResource arrowUp(); + + @Source("com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png") + ImageResource arrowDown(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettings.java index a414bf5f0e8..ee54295ef35 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettings.java @@ -14,7 +14,7 @@ public class RegattaRaceStatesSettings { this.visibleCourseAreas = new ArrayList(); this.visibleRegattas = new ArrayList(); this.showOnlyRacesOfSameDay = false; - this.showOnlyCurrentlyRunningRaces = false; + this.showOnlyCurrentlyRunningRaces = true; } public RegattaRaceStatesSettings(List visibleCourseAreas, List visibleRegattas, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsDialogComponent.java index 39bb0815b66..4e575a1a021 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsDialogComponent.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FocusWidget; @@ -18,29 +19,34 @@ import com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent; import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogComponent { private final StringMessages stringMessages; private final RegattaRaceStatesSettings initialSettings; + private final String eventIdAsString; private final List courseAreas; - private final List regattaNames; + private final List raceGroups; private CheckBox showOnlyRacesOfSameDayCheckBox; private CheckBox showOnlyCurrentlyRunningRacesCheckBox; private final Map courseAreaCheckBoxMap; private final Map regattaCheckBoxMap; + private final Anchor resultingLink; private final static String SETTINGS_DIALOG_COMPONENT = "SettingsDialogComponent"; public RegattaRaceStatesSettingsDialogComponent(RegattaRaceStatesSettings settings, StringMessages stringMessages, - List courseAreas, List regattaNames) { + String eventIdAsString, List courseAreas, List raceGroups) { this.stringMessages = stringMessages; this.initialSettings = settings; + this.eventIdAsString = eventIdAsString; this.courseAreas = courseAreas; - this.regattaNames = regattaNames; + this.raceGroups = raceGroups; this.courseAreaCheckBoxMap = new HashMap(); this.regattaCheckBoxMap = new HashMap(); + this.resultingLink = new Anchor(stringMessages.asLink()); } private FlowPanel fillCourseAreaWidget(DataEntryDialog dialog) { @@ -84,7 +90,7 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC flowPanel.add(regattaNamesPanel); int maxRegattasPerRow = 4; - int numberOfRegattas = regattaNames.size(); + int numberOfRegattas = raceGroups.size(); int numberOfRequiredRows = numberOfRegattas / maxRegattasPerRow; if (numberOfRegattas % maxRegattasPerRow != 0) { numberOfRequiredRows++; @@ -95,10 +101,10 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC Grid regattaGrid = new Grid(numberOfRequiredRows, maxRegattasPerRow); regattaNamesPanel.add(regattaGrid); - for (String regattaName : regattaNames) { - CheckBox checkBox = dialog.createCheckbox(regattaName); - checkBox.setValue(Util.contains(initialSettings.getVisibleRegattas(), regattaName)); - regattaCheckBoxMap.put(regattaName, checkBox); + for (RaceGroupDTO raceGroup : raceGroups) { + CheckBox checkBox = dialog.createCheckbox(raceGroup.displayName); + checkBox.setValue(Util.contains(initialSettings.getVisibleRegattas(), raceGroup.getName())); + regattaCheckBoxMap.put(raceGroup.getName(), checkBox); regattaGrid.setWidget(rowIndex, columnIndex++, checkBox); if(columnIndex == maxRegattasPerRow) { @@ -130,19 +136,20 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC additionalSettingsPanel.add(getShowOnlyRacesOfSameDayWidget(dialog)); additionalSettingsPanel.add(getShowOnlyCurrentlyRunningRacesWidget(dialog)); - + return flowPanel; } @Override public Widget getAdditionalWidget(DataEntryDialog dialog) { - VerticalPanel vp = new VerticalPanel(); + VerticalPanel verticalPanel = new VerticalPanel(); - vp.add(fillCourseAreaWidget(dialog)); - vp.add(fillRegattaNamesWidget(dialog)); - vp.add(getAdditionalSettingsWidget(dialog)); + verticalPanel.add(fillCourseAreaWidget(dialog)); + verticalPanel.add(fillRegattaNamesWidget(dialog)); + verticalPanel.add(getAdditionalSettingsWidget(dialog)); + verticalPanel.add(resultingLink); - return vp; + return verticalPanel; } @Override @@ -170,8 +177,11 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC public Validator getValidator() { return new Validator() { @Override - public String getErrorMessage(RegattaRaceStatesSettings valueToValidate) { + public String getErrorMessage(RegattaRaceStatesSettings settings) { String errorMessage = null; + if (errorMessage == null) { + updateLinkUrl(eventIdAsString, settings); + } return errorMessage; } }; @@ -181,5 +191,17 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC public FocusWidget getFocusWidget() { return null; } + + private void updateLinkUrl(String eventIdAsString, RegattaRaceStatesSettings settings) { + boolean isSetVisibleCourseAreasInUrl = true; + boolean isSetVisibleRegattasInUrl = true; + if (settings.getVisibleCourseAreas().size() == courseAreas.size()) { + isSetVisibleCourseAreasInUrl = false; + } + if (settings.getVisibleRegattas().size() == raceGroups.size()) { + isSetVisibleRegattasInUrl = false; + } + resultingLink.setHref(RegattaOverviewEntryPoint.getUrl(eventIdAsString, settings, isSetVisibleCourseAreasInUrl, isSetVisibleRegattasInUrl)); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsJsonDeSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsJsonDeSerializer.java new file mode 100644 index 00000000000..8661d66de23 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/regattaoverview/RegattaRaceStatesSettingsJsonDeSerializer.java @@ -0,0 +1,67 @@ +package com.sap.sailing.gwt.ui.regattaoverview; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONBoolean; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONString; +import com.sap.sailing.gwt.ui.client.GwtJsonDeSerializer; + +public class RegattaRaceStatesSettingsJsonDeSerializer implements GwtJsonDeSerializer { + + private static final String FIELD_VISIBLE_COURSE_AREAS = "visibleCourseAreas"; + private static final String FIELD_VISIBLE_REGATTAS = "visibleRegattas"; + private static final String FIELD_SHOW_ONLY_CURRENTLY_RUNNING_RACES = "showOnlyCurrentlyRunningRaces"; + private static final String FIELD_SHOW_ONLY_RACES_OF_SAME_DAY = "showOnlyRacesOfSameDay"; + + @Override + public JSONObject serialize(RegattaRaceStatesSettings settings) { + JSONObject result = new JSONObject(); + result.put(FIELD_SHOW_ONLY_CURRENTLY_RUNNING_RACES, JSONBoolean.getInstance(settings.isShowOnlyCurrentlyRunningRaces())); + result.put(FIELD_SHOW_ONLY_RACES_OF_SAME_DAY, JSONBoolean.getInstance(settings.isShowOnlyRacesOfSameDay())); + + JSONArray visibleCourseAreas = new JSONArray(); + for (int i = 0 ; i < settings.getVisibleCourseAreas().size() ; i++) { + visibleCourseAreas.set(i, new JSONString(settings.getVisibleCourseAreas().get(i))); + } + result.put(FIELD_VISIBLE_COURSE_AREAS, visibleCourseAreas); + + JSONArray visibleRegattas = new JSONArray(); + for (int i = 0 ; i < settings.getVisibleRegattas().size() ; i++) { + visibleRegattas.set(i, new JSONString(settings.getVisibleRegattas().get(i))); + } + result.put(FIELD_VISIBLE_REGATTAS, visibleRegattas); + + return result; + } + + @Override + public RegattaRaceStatesSettings deserialize(JSONObject object) { + if (object == null) { + return null; + } + + JSONBoolean showOnlyCurrentlyRunningRaces = (JSONBoolean) object.get(FIELD_SHOW_ONLY_CURRENTLY_RUNNING_RACES); + JSONBoolean showOnlyRacesOfSameDay = (JSONBoolean) object.get(FIELD_SHOW_ONLY_RACES_OF_SAME_DAY); + + JSONArray jsonVisibleCourseAreas = (JSONArray) object.get(FIELD_VISIBLE_COURSE_AREAS); + List visibleCourseAreas = new ArrayList(); + for (int i = 0 ; i < jsonVisibleCourseAreas.size() ; i++) { + JSONString jsonCourseArea = (JSONString) jsonVisibleCourseAreas.get(i); + visibleCourseAreas.add(jsonCourseArea.stringValue()); + } + + JSONArray jsonVisibleRegattas = (JSONArray) object.get(FIELD_VISIBLE_REGATTAS); + List visibleRegattas = new ArrayList(); + for (int i = 0 ; i < jsonVisibleRegattas.size() ; i++) { + JSONString jsonRegatta = (JSONString) jsonVisibleRegattas.get(i); + visibleRegattas.add(jsonRegatta.stringValue()); + } + + return new RegattaRaceStatesSettings(visibleCourseAreas, visibleRegattas, + showOnlyRacesOfSameDay.booleanValue(), showOnlyCurrentlyRunningRaces.booleanValue()); + } + +} 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 d3172c9f920..3391cf04fa8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -13,6 +13,7 @@ import java.net.URL; import java.net.UnknownHostException; import java.text.ParseException; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -126,6 +127,8 @@ import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.racelog.utils.RaceStateOfSameDayHelper; +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.MetaLeaderboard; @@ -143,8 +146,9 @@ import com.sap.sailing.domain.polarsheets.PolarSheetsWindStepping; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.analyzing.impl.AbortingFlagFinder; +import com.sap.sailing.domain.racelog.analyzing.impl.FinishedTimeFinder; import com.sap.sailing.domain.racelog.analyzing.impl.GateLineOpeningTimeFinder; -import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagFinder; +import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagsFinder; import com.sap.sailing.domain.racelog.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.racelog.analyzing.impl.PathfinderFinder; import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer; @@ -196,6 +200,8 @@ import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO; import com.sap.sailing.gwt.ui.shared.MarkpassingManeuverDTO; import com.sap.sailing.gwt.ui.shared.QuickRankDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; import com.sap.sailing.gwt.ui.shared.RaceInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsDTO; @@ -600,38 +606,50 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S series.isStartsWithZeroScore(), series.isFirstColumnIsNonDiscardableCarryForward()); return result; } - - private RaceInfoDTO createRaceInfoDTO(RaceColumn raceColumn, Fleet fleet) { + + private RaceInfoDTO createRaceInfoDTO(String seriesName, RaceColumn raceColumn, Fleet fleet) { RaceInfoDTO raceInfoDTO = new RaceInfoDTO(); RaceLog raceLog = raceColumn.getRaceLog(fleet); if (raceLog != null) { StartTimeFinder startTimeFinder = new StartTimeFinder(raceLog); - if(startTimeFinder.getStartTime()!=null){ - raceInfoDTO.startTime = startTimeFinder.getStartTime().asDate(); + TimePoint startTime = startTimeFinder.analyze(); + if (startTime != null) { + raceInfoDTO.startTime = startTime.asDate(); } RaceStatusAnalyzer raceStatusAnalyzer = new RaceStatusAnalyzer(raceLog); - raceInfoDTO.lastStatus = raceStatusAnalyzer.getStatus(); + raceInfoDTO.lastStatus = raceStatusAnalyzer.analyze(); PathfinderFinder pathfinderFinder = new PathfinderFinder(raceLog); - raceInfoDTO.pathfinderId = pathfinderFinder.getPathfinderId(); + raceInfoDTO.pathfinderId = pathfinderFinder.analyze(); GateLineOpeningTimeFinder gateLineOpeningTimeFinder = new GateLineOpeningTimeFinder(raceLog); - raceInfoDTO.gateLineOpeningTime = gateLineOpeningTimeFinder.getGateLineOpeningTime(); + raceInfoDTO.gateLineOpeningTime = gateLineOpeningTimeFinder.analyze(); + + if (raceLog.getLastRawFix() != null) { + raceInfoDTO.lastUpdateTime = raceLog.getLastRawFix().getTimePoint().asDate(); + } + + FinishedTimeFinder finishedTimeFinder = new FinishedTimeFinder(raceLog); + TimePoint finishedTime = finishedTimeFinder.analyze(); + if (finishedTime != null) { + raceInfoDTO.finishedTime = finishedTime.asDate(); + } - LastFlagFinder lastFlagFinder = new LastFlagFinder(raceLog); + LastFlagsFinder lastFlagFinder = new LastFlagsFinder(raceLog); - RaceLogFlagEvent lastFlagEvent = lastFlagFinder.getLastFlagEvent(); + RaceLogFlagEvent lastFlagEvent = LastFlagsFinder.getMostRecent(lastFlagFinder.analyze()); if (lastFlagEvent != null) { raceInfoDTO.lastUpperFlag = lastFlagEvent.getUpperFlag(); raceInfoDTO.lastLowerFlag = lastFlagEvent.getLowerFlag(); raceInfoDTO.isLastFlagDisplayed = lastFlagEvent.isDisplayed(); } + AbortingFlagFinder abortingFlagFinder = new AbortingFlagFinder(raceLog); - RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.getAbortingFlagEvent(); + RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.analyze(); if (abortingFlagEvent != null) { raceInfoDTO.isRaceAbortedInPassBefore = true; @@ -643,12 +661,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } LastPublishedCourseDesignFinder courseDesignFinder = new LastPublishedCourseDesignFinder(raceLog); - raceInfoDTO.lastCourseDesign = convertCourseDesignToRaceCourseDTO(courseDesignFinder.getLastCourseDesign()); + CourseBase lastCourse = courseDesignFinder.analyze(); + raceInfoDTO.lastCourseDesign = convertCourseDesignToRaceCourseDTO(lastCourse); + if (lastCourse != null) { + raceInfoDTO.lastCourseName = lastCourse.getName(); + } } + raceInfoDTO.seriesName = seriesName; raceInfoDTO.raceName = raceColumn.getName(); raceInfoDTO.fleetName = fleet.getName(); raceInfoDTO.fleetOrdering = fleet.getOrdering(); raceInfoDTO.raceIdentifier = raceColumn.getRaceIdentifier(fleet); + raceInfoDTO.isTracked = raceColumn.getTrackedRace(fleet) != null ? true : false; + return raceInfoDTO; } @@ -2529,43 +2554,59 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public List getRegattaOverviewEntriesForEvent(String eventIdAsString) { - List result = new ArrayList(); + public List getRegattaStructureForEvent(String eventIdAsString) { + List raceGroups = new ArrayList(); Event event = getService().getEvent(convertIdentifierStringToUuid(eventIdAsString)); if (event != null) { for (CourseArea courseArea : event.getVenue().getCourseAreas()) { for (Leaderboard leaderboard : getService().getLeaderboards().values()) { - if (leaderboard.getDefaultCourseArea() != null && leaderboard.getDefaultCourseArea().equals(courseArea)) { - String regattaName = getRegattaNameFromLeaderboard(leaderboard); - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - RegattaOverviewEntryDTO entry = new RegattaOverviewEntryDTO(); - entry.courseAreaName = courseArea.getName(); - entry.courseAreaIdAsString = courseArea.getId().toString(); - entry.regattaName = regattaName; - entry.raceInfo = createRaceInfoDTO(raceColumn, fleet); - result.add(entry); + if (leaderboard.getDefaultCourseArea() != null && leaderboard.getDefaultCourseArea() == courseArea) { + RaceGroupDTO raceGroup = new RaceGroupDTO(leaderboard.getName()); + raceGroup.courseAreaIdAsString = courseArea.getId().toString(); + raceGroup.displayName = getRegattaNameFromLeaderboard(leaderboard); + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; + for (Series series : regattaLeaderboard.getRegatta().getSeries()) { + RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(series.getName()); + raceGroup.getSeries().add(seriesDTO); + for (Fleet fleet : series.getFleets()) { + FleetDTO fleetDTO = new FleetDTO(fleet.getName(), fleet.getOrdering(), fleet.getColor()); + seriesDTO.getFleets().add(fleetDTO); + } } + } else { + RaceGroupSeriesDTO seriesDTO = new RaceGroupSeriesDTO(LeaderboardNameConstants.DEFAULT_SERIES_NAME); + raceGroup.getSeries().add(seriesDTO); + FleetDTO fleetDTO = new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null); + seriesDTO.getFleets().add(fleetDTO); } + raceGroups.add(raceGroup); } } } } - return result; + return raceGroups; } + /** + * The name of the regatta to be shown on the regatta overview webpage is retrieved from the name of the {@link Leaderboard}. Since regattas are + * not always represented by a {@link Regatta} object in the Sailing Suite but need to be shown on the regatta overview page, the leaderboard is + * used as the representative of the sailing regatta. When a display name is set for a leaderboard, this name is favored against the (mostly technical) + * regatta name as the display name represents the publicly visible name of the regatta. + *
+ * When the leaderboard is a {@link RegattaLeaderboard} the name of the {@link Regatta} is used, otherwise the leaderboard + * is a {@link FlexibleLeaderboard} and it's name is used as the last option. + * @param leaderboard The {@link Leaderboard} from which the name is be retrieved + * @return the name of the regatta to be shown on the regatta overview page + */ private String getRegattaNameFromLeaderboard(Leaderboard leaderboard) { String regattaName; - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - if (regattaLeaderboard.getDisplayName() != null) { - regattaName = regattaLeaderboard.getDisplayName(); - } else { - regattaName = regattaLeaderboard.getRegatta().getName(); - } + if (leaderboard.getDisplayName() != null && !leaderboard.getDisplayName().isEmpty()) { + regattaName = leaderboard.getDisplayName(); } else { - if (leaderboard.getDisplayName() != null) { - regattaName = leaderboard.getDisplayName(); + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; + regattaName = regattaLeaderboard.getRegatta().getName(); } else { regattaName = leaderboard.getName(); } @@ -2915,6 +2956,124 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S protected com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() { return baseDomainFactory; } + + @Override + public List getRaceStateEntriesForRaceGroup(String eventIdAsString, List visibleCourseAreaIdsAsString, + List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay) { + List result = new ArrayList(); + + Calendar dayToCheck = Calendar.getInstance(); + dayToCheck.setTime(new Date()); + + Event event = getService().getEvent(convertIdentifierStringToUuid(eventIdAsString)); + if (event != null) { + for (CourseArea courseArea : event.getVenue().getCourseAreas()) { + if (!visibleCourseAreaIdsAsString.contains(courseArea.getId().toString())) { + continue; + } + for (Leaderboard leaderboard : getService().getLeaderboards().values()) { + if (leaderboard.getDefaultCourseArea() != null && leaderboard.getDefaultCourseArea().equals(courseArea)) { + if (!visibleRegattas.contains(leaderboard.getName())) { + continue; + } + String regattaName = getRegattaNameFromLeaderboard(leaderboard); + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; + for (Series series : regattaLeaderboard.getRegatta().getSeries()) { + Map> entriesPerFleet = new HashMap>(); + for (RaceColumn raceColumn : series.getRaceColumns()) { + getRegattaOverviewEntries(showOnlyRacesOfSameDay, dayToCheck, + courseArea, leaderboard, regattaName, series.getName(), raceColumn, entriesPerFleet); + } + result.addAll(getRegattaOverviewEntriesToBeShown(showOnlyCurrentlyRunningRaces, entriesPerFleet)); + } + + } else { + Map> entriesPerFleet = new HashMap>(); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + getRegattaOverviewEntries(showOnlyRacesOfSameDay, dayToCheck, courseArea, + leaderboard, regattaName, LeaderboardNameConstants.DEFAULT_SERIES_NAME, raceColumn, entriesPerFleet); + } + result.addAll(getRegattaOverviewEntriesToBeShown(showOnlyCurrentlyRunningRaces, entriesPerFleet)); + } + } + } + } + } + return result; + } + + private void getRegattaOverviewEntries(boolean showOnlyRacesOfSameDay, Calendar dayToCheck, + CourseArea courseArea, Leaderboard leaderboard, String regattaName, String seriesName, RaceColumn raceColumn, + Map> entriesPerFleet) { + + for (Fleet fleet : raceColumn.getFleets()) { + RegattaOverviewEntryDTO entry = createRegattaOverviewEntryDTO(courseArea, + leaderboard, regattaName, seriesName, raceColumn, fleet, + showOnlyRacesOfSameDay, dayToCheck); + if (entry != null) { + addRegattaOverviewEntryToEntriesPerFleet(entriesPerFleet, fleet, entry); + } + } + } + + private List getRegattaOverviewEntriesToBeShown(boolean showOnlyCurrentlyRunningRaces, + Map> entriesPerFleet) { + List result = new ArrayList(); + for (List entryList : entriesPerFleet.values()) { + result.addAll(entryList); + if (showOnlyCurrentlyRunningRaces) { + List finishedEntries = new ArrayList(); + for (RegattaOverviewEntryDTO entry : entryList) { + if (!RaceLogRaceStatus.isActive(entry.raceInfo.lastStatus)) { + if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { + finishedEntries.add(entry); + } else if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED)) { + //don't filter when the race is unscheduled and aborted before + if (!entry.raceInfo.isRaceAbortedInPassBefore) { + result.remove(entry); + } + + } + } + } + if (!finishedEntries.isEmpty()) { + //keep the last finished race in the list to be shown + int indexOfLastElement = finishedEntries.size() - 1; + finishedEntries.remove(indexOfLastElement); + + //... and remove all other finished races + result.removeAll(finishedEntries); + } + } + } + return result; + } + + private void addRegattaOverviewEntryToEntriesPerFleet(Map> entriesPerFleet, + Fleet fleet, RegattaOverviewEntryDTO entry) { + if (!entriesPerFleet.containsKey(fleet.getName())) { + entriesPerFleet.put(fleet.getName(), new ArrayList()); + } + entriesPerFleet.get(fleet.getName()).add(entry); + } + + private RegattaOverviewEntryDTO createRegattaOverviewEntryDTO(CourseArea courseArea, Leaderboard leaderboard, + String regattaName, String seriesName, RaceColumn raceColumn, Fleet fleet, boolean showOnlyRacesOfSameDay, Calendar dayToCheck) { + RegattaOverviewEntryDTO entry = new RegattaOverviewEntryDTO(); + entry.courseAreaName = courseArea.getName(); + entry.courseAreaIdAsString = courseArea.getId().toString(); + entry.regattaDisplayName = regattaName; + entry.regattaName = leaderboard.getName(); + entry.raceInfo = createRaceInfoDTO(seriesName, raceColumn, fleet); + + if (showOnlyRacesOfSameDay) { + if (!RaceStateOfSameDayHelper.isRaceStateOfSameDay(entry.raceInfo.startTime, entry.raceInfo.finishedTime, dayToCheck)) { + entry = null; + } + } + return entry; + } public String getBuildVersion() { String version = "Unknown or Development"; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupDTO.java new file mode 100644 index 00000000000..ce93db3b051 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupDTO.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.ui.shared; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.domain.common.dto.NamedDTO; + +public class RaceGroupDTO extends NamedDTO implements IsSerializable { + + private static final long serialVersionUID = 8432572954520767329L; + public String courseAreaIdAsString; + public String displayName; + private List series = new ArrayList(); + + public RaceGroupDTO() {} + + public RaceGroupDTO(String name) { + super(name); + } + + public List getSeries() { + return series; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupSeriesDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupSeriesDTO.java new file mode 100644 index 00000000000..d109899f0b2 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceGroupSeriesDTO.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.ui.shared; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.NamedDTO; + +public class RaceGroupSeriesDTO extends NamedDTO implements IsSerializable { + + private static final long serialVersionUID = 8432572954520767329L; + private List fleets = new ArrayList(); + + public RaceGroupSeriesDTO() {} + + public RaceGroupSeriesDTO(String name) { + super(name); + } + + public List getFleets() { + return fleets; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceInfoDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceInfoDTO.java index 8b310eb3180..8d316fc7aa9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceInfoDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceInfoDTO.java @@ -12,15 +12,21 @@ public class RaceInfoDTO implements IsSerializable { public String fleetName; public int fleetOrdering; public Date startTime; + public Date finishedTime; + public Date lastUpdateTime; public RaceLogRaceStatus lastStatus; public Flags lastUpperFlag; public Flags lastLowerFlag; public boolean isLastFlagDisplayed; + public boolean isTracked; public RaceCourseDTO lastCourseDesign; + public String lastCourseName; public RaceIdentifier raceIdentifier; public String pathfinderId; public Long gateLineOpeningTime; public boolean isRaceAbortedInPassBefore; + public String seriesName; + // for GWT serialization public RaceInfoDTO() { } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java index 9960fbcd027..45e3ba074a9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java @@ -5,8 +5,9 @@ import com.google.gwt.user.client.rpc.IsSerializable; public class RegattaOverviewEntryDTO implements IsSerializable { public String courseAreaIdAsString; public String courseAreaName; - public String regattaName; + public String regattaDisplayName; public RaceInfoDTO raceInfo; + public String regattaName; // for GWT serialization public RegattaOverviewEntryDTO() { } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png index ad7d485a7e0..ebf713b5c6f 100644 Binary files a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/down.png differ diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png index 800755d59cc..a7a5e25ef6a 100644 Binary files a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/flags/flags_racecommittee/up.png differ diff --git a/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/Activator.java b/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/Activator.java index 439efe3fc3b..32cf90627d3 100644 --- a/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/Activator.java +++ b/java/com.sap.sailing.manage2sail.resultimport/src/com/sap/sailing/manage2sail/resultimport/Activator.java @@ -18,14 +18,14 @@ import com.sap.sailing.resultimport.ResultUrlRegistry; import com.sap.sailing.xrr.resultimport.ParserFactory; public class Activator implements BundleActivator { - private static String MANAGE2SAIL_TEST_URL = "https://orm.manage2sail.com/shadowtest_info/api/public/links/event/58f73e6c-ec07-4655-972c-e5d730f0048e?accesstoken=bDAv8CwsTM94ujZ&mediaType=json"; + // private static String MANAGE2SAIL_TEST_URL = "https://orm.manage2sail.com/shadowtest_info/api/public/links/event/58f73e6c-ec07-4655-972c-e5d730f0048e?accesstoken=bDAv8CwsTM94ujZ&mediaType=json"; private static String MANAGE2SAIL_PROD_URL = "http://manage2sail.com/api/public/links/event/da33884e-24fe-44f6-8501-d253587f7cc8?accesstoken=bDAv8CwsTM94ujZ&mediaType=json"; public void start(BundleContext bundleContext) throws Exception { final ScoreCorrectionProviderImpl service = new ScoreCorrectionProviderImpl(ParserFactory.INSTANCE, ResultUrlRegistry.INSTANCE); bundleContext.registerService(ScoreCorrectionProvider.class, service, /* properties */null); - ResultUrlRegistry.INSTANCE.registerResultUrl(ScoreCorrectionProviderImpl.NAME, new URL(MANAGE2SAIL_TEST_URL)); + // ResultUrlRegistry.INSTANCE.registerResultUrl(ScoreCorrectionProviderImpl.NAME, new URL(MANAGE2SAIL_TEST_URL)); ResultUrlRegistry.INSTANCE.registerResultUrl(ScoreCorrectionProviderImpl.NAME, new URL(MANAGE2SAIL_PROD_URL)); createAnAllCertificatesTrustingManagerforSSL(); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogMongoDBTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogMongoDBTest.java index 16a7a235ae9..d3ec6c9f4dc 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogMongoDBTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/RaceLogMongoDBTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import java.net.UnknownHostException; import java.util.UUID; @@ -11,15 +12,23 @@ import com.mongodb.MongoException; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.Gate; import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.SpeedWithBearing; import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.base.impl.GateImpl; +import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.base.impl.MarkImpl; import com.sap.sailing.domain.base.impl.WaypointImpl; +import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.NauticalSide; +import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.domain.tracking.impl.WindImpl; public abstract class RaceLogMongoDBTest extends AbstractMongoDBTest { @@ -78,5 +87,24 @@ public abstract class RaceLogMongoDBTest extends AbstractMongoDBTest { return course; } + + protected void compareWind(Wind storedWindFix, Wind loadedWindFix) { + assertEquals(storedWindFix.getTimePoint(), loadedWindFix.getTimePoint()); + assertNotNull(storedWindFix.getPosition()); + assertNotNull(loadedWindFix.getPosition()); + assertEquals(storedWindFix.getPosition().getLatDeg(), loadedWindFix.getPosition().getLatDeg(), 0); + assertEquals(storedWindFix.getPosition().getLngDeg(), loadedWindFix.getPosition().getLngDeg(), 0); + assertEquals(storedWindFix.getKnots(), loadedWindFix.getKnots(), 0); + assertNotNull(storedWindFix.getBearing()); + assertNotNull(loadedWindFix.getBearing()); + assertEquals(storedWindFix.getBearing().getDegrees(), loadedWindFix.getBearing().getDegrees(), 0); + } + + protected Wind createWindFix() { + Position position = new DegreePosition(23.0313, 2.2344); + Bearing bearing = new DegreeBearingImpl(25.5); + SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(10.4, bearing); + return new WindImpl(position, now, speedBearing); + } } 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 aa4084984a6..70d89f6a923 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 @@ -35,7 +35,6 @@ 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.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.EventImpl; import com.sap.sailing.domain.base.impl.FleetImpl; @@ -87,7 +86,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final String[] courseAreaNames = new String[] { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrott" }; final Venue venue = new VenueImpl(venueName); for (String courseAreaName : courseAreaNames) { - CourseArea courseArea = new CourseAreaImpl(courseAreaName, UUID.randomUUID()); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); venue.addCourseArea(courseArea); } MongoObjectFactory mof = MongoFactory.INSTANCE.getMongoObjectFactory(getMongoService()); @@ -115,7 +114,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest final String publicationUrl = "http://myevent.sapsailing.com"; final String courseAreaName = "Alpha"; final Venue venue = new VenueImpl(venueName); - CourseArea courseArea = new CourseAreaImpl(courseAreaName, UUID.randomUUID()); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); venue.addCourseArea(courseArea); MongoObjectFactory mof = MongoFactory.INSTANCE.getMongoObjectFactory(getMongoService()); 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 3b536af2ce4..f26e0bf0b9a 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 @@ -1,6 +1,7 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.io.Serializable; import java.net.UnknownHostException; @@ -11,6 +12,9 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; import com.mongodb.MongoException; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; @@ -28,10 +32,13 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.persistence.MongoFactory; import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; +import com.sap.sailing.domain.persistence.impl.FieldNames; +import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; +import com.sap.sailing.domain.persistence.impl.MongoUtils; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent; @@ -43,10 +50,13 @@ import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoDBTest { @@ -89,6 +99,28 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD return loadedLeaderboard.getRaceColumnByName(raceColumnName).getRaceLog(loadedDefaultFleet); } + @Test + public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogProtestStartTimeEvent() { + RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, 0, MillisecondsTimePoint.now()); + + addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogProtestStartTimeEvent actualEvent = (RaceLogProtestStartTimeEvent) loadedEvent; + assertEquals(expectedEvent.getTimePoint(), actualEvent.getTimePoint()); + assertEquals(expectedEvent.getPassId(), actualEvent.getPassId()); + assertEquals(expectedEvent.getId(), actualEvent.getId()); + assertEquals(expectedEvent.getProtestStartTime(), actualEvent.getProtestStartTime()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } + @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogStartProcedureChangedEvent() { RaceLogStartProcedureChangedEvent expectedEvent = RaceLogEventFactory.INSTANCE.createStartProcedureChangedEvent(now, 0, StartProcedureType.ESS); @@ -177,8 +209,12 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0); + public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { + Competitor storedCompetitor = DomainFactory.INSTANCE.createCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", null, null); + List> storedPositioningList = new ArrayList>(); + storedPositioningList.add(new Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); + + RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, storedPositioningList); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -197,6 +233,50 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD } } + @Test + public void testStoreAndRetrieveSimpleLeaderboardWithBackwardsCompatibleRaceLogFinishPositioningConfirmedEvent() { + RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, null); + + createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry(); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; + assertEquals(now, loadedConfirmedEvent.getTimePoint()); + assertEquals(0, loadedConfirmedEvent.getPassId()); + assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertNull(event.getPositionedCompetitors()); + assertNull(loadedConfirmedEvent.getPositionedCompetitors()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } + + private void createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry() { + Fleet defaultFleet = leaderboard.getFleet(null); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + mongoObjectFactory.storeLeaderboard(leaderboard); + + DBObject result = new BasicDBObject(); + result.put(FieldNames.TIME_AS_MILLIS.name(), now.asMillis()); + result.put(FieldNames.RACE_LOG_EVENT_CREATED_AT.name(), now.asMillis()); + result.put(FieldNames.RACE_LOG_EVENT_ID.name(), UUID.randomUUID()); + result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), 0); + result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), new BasicDBList()); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); + + DBObject raceLogResult = new BasicDBObject(); + raceLogResult.put(FieldNames.RACE_LOG_IDENTIFIER.name(), MongoUtils.escapeDollarAndDot(raceColumn.getRaceLogIdentifier(defaultFleet).getIdentifier().toString())); + raceLogResult.put(FieldNames.RACE_LOG_EVENT.name(), result); + + MongoObjectFactoryImpl factoryImpl = (MongoObjectFactoryImpl) mongoObjectFactory; + factoryImpl.getRaceLogCollection().insert(raceLogResult); + } + @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.createCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", null, null); @@ -343,5 +423,28 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD loadedRaceLog.unlockAfterRead(); } } + + @Test + public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogWindFixEvent() { + Wind wind = createWindFix(); + RaceLogWindFixEvent event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, 0, wind); + + addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogWindFixEvent windEvent = (RaceLogWindFixEvent) loadedEvent; + assertEquals(event.getTimePoint(), windEvent.getTimePoint()); + assertEquals(event.getPassId(), windEvent.getPassId()); + assertEquals(event.getId(), windEvent.getId()); + compareWind(event.getWindFix(), windEvent.getWindFix()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } } 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 a0bb8caafb0..52fdcbd6aa2 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 @@ -1,6 +1,7 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.io.Serializable; import java.net.UnknownHostException; @@ -12,6 +13,9 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; import com.mongodb.MongoException; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -38,6 +42,9 @@ import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; +import com.sap.sailing.domain.persistence.impl.FieldNames; +import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl; +import com.sap.sailing.domain.persistence.impl.MongoUtils; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent; @@ -49,10 +56,13 @@ import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest { @@ -121,7 +131,29 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogStartProcedureChangedEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogProtestStartTimeEvent() { + RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, 0, MillisecondsTimePoint.now()); + + addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogProtestStartTimeEvent actualEvent = (RaceLogProtestStartTimeEvent) loadedEvent; + assertEquals(expectedEvent.getTimePoint(), actualEvent.getTimePoint()); + assertEquals(expectedEvent.getPassId(), actualEvent.getPassId()); + assertEquals(expectedEvent.getId(), actualEvent.getId()); + assertEquals(expectedEvent.getProtestStartTime(), actualEvent.getProtestStartTime()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } + + @Test + public void testStoreAndRetrieveRegattaWithRaceLogStartProcedureChangedEvent() { RaceLogStartProcedureChangedEvent expectedEvent = RaceLogEventFactory.INSTANCE.createStartProcedureChangedEvent(now, 0, StartProcedureType.ESS); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); @@ -143,7 +175,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogPathfinderEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogPathfinderEvent() { RaceLogPathfinderEvent expectedEvent = RaceLogEventFactory.INSTANCE.createPathfinderEvent(now, 0, "GER 20"); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); @@ -165,7 +197,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogGateLineOpeningTimeEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogGateLineOpeningTimeEvent() { RaceLogGateLineOpeningTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createGateLineOpeningTimeEvent(now, 0, 1234l); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); @@ -187,7 +219,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogPassChangeEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogPassChangeEvent() { RaceLogPassChangeEvent event = RaceLogEventFactory.INSTANCE.createPassChangeEvent(now, 0); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -208,7 +240,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() { Competitor storedCompetitor = DomainFactory.INSTANCE.createCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", null, null); List> storedPositioningList = new ArrayList>(); storedPositioningList.add(new Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); @@ -238,8 +270,12 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningConfirmedEvent() { - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0); + public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() { + Competitor storedCompetitor = DomainFactory.INSTANCE.createCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", null, null); + List> storedPositioningList = new ArrayList>(); + storedPositioningList.add(new Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); + + RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, storedPositioningList); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -252,6 +288,11 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest assertEquals(event.getTimePoint(), loadedConfirmedEvent.getTimePoint()); assertEquals(event.getPassId(), loadedConfirmedEvent.getPassId()); assertEquals(event.getId(), loadedConfirmedEvent.getId()); + assertEquals(event.getInvolvedBoats().size(), loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(event.getPositionedCompetitors().size(), loadedConfirmedEvent.getPositionedCompetitors().size()); + assertEquals(event.getPositionedCompetitors().get(0).getA(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getA()); + assertEquals(event.getPositionedCompetitors().get(0).getB(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getB()); + assertEquals(event.getPositionedCompetitors().get(0).getC().name(), loadedConfirmedEvent.getPositionedCompetitors().get(0).getC().name()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { loadedRaceLog.unlockAfterRead(); @@ -259,7 +300,52 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogCourseAreaChangeEvent() { + public void testStoreAndRetrieveRegattaWithBackwardsCompatibleRaceLogFinishPositioningConfirmedEvent() { + RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, null); + + createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry(); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; + assertEquals(now, loadedConfirmedEvent.getTimePoint()); + assertEquals(0, loadedConfirmedEvent.getPassId()); + assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertNull(event.getPositionedCompetitors()); + assertNull(loadedConfirmedEvent.getPositionedCompetitors()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } + + private void createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry() { + Series series = regatta.getSeriesByName(seriesName); + Fleet fleet = series.getFleetByName(yellowFleetName); + RaceColumn raceColumn = series.getRaceColumnByName(raceColumnName); + mongoObjectFactory.storeRegatta(regatta); + + DBObject result = new BasicDBObject(); + result.put(FieldNames.TIME_AS_MILLIS.name(), now.asMillis()); + result.put(FieldNames.RACE_LOG_EVENT_CREATED_AT.name(), now.asMillis()); + result.put(FieldNames.RACE_LOG_EVENT_ID.name(), UUID.randomUUID()); + result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), 0); + result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), new BasicDBList()); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); + + DBObject raceLogResult = new BasicDBObject(); + raceLogResult.put(FieldNames.RACE_LOG_IDENTIFIER.name(), MongoUtils.escapeDollarAndDot(raceColumn.getRaceLogIdentifier(fleet).getIdentifier().toString())); + raceLogResult.put(FieldNames.RACE_LOG_EVENT.name(), result); + + MongoObjectFactoryImpl factoryImpl = (MongoObjectFactoryImpl) mongoObjectFactory; + factoryImpl.getRaceLogCollection().insert(raceLogResult); + } + + @Test + public void testStoreAndRetrieveRegattaWithRaceLogCourseAreaChangeEvent() { final UUID uuid = UUID.randomUUID(); RaceLogCourseAreaChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseAreaChangedEvent(now, 0, uuid); @@ -282,7 +368,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogRaceStatusEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogRaceStatusEvent() { RaceLogRaceStatusEvent event = RaceLogEventFactory.INSTANCE.createRaceStatusEvent(now, 0, RaceLogRaceStatus.SCHEDULED); @@ -305,7 +391,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogStartTimeEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogStartTimeEvent() { RaceLogStartTimeEvent event = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, 0, now); @@ -329,7 +415,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFlagEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogFlagEvent() { RaceLogFlagEvent event = RaceLogEventFactory.INSTANCE.createFlagEvent(now, 0, Flags.FIRSTSUBSTITUTE, Flags.NONE, true); @@ -353,7 +439,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest } @Test - public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogCourseDesignChangedEvent() { + public void testStoreAndRetrieveRegattaWithRaceLogCourseDesignChangedEvent() { CourseBase course = createCourseBase(); RaceLogCourseDesignChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now, 0, course); @@ -374,5 +460,28 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends RaceLogMongoDBTest loadedRaceLog.unlockAfterRead(); } } + + @Test + public void testStoreAndRetrieveRegattaWithRaceLogWindFixEvent() { + Wind wind = createWindFix(); + RaceLogWindFixEvent event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, 0, wind); + + addAndStoreRaceLogEvent(regatta, raceColumnName, event); + + RaceLog loadedRaceLog = retrieveRaceLog(); + + loadedRaceLog.lockForRead(); + try { + RaceLogEvent loadedEvent = loadedRaceLog.getFirstRawFix(); + RaceLogWindFixEvent windEvent = (RaceLogWindFixEvent) loadedEvent; + assertEquals(event.getTimePoint(), windEvent.getTimePoint()); + assertEquals(event.getPassId(), windEvent.getPassId()); + assertEquals(event.getId(), windEvent.getId()); + compareWind(event.getWindFix(), windEvent.getWindFix()); + assertEquals(1, Util.size(loadedRaceLog.getFixes())); + } finally { + loadedRaceLog.unlockAfterRead(); + } + } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerChooserTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java similarity index 65% rename from java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerChooserTest.java rename to java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 724babbc022..4e5ec17ded8 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerChooserTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -1,142 +1,166 @@ -package com.sap.sailing.server.gateway.serialization.test.racelog; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.StartProcedureType; -import com.sap.sailing.domain.racelog.RaceLogEvent; -import com.sap.sailing.domain.racelog.RaceLogEventFactory; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.server.gateway.serialization.racelog.RaceLogEventSerializerChooser; -import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializerChooserImpl; - -public class RaceLogEventSerializerChooserTest { - - private RaceLogEventSerializerChooser chooser; - - private JsonSerializer flagEventSerializer; - private JsonSerializer startTimeSerializer; - private JsonSerializer raceStatusSerializer; - private JsonSerializer courseAreaChangedEventSerializer; - private JsonSerializer passChangedSerializer; - private JsonSerializer courseDesignChangedEventSerializer; - private JsonSerializer finishPositioningListChangedEventSerializer; - private JsonSerializer finishPositioningConfirmedEventSerializer; - private JsonSerializer pathfinderEventSerializer; - private JsonSerializer gateLineOpeningTimeEventSerializer; - private JsonSerializer startProcedureTypeChangedEventSerializer; - - private RaceLogEventFactory factory; - - @SuppressWarnings("unchecked") - @Before - public void setUp() { - flagEventSerializer = mock(JsonSerializer.class); - startTimeSerializer = mock(JsonSerializer.class); - raceStatusSerializer = mock(JsonSerializer.class); - courseAreaChangedEventSerializer = mock(JsonSerializer.class); - passChangedSerializer = mock(JsonSerializer.class); - courseDesignChangedEventSerializer = mock(JsonSerializer.class); - finishPositioningListChangedEventSerializer = mock(JsonSerializer.class); - finishPositioningConfirmedEventSerializer = mock(JsonSerializer.class); - pathfinderEventSerializer = mock(JsonSerializer.class); - gateLineOpeningTimeEventSerializer = mock(JsonSerializer.class); - startProcedureTypeChangedEventSerializer = mock(JsonSerializer.class); - - chooser = new RaceLogEventSerializerChooserImpl( - flagEventSerializer, - startTimeSerializer, - raceStatusSerializer, - courseAreaChangedEventSerializer, - passChangedSerializer, - courseDesignChangedEventSerializer, - finishPositioningListChangedEventSerializer, - finishPositioningConfirmedEventSerializer, - pathfinderEventSerializer, gateLineOpeningTimeEventSerializer, - startProcedureTypeChangedEventSerializer); - - factory = RaceLogEventFactory.INSTANCE; - } - - @Test - public void testChoosesFlagEventSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFlagEvent(null, 0, null, null, false); - assertEquals(flagEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesStartTimeSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createStartTimeEvent(null, 0, null); - assertEquals(startTimeSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesRaceStatusSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createRaceStatusEvent(null, 0, RaceLogRaceStatus.SCHEDULED); - assertEquals(raceStatusSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesCourseAreaChangedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createCourseAreaChangedEvent(null, 0, null); - assertEquals(courseAreaChangedEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesPassChangedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createPassChangeEvent(null, 0); - assertEquals(passChangedSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesCourseDesignChangedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createCourseDesignChangedEvent(null, 0, null); - assertEquals(courseDesignChangedEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesFinishPositioningListChangedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFinishPositioningListChangedEvent(null, 0, null); - assertEquals(finishPositioningListChangedEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesFinishPositioningConfirmedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFinishPositioningConfirmedEvent(null, 0); - assertEquals(finishPositioningConfirmedEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesPathfinderSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createPathfinderEvent(null, 0, "GER 20"); - assertEquals(pathfinderEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testChoosesGateLineOpeningTimeSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createGateLineOpeningTimeEvent(null, 0, new Long(0)); - assertEquals(gateLineOpeningTimeEventSerializer, chooser.getSerializer(event)); - } - - @Test - public void testStartProcedureTypeChangedSerializer() { - // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createStartProcedureChangedEvent(null, 0, StartProcedureType.ESS); - assertEquals(startProcedureTypeChangedEventSerializer, chooser.getSerializer(event)); - } - -} +package com.sap.sailing.server.gateway.serialization.test.racelog; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.racelog.StartProcedureType; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogEventFactory; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer; + +public class RaceLogEventSerializerTest { + + private RaceLogEventSerializer serializer; + + private JsonSerializer flagEventSerializer; + private JsonSerializer startTimeSerializer; + private JsonSerializer raceStatusSerializer; + private JsonSerializer courseAreaChangedEventSerializer; + private JsonSerializer passChangedSerializer; + private JsonSerializer courseDesignChangedEventSerializer; + private JsonSerializer finishPositioningListChangedEventSerializer; + private JsonSerializer finishPositioningConfirmedEventSerializer; + private JsonSerializer pathfinderEventSerializer; + private JsonSerializer gateLineOpeningTimeEventSerializer; + private JsonSerializer startProcedureTypeChangedEventSerializer; + private JsonSerializer protestStartTimeEventSerializer; + private JsonSerializer windFixEventSerializer; + + private RaceLogEventFactory factory; + + @SuppressWarnings("unchecked") + @Before + public void setUp() { + flagEventSerializer = mock(JsonSerializer.class); + startTimeSerializer = mock(JsonSerializer.class); + raceStatusSerializer = mock(JsonSerializer.class); + courseAreaChangedEventSerializer = mock(JsonSerializer.class); + passChangedSerializer = mock(JsonSerializer.class); + courseDesignChangedEventSerializer = mock(JsonSerializer.class); + finishPositioningListChangedEventSerializer = mock(JsonSerializer.class); + finishPositioningConfirmedEventSerializer = mock(JsonSerializer.class); + pathfinderEventSerializer = mock(JsonSerializer.class); + gateLineOpeningTimeEventSerializer = mock(JsonSerializer.class); + startProcedureTypeChangedEventSerializer = mock(JsonSerializer.class); + protestStartTimeEventSerializer = mock(JsonSerializer.class); + windFixEventSerializer = mock(JsonSerializer.class); + + serializer = new RaceLogEventSerializer(flagEventSerializer, startTimeSerializer, raceStatusSerializer, + courseAreaChangedEventSerializer, passChangedSerializer, courseDesignChangedEventSerializer, + finishPositioningListChangedEventSerializer, finishPositioningConfirmedEventSerializer, + pathfinderEventSerializer, gateLineOpeningTimeEventSerializer, + startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer); + + factory = RaceLogEventFactory.INSTANCE; + } + + @Test + public void testChoosesFlagEventSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createFlagEvent(null, 0, null, null, false); + serializer.serialize(event); + verify(flagEventSerializer).serialize(event); + } + + @Test + public void testChoosesStartTimeSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createStartTimeEvent(null, 0, null); + serializer.serialize(event); + verify(startTimeSerializer).serialize(event); + } + + @Test + public void testChoosesRaceStatusSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createRaceStatusEvent(null, 0, RaceLogRaceStatus.SCHEDULED); + serializer.serialize(event); + verify(raceStatusSerializer).serialize(event); + } + + @Test + public void testChoosesCourseAreaChangedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createCourseAreaChangedEvent(null, 0, null); + serializer.serialize(event); + verify(courseAreaChangedEventSerializer).serialize(event); + } + + @Test + public void testChoosesPassChangedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createPassChangeEvent(null, 0); + serializer.serialize(event); + verify(passChangedSerializer).serialize(event); + } + + @Test + public void testChoosesCourseDesignChangedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createCourseDesignChangedEvent(null, 0, null); + serializer.serialize(event); + verify(courseDesignChangedEventSerializer).serialize(event); + } + + @Test + public void testChoosesFinishPositioningListChangedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createFinishPositioningListChangedEvent(null, 0, null); + serializer.serialize(event); + verify(finishPositioningListChangedEventSerializer).serialize(event); + } + + @Test + public void testChoosesFinishPositioningConfirmedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createFinishPositioningConfirmedEvent(null, 0, null); + serializer.serialize(event); + verify(finishPositioningConfirmedEventSerializer).serialize(event); + } + + @Test + public void testChoosesPathfinderSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createPathfinderEvent(null, 0, "GER 20"); + serializer.serialize(event); + verify(pathfinderEventSerializer).serialize(event); + } + + @Test + public void testChoosesGateLineOpeningTimeSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createGateLineOpeningTimeEvent(null, 0, new Long(0)); + serializer.serialize(event); + verify(gateLineOpeningTimeEventSerializer).serialize(event); + } + + @Test + public void testStartProcedureTypeChangedSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createStartProcedureChangedEvent(null, 0, StartProcedureType.ESS); + serializer.serialize(event); + verify(startProcedureTypeChangedEventSerializer).serialize(event); + } + + @Test + public void testProtestStartTimeSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createProtestStartTimeEvent(null, 0, null); + serializer.serialize(event); + verify(protestStartTimeEventSerializer).serialize(event); + } + + @Test + public void testWindFixSerializer() { + // we use the real event type here because we do not want to re-implement the dispatching. + RaceLogEvent event = factory.createWindFixEvent(null, 0, null); + serializer.serialize(event); + verify(windFixEventSerializer).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 new file mode 100644 index 00000000000..a3f89adcdb5 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -0,0 +1,105 @@ +package com.sap.sailing.server.gateway.serialization.test.racelog; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.domain.common.impl.Util.Triple; +import com.sap.sailing.domain.racelog.RaceLogEventFactory; +import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer; +import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogFinishPositioningConfirmedEventDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogFinishPositioningConfirmedEventSerializer; + +public class RaceLogFinishPositioningConfirmedEventSerializerTest { + + private RaceLogFinishPositioningConfirmedEventSerializer serializer; + private RaceLogFinishPositioningConfirmedEventDeserializer deserializer; + private RaceLogFinishPositioningConfirmedEvent event; + private TimePoint now; + private List> positioningList; + + @Before + public void setUp() { + SharedDomainFactory factory = DomainFactory.INSTANCE; + serializer = new RaceLogFinishPositioningConfirmedEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer(new PersonJsonSerializer()))); + deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorDeserializer(factory)); + + now = MillisecondsTimePoint.now(); + positioningList = new ArrayList<>(); + } + + @Test + public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEvent() throws JsonDeserializationException { + positioningList.add(new Triple(UUID.randomUUID(), "SAP Extreme", MaxPointsReason.NONE)); + event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, positioningList); + JSONObject jsonConfirmationEvent = serializer.serialize(event); + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); + + assertEquals(event.getId(), deserializedEvent.getId()); + assertEquals(event.getPassId(), deserializedEvent.getPassId()); + assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); + assertEquals(0, Util.size(event.getInvolvedBoats())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertNotNull(event.getPositionedCompetitors()); + assertNotNull(deserializedEvent.getPositionedCompetitors()); + assertEquals(1, event.getPositionedCompetitors().size()); + assertEquals(1, deserializedEvent.getPositionedCompetitors().size()); + assertEquals(event.getPositionedCompetitors().get(0).getA(), deserializedEvent.getPositionedCompetitors().get(0).getA()); + assertEquals(event.getPositionedCompetitors().get(0).getB(), deserializedEvent.getPositionedCompetitors().get(0).getB()); + assertEquals(event.getPositionedCompetitors().get(0).getC(), deserializedEvent.getPositionedCompetitors().get(0).getC()); + } + + @Test + public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEventWithoutPositioningBackwardsCompatible() throws JsonDeserializationException { + event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, null); + JSONObject jsonConfirmationEvent = serializer.serialize(event); + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); + + assertEquals(event.getId(), deserializedEvent.getId()); + assertEquals(event.getPassId(), deserializedEvent.getPassId()); + assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); + assertEquals(0, Util.size(event.getInvolvedBoats())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertNull(event.getPositionedCompetitors()); + assertNotNull(deserializedEvent.getPositionedCompetitors()); + assertEquals(0, deserializedEvent.getPositionedCompetitors().size()); + } + + @Test + public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEventWithEmptyPositioning() throws JsonDeserializationException { + event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, 0, positioningList); + JSONObject jsonConfirmationEvent = serializer.serialize(event); + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); + + assertEquals(event.getId(), deserializedEvent.getId()); + assertEquals(event.getPassId(), deserializedEvent.getPassId()); + assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); + assertEquals(0, Util.size(event.getInvolvedBoats())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertNotNull(event.getPositionedCompetitors()); + assertNotNull(deserializedEvent.getPositionedCompetitors()); + assertEquals(0, event.getPositionedCompetitors().size()); + assertEquals(0, deserializedEvent.getPositionedCompetitors().size()); + } + +} 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 new file mode 100644 index 00000000000..3c9a69bac14 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java @@ -0,0 +1,90 @@ +package com.sap.sailing.server.gateway.serialization.test.racelog; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.SpeedWithBearing; +import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.domain.racelog.RaceLogEventFactory; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.domain.tracking.impl.WindImpl; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogWindFixEventDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogWindFixEventSerializer; + +public class RaceLogWindFixEventSerializerTest { + + private RaceLogWindFixEventSerializer serializer; + private RaceLogWindFixEventDeserializer deserializer; + private RaceLogWindFixEvent event; + private TimePoint now; + + @Before + public void setUp() { + SharedDomainFactory factory = DomainFactory.INSTANCE; + serializer = new RaceLogWindFixEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer(new PersonJsonSerializer())), + new WindJsonSerializer(new PositionJsonSerializer())); + deserializer = new RaceLogWindFixEventDeserializer(new CompetitorDeserializer(factory), + new WindJsonDeserializer(new PositionJsonDeserializer())); + + now = MillisecondsTimePoint.now(); + + event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, 0, createWindFix()); + } + + @Test + public void testSerializeAndDeserializeRaceLogWindFixEvent() throws JsonDeserializationException { + JSONObject jsonWindFixEvent = serializer.serialize(event); + RaceLogWindFixEvent deserializedEvent = (RaceLogWindFixEvent) deserializer.deserialize(jsonWindFixEvent); + + assertEquals(event.getId(), deserializedEvent.getId()); + assertEquals(event.getPassId(), deserializedEvent.getPassId()); + assertEquals(event.getTimePoint(), deserializedEvent.getTimePoint()); + assertEquals(0, Util.size(event.getInvolvedBoats())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + + compareWind(event.getWindFix(), deserializedEvent.getWindFix()); + } + + private void compareWind(Wind serializedWindFix, Wind deserializedWindFix) { + assertEquals(serializedWindFix.getTimePoint(), deserializedWindFix.getTimePoint()); + assertNotNull(serializedWindFix.getPosition()); + assertNotNull(deserializedWindFix.getPosition()); + assertEquals(serializedWindFix.getPosition().getLatDeg(), deserializedWindFix.getPosition().getLatDeg(), 0); + assertEquals(serializedWindFix.getPosition().getLngDeg(), deserializedWindFix.getPosition().getLngDeg(), 0); + assertEquals(serializedWindFix.getKnots(), deserializedWindFix.getKnots(), 0); + assertNotNull(serializedWindFix.getBearing()); + assertNotNull(deserializedWindFix.getBearing()); + assertEquals(serializedWindFix.getBearing().getDegrees(), deserializedWindFix.getBearing().getDegrees(), 0); + } + + private Wind createWindFix() { + Position position = new DegreePosition(23.0313, 2.2344); + Bearing bearing = new DegreeBearingImpl(25.5); + SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(10.4, bearing); + return new WindImpl(position, now, speedBearing); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF index 533b5a76c9c..74da3dfb149 100644 --- a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF @@ -17,5 +17,4 @@ Export-Package: com.sap.sailing.server.gateway.deserialization, com.sap.sailing.server.gateway.serialization.coursedata.impl, com.sap.sailing.server.gateway.serialization.impl, com.sap.sailing.server.gateway.serialization.racegroup.impl, - com.sap.sailing.server.gateway.serialization.racelog, com.sap.sailing.server.gateway.serialization.racelog.impl diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/CourseDataDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/CourseDataDeserializer.java index b3982081551..b8d25056913 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/CourseDataDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/coursedata/impl/CourseDataDeserializer.java @@ -26,7 +26,7 @@ public class CourseDataDeserializer implements JsonDeserializer { @Override public CourseBase deserialize(JSONObject object) throws JsonDeserializationException { - String courseName = object.get(CourseBaseJsonSerializer.FIELD_NAME).toString(); + String courseName = (String) object.get(CourseBaseJsonSerializer.FIELD_NAME); JSONArray jsonWaypoints = (JSONArray) object.get(CourseBaseJsonSerializer.FIELD_WAYPOINTS); List waypoints = new ArrayList(); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ColorDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ColorDeserializer.java index 099d9d5a727..b78f68f840a 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ColorDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/ColorDeserializer.java @@ -9,12 +9,11 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; public class ColorDeserializer implements JsonDeserializer { - public Color deserialize(JSONObject object) - throws JsonDeserializationException { - Number red = (Number) object.get("r"); - Number green = (Number) object.get("g"); - Number blue = (Number) object.get("b"); - return new RGBColor(red.intValue(), green.intValue(), blue.intValue()); - } - + public Color deserialize(JSONObject object) throws JsonDeserializationException { + Number red = (Number) object.get("r"); + Number green = (Number) object.get("g"); + Number blue = (Number) object.get("b"); + return new RGBColor(red.intValue(), green.intValue(), blue.intValue()); + } + } \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java index 975f9561806..0ebd92596ae 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/CourseAreaJsonDeserializer.java @@ -5,19 +5,25 @@ import java.io.Serializable; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; +import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.CourseAreaJsonSerializer; public class CourseAreaJsonDeserializer implements JsonDeserializer { - public CourseArea deserialize(JSONObject object) - throws JsonDeserializationException { - String name = object.get(CourseAreaJsonSerializer.FIELD_NAME).toString(); - Serializable id = (Serializable) object.get(CourseAreaJsonSerializer.FIELD_ID); - - return new CourseAreaImpl(name, Helpers.tryUuidConversion(id)); - } + private SharedDomainFactory factory; + + public CourseAreaJsonDeserializer(SharedDomainFactory factory) { + this.factory = factory; + } + + public CourseArea deserialize(JSONObject object) + throws JsonDeserializationException { + String name = object.get(CourseAreaJsonSerializer.FIELD_NAME).toString(); + Serializable id = (Serializable) object.get(CourseAreaJsonSerializer.FIELD_ID); + + return factory.getOrCreateCourseArea(Helpers.tryUuidConversion(id), name); + } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/PositionJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/PositionJsonDeserializer.java new file mode 100644 index 00000000000..47322be68b7 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/PositionJsonDeserializer.java @@ -0,0 +1,19 @@ +package com.sap.sailing.server.gateway.deserialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.DegreePosition; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; + +public class PositionJsonDeserializer implements JsonDeserializer { + + public Position deserialize(JSONObject object) throws JsonDeserializationException { + Number latitudeDeg = (Number) object.get(PositionJsonSerializer.FIELD_LATITUDE_DEG); + Number longitudeDeg = (Number) object.get(PositionJsonSerializer.FIELD_LONGITUDE_DEG); + return new DegreePosition(latitudeDeg.doubleValue(), longitudeDeg.doubleValue()); + } + +} \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/VenueJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/VenueJsonDeserializer.java index 96a7ba2ef48..6530df399ef 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/VenueJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/VenueJsonDeserializer.java @@ -11,27 +11,27 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer; public class VenueJsonDeserializer implements JsonDeserializer { - private JsonDeserializer courseAreaDeserializer; - - public VenueJsonDeserializer(JsonDeserializer courseAreaDeserializer) { - this.courseAreaDeserializer = courseAreaDeserializer; - } - - public Venue deserialize(JSONObject object) - throws JsonDeserializationException { - - String name = object.get(VenueJsonSerializer.FIELD_NAME).toString(); - Venue venue = new VenueImpl(name); - - JSONArray courseAreaArray = Helpers.getNestedArraySafe( - object, - VenueJsonSerializer.FIELD_COURSE_AREAS); - for (Object element : courseAreaArray) { - JSONObject courseAreaObject = Helpers.toJSONObjectSafe(element); - venue.addCourseArea(courseAreaDeserializer.deserialize(courseAreaObject)); - } - - return venue; - } + private JsonDeserializer courseAreaDeserializer; + + public VenueJsonDeserializer(JsonDeserializer courseAreaDeserializer) { + this.courseAreaDeserializer = courseAreaDeserializer; + } + + public Venue deserialize(JSONObject object) + throws JsonDeserializationException { + + String name = object.get(VenueJsonSerializer.FIELD_NAME).toString(); + Venue venue = new VenueImpl(name); + + JSONArray courseAreaArray = Helpers.getNestedArraySafe( + object, + VenueJsonSerializer.FIELD_COURSE_AREAS); + for (Object element : courseAreaArray) { + JSONObject courseAreaObject = Helpers.toJSONObjectSafe(element); + venue.addCourseArea(courseAreaDeserializer.deserialize(courseAreaObject)); + } + + return venue; + } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/WindJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/WindJsonDeserializer.java new file mode 100644 index 00000000000..e6bdb98fb09 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/WindJsonDeserializer.java @@ -0,0 +1,40 @@ +package com.sap.sailing.server.gateway.deserialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.SpeedWithBearing; +import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.DegreeBearingImpl; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.domain.tracking.impl.WindImpl; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; + +public class WindJsonDeserializer implements JsonDeserializer { + private JsonDeserializer positionDeserializer; + + public WindJsonDeserializer(JsonDeserializer positionDeserializer) { + this.positionDeserializer = positionDeserializer; + } + + public Wind deserialize(JSONObject object) throws JsonDeserializationException { + + JSONObject positionJsonObject = Helpers.getNestedObjectSafe(object, WindJsonSerializer.FIELD_POSITION); + Position position = positionDeserializer.deserialize(positionJsonObject); + + Number timeStamp = (Number) object.get(WindJsonSerializer.FIELD_TIMEPOINT); + Number bearing = (Number) object.get(WindJsonSerializer.FIELD_BEARING); + Number speedInKnots = (Number) object.get(WindJsonSerializer.FIELD_SPEED_IN_KNOTS); + + Bearing degreeBearing = new DegreeBearingImpl(bearing.doubleValue()); + SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(speedInKnots.doubleValue(), degreeBearing); + Wind wind = new WindImpl(position, new MillisecondsTimePoint(timeStamp.longValue()), speedBearing); + + return wind; + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racegroup/impl/SeriesWithRowsDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racegroup/impl/SeriesWithRowsDeserializer.java index d4e53c65514..ab8078a91b9 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racegroup/impl/SeriesWithRowsDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racegroup/impl/SeriesWithRowsDeserializer.java @@ -15,26 +15,23 @@ import com.sap.sailing.server.gateway.serialization.racegroup.impl.RaceRowsOfSer public class SeriesWithRowsDeserializer implements JsonDeserializer { - private JsonDeserializer raceRowDeserializer; - - public SeriesWithRowsDeserializer(JsonDeserializer raceRowDeserializer) { - this.raceRowDeserializer = raceRowDeserializer; - } + private JsonDeserializer raceRowDeserializer; + + public SeriesWithRowsDeserializer(JsonDeserializer raceRowDeserializer) { + this.raceRowDeserializer = raceRowDeserializer; + } + + public SeriesWithRows deserialize(JSONObject object) throws JsonDeserializationException { + String name = object.get("name").toString(); + boolean isMedal = (Boolean) object.get("isMedal"); + + Collection rows = new ArrayList(); + for (Object fleetObject : Helpers.getNestedArraySafe(object, RaceRowsOfSeriesWithRowsSerializer.FIELD_FLEETS)) { + JSONObject fleetJson = Helpers.toJSONObjectSafe(fleetObject); + rows.add(raceRowDeserializer.deserialize(fleetJson)); + } + + return new SeriesWithRowsImpl(name, isMedal, rows); + } - public SeriesWithRows deserialize(JSONObject object) - throws JsonDeserializationException { - String name = object.get("name").toString(); - boolean isMedal = (Boolean) object.get("isMedal"); - - Collection rows = new ArrayList(); - for (Object fleetObject : Helpers.getNestedArraySafe( - object, - RaceRowsOfSeriesWithRowsSerializer.FIELD_FLEETS)) { - JSONObject fleetJson = Helpers.toJSONObjectSafe(fleetObject); - rows.add(raceRowDeserializer.deserialize(fleetJson)); - } - - return new SeriesWithRowsImpl(name, isMedal, rows); - } - } \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java index e79696c743d..155e392b036 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java @@ -13,6 +13,8 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.GateDeseri 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.CompetitorDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.BaseRaceLogEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogCourseAreaChangedEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogCourseDesignChangedEventSerializer; @@ -22,9 +24,11 @@ import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogFlagEven import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogGateLineOpeningTimeEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogPassChangeEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogPathfinderEventSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogProtestStartTimeEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogRaceStatusEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogStartProcedureChangedEventSerializer; import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogStartTimeEventSerializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogWindFixEventSerializer; public class RaceLogEventDeserializer implements JsonDeserializer { @@ -45,7 +49,11 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogPassChangeEventDeserializer(competitorDeserializer), new RaceLogPathFinderEventDeserializer(competitorDeserializer), new RaceLogGateLineOpeningTimeEventDeserializer(competitorDeserializer), - new RaceLogStartProcedureChangedEventDeserializer(competitorDeserializer)); + new RaceLogStartProcedureChangedEventDeserializer(competitorDeserializer), + new RaceLogProtestStartTimeEventDeserializer(competitorDeserializer), + new RaceLogWindFixEventDeserializer(competitorDeserializer, + new WindJsonDeserializer( + new PositionJsonDeserializer()))); } protected final JsonDeserializer flagEventDeserializer; @@ -59,6 +67,8 @@ public class RaceLogEventDeserializer implements JsonDeserializer protected final JsonDeserializer pathfinderEventDeserializer; protected final JsonDeserializer gateLineOpeningTimeEventDeserializer; protected final JsonDeserializer startProcedureChangedEventDeserializer; + protected final JsonDeserializer protestStartTimeEventDeserializer; + protected final JsonDeserializer windFixEventDeserializer; public RaceLogEventDeserializer(JsonDeserializer flagEventDeserializer, JsonDeserializer startTimeEventDeserializer, @@ -70,7 +80,9 @@ public class RaceLogEventDeserializer implements JsonDeserializer JsonDeserializer passChangeEventDeserializer, JsonDeserializer pathfinderEventDeserializer, JsonDeserializer gateLineOpeningTimeEventDeserializer, - JsonDeserializer startProcedureChangedEventDeserializer) { + JsonDeserializer startProcedureChangedEventDeserializer, + JsonDeserializer protestStartTimeEventDeserializer, + JsonDeserializer windFixEventDeserializer) { this.flagEventDeserializer = flagEventDeserializer; this.startTimeEventDeserializer = startTimeEventDeserializer; this.raceStatusEventDeserializer = raceStatusEventDeserializer; @@ -82,6 +94,8 @@ public class RaceLogEventDeserializer implements JsonDeserializer this.pathfinderEventDeserializer = pathfinderEventDeserializer; this.gateLineOpeningTimeEventDeserializer = gateLineOpeningTimeEventDeserializer; this.startProcedureChangedEventDeserializer = startProcedureChangedEventDeserializer; + this.protestStartTimeEventDeserializer = protestStartTimeEventDeserializer; + this.windFixEventDeserializer = windFixEventDeserializer; } protected JsonDeserializer getDeserializer(JSONObject object) throws JsonDeserializationException { @@ -109,6 +123,10 @@ public class RaceLogEventDeserializer implements JsonDeserializer return gateLineOpeningTimeEventDeserializer; } else if (type.equals(RaceLogStartProcedureChangedEventSerializer.VALUE_CLASS)) { return startProcedureChangedEventDeserializer; + } else if (type.equals(RaceLogProtestStartTimeEventSerializer.VALUE_CLASS)) { + return protestStartTimeEventDeserializer; + } else if (type.equals(RaceLogWindFixEventSerializer.VALUE_CLASS)) { + return windFixEventDeserializer; } throw new JsonDeserializationException(String.format("There is no deserializer defined for event type %s.", diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java index 910df8c5846..870c60e1c0d 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java @@ -1,15 +1,21 @@ package com.sap.sailing.server.gateway.deserialization.racelog.impl; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; +import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogFinishPositioningConfirmedEventSerializer; public class RaceLogFinishPositioningConfirmedEventDeserializer extends BaseRaceLogEventDeserializer { @@ -20,8 +26,31 @@ public class RaceLogFinishPositioningConfirmedEventDeserializer extends BaseRace @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { + + JSONArray jsonPositionedCompetitors = Helpers.getNestedArraySafe(object, RaceLogFinishPositioningConfirmedEventSerializer.FIELD_POSITIONED_COMPETITORS); + List> positionedCompetitors = deserializePositionedCompetitors(jsonPositionedCompetitors); - return factory.createFinishPositioningConfirmedEvent(createdAt, timePoint, id, competitors, passId); + return factory.createFinishPositioningConfirmedEvent(createdAt, timePoint, id, competitors, passId, positionedCompetitors); + } + + private List> deserializePositionedCompetitors(JSONArray jsonPositionedCompetitors) throws JsonDeserializationException { + List> positionedCompetitors = new ArrayList>(); + + for (Object object : jsonPositionedCompetitors) { + JSONObject jsonPositionedCompetitor = Helpers.toJSONObjectSafe(object); + + Serializable competitorId = (Serializable) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_COMPETITOR_ID); + competitorId = Helpers.tryUuidConversion(competitorId); + String competitorName = (String) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_COMPETITOR_NAME); + + String maxPointsReasonName = (String) jsonPositionedCompetitor.get(RaceLogFinishPositioningConfirmedEventSerializer.FIELD_SCORE_CORRECTIONS_MAX_POINTS_REASON); + MaxPointsReason maxPointsReason = MaxPointsReason.valueOf(maxPointsReasonName); + + Triple positionedCompetitor = new Triple(competitorId, competitorName, maxPointsReason); + positionedCompetitors.add(positionedCompetitor); + } + + return positionedCompetitors; } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java new file mode 100644 index 00000000000..4d4e10206bb --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.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.base.Competitor; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogProtestStartTimeEventSerializer; + +public class RaceLogProtestStartTimeEventDeserializer extends BaseRaceLogEventDeserializer { + + public RaceLogProtestStartTimeEventDeserializer(JsonDeserializer competitorDeserializer) { + super(competitorDeserializer); + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, TimePoint timePoint, + int passId, List competitors) throws JsonDeserializationException { + Long protestStartTime = (Long) object.get(RaceLogProtestStartTimeEventSerializer.FIELD_PROTEST_START_TIME); + return factory.createProtestStartTimeEvent(createdAt, timePoint, id, competitors, passId, + new MillisecondsTimePoint(protestStartTime)); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java new file mode 100644 index 00000000000..38683db4b37 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java @@ -0,0 +1,36 @@ +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.base.Competitor; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogWindFixEventSerializer; + +public class RaceLogWindFixEventDeserializer extends BaseRaceLogEventDeserializer { + + private final JsonDeserializer windDeserializer; + + public RaceLogWindFixEventDeserializer(JsonDeserializer competitorDeserializer, JsonDeserializer windDeserializer) { + super(competitorDeserializer); + this.windDeserializer = windDeserializer; + } + + @Override + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, TimePoint timePoint, + int passId, List competitors) throws JsonDeserializationException { + JSONObject windJsonObject = Helpers.getNestedObjectSafe(object, RaceLogWindFixEventSerializer.FIELD_WIND); + + Wind wind = windDeserializer.deserialize(windJsonObject); + + return factory.createWindFixEvent(createdAt, timePoint, id, competitors, passId, wind); + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionJsonSerializer.java new file mode 100644 index 00000000000..a0624ac8555 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionJsonSerializer.java @@ -0,0 +1,21 @@ +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class PositionJsonSerializer implements JsonSerializer { + public static final String FIELD_LATITUDE_DEG = "latitude_deg"; + public static final String FIELD_LONGITUDE_DEG = "longitude_deg"; + + @Override + public JSONObject serialize(Position position) { + JSONObject result = new JSONObject(); + + result.put(FIELD_LATITUDE_DEG, position.getLatDeg()); + result.put(FIELD_LONGITUDE_DEG, position.getLngDeg()); + + return result; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionedMarkJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionedMarkJsonSerializer.java new file mode 100644 index 00000000000..30d237c07cb --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/PositionedMarkJsonSerializer.java @@ -0,0 +1,32 @@ +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.ControlPoint; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class PositionedMarkJsonSerializer implements JsonSerializer> { + public static final String FIELD_MARK = "mark"; + public static final String FIELD_POSITION = "position"; + + private final JsonSerializer markSerializer; + private final JsonSerializer positionSerializer; + + public PositionedMarkJsonSerializer(JsonSerializer markSerializer, JsonSerializer positionSerializer) { + this.markSerializer = markSerializer; + this.positionSerializer = positionSerializer; + } + + @Override + public JSONObject serialize(Pair positionedMark) { + JSONObject result = new JSONObject(); + + result.put(FIELD_MARK, markSerializer.serialize(positionedMark.getA())); + result.put(FIELD_POSITION, positionSerializer.serialize(positionedMark.getB())); + + return result; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/WindJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/WindJsonSerializer.java new file mode 100644 index 00000000000..0a95970edf2 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/WindJsonSerializer.java @@ -0,0 +1,32 @@ +package com.sap.sailing.server.gateway.serialization.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class WindJsonSerializer implements JsonSerializer { + public static final String FIELD_POSITION = "position"; + public static final String FIELD_TIMEPOINT = "timepoint"; + public static final String FIELD_SPEED_IN_KNOTS = "speedinknots"; + public static final String FIELD_BEARING = "bearing"; + + private final JsonSerializer positionSerializer; + + public WindJsonSerializer(JsonSerializer positionSerializer) { + this.positionSerializer = positionSerializer; + } + + @Override + public JSONObject serialize(Wind wind) { + JSONObject result = new JSONObject(); + + result.put(FIELD_POSITION, positionSerializer.serialize(wind.getPosition())); + result.put(FIELD_TIMEPOINT, wind.getTimePoint().asMillis()); + result.put(FIELD_SPEED_IN_KNOTS, wind.getKnots()); + result.put(FIELD_BEARING, wind.getBearing().getDegrees()); + + return result; + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/RaceLogEventSerializerChooser.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/RaceLogEventSerializerChooser.java deleted file mode 100644 index 05bf9d2c403..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/RaceLogEventSerializerChooser.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.racelog; - -import com.sap.sailing.domain.racelog.RaceLogEvent; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; - -public interface RaceLogEventSerializerChooser { - JsonSerializer getSerializer(RaceLogEvent event); -} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index 74222016353..eae977da350 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -3,19 +3,34 @@ package com.sap.sailing.server.gateway.serialization.racelog.impl; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent; +import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.racelog.RaceLogFlagEvent; +import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; +import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; +import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; 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.racelog.RaceLogEventSerializerChooser; +import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.WindJsonSerializer; -public class RaceLogEventSerializer implements JsonSerializer { +public class RaceLogEventSerializer implements JsonSerializer, RaceLogEventVisitor { public static JsonSerializer create(JsonSerializer competitorSerializer) { - return new RaceLogEventSerializer(new RaceLogEventSerializerChooserImpl( + return new RaceLogEventSerializer( new RaceLogFlagEventSerializer(competitorSerializer), new RaceLogStartTimeEventSerializer(competitorSerializer), new RaceLogRaceStatusEventSerializer(competitorSerializer), @@ -31,17 +46,69 @@ public class RaceLogEventSerializer implements JsonSerializer { new RaceLogFinishPositioningConfirmedEventSerializer(competitorSerializer), new RaceLogPathfinderEventSerializer(competitorSerializer), new RaceLogGateLineOpeningTimeEventSerializer(competitorSerializer), - new RaceLogStartProcedureChangedEventSerializer(competitorSerializer))); + new RaceLogStartProcedureChangedEventSerializer(competitorSerializer), + new RaceLogProtestStartTimeEventSerializer(competitorSerializer), + new RaceLogWindFixEventSerializer(competitorSerializer, + new WindJsonSerializer( + new PositionJsonSerializer()))); } - private RaceLogEventSerializerChooser serializerChooser; + 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 JsonSerializer chosenSerializer; - public RaceLogEventSerializer(RaceLogEventSerializerChooser serializerChooser) { - this.serializerChooser = serializerChooser; + 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) { + 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.chosenSerializer = null; } protected JsonSerializer getSerializer(RaceLogEvent event) { - return serializerChooser.getSerializer(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 @@ -49,4 +116,69 @@ public class RaceLogEventSerializer implements JsonSerializer { 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; + } + } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializerChooserImpl.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializerChooserImpl.java deleted file mode 100644 index a79fcd699d4..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializerChooserImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.racelog.impl; - -import com.sap.sailing.domain.racelog.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.racelog.RaceLogEvent; -import com.sap.sailing.domain.racelog.RaceLogEventVisitor; -import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.racelog.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.racelog.RaceLogFlagEvent; -import com.sap.sailing.domain.racelog.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent; -import com.sap.sailing.domain.racelog.RaceLogPathfinderEvent; -import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.racelog.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.server.gateway.serialization.racelog.RaceLogEventSerializerChooser; - -public class RaceLogEventSerializerChooserImpl implements RaceLogEventSerializerChooser, RaceLogEventVisitor { - - 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 JsonSerializer chosenSerializer; - - public RaceLogEventSerializerChooserImpl( - JsonSerializer flagEventSerializer, - JsonSerializer startTimeSerializer, - JsonSerializer raceStatusSerializer, - JsonSerializer courseAreaChangedEventSerializer, - JsonSerializer passChangedEventSerializer, - JsonSerializer courseDesignChangedEventSerializer, - JsonSerializer finishPositioningListChangedEventSerializer, - JsonSerializer finishPositioningConfirmedEventSerializer, - JsonSerializer pathfinderEventSerializer, - JsonSerializer gateLineOpeningTimeEventSerializer, - JsonSerializer startProcedureChangedEventSerializer) { - 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.chosenSerializer = null; - } - - @Override - public 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 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; - } - -} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFinishPositioningConfirmedEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFinishPositioningConfirmedEventSerializer.java index 98d718e3fac..7852dc6c79d 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFinishPositioningConfirmedEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFinishPositioningConfirmedEventSerializer.java @@ -1,8 +1,14 @@ package com.sap.sailing.server.gateway.serialization.racelog.impl; +import java.io.Serializable; +import java.util.List; + +import org.json.simple.JSONArray; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.server.gateway.serialization.JsonSerializer; @@ -11,6 +17,11 @@ public class RaceLogFinishPositioningConfirmedEventSerializer extends BaseRaceLo public static final String VALUE_CLASS = RaceLogFinishPositioningConfirmedEvent.class.getSimpleName(); + public static final String FIELD_POSITIONED_COMPETITORS = "positionedCompetitors"; + public static final String FIELD_COMPETITOR_ID = "competitorId"; + public static final String FIELD_COMPETITOR_NAME = "competitorName"; + public static final String FIELD_SCORE_CORRECTIONS_MAX_POINTS_REASON = "maxPointsReason"; + public RaceLogFinishPositioningConfirmedEventSerializer(JsonSerializer competitorSerializer) { super(competitorSerializer); } @@ -25,8 +36,27 @@ public class RaceLogFinishPositioningConfirmedEventSerializer extends BaseRaceLo RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) object; JSONObject result = super.serialize(finishPositioningConfirmedEvent); + + result.put(FIELD_POSITIONED_COMPETITORS, serializePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitors())); return result; } + + private JSONArray serializePositionedCompetitors(List> positionedCompetitors) { + JSONArray jsonPositionedCompetitors = new JSONArray(); + + if (positionedCompetitors != null) { // for backwards compatibility reasons + for (Triple positionedCompetitor : positionedCompetitors) { + JSONObject jsonPositionedCompetitor = new JSONObject(); + + jsonPositionedCompetitor.put(FIELD_COMPETITOR_ID, positionedCompetitor.getA().toString()); + jsonPositionedCompetitor.put(FIELD_COMPETITOR_NAME, positionedCompetitor.getB()); + jsonPositionedCompetitor.put(FIELD_SCORE_CORRECTIONS_MAX_POINTS_REASON, positionedCompetitor.getC().name()); + jsonPositionedCompetitors.add(jsonPositionedCompetitor); + } + } + + return jsonPositionedCompetitors; + } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogProtestStartTimeEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogProtestStartTimeEventSerializer.java new file mode 100644 index 00000000000..9527fae3087 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogProtestStartTimeEventSerializer.java @@ -0,0 +1,32 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogProtestStartTimeEvent; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogProtestStartTimeEventSerializer extends BaseRaceLogEventSerializer { + + public static final String VALUE_CLASS = RaceLogProtestStartTimeEvent.class.getSimpleName(); + public static final String FIELD_PROTEST_START_TIME = "protestStartTime"; + + public RaceLogProtestStartTimeEventSerializer(JsonSerializer competitorSerializer) { + super(competitorSerializer); + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } + + @Override + public JSONObject serialize(RaceLogEvent object) { + RaceLogProtestStartTimeEvent event = (RaceLogProtestStartTimeEvent) object; + JSONObject result = super.serialize(event); + result.put(FIELD_PROTEST_START_TIME, event.getProtestStartTime().asMillis()); + return result; + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogWindFixEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogWindFixEventSerializer.java new file mode 100644 index 00000000000..51414c7f87b --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogWindFixEventSerializer.java @@ -0,0 +1,36 @@ +package com.sap.sailing.server.gateway.serialization.racelog.impl; + +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.RaceLogWindFixEvent; +import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; + +public class RaceLogWindFixEventSerializer extends BaseRaceLogEventSerializer { + + public static final String VALUE_CLASS = RaceLogWindFixEvent.class.getSimpleName(); + public static final String FIELD_WIND = "wind"; + + JsonSerializer windSerializer; + + public RaceLogWindFixEventSerializer(JsonSerializer competitorSerializer, JsonSerializer windSerializer) { + super(competitorSerializer); + this.windSerializer = windSerializer; + } + + @Override + protected String getClassFieldValue() { + return VALUE_CLASS; + } + + @Override + public JSONObject serialize(RaceLogEvent object) { + RaceLogWindFixEvent event = (RaceLogWindFixEvent) object; + JSONObject result = super.serialize(event); + result.put(FIELD_WIND, windSerializer.serialize(event.getWindFix())); + return result; + } + +} diff --git a/java/com.sap.sailing.server.gateway/WEB-INF/web.xml b/java/com.sap.sailing.server.gateway/WEB-INF/web.xml index 46d528f9ecc..898c32a17bc 100644 --- a/java/com.sap.sailing.server.gateway/WEB-INF/web.xml +++ b/java/com.sap.sailing.server.gateway/WEB-INF/web.xml @@ -41,6 +41,15 @@ /rc/marks + + RCMarkPositions + com.sap.sailing.server.gateway.impl.rc.MarkPositionsJsonExportServlet + + + RCMarkPositions + /rc/markpositions + + RCCurrentCourse com.sap.sailing.server.gateway.impl.rc.CourseJsonExportServlet diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java index ba1c1b368f7..a8eff3ae269 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/EventRaceStatesJsonGetServlet.java @@ -20,13 +20,14 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.racelog.utils.RaceStateOfSameDayHelper; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogFlagEvent; import com.sap.sailing.domain.racelog.analyzing.impl.AbortingFlagFinder; import com.sap.sailing.domain.racelog.analyzing.impl.FinishedTimeFinder; import com.sap.sailing.domain.racelog.analyzing.impl.GateLineOpeningTimeFinder; -import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagFinder; +import com.sap.sailing.domain.racelog.analyzing.impl.LastFlagsFinder; import com.sap.sailing.domain.racelog.analyzing.impl.PathfinderFinder; import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer; import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder; @@ -111,29 +112,13 @@ public class EventRaceStatesJsonGetServlet extends AbstractJsonHttpServlet { boolean result = false; RaceLog raceLog = raceColumn.getRaceLog(fleet); if (raceLog != null && !raceLog.isEmpty()) { - TimePoint startTime = new StartTimeFinder(raceLog).getStartTime(); - TimePoint finishedTime = new FinishedTimeFinder(raceLog).getFinishedTime(); - if(finishedTime != null) { - Calendar finishedTimeCal = Calendar.getInstance(); - finishedTimeCal.setTime(finishedTime.asDate()); - if(isSameDay(now, finishedTimeCal)) { - result = true; - } - } else if(startTime != null) { - Calendar startTimeCal = Calendar.getInstance(); - startTimeCal.setTime(startTime.asDate()); - if(isSameDay(now, startTimeCal)) { - result = true; - } - } + TimePoint startTime = new StartTimeFinder(raceLog).analyze(); + TimePoint finishedTime = new FinishedTimeFinder(raceLog).analyze(); + + result = RaceStateOfSameDayHelper.isRaceStateOfSameDay(startTime, finishedTime, now); } return result; } - - private boolean isSameDay(Calendar cal1, Calendar cal2) { - return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && - cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); - } private JSONObject createRaceStateJsonObject(RaceColumn raceColumn, Fleet fleet) { JSONObject result = new JSONObject(); @@ -146,20 +131,20 @@ public class EventRaceStatesJsonGetServlet extends AbstractJsonHttpServlet { JSONObject raceLogStateJson = new JSONObject(); result.put("raceState", raceLogStateJson); StartTimeFinder startTimeFinder = new StartTimeFinder(raceLog); - raceLogStateJson.put("startTime", startTimeFinder.getStartTime() != null ? startTimeFinder.getStartTime().toString() : null); + raceLogStateJson.put("startTime", startTimeFinder.analyze() != null ? startTimeFinder.analyze().toString() : null); FinishedTimeFinder finishedTimeFinder = new FinishedTimeFinder(raceLog); - raceLogStateJson.put("endTime", finishedTimeFinder.getFinishedTime() != null ? finishedTimeFinder.getFinishedTime().toString() : null); + raceLogStateJson.put("endTime", finishedTimeFinder.analyze() != null ? finishedTimeFinder.analyze().toString() : null); RaceStatusAnalyzer raceStatusAnalyzer = new RaceStatusAnalyzer(raceLog); - RaceLogRaceStatus lastStatus = raceStatusAnalyzer.getStatus(); + RaceLogRaceStatus lastStatus = raceStatusAnalyzer.analyze(); raceLogStateJson.put("lastStatus", lastStatus.name()); PathfinderFinder pathfinderFinder = new PathfinderFinder(raceLog); - raceLogStateJson.put("pathfinderId", pathfinderFinder.getPathfinderId()); + raceLogStateJson.put("pathfinderId", pathfinderFinder.analyze()); GateLineOpeningTimeFinder gateLineOpeningTimeFinder = new GateLineOpeningTimeFinder(raceLog); - raceLogStateJson.put("gateLineOpeningTime", gateLineOpeningTimeFinder.getGateLineOpeningTime()); + raceLogStateJson.put("gateLineOpeningTime", gateLineOpeningTimeFinder.analyze()); AbortingFlagFinder abortingFlagFinder = new AbortingFlagFinder(raceLog); - RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.getAbortingFlagEvent(); - LastFlagFinder lastFlagFinder = new LastFlagFinder(raceLog); - RaceLogFlagEvent lastFlagEvent = lastFlagFinder.getLastFlagEvent(); + RaceLogFlagEvent abortingFlagEvent = abortingFlagFinder.analyze(); + LastFlagsFinder lastFlagFinder = new LastFlagsFinder(raceLog); + RaceLogFlagEvent lastFlagEvent = LastFlagsFinder.getMostRecent(lastFlagFinder.analyze()); if (lastFlagEvent != null) { setLastFlagField(raceLogStateJson, lastFlagEvent.getUpperFlag().name(), lastFlagEvent.getLowerFlag().name(), lastFlagEvent.isDisplayed()); } else if (lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED) && abortingFlagEvent != null) { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java index 1e50a67aa2f..4091fa059bc 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/AddEntryToRaceLogJsonPostServlet.java @@ -91,6 +91,7 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet { } catch (ParseException pe) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Invalid JSON in request body:\n%s", pe)); + logger.warning(String.format("Exception while parsing post request:\n%s", pe.toString())); return; } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java new file mode 100644 index 00000000000..3055c85677e --- /dev/null +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarkPositionsJsonExportServlet.java @@ -0,0 +1,120 @@ +package com.sap.sailing.server.gateway.impl.rc; + +import java.io.IOException; +import java.util.UUID; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.simple.JSONArray; + +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.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.Util.Pair; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.gateway.AbstractJsonHttpServlet; +import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PositionJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PositionedMarkJsonSerializer; + +public class MarkPositionsJsonExportServlet extends AbstractJsonHttpServlet { + + private static final long serialVersionUID = -5489857104922281761L; + + public static final String PARAMS_LEADERBOARD_NAME = "leaderboard"; + public static final String PARAMS_RACE_COLUMN_NAME = "raceColumn"; + public static final String PARAMS_RACE_FLEET_NAME = "fleet"; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + String leaderboardName = request.getParameter(PARAMS_LEADERBOARD_NAME); + if (leaderboardName == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + String.format("Missing parameter '%s'.", PARAMS_LEADERBOARD_NAME)); + return; + } + + String raceColumnName = request.getParameter(PARAMS_RACE_COLUMN_NAME); + if (raceColumnName == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + String.format("Missing parameter '%s'.", PARAMS_RACE_COLUMN_NAME)); + return; + } + + String fleetName = request.getParameter(PARAMS_RACE_FLEET_NAME); + if (fleetName == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + String.format("Missing parameter '%s'.", PARAMS_RACE_FLEET_NAME)); + return; + } + + RacingEventService service = getService(); + + Leaderboard leaderboard = service.getLeaderboardByName(leaderboardName); + if (leaderboard == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such leaderboard found."); + return; + } + + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such race column found."); + return; + } + + Fleet fleet = raceColumn.getFleetByName(fleetName); + if (fleet == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "No such fleet found."); + return; + } + + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + + JSONArray result = new JSONArray(); + + if (trackedRace != null) { + MarkJsonSerializer markSerializer = new MarkJsonSerializer(); + PositionJsonSerializer positionSerializer = new PositionJsonSerializer(); + PositionedMarkJsonSerializer positionedMarkSerializer = new PositionedMarkJsonSerializer(markSerializer, positionSerializer); + + //TODO propagate only marks that are on the course area of the race + //Position courseAreaCenterPosition = leaderboard.getDefaultCourseArea().getPosition(); + //Distance courseAreaRadius = leaderboard.getDefaultCourseArea().getRadius(); + for (Mark mark : trackedRace.getMarks()) { + if (toUUID(mark.getId().toString()) != null) { + Position position = trackedRace.getOrCreateTrack(mark).getEstimatedPosition(MillisecondsTimePoint.now(), false); + + //The position of the mark needs to be in the course area + //if (isMarkInCourseArea(courseAreaCenterPosition, courseAreaRadius, position)) { + result.add(positionedMarkSerializer.serialize(new Pair(mark, position))); + //} + + } + } + } + + result.writeJSONString(response.getWriter()); + response.setContentType("application/json"); + } + + @SuppressWarnings("unused") //unused since course area has no position yet + private boolean isMarkInCourseArea(Position courseAreaCenterPosition, Distance courseAreaRadius, Position position) { + return position.getDistance(courseAreaCenterPosition).compareTo(courseAreaRadius) < 0; + } + + private UUID toUUID(String value) { + try { + return UUID.fromString(value); + } catch (IllegalArgumentException iae) { + return null; + } + } +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java index 2860acb1d33..c8dc7b30b6d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/MarksJsonExportServlet.java @@ -75,7 +75,7 @@ public class MarksJsonExportServlet extends AbstractJsonHttpServlet { if (trackedRace != null) { MarkJsonSerializer serializer = new MarkJsonSerializer(); - + for (Mark mark : trackedRace.getMarks()) { if (toUUID(mark.getId().toString()) != null) { result.add(serializer.serialize(mark)); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupFactory.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupFactory.java index 6a42cf54a19..c438c88802a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupFactory.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupFactory.java @@ -56,13 +56,21 @@ public class RaceGroupFactory { Map> seriesToRaceColumns = getSeriesToRaceColumns(leaderboard); Collection seriesWithRows = new ArrayList<>(); - for (Series series : seriesToRaceColumns.keySet()) { + for (Series series : getSeriesIterable(leaderboard, seriesToRaceColumns)) { seriesWithRows.add(new SeriesWithRowsImpl(series.getName(), series.isMedal(), getRows(series, seriesToRaceColumns.get(series)))); } return seriesWithRows; } + private Iterable getSeriesIterable(Leaderboard leaderboard, Map> seriesToRaceColumns) { + // for RegattaLeaderboards we want to preserve the order of series + if (leaderboard instanceof RegattaLeaderboard) { + return ((RegattaLeaderboard) leaderboard).getRegatta().getSeries(); + } + return seriesToRaceColumns.keySet(); + } + private Collection getRows(Series series, List raceColumns) { Collection rows = new ArrayList<>(); for (Fleet fleet : series.getFleets()) { 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 24eac83907e..26b840348f4 100644 --- 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 @@ -1,11 +1,10 @@ package com.sap.sailing.server.replication.test; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; +import java.util.List; import java.util.UUID; import junit.framework.Assert; @@ -75,7 +74,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(seriesName, fleetName, raceColumnName, regatta); - addAndValidate(masterLog, replicaLog); + addAndValidateEventIds(masterLog, replicaLog); } @Test @@ -92,7 +91,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(seriesName, fleetName, raceColumnName, masterRegatta); - addAndValidate(masterLog, replicaLog); + addAndValidateEventIds(masterLog, replicaLog); } @Test @@ -108,7 +107,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(seriesName, fleetName, raceColumnName, masterRegatta); - addAndValidate(masterLog, replicaLog, raceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, raceLogEvent); } @Test @@ -123,7 +122,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(fleetName, raceColumnName, masterLeaderboard); - addAndValidate(masterLog, replicaLog, raceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, raceLogEvent); } @Test @@ -140,7 +139,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(seriesName, fleetName, raceColumnName, masterRegatta); - addAndValidate(masterLog, replicaLog, anotherRaceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, anotherRaceLogEvent); } @Test @@ -161,7 +160,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { RaceLog replicaLog = getReplicaLog(seriesName, fleetName, raceColumnName, masterRegatta); anotherRaceLogEvent = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(MillisecondsTimePoint.now(), 43, createCourseData()); - addAndValidate(masterLog, replicaLog, anotherRaceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, anotherRaceLogEvent); compareReplicatedCourseDesignEvent(replicaLog, (RaceLogCourseDesignChangedEvent) anotherRaceLogEvent); } @@ -179,7 +178,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB()); RaceLog replicaLog = getReplicaLog(fleetName, raceColumnName, masterLeaderboard); - addAndValidate(masterLog, replicaLog, anotherRaceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, anotherRaceLogEvent); } @Test @@ -198,7 +197,7 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { RaceLog replicaLog = getReplicaLog(fleetName, raceColumnName, masterLeaderboard); anotherRaceLogEvent = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(MillisecondsTimePoint.now(), 43, createCourseData()); - addAndValidate(masterLog, replicaLog, anotherRaceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, anotherRaceLogEvent); compareReplicatedCourseDesignEvent(replicaLog, (RaceLogCourseDesignChangedEvent) anotherRaceLogEvent); } @@ -234,12 +233,15 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { Thread.sleep(3000); RaceLog replicaLog = getReplicaLog(fleetName, raceColumnName, masterLeaderboard); - addAndValidate(masterLog, replicaLog, anotherRaceLogEvent); + addAndValidateEventIds(masterLog, replicaLog, anotherRaceLogEvent); } - private void addAndValidate(RaceLog masterLog, RaceLog replicaLog, RaceLogEvent... addedEvents) throws InterruptedException { + /** + * Validation is done based only on the identifier and type of the {@link RaceLogEvent}s. + */ + private void addAndValidateEventIds(RaceLog masterLog, RaceLog replicaLog, RaceLogEvent... addedEvents) throws InterruptedException { // 1. Check state of replica after initial load... - assertLogsEqual(masterLog, replicaLog); + assertEqualsOnId(masterLog, replicaLog); // 2. ... add all incoming events... for (RaceLogEvent event : addedEvents) { @@ -248,15 +250,18 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { // 3. ... and give replication some time to deliver messages. Thread.sleep(3000); - assertLogsEqual(masterLog, replicaLog); + assertEqualsOnId(masterLog, replicaLog); } - private void assertLogsEqual(RaceLog masterLog, RaceLog replicaLog) { + /** + * Equality of the events is done based only on the identifier and type. + */ + private void assertEqualsOnId(RaceLog masterLog, RaceLog replicaLog) { replicaLog.lockForRead(); try { masterLog.lockForRead(); try { - assertEvents(masterLog.getRawFixes(), replicaLog.getRawFixes()); + assertEqualsOnId(masterLog.getRawFixes(), replicaLog.getRawFixes()); } finally { masterLog.unlockAfterRead(); } @@ -265,17 +270,20 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest { } } - private void assertEvents(Iterable expectedEvents, Iterable actualEvents) { - Collection expectedCollection = new ArrayList<>(); + /** + * Equality of the events is done based only on the {@link RaceLogEvent}'s identifier and type. + */ + private void assertEqualsOnId(Iterable expectedEvents, Iterable actualEvents) { + List expectedCollection = new ArrayList<>(); Util.addAll(expectedEvents, expectedCollection); - Collection actualCollection = new ArrayList<>(); + List actualCollection = new ArrayList<>(); Util.addAll(actualEvents, actualCollection); - //assertEquals(expectedCollection.size(), actualCollection.size()); assertEquals(Util.size(expectedEvents), Util.size(actualEvents)); - for (RaceLogEvent event : expectedEvents) { - assertTrue(actualCollection.contains(event)); + for (int i = 0; i < expectedCollection.size(); i++) { + assertEquals(expectedCollection.get(i).getClass(), actualCollection.get(i).getClass()); + assertEquals(expectedCollection.get(i).getId(), actualCollection.get(i).getId()); } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java index 0abc4c3997c..a50a1caef4c 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RaceLogScoringReplicator.java @@ -19,6 +19,7 @@ import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; +import com.sap.sailing.domain.racelog.analyzing.impl.ConfirmedFinishPositioningListFinder; import com.sap.sailing.domain.racelog.analyzing.impl.FinishPositioningListFinder; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.RacingEventService; @@ -120,12 +121,20 @@ public class RaceLogScoringReplicator implements RaceColumnListener { int numberOfCompetitorsInLeaderboard = Util.size(leaderboard.getCompetitors()); int numberOfCompetitorsInRace; + List> positioningList; numberOfCompetitorsInRace = getNumberOfCompetitorsInRace(raceColumn, fleet, numberOfCompetitorsInLeaderboard); - FinishPositioningListFinder positioningListFinder = new FinishPositioningListFinder(raceLog); - - List> positioningList = positioningListFinder.getFinishPositioningList(); + ConfirmedFinishPositioningListFinder confirmedPositioningListFinder = new ConfirmedFinishPositioningListFinder(raceLog); + positioningList = confirmedPositioningListFinder.analyze(); + + if (positioningList == null) { + // we expect this case for old sailing events such as ESS Singapore, Quingdao, where the confirmation event did not contain the finish + // positioning list + FinishPositioningListFinder positioningListFinder = new FinishPositioningListFinder(raceLog); + positioningList = positioningListFinder.analyze(); + } + if (positioningList != null) { for (Triple positionedCompetitor : positioningList) { Competitor competitor = DomainFactory.INSTANCE.getExistingCompetitorById(positionedCompetitor.getA()); 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 a12fb6a9b71..d2cf37706ef 100755 --- 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 @@ -43,7 +43,6 @@ import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.RegattaListener; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.EventImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.common.LeaderboardNameConstants; @@ -268,10 +267,10 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen // This is more for debugging purposes than for anything else. addFlexibleLeaderboard(LeaderboardNameConstants.DEFAULT_LEADERBOARD_NAME, null, new int[] { 5, 8 }, tractracDomainFactory.getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), null); + loadStoredEvents(); loadStoredRegattas(); loadRaceIDToRegattaAssociations(); loadStoredLeaderboardsAndGroups(); - loadStoredEvents(); loadMediaLibary(); } @@ -1808,7 +1807,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen @Override public CourseArea addCourseArea(Serializable eventId, String courseAreaName, Serializable courseAreaId) { - CourseArea courseArea = new CourseAreaImpl(courseAreaName, courseAreaId); + CourseArea courseArea = getBaseDomainFactory().getOrCreateCourseArea(courseAreaId, courseAreaName); synchronized (eventsById) { if (!eventsById.containsKey(eventId)) { throw new IllegalArgumentException("No sailing event with ID " + eventId + " found."); diff --git a/java/com.sap.sailing.www/build.properties b/java/com.sap.sailing.www/build.properties index ffa2e11d71d..6660e35b9b4 100644 --- a/java/com.sap.sailing.www/build.properties +++ b/java/com.sap.sailing.www/build.properties @@ -9,4 +9,5 @@ bin.includes = META-INF/,\ SAP.html,\ STG.html,\ browser-info.html,\ - browser-info.css + browser-info.css,\ + postrace/ diff --git a/java/com.sap.sailing.www/postrace/images/._404errorPageIcon.png b/java/com.sap.sailing.www/postrace/images/._404errorPageIcon.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._404errorPageIcon.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._barcode-automatic-connection-sbo.png b/java/com.sap.sailing.www/postrace/images/._barcode-automatic-connection-sbo.png new file mode 100755 index 00000000000..93cbd52ccdd Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._barcode-automatic-connection-sbo.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._barcode-business-objects.png b/java/com.sap.sailing.www/postrace/images/._barcode-business-objects.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._barcode-business-objects.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-button-corporate.png b/java/com.sap.sailing.www/postrace/images/._sbo-button-corporate.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-button-corporate.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-button-exploration.png b/java/com.sap.sailing.www/postrace/images/._sbo-button-exploration.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-button-exploration.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-explorer-icon.png b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-icon.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-icon.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-explorer-loading.png b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-loading.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-loading.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-explorer-password.png b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-password.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-explorer-password.png differ diff --git a/java/com.sap.sailing.www/postrace/images/._sbo-ipad-password.png b/java/com.sap.sailing.www/postrace/images/._sbo-ipad-password.png new file mode 100755 index 00000000000..9a990e21019 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/._sbo-ipad-password.png differ diff --git a/java/com.sap.sailing.www/postrace/images/404errorPageIcon.png b/java/com.sap.sailing.www/postrace/images/404errorPageIcon.png new file mode 100755 index 00000000000..443c552cd2a Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/404errorPageIcon.png differ diff --git a/java/com.sap.sailing.www/postrace/images/barcode-automatic-connection-sbo.png b/java/com.sap.sailing.www/postrace/images/barcode-automatic-connection-sbo.png new file mode 100755 index 00000000000..91f443cc549 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/barcode-automatic-connection-sbo.png differ diff --git a/java/com.sap.sailing.www/postrace/images/barcode-business-objects.png b/java/com.sap.sailing.www/postrace/images/barcode-business-objects.png new file mode 100755 index 00000000000..965f92beb64 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/barcode-business-objects.png differ diff --git a/java/com.sap.sailing.www/postrace/images/btn-cta-orangeleft.png b/java/com.sap.sailing.www/postrace/images/btn-cta-orangeleft.png new file mode 100755 index 00000000000..f92cbec65c9 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/btn-cta-orangeleft.png differ diff --git a/java/com.sap.sailing.www/postrace/images/header_bg.png b/java/com.sap.sailing.www/postrace/images/header_bg.png new file mode 100755 index 00000000000..bcbea73cc55 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/header_bg.png differ diff --git a/java/com.sap.sailing.www/postrace/images/header_bg_modern.png b/java/com.sap.sailing.www/postrace/images/header_bg_modern.png new file mode 100755 index 00000000000..6565ca0329f Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/header_bg_modern.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sap_66_transparent.png b/java/com.sap.sailing.www/postrace/images/sap_66_transparent.png new file mode 100755 index 00000000000..7e76e7fcf00 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sap_66_transparent.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-button-corporate.png b/java/com.sap.sailing.www/postrace/images/sbo-button-corporate.png new file mode 100755 index 00000000000..6bce7213ad0 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-button-corporate.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-button-exploration.png b/java/com.sap.sailing.www/postrace/images/sbo-button-exploration.png new file mode 100755 index 00000000000..13e0951dc67 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-button-exploration.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-explorer-icon.png b/java/com.sap.sailing.www/postrace/images/sbo-explorer-icon.png new file mode 100755 index 00000000000..4d2e5a871b6 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-explorer-icon.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-explorer-loading.png b/java/com.sap.sailing.www/postrace/images/sbo-explorer-loading.png new file mode 100755 index 00000000000..2ab4e7a6869 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-explorer-loading.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-explorer-password.png b/java/com.sap.sailing.www/postrace/images/sbo-explorer-password.png new file mode 100755 index 00000000000..c9dccaa4652 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-explorer-password.png differ diff --git a/java/com.sap.sailing.www/postrace/images/sbo-ipad-password.png b/java/com.sap.sailing.www/postrace/images/sbo-ipad-password.png new file mode 100755 index 00000000000..c7d9b146a62 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/sbo-ipad-password.png differ diff --git a/java/com.sap.sailing.www/postrace/images/white_gradient_header.png b/java/com.sap.sailing.www/postrace/images/white_gradient_header.png new file mode 100755 index 00000000000..f160fbe983c Binary files /dev/null and b/java/com.sap.sailing.www/postrace/images/white_gradient_header.png differ diff --git a/java/com.sap.sailing.www/postrace/normalize.css b/java/com.sap.sailing.www/postrace/normalize.css new file mode 100755 index 00000000000..6e8e42d8cee --- /dev/null +++ b/java/com.sap.sailing.www/postrace/normalize.css @@ -0,0 +1,527 @@ +/*! normalize.css v1.1.2 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/** + * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. + * Known issue: no IE 6 support. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/** + * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-size: 100%; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Address `font-family` inconsistency between `textarea` and other form + * elements. + */ + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/** + * Address margins handled incorrectly in IE 6/7. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/** + * Address `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/** + * Address font sizes and margins set differently in IE 6/7. + * Address font sizes within `section` and `article` in Firefox 4+, Safari 5, + * and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.67em; + margin: 2.33em 0; +} + +/** + * Address styling not present in IE 7/8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/** + * Address styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address differences between Firefox and other browsers. + * Known issue: no IE 6/7 normalization. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Address styling not present in IE 6/7/8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address margins set differently in IE 6/7. + */ + +p, +pre { + margin: 1em 0; +} + +/** + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/** + * Improve readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/** + * Address CSS quotes not supported in IE 6/7. + */ + +q { + quotes: none; +} + +/** + * Address `quotes` property not supported in Safari 4. + */ + +q:before, +q:after { + content: ''; + content: none; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Lists + ========================================================================== */ + +/** + * Address margins set differently in IE 6/7. + */ + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/** + * Address paddings set differently in IE 6/7. + */ + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/** + * Correct list images handled incorrectly in IE 7. + */ + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. + * 2. Improve image quality when scaled in IE 7. + */ + +img { + border: 0; /* 1 */ + -ms-interpolation-mode: bicubic; /* 2 */ +} + +/** + * Correct overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/** + * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/** + * Correct margin displayed oddly in IE 6/7. + */ + +form { + margin: 0; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct color not being inherited in IE 6/7/8/9. + * 2. Correct text not wrapping in Firefox 3. + * 3. Correct alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; + white-space: normal; /* 2 */ + *margin-left: -7px; /* 3 */ +} + +/** + * 1. Correct font size not being inherited in all browsers. + * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, + * and Chrome. + * 3. Improve appearance and consistency in all browsers. + */ + +button, +input, +select, +textarea { + font-size: 100%; /* 1 */ + margin: 0; /* 2 */ + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ +} + +/** + * Address Firefox 3+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+. + * Correct `select` style inheritance in Firefox 4+ and Opera. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Remove inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + *overflow: visible; /* 4 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * 1. Address box sizing set to content-box in IE 8/9. + * 2. Remove excess padding in IE 8/9. + * 3. Remove excess padding in IE 7. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Remove inner padding and border in Firefox 3+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * 1. Remove default vertical scrollbar in IE 6/7/8/9. + * 2. Improve readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/java/com.sap.sailing.www/postrace/post-race-analytics-info.css b/java/com.sap.sailing.www/postrace/post-race-analytics-info.css new file mode 100755 index 00000000000..c4f0678191d --- /dev/null +++ b/java/com.sap.sailing.www/postrace/post-race-analytics-info.css @@ -0,0 +1,95 @@ +@import url(fontface.css); + +body { + font: 12px Arial, Helvetica, sans-serif; + margin: 0; + padding: 0 0 50px 0; + background: #ebebec; +} + + +.LogoAndTitlePanel { + height: 68px; + font-family: Arial, Verdana, sans-serif; + position: fixed; + width: 100%; + top: 0; + /*background-image: url(../images/white_gradient_header.png), url(../images/header_bg_modern.png); + background-position: center top, 0 0; + background-repeat: no-repeat, repeat-x; + */ + background: url(images/header_bg_modern.png) 0 0 repeat-x; + box-shadow: 0 0 20px #858585; + -moz-box-shadow: 0 0 20px #858585; + -webkit-box-shadow: 0 0 20px #858585; +} + +.LogoAndTitlePanel:after { + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +.sapLogo { + float: left; + margin: 13px 0 0 12px; +} + +.sailingAnalyticsLabelPanel { + margin: 10px 0 0 0; +} + +.sailingAnalyticsLabel { + float: left; + color: #fff; + font-size: 14px; + font-weight: bold; + margin: 15px 0 0 0; +} + +a { + color: rgb(0, 102, 179); + font-weight: bold; + padding: 0px 0px 2px; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1, h2, h3, h4, h5 { + color: rgb(51, 51, 51); +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 22px; +} + +h4 { + font-size: 18px; +} + +h5 { + font-size: 16px; +} + +#content { + margin: 100px auto 0; + width: 960px; +} + +.section { + margin: 0 0 10px 0; + border-bottom: 1px solid #999999; +} + +.subsection { + padding: 0 0 0 20px; +} diff --git a/java/com.sap.sailing.www/postrace/post-race-analytics-info.html b/java/com.sap.sailing.www/postrace/post-race-analytics-info.html new file mode 100755 index 00000000000..3f2f61ff360 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/post-race-analytics-info.html differ diff --git a/java/com.sap.sailing.www/postrace/sap.ico b/java/com.sap.sailing.www/postrace/sap.ico new file mode 100755 index 00000000000..5975b8922e1 Binary files /dev/null and b/java/com.sap.sailing.www/postrace/sap.ico differ diff --git a/mobile/com.sap.sailing.racecommittee.app/.gitignore b/mobile/com.sap.sailing.racecommittee.app/.gitignore new file mode 100755 index 00000000000..a02fbbe0ad4 --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/.gitignore @@ -0,0 +1,2 @@ +/gen +/bin diff --git a/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml b/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml index 3c6b86af008..5accfbcbe01 100644 --- a/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml +++ b/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml @@ -2,51 +2,61 @@ + android:versionName="1.0" > - + android:targetSdkVersion="17" /> + - + - - - + + + - + - - + android:hardwareAccelerated="true" + android:icon="@drawable/sap_sailing_app_icon" + android:label="@string/app_name" + android:theme="@style/Theme.Welter" > + + + + + + - + - - + + + + + + + - + + - + - \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/libs/google-play-services.jar b/mobile/com.sap.sailing.racecommittee.app/libs/google-play-services.jar new file mode 100644 index 00000000000..b54200b1bea Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/libs/google-play-services.jar differ diff --git a/mobile/com.sap.sailing.racecommittee.app/lint.xml b/mobile/com.sap.sailing.racecommittee.app/lint.xml index 694ca087b0a..d27cac8eac6 100644 --- a/mobile/com.sap.sailing.racecommittee.app/lint.xml +++ b/mobile/com.sap.sailing.racecommittee.app/lint.xml @@ -1,3 +1,6 @@ - - + + + + + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/project.properties b/mobile/com.sap.sailing.racecommittee.app/project.properties index d7a5c33094d..d738ab2b3db 100644 --- a/mobile/com.sap.sailing.racecommittee.app/project.properties +++ b/mobile/com.sap.sailing.racecommittee.app/project.properties @@ -11,5 +11,6 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-13 -android.library.reference.1=../com.sap.sailing.racecommittee.glue +target=Google Inc.:Google APIs:13 +android.library.reference.1=..\\com.sap.sailing.racecommittee.glue +android.library.reference.2=..\\google-play-services_lib diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_compose.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_compose.png new file mode 100644 index 00000000000..a911141cc69 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_compose.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_delete.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_delete.png new file mode 100644 index 00000000000..e2c8700c348 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_delete.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_gallery.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_gallery.png new file mode 100644 index 00000000000..d3a02009d50 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/ic_menu_gallery.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/list_activated_holo.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/list_activated_holo.9.png new file mode 100644 index 00000000000..f05602f7890 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/list_activated_holo.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_active_holo_dark.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_active_holo_dark.9.png new file mode 100644 index 00000000000..1f0521a612f Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_active_holo_dark.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_default_holo_dark.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_default_holo_dark.9.png new file mode 100644 index 00000000000..99b16056b13 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_default_holo_dark.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_disabled_holo_dark.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_disabled_holo_dark.9.png new file mode 100644 index 00000000000..95d7c86e5b4 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_disabled_holo_dark.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_focused_holo_dark.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_focused_holo_dark.9.png new file mode 100644 index 00000000000..2e2fadd83cf Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_focused_holo_dark.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_pressed_holo_dark.9.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_pressed_holo_dark.9.png new file mode 100644 index 00000000000..083194a6fa1 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable-mdpi/spinner_pressed_holo_dark.9.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/boat.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable/boat.png new file mode 100644 index 00000000000..a4de1260aba Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable/boat.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_big.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_big.png new file mode 100644 index 00000000000..4ffff6cfd55 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_big.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_finish_big.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_finish_big.png new file mode 100644 index 00000000000..575bb7483a2 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_black_finish_big.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_red_big.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_red_big.png new file mode 100644 index 00000000000..4f6129fdb61 Binary files /dev/null and b/mobile/com.sap.sailing.racecommittee.app/res/drawable/buoy_red_big.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/ic_menu_share_holo_light.png b/mobile/com.sap.sailing.racecommittee.app/res/drawable/ic_menu_share_holo_light.png index 682b2fdec4c..ebd2ea2ebda 100644 Binary files a/mobile/com.sap.sailing.racecommittee.app/res/drawable/ic_menu_share_holo_light.png and b/mobile/com.sap.sailing.racecommittee.app/res/drawable/ic_menu_share_holo_light.png differ diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/list_selector.xml b/mobile/com.sap.sailing.racecommittee.app/res/drawable/list_selector.xml index 81561f75521..adfe7fae52b 100644 --- a/mobile/com.sap.sailing.racecommittee.app/res/drawable/list_selector.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/drawable/list_selector.xml @@ -1,9 +1,9 @@ - - - - + + + + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/spinner_background_holo_dark.xml b/mobile/com.sap.sailing.racecommittee.app/res/drawable/spinner_background_holo_dark.xml new file mode 100644 index 00000000000..eb6b18b516c --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/drawable/spinner_background_holo_dark.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/mobile/com.sap.sailing.racecommittee.app/res/drawable/title_bar_bg.xml b/mobile/com.sap.sailing.racecommittee.app/res/drawable/title_bar_bg.xml index 2a51caffb64..dfc4094189c 100644 --- a/mobile/com.sap.sailing.racecommittee.app/res/drawable/title_bar_bg.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/drawable/title_bar_bg.xml @@ -1,19 +1,23 @@ - - - - - - - - - - + + --> + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/action_bar_spinner_item.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/action_bar_spinner_item.xml new file mode 100644 index 00000000000..119f4a98439 --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/action_bar_spinner_item.xml @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/list_fragment.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/list_fragment.xml new file mode 100644 index 00000000000..bbaa8b583c6 --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/list_fragment.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/login_view.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/login_view.xml index 365ffad30f5..0b4f3227dbd 100644 --- a/mobile/com.sap.sailing.racecommittee.app/res/layout/login_view.xml +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/login_view.xml @@ -7,46 +7,26 @@ android:baselineAligned="false" android:background="@drawable/background" > - - - - - - + + - - - - - - + android:layout_weight="0.5"> + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/photo_adapter_item.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/photo_adapter_item.xml new file mode 100644 index 00000000000..bf35463a16d --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/photo_adapter_item.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/protest_time_view.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/protest_time_view.xml new file mode 100644 index 00000000000..fcb7e07a4d5 --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/protest_time_view.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + +