diff --git a/Operating-Igtimi-WindBots/windbot-operations.md b/Operating-Igtimi-WindBots/windbot-operations.md new file mode 100644 index 00000000000..a7acb6b583f --- /dev/null +++ b/Operating-Igtimi-WindBots/windbot-operations.md @@ -0,0 +1,13 @@ +# Operating Igtimi WindBots + +For wind measurements we're trying to consistently use Igtimi WindBot equipment. The AdminConsole has a tab "Igtimi Accounts" where accounts for the Igtimi YachtBot web site can be managed. WindBots associated with any of these accounts will feed their wind readings, when active, into races being tracked. Operations of the WindBots mainly needs to take care of charging the devices, turning them on when they leave the harbor and turning them off when they leave the race course. This can also be delegated to race officials carrying these devices on their vessels. + +The devices have three LEDs whose status works as follows: + +1. The three LED’s are “power”, “connection”, and “GPS” in order from top to bottom. +2. All the lights should be on when operating normally. +3. Slow flashing is normal while booting. +4. Fast flashing means that function can’t start or has failed - e.g. SIM not inserted. i.e. you shouldn’t see this +5. During sync, the “power” light blips and the “connection” LED should stay on until the sync has finished. + +More information on running the WindBots can be found [here](https://igtimi.desk.com/customer/portal/articles/1494533-yachtbot-tracker-basic-operation?b_id=1690). \ No newline at end of file diff --git a/home.md b/home.md index 3b92ad2e70a..9c401284120 100644 --- a/home.md +++ b/home.md @@ -1,6 +1,6 @@ # Welcome to the SAP Sailing Wiki -This is the Sailing Analytics Wiki where useful information regarding this project can be found. +This is the Wiki where useful information regarding this project can be found. ### The Pitch @@ -15,14 +15,16 @@ Like businesses, sailors need the latest information to make strategic decisions * [[EC2 Backup Strategy|wiki/amazon-ec2-backup-strategy]] * [[TracTrac|wiki/tractrac-lifecycle]] * [[Analytics on a stick|wiki/analytics-on-a-stick]] + * [[Operating Igtimi WindBots/windbot-operations]] * [[Monitoring Apache and RabbitMQ|wiki/monitoring-apache-and-rabbitmq]] * [[JMX Support|wiki/jmx]] * Information for Developers - * [[Cook Book|wiki/cook-book]] * [[OnBoarding Information|wiki/onboarding]] + * [[Cook Book|wiki/cook-book]] * [[Building and Deploying|wiki/building-and-deploying]] * [[Continuous Integration with Hudson/Jenkins|wiki/ci]] * [[UI Tests with Selenium|wiki/selenium-ui-tests]] + * [[Profiling|wiki/profiling]] * [[Typical Development Scenarios|wiki/typical-development-scenarios]] * [[Load Tests|wiki/server-load-tests]] * [[Server Replication|wiki/server-replication]] @@ -50,6 +52,7 @@ Like businesses, sailors need the latest information to make strategic decisions * [[General Event Planning|wiki/general-event-planning]] * [[Information about Extreme Sailing Series|wiki/extreme-sailing-series]] * [[Travemünder Woche 2014 event page|wiki/tw2014]] + * [[505 worlds Kiel 2014 event page|wiki/505-worlds-kiel-2014]] ### Internal services (not related to wiki but useful) diff --git a/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestLeaderboardGroupFilteringRetrievalProcessor.java b/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestLeaderboardGroupFilteringRetrievalProcessor.java index b39b8004344..15ec5f0c560 100644 --- a/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestLeaderboardGroupFilteringRetrievalProcessor.java +++ b/java/com.sap.sailing.datamining.test/src/com/sap/sailing/datamining/impl/components/TestLeaderboardGroupFilteringRetrievalProcessor.java @@ -66,11 +66,11 @@ public class TestLeaderboardGroupFilteringRetrievalProcessor { private Map getGroupsInService() { Map groups = new HashMap<>(); - groups.put("LG1", new LeaderboardGroupImpl("LG1", "", false, new ArrayList())); - groups.put("LG2", new LeaderboardGroupImpl("LG2", "", false, new ArrayList())); - groups.put("LG3", new LeaderboardGroupImpl("LG3", "", false, new ArrayList())); - groups.put("LG4", new LeaderboardGroupImpl("LG4", "", false, new ArrayList())); - groups.put("LG5", new LeaderboardGroupImpl("LG5", "", false, new ArrayList())); + groups.put("LG1", new LeaderboardGroupImpl("LG1", "", /* displayName */ null, false, new ArrayList())); + groups.put("LG2", new LeaderboardGroupImpl("LG2", "", /* displayName */ null, false, new ArrayList())); + groups.put("LG3", new LeaderboardGroupImpl("LG3", "", /* displayName */ null, false, new ArrayList())); + groups.put("LG4", new LeaderboardGroupImpl("LG4", "", /* displayName */ null, false, new ArrayList())); + groups.put("LG5", new LeaderboardGroupImpl("LG5", "", /* displayName */ null, false, new ArrayList())); return groups; } @@ -86,11 +86,11 @@ public class TestLeaderboardGroupFilteringRetrievalProcessor { private Collection getExpectedRetrievedGroups() { Collection groups = new HashSet<>(); - groups.add(new LeaderboardGroupImpl("LG1", "", false, new ArrayList())); - groups.add(new LeaderboardGroupImpl("LG2", "", false, new ArrayList())); - groups.add(new LeaderboardGroupImpl("LG3", "", false, new ArrayList())); - groups.add(new LeaderboardGroupImpl("LG4", "", false, new ArrayList())); - groups.add(new LeaderboardGroupImpl("LG5", "", false, new ArrayList())); + groups.add(new LeaderboardGroupImpl("LG1", "", /* displayName */ null, false, new ArrayList())); + groups.add(new LeaderboardGroupImpl("LG2", "", /* displayName */ null, false, new ArrayList())); + groups.add(new LeaderboardGroupImpl("LG3", "", /* displayName */ null, false, new ArrayList())); + groups.add(new LeaderboardGroupImpl("LG4", "", /* displayName */ null, false, new ArrayList())); + groups.add(new LeaderboardGroupImpl("LG5", "", /* displayName */ null, false, new ArrayList())); return groups; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractBearing.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractBearing.java index 9a89c3f3c14..24f4b293e23 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractBearing.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractBearing.java @@ -60,5 +60,10 @@ public abstract class AbstractBearing implements Bearing { return object != null && object instanceof Bearing && getDegrees() == ((Bearing) object).getDegrees(); } + @Override + public double getRadians() { + return getDegrees() / 180. * Math.PI; + } + } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java new file mode 100644 index 00000000000..4e99e41b06a --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java @@ -0,0 +1,133 @@ +package com.sap.sailing.domain.common; + +import com.sap.sailing.domain.common.impl.MeterDistance; + + +public enum BoatClassMasterdata { + _2_4M ("2.4 Meter", true, 4.11, 0.81, BoatHullType.MONOHULL, "2.4M", "2.4mR"), + _5O5 ("5O5", true, 5.03, 1.88, BoatHullType.MONOHULL, "505", "5o5", "505er", "5o5er"), + _12M ("12 Meter", true, 5.97, 1.43, BoatHullType.MONOHULL, "12M", "12mR", "12SQM"), + _29ER ("29er", true, 4.45, 1.70, BoatHullType.MONOHULL), + _29ERXX ("29erXX", true, 4.45, 1.77, BoatHullType.MONOHULL, "29XX"), + _49ER ("49er", true, 4.88, 1.93, BoatHullType.MONOHULL), + _49ERFX ("49erFX", true, 4.88, 1.93, BoatHullType.MONOHULL, "49FX"), + _420 ("420", true, 4.20, 1.65, BoatHullType.MONOHULL, "420er", "420M", "420W"), + _470 ("470", true, 4.70, 1.68, BoatHullType.MONOHULL, "470er", "470M", "470W"), + A_CAT ("A-Catamaran", true, 5.49, 2.30, BoatHullType.CATAMARAN, "A-Cat", "ACat", "A-Class Catamaran"), + ALBIN_EXPRESS ("Albin Express", true, 7.77, 2.50, BoatHullType.MONOHULL), + B_ONE ("B/ONE", true, 7.80, 2.49, BoatHullType.MONOHULL, "B-ONE"), + DRAGON_INT ("Dragon Int.", true, 8.89, 1.96, BoatHullType.MONOHULL, "Drachen", "Dragon"), + EXTREME_40 ("Extreme 40", false, 12.2, 6.60, BoatHullType.CATAMARAN, "Extreme-40", "Extreme40", "ESS40"), + EUROPE_INT ("Europe Int.", true, 3.35, 1.35, BoatHullType.MONOHULL, "Europe"), + F_18 ("Formula 18", true, 6.85, 2.25, BoatHullType.CATAMARAN, "F18", "F-18"), + FARR_30 ("Farr 30", true, 9.42, 3.08, BoatHullType.MONOHULL, "F30", "F-30", "Farr-30"), + FINN ("Finn", true, 4.50, 1.51, BoatHullType.MONOHULL), + FOLKBOAT ("Folkboat", true, 7.68, 2.20, BoatHullType.MONOHULL, "Folke", "Folkeboot"), + F_16 ("Formula 16", true, 5.00, 2.50, BoatHullType.CATAMARAN, "F16", "F-16"), + HOBIE_16 ("Hobie 16", true, 5.05, 2.41, BoatHullType.CATAMARAN, "H16"), + H_BOAT ("H-Boat", true, 8.28, 2.18, BoatHullType.MONOHULL, "HB"), + HOBIE_TIGER ("Hobie Tiger", true, 5.51, 2.60, BoatHullType.CATAMARAN), + HOBIE_WILD_CAT ("Hobie Wild Cat", true, 5.49, 2.59, BoatHullType.CATAMARAN, "Hobie Wild Cat F18"), + J70 ("J/70", true, 6.93, 2.25, BoatHullType.MONOHULL, "J70", "J-70"), + J80 ("J/80", true, 8.0, 2.51, BoatHullType.MONOHULL, "J80", "J-80"), + J24 ("J/24", true, 7.32, 2.67, BoatHullType.MONOHULL, "J24", "J-24"), + KITE ("Kite", true, 3.35, 1.52, BoatHullType.MONOHULL), // + LASER_4_7 ("Laser 4.7", true, 4.20, 1.39, BoatHullType.MONOHULL, "L4.7"), + LASER_RADIAL ("Laser Radial", true, 4.19, 1.41, BoatHullType.MONOHULL, "LAR", "Laser RAD", "RAD", "Radial"), + LASER_INT ("Laser Int.", true, 4.19, 1.39, BoatHullType.MONOHULL, "Laser", "LSR"), + LASER_SB3 ("Laser SB3", true, 6.15, 2.15, BoatHullType.MONOHULL, "LSB3", "SB20"), + MELGES_24 ("Melges 24", true, 7.32, 2.50, BoatHullType.MONOHULL, "Melges-24", "M24"), + MINI_TRANSAT ("Mini Transat 6.50", true, 6.50, 3.00, BoatHullType.MONOHULL, "Mini Transat"), + MUSTO_SKIFF ("Musto Skiff", true, 4.55, 1.35, BoatHullType.MONOHULL, "Musto Performance Skiff", "MPS", "Musto"), + NACRA_17 ("Nacra 17", true, 5.25, 2.59, BoatHullType.CATAMARAN, "N17", "Nacra-17"), + OK ("OK Dinghy", true, 5.25, 2.59, BoatHullType.MONOHULL, "OK-Dinghy", "OK-Jolle", "OK"), + OPTIMIST ("Optimist", true, 2.34, 1.07, BoatHullType.MONOHULL, "Opti", "Optimist Dinghy"), + PLATU_25 ("Platu 25", true, 7.53, 2.62, BoatHullType.MONOHULL, "Platu", "Platu-25", "PLA", "B25"), + RS_X ("RS:X", true, 2.86, 0.93, BoatHullType.SURFERBOARD, "RS-X", "RSX", "RS:X"), + SONAR ("Sonar", true, 7.01, 2.39, BoatHullType.MONOHULL), + STAR ("Star", true, 6.92, 1.74, BoatHullType.MONOHULL), + STREAMLINE ("Streamline", true, 7.15, 2.55, BoatHullType.MONOHULL), + SWAN_45 ("Swan 45", true, 13.83, 3.91, BoatHullType.MONOHULL, "Swan", "Swan-45"), + //TODO: which boatclasses of swan are important (there are several ones) + TORNADO ("Tornado Catamaran", true, 6.10, 3.02, BoatHullType.CATAMARAN, "Tornado", "Tornado Cat"), + X_99 ("X-99", true, 9.96, 2.95, BoatHullType.MONOHULL, "X99"), + CONTENDER ("Contender", true, 4.88, 1.42, BoatHullType.MONOHULL), + RC44 ("RC44", true, 13.35, 2.75, BoatHullType.MONOHULL), + FLYING_DUTCHMAN ("Flying Dutchman", true, 6.10, 1.80, BoatHullType.MONOHULL), + DYAS("Dyas", true, 7.15, 1.95, BoatHullType.MONOHULL), + INTERNATIONAL_14("International 14", true, 4.27, 1.83, BoatHullType.MONOHULL, "I14"), + OPEN_BIC("O'pen BIC", true, 2.75, 1.14, BoatHullType.MONOHULL, "OpenBIC"); + + private final String displayName; + private final String[] alternativeNames; + private final double hullLengthInMeter; + private final double hullBeamInMeter; + private final BoatHullType hullType; + private final boolean typicallyStartsUpwind; + + private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeter, + double hullBeamInMeter, BoatHullType hullType, String... alternativeNames) { + this.displayName = displayName; + this.typicallyStartsUpwind = typicallyStartsUpwind; + this.hullLengthInMeter = hullLengthInMeter; + this.hullBeamInMeter = hullBeamInMeter; + this.hullType = hullType; + this.alternativeNames = alternativeNames; + } + + private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeter, + double hullBeamInMeter, BoatHullType hullType) { + this.displayName = displayName; + this.typicallyStartsUpwind = typicallyStartsUpwind; + this.hullLengthInMeter = hullLengthInMeter; + this.hullBeamInMeter = hullBeamInMeter; + this.hullType = hullType; + this.alternativeNames = null; + } + + public static BoatClassMasterdata resolveBoatClass(String boatClassName) { + String boatClassNameToResolve = unifyBoatClassName(boatClassName); + + for (BoatClassMasterdata boatClass : values()) { + if (unifyBoatClassName(boatClass.displayName).equals(boatClassNameToResolve)) { + return boatClass; + } + if(boatClass.alternativeNames != null) { + for (String name : boatClass.alternativeNames) { + if (unifyBoatClassName(name).equals(boatClassNameToResolve)) { + return boatClass; + } + } + } + } + return null; + } + + private static String unifyBoatClassName(String boatClassName) { + return boatClassName.toUpperCase().replaceAll("\\s+",""); + } + + public Distance getHullLength() { + return new MeterDistance(hullLengthInMeter); + } + + public String getDisplayName() { + return displayName; + } + + public String[] getAlternativeNames() { + return alternativeNames == null ? new String[0] : alternativeNames; + } + + public Distance getHullBeam() { + return new MeterDistance(hullBeamInMeter); + } + + public BoatHullType getHullType() { + return hullType; + } + + public boolean isTypicallyStartsUpwind() { + return typicallyStartsUpwind; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatHullType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatHullType.java new file mode 100644 index 00000000000..e793bf5c32e --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatHullType.java @@ -0,0 +1,5 @@ +package com.sap.sailing.domain.common; + +public enum BoatHullType { + MONOHULL, CATAMARAN, TRIMARAN, SURFERBOARD +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Bounds.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Bounds.java index 60a876a4f77..19958951201 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Bounds.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/Bounds.java @@ -2,17 +2,35 @@ package com.sap.sailing.domain.common; public interface Bounds { Position getNorthEast(); + Position getSouthWest(); + Position getNorthWest(); + Position getSouthEast(); - + Bounds intersect(Bounds other); + + /** + * A short-hand for {@link #union} + */ + Bounds extend(Bounds other); + + Bounds extend(Position p); + Bounds union(Bounds other); + boolean intersects(Bounds other); + boolean contains(Position other); + boolean contains(Bounds other); + boolean isCrossesDateLine(); + boolean containsLatDeg(double latDeg); + boolean containsLngDeg(double lngDeg); + boolean isEmpty(); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java index 763ee9280e2..ef368469292 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java @@ -3,5 +3,7 @@ package com.sap.sailing.domain.common; public enum ScoringSchemeType { LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN, HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE, - HIGH_POINT_WINNER_GETS_FIVE_IGNORING_RACE_COUNT + HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT, + HIGH_POINT_WINNER_GETS_FIVE_IGNORING_RACE_COUNT, + HIGH_POINT_WINNER_GETS_SIX_IGNORING_RACE_COUNT } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java index 8786609a8a8..e9231cde87f 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java @@ -41,8 +41,10 @@ public abstract class AbstractLeaderboardDTO implements Serializable { public Set getBoatClasses() { Set result = new HashSet(); - for (CompetitorDTO competitor : rows.keySet()) { - result.add(competitor.getBoatClass()); + if(rows != null) { + for (CompetitorDTO competitor : rows.keySet()) { + result.add(competitor.getBoatClass()); + } } return result; } @@ -121,16 +123,6 @@ public abstract class AbstractLeaderboardDTO implements Serializable { return getRaceColumnByName(raceColumnName).isMedalRace(); } - private RaceColumnDTO getOrCreateRaceColumn(String raceColumnName) { - RaceColumnDTO result = getRaceColumnByName(raceColumnName); - if (result == null) { - result = new RaceColumnDTO(/* isValidInTotalScore */ true); - result.setName(raceColumnName); - races.add(result); - } - return result; - } - /** * If the {@link RaceColumnDTO} by the name raceColumnName doesn't exist yet within this leaderboard * DTO, it is created, setting is {@link RaceColumnDTO#isValidInTotalScore()} to true. This method @@ -144,15 +136,26 @@ public abstract class AbstractLeaderboardDTO implements Serializable { * @param effectiveFactor * is what you get when you call {@link RaceColumn#getFactor()} on the race column that the resulting * {@link RaceColumnDTO} represents + * @param regattaName + * must not be null if seriesName is not null; specified + * separately from trackedRaceIdentifier because a column may belong to regatta/series + * despite not having a tracked race associated + * @param seriesName + * if null, this method will produce a {@link RaceColumnDTO}, otherwise a + * {@link RaceColumnInSeriesDTO} * @param fleetDTO * must not be null */ public RaceColumnDTO addRace(String raceColumnName, Double explicitFactor, double effectiveFactor, - FleetDTO fleetDTO, boolean medalRace, RegattaAndRaceIdentifier trackedRaceIdentifier, RaceDTO race) { + String regattaName, String seriesName, FleetDTO fleetDTO, boolean medalRace, RegattaAndRaceIdentifier trackedRaceIdentifier, RaceDTO race) { assert fleetDTO != null; - RaceColumnDTO raceColumnDTO = getOrCreateRaceColumn(raceColumnName); + RaceColumnDTO raceColumnDTO = getRaceColumnByName(raceColumnName); + if (raceColumnDTO == null) { + raceColumnDTO = RaceColumnDTOFactory.INSTANCE.createRaceColumnDTO(raceColumnName, medalRace, + explicitFactor, regattaName, seriesName); + races.add(raceColumnDTO); + } raceColumnDTO.setEffectiveFactor(effectiveFactor); - raceColumnDTO.setExplicitFactor(explicitFactor); boolean contains = false; for (FleetDTO fleet : raceColumnDTO.getFleets()) { if (fleet.getName().equals(fleetDTO.getName())) { @@ -163,16 +166,14 @@ public abstract class AbstractLeaderboardDTO implements Serializable { if (!contains) { raceColumnDTO.addFleet(fleetDTO); } - raceColumnDTO.setMedalRace(medalRace); raceColumnDTO.setRaceIdentifier(fleetDTO, trackedRaceIdentifier); raceColumnDTO.setRace(fleetDTO, race); return raceColumnDTO; } - public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace, boolean isValidInTotalScore) { - RaceColumnDTO raceColumn = new RaceColumnDTO(isValidInTotalScore); - raceColumn.setName(raceColumnName); - raceColumn.setMedalRace(medalRace); + public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace, String regattaName, String seriesName) { + final RaceColumnDTO raceColumn = RaceColumnDTOFactory.INSTANCE.createRaceColumnDTO(raceColumnName, + medalRace, /* explicit factor */ null, regattaName, seriesName); races.add(raceColumn); return raceColumn; } @@ -186,6 +187,30 @@ public abstract class AbstractLeaderboardDTO implements Serializable { return null; } + public int getRaceColumnsCount() { + return races.size(); + } + + public int getRacesCount() { + int result = 0; + for (RaceColumnDTO race : getRaceList()) { + result += race.getFleets().size(); + } + return result; + } + + public int getTrackedRacesCount() { + int result = 0; + for (RaceColumnDTO race : getRaceList()) { + for (FleetDTO fleet : race.getFleets()) { + if (race.isTrackedRace(fleet)) { + result++; + } + } + } + return result; + } + public List getRaceList() { return races; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatClassDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatClassDTO.java index 3577bd4ea37..9648c8cdd59 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatClassDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatClassDTO.java @@ -5,15 +5,26 @@ import java.io.Serializable; public class BoatClassDTO extends NamedDTO implements Serializable { private static final long serialVersionUID = 1981789833769906676L; private double hullLengthInMeters; + private String displayName; BoatClassDTO() {} + public BoatClassDTO(String name, String displayName, double hullLengthInMeters) { + super(name); + this.hullLengthInMeters = hullLengthInMeters; + } + public BoatClassDTO(String name, double hullLengthInMeters) { super(name); this.hullLengthInMeters = hullLengthInMeters; + this.displayName = null; } public double getHullLengthInMeters() { return hullLengthInMeters; } + + public String getDisplayName() { + return displayName; + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java index 3598bf5affa..b7e0ddbdcc4 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java @@ -116,4 +116,9 @@ public class LeaderboardRowDTO implements Serializable { return false; return true; } + + @Override + public String toString() { + return "LeaderboardRowDTO for competitor "+competitor; + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java index c399d6dbdf6..37262e14cfc 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java @@ -9,9 +9,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.TimingConstants; +import com.sap.sse.common.Util; public class RaceColumnDTO extends NamedDTO implements Serializable { private static final long serialVersionUID = -3228244237400937852L; @@ -19,25 +21,17 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { private List fleets; private Map trackedRaceIdentifiersPerFleet; private Map racesPerFleet; - private Boolean isValidInTotalScore; private Double explicitFactor; private double effectiveFactor; private Map raceLogTrackingInfos = new HashMap(); - RaceColumnDTO() {} // for GWT serialization - - public RaceColumnDTO(Boolean isValidInTotalScore) { - this.isValidInTotalScore = isValidInTotalScore; + public RaceColumnDTO() { trackedRaceIdentifiersPerFleet = new HashMap(); racesPerFleet = new HashMap(); fleets = new ArrayList(); } - public boolean isValidInTotalScore() { - return isValidInTotalScore; - } - public String getRaceColumnName() { return getName(); } @@ -54,6 +48,17 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { return trackedRaceIdentifiersPerFleet.values().contains(raceIdentifier); } + public FleetDTO getFleet(RaceIdentifier raceIdentifier) { + FleetDTO result = null; + for (FleetDTO identifier : trackedRaceIdentifiersPerFleet.keySet()) { + if (Util.equalsWithNull(trackedRaceIdentifiersPerFleet.get(identifier), raceIdentifier)) { + result = identifier; + break; + } + } + return result; + } + public boolean isMedalRace() { return medalRace; } @@ -93,7 +98,7 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { this.racesPerFleet.put(fleet, race); } - public Iterable getFleets() { + public List getFleets() { return fleets; } @@ -178,20 +183,18 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { return result; } - /** - * Returns live state for the current server time - * @see RaceColumnDTO#isLive(FleetDTO, long) - * @param fleet - * @return - */ - public boolean isLiveInServerTime(FleetDTO fleet) { - return isLive(fleet, 0); - } - public boolean containsRace(RaceIdentifier preSelectedRace) { return trackedRaceIdentifiersPerFleet.values().contains(preSelectedRace); } + public boolean hasLiveRaces(long serverTimePointAsMillis) { + boolean result = false; + for(FleetDTO fleet: fleets) { + result |= isLive(fleet, serverTimePointAsMillis); + } + return result; + } + public boolean hasTrackedRaces() { Set raceIdentifiers = new HashSet(trackedRaceIdentifiersPerFleet.values()); raceIdentifiers.remove(null); @@ -229,7 +232,6 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((explicitFactor == null) ? 0 : explicitFactor.hashCode()); result = prime * result + ((fleets == null) ? 0 : fleets.hashCode()); - result = prime * result + ((isValidInTotalScore == null) ? 0 : isValidInTotalScore.hashCode()); result = prime * result + (medalRace ? 1231 : 1237); result = prime * result + ((racesPerFleet == null) ? 0 : racesPerFleet.hashCode()); result = prime * result @@ -258,11 +260,6 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { return false; } else if (!fleets.equals(other.fleets)) return false; - if (isValidInTotalScore == null) { - if (other.isValidInTotalScore != null) - return false; - } else if (!isValidInTotalScore.equals(other.isValidInTotalScore)) - return false; if (medalRace != other.medalRace) return false; if (racesPerFleet == null) { @@ -293,4 +290,8 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { public void setRaceLogTrackingInfo(FleetDTO fleet, RaceLogTrackingInfoDTO info) { raceLogTrackingInfos.put(fleet, info); } + + public String getSeriesName() { + return LeaderboardNameConstants.DEFAULT_SERIES_NAME; + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java new file mode 100755 index 00000000000..7d8a0efbb67 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTOFactory.java @@ -0,0 +1,29 @@ +package com.sap.sailing.domain.common.dto; + +public class RaceColumnDTOFactory { + public static final RaceColumnDTOFactory INSTANCE = new RaceColumnDTOFactory(); + + /** + * @param regattaName + * must not be null if seriesName is not null + * @param seriesName + * when null, a regular {@link RaceColumnDTO} will be produced and initialized from the + * properties passed; otherwise, a {@link RaceColumnInSeriesDTO} will be created. + */ + public RaceColumnDTO createRaceColumnDTO(String columnName, boolean isMedal, Double explicitFactor, String regattaName, String seriesName) { + final RaceColumnDTO raceColumnDTO; + if (seriesName != null) { + raceColumnDTO = new RaceColumnInSeriesDTO(seriesName, regattaName); + } else { + raceColumnDTO = new RaceColumnDTO(); + } + fillRaceColumnDTO(raceColumnDTO, columnName, isMedal, explicitFactor); + return raceColumnDTO; + } + + private void fillRaceColumnDTO(RaceColumnDTO raceColumnDTO, String columnName, boolean isMedal, Double explicitFactor) { + raceColumnDTO.setName(columnName); + raceColumnDTO.setMedalRace(isMedal); + raceColumnDTO.setExplicitFactor(explicitFactor); + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java index dd9f5fd6056..9b4291b1d0f 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnInSeriesDTO.java @@ -45,6 +45,7 @@ public class RaceColumnInSeriesDTO extends RaceColumnDTO { return true; } + @Override public String getSeriesName() { return seriesName; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceDTO.java index 794ea1f1e20..42798eb83c0 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceDTO.java @@ -28,6 +28,7 @@ public class RaceDTO extends NamedDTO { public PlacemarkOrderDTO places; public TrackedRaceDTO trackedRace; + public TrackedRaceStatisticsDTO trackedRaceStatistics; private String regattaName; public String boatClass; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/TrackedRaceStatisticsDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/TrackedRaceStatisticsDTO.java new file mode 100644 index 00000000000..01903a448de --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/TrackedRaceStatisticsDTO.java @@ -0,0 +1,38 @@ +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sailing.domain.common.Duration; + +public class TrackedRaceStatisticsDTO implements Serializable { + private static final long serialVersionUID = -2123085927945474642L; + + /** Indicators if statistical data is available for a date or not */ + public boolean hasGPSData; + public boolean hasAudioData; + public boolean hasVideoData; + public boolean hasMeasuredWindData; + public boolean hasLegProgressData; + public boolean hasLeaderOrWinnerData; + + public Duration averageGPSDataSampleInterval; + public Integer measuredWindSourcesCount; + public Duration averageWindDataSampleInterval; + public Integer audioTracksCount; + public Integer videoTracksCount; + + public Integer totalLegsCount; + public Integer currentLegNo; + public CompetitorDTO leaderOrWinner; + /** + * Default constructor for GWT-Serialization + */ + public TrackedRaceStatisticsDTO() { + hasGPSData = false; + hasAudioData= false; + hasVideoData= false; + hasMeasuredWindData = false; + hasLegProgressData = false; + hasLeaderOrWinnerData = false; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/BoundsImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/BoundsImpl.java index 5ef09a1da53..86784eb8cd3 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/BoundsImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/BoundsImpl.java @@ -98,6 +98,16 @@ public class BoundsImpl implements Bounds { } return new BoundsImpl(new DegreePosition(minLatDeg, bestWest), new DegreePosition(maxLatDeg, bestEast)); } + + @Override + public Bounds extend(Bounds other) { + return union(other); + } + + @Override + public Bounds extend(Position p) { + return union(new BoundsImpl(p, p)); + } private boolean spansLngDeg(double westLngDeg, double eastLngDeg, double lngDeg) { return isCrossingDateLine(westLngDeg, eastLngDeg) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/DegreeBearingImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/DegreeBearingImpl.java index 63061a72f50..60ff5fd53f6 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/DegreeBearingImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/DegreeBearingImpl.java @@ -20,10 +20,5 @@ public class DegreeBearingImpl extends AbstractBearing implements Bearing { public double getDegrees() { return bearingDeg; } - - @Override - public double getRadians() { - return getDegrees() / 180. * Math.PI; - } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/media/MediaTrack.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/media/MediaTrack.java index 68e2f3fea62..b3643ff9426 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/media/MediaTrack.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/media/MediaTrack.java @@ -28,6 +28,15 @@ public class MediaTrack implements Serializable { public String toString() { return mediaType.name() + '/' + mediaSubType.toString(); } + + public static MimeType byName(String mimeTypeName) { + try { + return MimeType.valueOf(mimeTypeName); + } catch (IllegalArgumentException ex) { + return null; + } + } + } public enum MediaType { diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/shared/IgtimiWindReceiver.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/shared/IgtimiWindReceiver.java index f0f4b765eb9..4cd68bc1f7f 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/shared/IgtimiWindReceiver.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/shared/IgtimiWindReceiver.java @@ -185,42 +185,51 @@ public class IgtimiWindReceiver implements BulkFixReceiver { Speed aws = getAWS(timePoint, awsPair); com.sap.sse.common.Util.Pair gpsPair = getSurroundingFixes(getGpsTrack(deviceSerialNumber), timePoint); Position pos = getPosition(timePoint, gpsPair); - com.sap.sse.common.Util.Pair hdgPair = getSurroundingFixes(getHdgTrack(deviceSerialNumber), timePoint); - com.sap.sse.common.Util.Pair hdgmPair = getSurroundingFixes(getHdgmTrack(deviceSerialNumber), timePoint); - Bearing heading = getHeading(timePoint, hdgPair, hdgmPair, pos); - if (awa != null && aws != null && pos != null && heading != null) { - Bearing apparentWindDirection = heading.add(awa); - SpeedWithBearing apparentWindSpeedWithDirection = new KnotSpeedWithBearingImpl(aws.getKnots(), apparentWindDirection); - /* - * Hint from Brent Russell from Igtimi, at 2013-12-05 on the question whether to use GpsLatLong to improve - * precision of boat speed / coarse over SOG/COG measurements: - * - * "Personally I would use COG/SOG exclusively, and if unhappy with the result add a small amount of - * smoothing and consider dropping samples as outliers if they cause a SOG discontinuity. The latter might - * happen as a satellite is dropped/acquired - and I'd expect to see a time correlated position jump as - * well. Probably not though a direction/speed correlation :) - * - * All our GPS systems are using Doppler to calculate COG/SOG and this should be the most accurate measure. - * I don't believe that delta position really adds any more "truth" to the measurement of physical reality, - * if that makes sense. I'd trust d-p even less at low speeds, where you'll see the most disagreement. Also - * there is a significant quantisation noise error in the d-p calculations from the GPS resolution too, so - * you'd have to smooth it before averaging - possibly in a speed dependent way. - * - * Remember that Doppler COG/SOG is using the same raw satellite measurements that are being used to - * calculate position, just the algorithm is different. I suspect that merging the two might be, in - * practice, just a slightly indirect way of averaging. If you like the central limit theorem in action over - * the set of algorithms! - * - * So again, my personal preference would be to work with the data that should be the most accurate - * (COG/SOG) and consider algorithms that handle smoothing of that data best." - */ - com.sap.sse.common.Util.Pair sogPair = getSurroundingFixes(getSogTrack(deviceSerialNumber), timePoint); - Speed sog = getSOG(timePoint, sogPair); - com.sap.sse.common.Util.Pair cogPair = getSurroundingFixes(getCogTrack(deviceSerialNumber), timePoint); - Bearing cog = getCOG(timePoint, cogPair); - SpeedWithBearing sogCog = new KnotSpeedWithBearingImpl(sog.getKnots(), cog); - SpeedWithBearing trueWindSpeedAndDirection = apparentWindSpeedWithDirection.add(sogCog); - result = new WindImpl(pos, timePoint, trueWindSpeedAndDirection); + if (pos != null) { + com.sap.sse.common.Util.Pair hdgPair = getSurroundingFixes(getHdgTrack(deviceSerialNumber), timePoint); + com.sap.sse.common.Util.Pair hdgmPair = getSurroundingFixes(getHdgmTrack(deviceSerialNumber), timePoint); + Bearing heading = getHeading(timePoint, hdgPair, hdgmPair, pos); + if (awa != null && aws != null && heading != null) { + Bearing apparentWindDirection = heading.add(awa); + SpeedWithBearing apparentWindSpeedWithDirection = new KnotSpeedWithBearingImpl(aws.getKnots(), apparentWindDirection); + /* + * Hint from Brent Russell from Igtimi, at 2013-12-05 on the question whether to use GpsLatLong to + * improve precision of boat speed / coarse over SOG/COG measurements: + * + * "Personally I would use COG/SOG exclusively, and if unhappy with the result add a small amount of + * smoothing and consider dropping samples as outliers if they cause a SOG discontinuity. The latter + * might happen as a satellite is dropped/acquired - and I'd expect to see a time correlated position + * jump as well. Probably not though a direction/speed correlation :) + * + * All our GPS systems are using Doppler to calculate COG/SOG and this should be the most accurate + * measure. I don't believe that delta position really adds any more "truth" to the measurement of + * physical reality, if that makes sense. I'd trust d-p even less at low speeds, where you'll see the + * most disagreement. Also there is a significant quantisation noise error in the d-p calculations from + * the GPS resolution too, so you'd have to smooth it before averaging - possibly in a speed dependent + * way. + * + * Remember that Doppler COG/SOG is using the same raw satellite measurements that are being used to + * calculate position, just the algorithm is different. I suspect that merging the two might be, in + * practice, just a slightly indirect way of averaging. If you like the central limit theorem in action + * over the set of algorithms! + * + * So again, my personal preference would be to work with the data that should be the most accurate + * (COG/SOG) and consider algorithms that handle smoothing of that data best." + */ + com.sap.sse.common.Util.Pair sogPair = getSurroundingFixes(getSogTrack(deviceSerialNumber), timePoint); + Speed sog = getSOG(timePoint, sogPair); + com.sap.sse.common.Util.Pair cogPair = getSurroundingFixes(getCogTrack(deviceSerialNumber), timePoint); + Bearing cog = getCOG(timePoint, cogPair); + if (sog != null && cog != null) { + SpeedWithBearing sogCog = new KnotSpeedWithBearingImpl(sog.getKnots(), cog); + SpeedWithBearing trueWindSpeedAndDirection = apparentWindSpeedWithDirection.add(sogCog); + result = new WindImpl(pos, timePoint, trueWindSpeedAndDirection); + } else { + result = null; + } + } else { + result = null; + } } else { result = null; } 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 04eacd01bed..3626d2d72f2 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 @@ -136,6 +136,8 @@ import com.sap.sailing.domain.racelog.RevokeEvent; import com.sap.sailing.domain.racelog.impl.CompetitorResultsImpl; import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl; import com.sap.sailing.domain.racelog.impl.RaceLogImpl; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; +import com.sap.sailing.domain.racelog.scoring.impl.AdditionalScoringInformationEventImpl; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -711,6 +713,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // migration: leaderboard groups that don't yet have a UUID receive a random one } String description = (String) o.get(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name()); + String displayName = (String) o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name()); boolean displayGroupsInReverseOrder = false; // default value Object displayGroupsInReverseOrderObj = o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name()); if (displayGroupsInReverseOrderObj != null) { @@ -732,7 +735,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } logger.info("loaded leaderboard group "+name); - LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayGroupsInReverseOrder, leaderboards); + LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayName, displayGroupsInReverseOrder, leaderboards); Object overallLeaderboardIdOrName = o.get(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name()); if (overallLeaderboardIdOrName != null) { final DBObject dbOverallLeaderboard; @@ -1341,6 +1344,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return loadRaceLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(CloseOpenEndedDeviceMappingEvent.class.getSimpleName())) { return loadRaceLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + } else if (eventClass.equals(AdditionalScoringInformationEventImpl.class.getSimpleName())) { + return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); @@ -1426,6 +1431,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { deviceMappingEventId, closingTimePoint); } + private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, + Serializable id, Integer passId, List competitors, DBObject dbObject) { + Object additionalScoringInformationTypeInfo = dbObject.get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); + AdditionalScoringInformationType informationType = AdditionalScoringInformationType.UNKNOWN; + if (additionalScoringInformationTypeInfo != null) { + informationType = AdditionalScoringInformationType.valueOf(additionalScoringInformationTypeInfo.toString()); + } else { + logger.warning("Could not find additional scoring information attached to db log for " + dbObject.toString()); + } + return raceLogEventFactory.createAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, competitors, passId, informationType); + } + private RaceLogEvent loadRaceLogRaceLogProtestStartTimeEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME); 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 76aec13d21b..189fefa5462 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 @@ -71,7 +71,8 @@ public enum FieldNames { LEADERBOARD_SCORE_CORRECTION_COMMENT, LEADERBOARD_COLUMN_FACTORS, // leaderboard group - LEADERBOARD_GROUP_UUID, LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION, LEADERBOARD_GROUP_LEADERBOARDS, LEADERBOARD_GROUP_OVERALL_LEADERBOARD, + LEADERBOARD_GROUP_UUID, LEADERBOARD_GROUP_NAME, LEADERBOARD_GROUP_DESCRIPTION, + LEADERBOARD_GROUP_DISPLAY_NAME, LEADERBOARD_GROUP_LEADERBOARDS, LEADERBOARD_GROUP_OVERALL_LEADERBOARD, LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER, // race ID to regatta name @@ -111,5 +112,8 @@ public enum FieldNames { FROM_MILLIS, TO_MILLIS, // Result Import url fields - RESULT_PROVIDERNAME, RESULT_URL + RESULT_PROVIDERNAME, RESULT_URL, + + // type of additional scoring information + RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE } 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 55c4eb1ed35..fa9302e3dcb 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 @@ -82,6 +82,7 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -441,6 +442,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_UUID.name(), leaderboardGroup.getId()); dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_NAME.name(), leaderboardGroup.getName()); dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name(), leaderboardGroup.getDescription()); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name(), leaderboardGroup.getDisplayName()); dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name(), leaderboardGroup.isDisplayGroupsInReverseOrder()); final Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); if (overallLeaderboard != null) { @@ -842,6 +844,21 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { return result; } + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, AdditionalScoringInformationEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeAdditionalScoringInformation(event)); + return result; + } + + private Object storeAdditionalScoringInformation(AdditionalScoringInformationEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), event.getClass().getSimpleName()); + result.put(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name(), event.getType().name()); + return result; + } + private Object storeRaceLogWindFix(RaceLogWindFixEvent event) { DBObject result = new BasicDBObject(); storeRaceLogEventProperties(event, result); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java index 39b0108f90e..7fd0e2517ed 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRaceLogStoreVisitor.java @@ -20,6 +20,7 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -166,4 +167,10 @@ public class MongoRaceLogStoreVisitor implements RaceLogEventVisitor { DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); mongoObjectFactory.storeRaceLogEventEvent(object); } + + @Override + public void visit(AdditionalScoringInformationEvent event) { + DBObject object = mongoObjectFactory.storeRaceLogEntry(raceLogIdentifier, event); + mongoObjectFactory.storeRaceLogEventEvent(object); + } } diff --git a/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF index e5aef624aa3..d9ad7470bde 100644 --- a/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF @@ -17,6 +17,8 @@ Export-Package: com.sap.sailing.domain.base, com.sap.sailing.domain.racelog, com.sap.sailing.domain.racelog.analyzing.impl, com.sap.sailing.domain.racelog.impl, + com.sap.sailing.domain.racelog.scoring, + com.sap.sailing.domain.racelog.scoring.impl, com.sap.sailing.domain.racelog.state, com.sap.sailing.domain.racelog.state.impl, com.sap.sailing.domain.racelog.state.racingprocedure, diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatClass.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatClass.java index 21ce155598e..c1bfbe481c0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatClass.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BoatClass.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.base; +import com.sap.sailing.domain.common.BoatHullType; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.TimePoint; import com.sap.sse.common.Named; @@ -37,9 +38,15 @@ public interface BoatClass extends Named, IsManagedBySharedDomainFactory { * start with a non-upwind leg even though this method returns true. */ boolean typicallyStartsUpwind(); - - Distance getHullLength(); + String getDisplayName(); + + Distance getHullLength(); + + Distance getHullBeam(); + + BoatHullType getHullType(); + /** * Downwind leg-based wind estimations are inherently less confident than upwind leg-based estimations because * jibing angles vary more greatly from boat to boat than tacking angles. diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardGroupBase.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardGroupBase.java index a73fe817219..0bf8ea7e4e1 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardGroupBase.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardGroupBase.java @@ -10,4 +10,6 @@ public interface LeaderboardGroupBase extends Renamable, WithID { String getDescription(); void setDescriptiom(String description); boolean hasOverallLeaderboard(); + String getDisplayName(); + void setDisplayName(String displayName); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatClassImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatClassImpl.java index 835b54c7510..1b213785fef 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatClassImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatClassImpl.java @@ -2,6 +2,8 @@ package com.sap.sailing.domain.base.impl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.common.BoatClassMasterdata; +import com.sap.sailing.domain.common.BoatHullType; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.common.impl.NamedImpl; @@ -35,18 +37,35 @@ public class BoatClassImpl extends NamedImpl implements BoatClass { private final long approximateManeuverDurationInMilliseconds; private final boolean typicallyStartsUpwind; + + private final String displayName; private final Distance hullLength; + + private final Distance hullBeam; + + private final BoatHullType hullType; public BoatClassImpl(String name, boolean typicallyStartsUpwind) { - super(name); - this.typicallyStartsUpwind = typicallyStartsUpwind; - approximateManeuverDurationInMilliseconds = 8000; // as discussed with Dennis Gehrlein - // TODO see bug 911: these values need to come from a master data base - hullLength = name.toLowerCase().contains("extreme") && name.contains("40") - ? new MeterDistance(40*12*2.54/100) - : new MeterDistance(5); // a good average for the olympic classes... + this(name, typicallyStartsUpwind, /* displayName */ null, + /* hull length */ new MeterDistance(5), /* hullBeam */ null, /* hullType */ null); } + + public BoatClassImpl(String name, BoatClassMasterdata masterData) { + this(name, masterData.isTypicallyStartsUpwind(), masterData.getDisplayName(), masterData.getHullLength(), + masterData.getHullBeam(), masterData.getHullType()); + } + + public BoatClassImpl(String name, boolean typicallyStartsUpwind, String displayName, + Distance hullLength, Distance hullBeam, BoatHullType hullType) { + super(name); + this.typicallyStartsUpwind = typicallyStartsUpwind; + this.displayName = displayName; + this.hullLength = hullLength; + this.hullBeam = hullBeam; + this.hullType = hullType; + approximateManeuverDurationInMilliseconds = 8000; // as discussed with Dennis Gehrlein + } @Override public long getApproximateManeuverDurationInMilliseconds() { @@ -110,4 +129,16 @@ public class BoatClassImpl extends NamedImpl implements BoatClass { return domainFactory.getOrCreateBoatClass(getName(), typicallyStartsUpwind()); } + public String getDisplayName() { + return displayName; + } + + public Distance getHullBeam() { + return hullBeam; + } + + public BoatHullType getHullType() { + return hullType; + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/LeaderboardGroupBaseImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/LeaderboardGroupBaseImpl.java index 59c1fd5e78e..347ba1d5e3a 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/LeaderboardGroupBaseImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/LeaderboardGroupBaseImpl.java @@ -11,12 +11,14 @@ public abstract class LeaderboardGroupBaseImpl implements LeaderboardGroupBase { private UUID id; private String name; + private String displayName; private String description; - public LeaderboardGroupBaseImpl(UUID id, String name, String description) { + public LeaderboardGroupBaseImpl(UUID id, String name, String description, String displayName) { this.id = id; this.name = name; this.description = description; + this.displayName = displayName; } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { @@ -51,4 +53,14 @@ public abstract class LeaderboardGroupBaseImpl implements LeaderboardGroupBase { this.name = name; } + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 19e0bb03206..e548557cf08 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -26,6 +26,7 @@ import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherMulti; import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle; +import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.Color; import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.PassingInstruction; @@ -268,6 +269,13 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) { synchronized (boatClassCache) { BoatClass result = boatClassCache.get(name); + if(result == null) { + BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name); + if(boatClassMasterdata != null) { + result = new BoatClassImpl(name, boatClassMasterdata); + boatClassCache.put(name, result); + } + } if (result == null) { result = new BoatClassImpl(name, typicallyStartsUpwind); boatClassCache.put(name, result); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/StrippedLeaderboardGroupImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/StrippedLeaderboardGroupImpl.java index 7df0a3d23a8..b97b42187ce 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/StrippedLeaderboardGroupImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/StrippedLeaderboardGroupImpl.java @@ -6,8 +6,8 @@ public class StrippedLeaderboardGroupImpl extends LeaderboardGroupBaseImpl { private static final long serialVersionUID = 7263952130620919924L; private final boolean hasOverallLeaderboard; - public StrippedLeaderboardGroupImpl(UUID id, String name, String description, boolean hasOverallLeaderboard) { - super(id, name, description); + public StrippedLeaderboardGroupImpl(UUID id, String name, String description, String displayName, boolean hasOverallLeaderboard) { + super(id, name, description, displayName); this.hasOverallLeaderboard = hasOverallLeaderboard; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index a27469b908f..f1b221ab707 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -219,7 +219,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), c .getBoat().getSailID(), c.getId().toString(), new BoatClassDTO(c.getBoat().getBoatClass() - .getName(), c.getBoat().getBoatClass().getHullLength().getMeters())); + .getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters())); weakCompetitorDTOCache.put(c, competitorDTO); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/InvalidatesLeaderboardCache.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/InvalidatesLeaderboardCache.java new file mode 100644 index 00000000000..5282ce66d41 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/InvalidatesLeaderboardCache.java @@ -0,0 +1,11 @@ +package com.sap.sailing.domain.racelog; + +/** + * Marker interface that all classes implementing {@link RaceLogEvent} should + * also implement, if the addition of that event should invalidate leaderboard cache. + * + * @author Simon Marcel Pamies + */ +public interface InvalidatesLeaderboardCache { + +} 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 41a28e44349..060ee5685d5 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 @@ -5,6 +5,7 @@ import java.util.HashSet; import java.util.NavigableSet; import java.util.UUID; +import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.WithID; import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException; import com.sap.sailing.domain.racelog.impl.RaceLogEventComparator; @@ -109,7 +110,8 @@ public interface RaceLog extends Track, WithID { RaceLogEvent getEventById(Serializable id); /** - * Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}. + * Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}. Events are sorted by + * their {@link TimePoint} and the oldest is returned first. * @return */ NavigableSet getUnrevokedEvents(); 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 26ec9195352..df3d771eff8 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,6 +12,8 @@ import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sailing.domain.racelog.impl.RaceLogEventFactoryImpl; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -117,4 +119,7 @@ public interface RaceLogEventFactory { CloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint logicalTimePoint, RaceLogEventAuthor author, int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint); + + AdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint timePoint, Serializable id, RaceLogEventAuthor author, int currentPassId, + AdditionalScoringInformationType informationType); } 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 9c73db4e60e..d3896c46577 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,8 @@ import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sailing.domain.racelog.impl.RaceLogEventRestoreFactoryImpl; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -90,4 +92,8 @@ public interface RaceLogEventRestoreFactory extends RaceLogEventFactory { CloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint); + + AdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint createdAt, RaceLogEventAuthor author, + TimePoint logicalTimePoint, Serializable pId, List competitors, int passId, + AdditionalScoringInformationType informationType); } 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 21f4c7f52c4..c746af2090c 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; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -51,4 +52,6 @@ public interface RaceLogEventVisitor { public void visit(DefineMarkEvent event); public void visit(CloseOpenEndedDeviceMappingEvent event); + + public void visit(AdditionalScoringInformationEvent additionalScoringInformation); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AdditionalScoringInformationFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AdditionalScoringInformationFinder.java new file mode 100644 index 00000000000..46133b89834 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/analyzing/impl/AdditionalScoringInformationFinder.java @@ -0,0 +1,57 @@ +package com.sap.sailing.domain.racelog.analyzing.impl; + +import java.util.ArrayList; +import java.util.List; + +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; + +/** + * Returns all {@link AdditionalScoringInformationEvent}s from the race log + * that have not been revoked when using {@link #analyze()}. The resulting list + * has the newest event first. The pass id is not relevant for the result. + * + * The reason that this finder returns a list is that there could be more than + * one event of the same class but having a different {@link AdditionalScoringInformationType}. + * + * One can also use {@link #analyze(AdditionalScoringInformationType)} to check + * for the existence of an event with exactly the provided type. + * + * @author Simon Marcel Pamies + */ +public class AdditionalScoringInformationFinder extends RaceLogAnalyzer> { + + public AdditionalScoringInformationFinder(RaceLog raceLog) { + super(raceLog); + } + + /** + * Analyze the race log for all events that match the given type filter. Returns only the newest + * one as we assume that there can be only one unrevoked event of the same type. + */ + public AdditionalScoringInformationEvent analyze(AdditionalScoringInformationType filterBy) { + AdditionalScoringInformationEvent result = null; + final List allUnrevokedEventsFromNewestToOldest = analyze(); + for (AdditionalScoringInformationEvent event : allUnrevokedEventsFromNewestToOldest) { + if (event != null && event.getType() == filterBy) { + result = event; + break; + } + } + return result; + } + + @Override + protected List performAnalysis() { + final List result = new ArrayList(); + // fetch all unrevoked events starting with newest going to oldest + for (RaceLogEvent event : getRaceLog().getUnrevokedEventsDescending()) { + if (event instanceof AdditionalScoringInformationEvent) { + result.add((AdditionalScoringInformationEvent) event); + } + } + return result; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/AbstractRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/AbstractRaceLogChangedVisitor.java index 138ac662ab8..5e8c5cb046d 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/AbstractRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/AbstractRaceLogChangedVisitor.java @@ -16,6 +16,7 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -125,4 +126,9 @@ public abstract class AbstractRaceLogChangedVisitor implements RaceLogEventVisit public void visit(CloseOpenEndedDeviceMappingEvent event) { notifyListenerAboutEventAdded(event); } + + @Override + public void visit(AdditionalScoringInformationEvent additionalScoringInformation) { + notifyListenerAboutEventAdded(additionalScoringInformation); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/BaseRaceLogEventVisitor.java index 16bca0b04ec..cc86383f8f7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/BaseRaceLogEventVisitor.java @@ -15,6 +15,7 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -132,4 +133,9 @@ public abstract class BaseRaceLogEventVisitor implements RaceLogEventVisitor { public void visit(CloseOpenEndedDeviceMappingEvent event) { } + + @Override + public void visit(AdditionalScoringInformationEvent event) { + + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogChangedVisitor.java index 4df2cd19f56..fbc9092a2d4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/impl/RaceLogChangedVisitor.java @@ -14,4 +14,5 @@ public class RaceLogChangedVisitor extends AbstractRaceLogChangedVisitor { protected void notifyListenerAboutEventAdded(RaceLogEvent event) { listener.eventAdded(event); } + } 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 6838ddef26b..97b5e60f141 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 @@ -2,6 +2,7 @@ package com.sap.sailing.domain.racelog.impl; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -30,6 +31,9 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; +import com.sap.sailing.domain.racelog.scoring.impl.AdditionalScoringInformationEventImpl; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -268,4 +272,11 @@ public class RaceLogEventFactoryImpl implements RaceLogEventFactory { return new CloseOpenEndedDeviceMappingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), passId, deviceMappingEventId, closingTimePoint); } + + @Override + public AdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint timePoint, Serializable id, + RaceLogEventAuthor author, int currentPassId, AdditionalScoringInformationType informationType) { + return new AdditionalScoringInformationEventImpl(MillisecondsTimePoint.now(), author, timePoint, id, Collections.emptyList(), currentPassId, + informationType); + } } 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 0f61f469175..70e1241ce1d 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 @@ -28,6 +28,9 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; +import com.sap.sailing.domain.racelog.scoring.impl.AdditionalScoringInformationEventImpl; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -178,4 +181,11 @@ public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl impl return new CloseOpenEndedDeviceMappingEventImpl(createdAt, author, logicalTimePoint, pId, passId, deviceMappingEventId, closingTimePoint); } + + @Override + public AdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint createdAt, + RaceLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, List competitors, int passId, + AdditionalScoringInformationType informationType) { + return new AdditionalScoringInformationEventImpl(createdAt, author, logicalTimePoint, pId, competitors, passId, informationType); + } } 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 04e3674d891..2e7397f6e3e 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 @@ -153,7 +153,6 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { RevokeEvent revokeEvent = (RevokeEvent) newEvent; try { checkIfSuccessfullyRevokes(revokeEvent); - lockForWrite(); revokedEventIds.add(revokeEvent.getRevokedEventId()); unlockAfterWrite(); @@ -169,15 +168,20 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { unlockAfterRead(); if (revokedEvent == null) { - throw new NotRevokableException("RevokeEvent added, that refers to non-existent event to be revoked"); - } + // it can happen that the event that has been revoked is not yet loaded - as we assume + // that race log events never get removed we can safely continue and assume that + // the event will be loaded later + logger.warning("RevokeEvent for "+revokeEvent.getShortInfo()+" added, that refers to non-existent event to be revoked. Could also happen that the revoke event is before the event to be revoked."); + } else { + if (! (revokedEvent instanceof Revokable)) { + throw new NotRevokableException("RevokeEvent trying to revoke non-revokable event"); + } - if (! (revokedEvent instanceof Revokable)) { - throw new NotRevokableException("RevokeEvent trying to revoke non-revokable event"); - } - - if (getInternalRawFixes().comparator().compare(revokeEvent, revokedEvent) <= 0) { - throw new NotRevokableException("RevokeEvent does not have sufficient priority"); + // make sure to compare only author priorities - assuming that revoke events are + // independent of passes and times + if (revokeEvent.getAuthor().compareTo(revokedEvent.getAuthor()) < 0) { + throw new NotRevokableException("RevokeEvent does not have sufficient priority"); + } } } @@ -301,7 +305,7 @@ public class RaceLogImpl extends TrackImpl implements RaceLog { try { for (RaceLogEvent event : getRawFixes()) { if (event instanceof RevokeEvent) { - revokedEventIds.add(event.getId()); + revokedEventIds.add(((RevokeEvent)event).getRevokedEventId()); } } } finally { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationEvent.java new file mode 100644 index 00000000000..07e570acead --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationEvent.java @@ -0,0 +1,22 @@ +package com.sap.sailing.domain.racelog.scoring; + +import com.sap.sailing.domain.racelog.InvalidatesLeaderboardCache; +import com.sap.sailing.domain.racelog.RaceLogEvent; +import com.sap.sailing.domain.racelog.Revokable; + +/** + * Event that could possibly overwrite scoring for a leaderboard column. The idea + * is that the scoring scheme checks if such an event is available and if it applies + * extended scoring rules. The additional information contains a type that indicates + * which action should be executed. + * + * @author Simon Marcel Pamies + */ +public interface AdditionalScoringInformationEvent extends RaceLogEvent, Revokable, InvalidatesLeaderboardCache { + + /** + * @return the type of information this event holds + */ + AdditionalScoringInformationType getType(); + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationType.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationType.java new file mode 100644 index 00000000000..004b3001ce4 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/AdditionalScoringInformationType.java @@ -0,0 +1,17 @@ +package com.sap.sailing.domain.racelog.scoring; + +public enum AdditionalScoringInformationType { + /** + * Indicates that for a scoring scheme adhering to a max point rule + * where the winner gets a higher number than its successors the + * maximum number of points is lowered. The concrete amount is + * decided by the scoring scheme. + */ + MAX_POINTS_DECREASE_MAX_SCORE, + + /** + * Unknown information scoring type - should not be used except + * for tests + */ + UNKNOWN +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/impl/AdditionalScoringInformationEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/impl/AdditionalScoringInformationEventImpl.java new file mode 100644 index 00000000000..f047869b925 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/scoring/impl/AdditionalScoringInformationEventImpl.java @@ -0,0 +1,44 @@ +package com.sap.sailing.domain.racelog.scoring.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.RaceLogEventAuthor; +import com.sap.sailing.domain.racelog.RaceLogEventVisitor; +import com.sap.sailing.domain.racelog.impl.RaceLogEventImpl; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; + +public class AdditionalScoringInformationEventImpl extends RaceLogEventImpl implements AdditionalScoringInformationEvent { + private static final long serialVersionUID = -7627714111951381979L; + + private final AdditionalScoringInformationType informationType; + + public AdditionalScoringInformationEventImpl(TimePoint createdAt, RaceLogEventAuthor author, TimePoint logicalTimePoint, + Serializable pId, List competitors, int pPassId, AdditionalScoringInformationType informationType) { + super(createdAt, author, logicalTimePoint, pId, competitors, pPassId); + this.informationType = informationType; + } + + @Override + public void accept(RaceLogEventVisitor visitor) { + visitor.visit(this); + } + + @Override + public String getShortInfo() { + return "UUID: " + getId() + " Type: " + getType().name(); + } + + @Override + public String toString() { + return super.toString() + " Type: " + getType().name(); + } + + @Override + public AdditionalScoringInformationType getType() { + return informationType; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/RaceState.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/RaceState.java index 5b02fd93a54..fc4b4d8badd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/RaceState.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/RaceState.java @@ -8,6 +8,8 @@ import com.sap.sailing.domain.racelog.CompetitorResults; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogEventAuthor; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure; import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedurePrerequisite; import com.sap.sailing.domain.racelog.state.racingprocedure.impl.RacingProcedurePrerequisiteAutoResolver; @@ -138,5 +140,13 @@ public interface RaceState extends ReadonlyRaceState { * Enters a new wind fix for this race. */ void setWindFix(TimePoint now, Wind wind); + + /** + * Marks this race state with a new {@link AdditionalScoringInformationEvent} or revokes + * an already existing one. + */ + void setAdditionalScoringInformationEnabled(TimePoint creationTimePoint, boolean enable, AdditionalScoringInformationType informationType); + + boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/impl/RaceStateImpl.java index 1cd3a7a1cd8..151ced36627 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/state/impl/RaceStateImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.racelog.state.impl; +import java.util.UUID; + import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.configuration.ConfigurationLoader; import com.sap.sailing.domain.base.configuration.RegattaConfiguration; @@ -8,11 +10,15 @@ import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException; import com.sap.sailing.domain.racelog.CompetitorResults; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEventAuthor; import com.sap.sailing.domain.racelog.RaceLogEventFactory; +import com.sap.sailing.domain.racelog.analyzing.impl.AdditionalScoringInformationFinder; import com.sap.sailing.domain.racelog.analyzing.impl.RaceStatusAnalyzer; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.racelog.state.RaceState; import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedure; import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedureFactory; @@ -158,4 +164,29 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { raceLog.add(factory.createWindFixEvent(timePoint, author, raceLog.getCurrentPassId(), wind)); } + @Override + public void setAdditionalScoringInformationEnabled(TimePoint timePoint, boolean enable, AdditionalScoringInformationType informationType) { + final AdditionalScoringInformationEvent event = new AdditionalScoringInformationFinder(raceLog).analyze(/*filterBy*/informationType); + if (enable) { + if (event == null) { + raceLog.add(factory.createAdditionalScoringInformationEvent(timePoint, UUID.randomUUID(), author, raceLog.getCurrentPassId(), informationType)); + } + } else { + if (event != null) { + try { + // revoke the newest one + raceLog.revokeEvent(author, event); + } catch (NotRevokableException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public boolean isAdditionalScoringInformationEnabled(AdditionalScoringInformationType informationType) { + final AdditionalScoringInformationEvent event = new AdditionalScoringInformationFinder(raceLog).analyze(/*filterBy*/informationType); + return event != null; + } + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/events/RevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/events/RevokeEventImpl.java index 01c45e24e86..d38756f9afd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/events/RevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/events/RevokeEventImpl.java @@ -30,4 +30,9 @@ public class RevokeEventImpl extends RaceLogEventImpl implements RevokeEvent { public Serializable getRevokedEventId() { return revokedEventId; } + + @Override + public String getShortInfo() { + return super.getShortInfo() + "Revoked: " + revokedEventId; + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackImpl.java index 152e4071625..88e4e1d968d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackImpl.java @@ -110,7 +110,7 @@ public class TrackImpl implements Track { * Callers that want to iterate over the collection returned need to synchronize on this object to * avoid {@link ConcurrentModificationException}s. * - * @return the smoothened fixes; this implementation simply delegates to {@link #getInternalRawFixes()} because for + * @return the smoothened fixes ordered by their time points; this implementation simply delegates to {@link #getInternalRawFixes()} because for * only {@link Timed} fixes we can't know how to remove outliers. Subclasses that constrain the * FixType may provide smoothening implementations. */ diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/ConcurrentHashBag.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/ConcurrentHashBag.java new file mode 100755 index 00000000000..05035023ca5 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/ConcurrentHashBag.java @@ -0,0 +1,92 @@ +package com.sap.sailing.util.impl; + +import java.util.AbstractCollection; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +/** + * An "almost" thread-safe bag implementation. The constraint: when for equal objects an add or remove is performed, + * there should be no concurrency regarding that key. The implementation uses a {@link ConcurrentHashMap} internally. + * + * @author Axel Uhl (D043530) + */ +public class ConcurrentHashBag extends AbstractCollection { + private ConcurrentHashMap map = new ConcurrentHashMap(); + private int size; + + @Override + public boolean contains(Object o) { + return map.containsKey(o); + } + + @Override + public boolean remove(Object o) { + @SuppressWarnings("unchecked") + T t = (T) o; + Integer oldCount = map.remove(t); + if (oldCount != null && oldCount != 1) { + map.put(t, oldCount - 1); + } + if (oldCount != null) { + size--; + } + return oldCount != null; + } + + @Override + public boolean add(T e) { + Integer oldCount = map.put(e, 1); + if (oldCount != null && oldCount != 0) { + map.put(e, oldCount + 1); + } + size++; + return true; + } + + @Override + public java.util.Iterator iterator() { + return new Iterator(); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + private class Iterator implements java.util.Iterator { + private final java.util.Iterator> iter = map.entrySet().iterator(); + private int howManyMore = 0; + private T lastElementOfWhichWeHaveMore; + + @Override + public boolean hasNext() { + return howManyMore > 0 || iter.hasNext(); + } + + @Override + public T next() { + final T result; + if (howManyMore > 0) { + result = lastElementOfWhichWeHaveMore; + howManyMore--; + } else { + Entry next = iter.next(); + howManyMore = next.getValue()-1; + lastElementOfWhichWeHaveMore = next.getKey(); + result = next.getKey(); + } + return result; + } + + @Override + public void remove() { + // TODO Auto-generated method stub + + } + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/LockUtil.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/LockUtil.java index 98deae3fc26..3169c27ec8b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/LockUtil.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/LockUtil.java @@ -2,7 +2,6 @@ package com.sap.sailing.util.impl; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -381,7 +380,7 @@ public class LockUtil { // capture the stack traces as quickly as possible to try to reflect the situation as it was when the lock couuldn't be obtained StackTraceElement[] writerStackTrace = writer != null ? writer.getStackTrace() : null; Map readerStackTraces = new HashMap(); - final List readers = lockParent.getReaders(); + final Iterable readers = lockParent.getReaders(); for (Thread reader : readers) { readerStackTraces.put(reader, reader.getStackTrace()); } @@ -396,7 +395,7 @@ public class LockUtil { message.append("\nThe current writer is:\n"); appendThreadData(message, writer, writerStackTrace); } - if (readers != null && !readers.isEmpty()) { + if (readers != null && !Util.isEmpty(readers)) { message.append("\nThe current readers are:\n"); for (Thread reader : readers) { appendThreadData(message, reader, readerStackTraces.get(reader)); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/NamedReentrantReadWriteLock.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/NamedReentrantReadWriteLock.java index d465b4de2f3..d8525e270a2 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/NamedReentrantReadWriteLock.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/util/impl/NamedReentrantReadWriteLock.java @@ -3,8 +3,6 @@ package com.sap.sailing.util.impl; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -35,7 +33,7 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen private final String writeLockName; private final WriteLockWrapper writeLockWrapper; private final ReadLockWrapper readLockWrapper; - private transient List readers; + private transient ConcurrentHashBag readers; private class WriteLockWrapper extends WriteLock { private static final long serialVersionUID = -4234819025137348944L; @@ -110,7 +108,8 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen public void lockInterruptibly() throws InterruptedException { try { readLock.lockInterruptibly(); - readers.add(Thread.currentThread()); + final Thread currentThread = Thread.currentThread(); + readers.add(currentThread); } catch (InterruptedException ie) { throw ie; } @@ -120,7 +119,8 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen public boolean tryLock() { boolean result = readLock.tryLock(); if (result) { - readers.add(Thread.currentThread()); + final Thread currentThread = Thread.currentThread(); + readers.add(currentThread); } return result; } @@ -129,7 +129,8 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { boolean result = readLock.tryLock(timeout, unit); if (result) { - readers.add(Thread.currentThread()); + final Thread currentThread = Thread.currentThread(); + readers.add(currentThread); } return result; } @@ -159,12 +160,12 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen this.writeLockName = "writeLock "+name; this.writeLockWrapper = new WriteLockWrapper(super.writeLock()); this.readLockWrapper = new ReadLockWrapper(super.readLock()); - this.readers = Collections.synchronizedList(new ArrayList()); + this.readers = new ConcurrentHashBag(); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); - this.readers = Collections.synchronizedList(new ArrayList()); + this.readers = new ConcurrentHashBag(); } @Override @@ -184,9 +185,9 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen /** * Contains the threads currently holding a read lock. Each thread is contained as many times as it - * successfully acquired the read lock re-entrantly. + * successfully acquired the read lock re-entrantly. The result is a snapshot that is not live. */ - public List getReaders() { + public Iterable getReaders() { return new ArrayList(readers); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java index bdb88d3b89b..413b31942dc 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SailMasterConnectorImpl.java @@ -27,6 +27,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.common.AbstractBearing; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.Speed; @@ -388,7 +389,7 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement final Speed velocityMadeGood = fixSections[vmgIndex].trim().length() == 0 ? null : new KnotSpeedImpl( Double.valueOf(fixSections[vmgIndex])); fixDetailIndex += 2; - final DegreeBearingImpl cog = new DegreeBearingImpl( + final AbstractBearing cog = new DegreeBearingImpl( Double.valueOf(fixSections[fixDetailIndex++])); final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(speedOverGroundInKnots, cog); final Integer nextMarkIndex = fixSections.length <= fixDetailIndex diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index ba5e9886d66..0f10c876b2c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -14,8 +14,11 @@ import java.io.ObjectInputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -72,6 +75,39 @@ public class LeaderboardDTODiffingTest { } return null; } + + @Test + public void testEmptyLegDetailsGetFilled() throws FileNotFoundException, IOException, ClassNotFoundException { + // remove legDetails for R9 for all competitors from previousVersion; remember which ones did contain data + Set hadLegDetailsInR9 = new HashSet<>(); + Map newRows = new HashMap<>(); + for (CompetitorDTO competitor : previousVersion.rows.keySet()) { + LeaderboardRowDTO competitorRow = new LeaderboardRowDTO(); + cloner.clone(newVersion.rows.get(competitor), competitorRow); + Map newFieldsByRaceColumnName = new HashMap<>(); + for (Entry e : competitorRow.fieldsByRaceColumnName.entrySet()) { + LeaderboardEntryDTO newEntry = new LeaderboardEntryDTO(); + cloner.clone(e.getValue(), newEntry); + newFieldsByRaceColumnName.put(e.getKey(), newEntry); + } + competitorRow.fieldsByRaceColumnName = newFieldsByRaceColumnName; + newRows.put(competitor, competitorRow); // use a copy of the row so we can null out legDetails for R9 in previousVersion only + LeaderboardRowDTO previousRow = previousVersion.rows.get(competitor); + assertNotSame(previousRow, competitorRow); + if (previousRow.fieldsByRaceColumnName.get("R9").legDetails != null) { + hadLegDetailsInR9.add(competitor); + previousRow.fieldsByRaceColumnName.get("R9").legDetails = null; + assertNotNull(competitorRow.fieldsByRaceColumnName.get("R9").legDetails != null); + } + } + newVersion.rows = newRows; + newVersion.strip(previousVersion); // should contain the leg details now + LeaderboardDTO applied = newVersion.getLeaderboardDTO(previousVersion); + // now applied must contain the leg details + for (CompetitorDTO competitor : hadLegDetailsInR9) { + assertNotNull(applied.rows.get(competitor).fieldsByRaceColumnName.get("R9").legDetails); + } + } @Test public void testLeaderboardSuccessfullyRead() { @@ -301,7 +337,7 @@ public class LeaderboardDTODiffingTest { public void testPartialRaceColumnDTOCompaction() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { // create a modified R9 RaceDTO clone in newVersion to make sure that even changing a property in the RaceDTO will keep the RaceColumnDTO from being omitted RaceColumnDTO r9 = newVersion.getRaceColumnByName("R9"); - RaceColumnDTO clonedR9 = new RaceColumnDTO(r9.isValidInTotalScore()); + RaceColumnDTO clonedR9 = new RaceColumnDTO(); cloner.clone(r9, clonedR9); // also clone the racesPerFleet map, or else we'd be modifying the previous version's one too final Field racesPerFleetField = clonedR9.getClass().getDeclaredField("racesPerFleet"); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java index 3f54d823faa..2d55faa233c 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java @@ -55,7 +55,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { private IRaceSubscriber raceSubscriber; private final Collection receivers; - @Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(2 * 60 * 1000); + @Rule public Timeout AbstractTracTracLiveTestTimeout = new Timeout(3 * 60 * 1000); protected AbstractTracTracLiveTest() throws URISyntaxException, MalformedURLException { receivers = new HashSet(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BoundsTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BoundsTest.java index 65bc5788241..90ec758979b 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BoundsTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/BoundsTest.java @@ -88,6 +88,28 @@ public class BoundsTest { assertEquals(5.0, u.getNorthEast().getLngDeg(), 0.00000001); } + @Test + public void unionTestWithEmptyBounds() { + Bounds b1 = new BoundsImpl(new DegreePosition(1, 1), new DegreePosition(3, 3)); + Bounds b2 = new BoundsImpl(new DegreePosition(4, 4), new DegreePosition(4, 4)); + Bounds u = b1.union(b2); + assertEquals(1.0, u.getSouthWest().getLatDeg(), 0.00000001); + assertEquals(1.0, u.getSouthWest().getLngDeg(), 0.00000001); + assertEquals(4.0, u.getNorthEast().getLatDeg(), 0.00000001); + assertEquals(4.0, u.getNorthEast().getLngDeg(), 0.00000001); + } + + @Test + public void unionTestWithTwoEmptyBounds() { + Bounds b1 = new BoundsImpl(new DegreePosition(1, 1), new DegreePosition(1, 1)); + Bounds b2 = new BoundsImpl(new DegreePosition(4, 4), new DegreePosition(4, 4)); + Bounds u = b1.union(b2); + assertEquals(1.0, u.getSouthWest().getLatDeg(), 0.00000001); + assertEquals(1.0, u.getSouthWest().getLngDeg(), 0.00000001); + assertEquals(4.0, u.getNorthEast().getLatDeg(), 0.00000001); + assertEquals(4.0, u.getNorthEast().getLngDeg(), 0.00000001); + } + @Test public void simpleIntersectsTest() { Bounds b1 = new BoundsImpl(new DegreePosition(1, 1), new DegreePosition(3, 3)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrentCollectionsPerformanceTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrentCollectionsPerformanceTest.java new file mode 100755 index 00000000000..d3bc8e3d580 --- /dev/null +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrentCollectionsPerformanceTest.java @@ -0,0 +1,62 @@ +package com.sap.sailing.domain.test; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.junit.Test; + +import com.sap.sailing.util.impl.ConcurrentHashBag; +import com.sap.sse.common.Util; + +/** + * Measures the performance of different concurrent collections types and shows their add and remove behavior for + * different collection sizes and different numbers of concurrently accessing threads. The collections used must be able + * to hold the same element multiple times, keeping count, not necessarily order. + * + * @author Axel Uhl (D043530) + * + */ +public class ConcurrentCollectionsPerformanceTest { + private static final int COUNT = 10000; + + @Test + public void testConcurrentLinkedQueue() { + Collection c = new ConcurrentLinkedQueue(); + System.out.println("ConcurrentLinkedQueue" + runWith(c)); + } + + @Test + public void testConcurrentHashMap() { + Collection c = new ConcurrentHashBag(); + System.out.println("ConcurrentHashBag" + runWith(c)); + } + + private com.sap.sse.common.Util.Pair runWith(Collection c) { + List l = new ArrayList<>(COUNT); + for (int i=0; i(l)) { + l.add(o); + } + long startInsert = System.currentTimeMillis(); + for (Object o : l) { + c.add(o); + } + long endInsert = System.currentTimeMillis(); + assertEquals(l.size(), c.size()); + Collections.shuffle(l); + long startRemove = System.currentTimeMillis(); + for (Object o : l) { + c.remove(o); + } + long endRemove = System.currentTimeMillis(); + return new Util.Pair(endInsert-startInsert, endRemove-startRemove); + } +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/EventLeaderboardGroupLinkTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/EventLeaderboardGroupLinkTest.java index 42754e124f9..27fa19b68b4 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/EventLeaderboardGroupLinkTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/EventLeaderboardGroupLinkTest.java @@ -21,10 +21,10 @@ public class EventLeaderboardGroupLinkTest { @Test public void testLivelinessAndIteratorStabilityOfUnmodifiableLeaderboardGroupCollection() { Event e = new EventImpl("E", null, null, "Venue", /* public */ true, UUID.randomUUID()); - LeaderboardGroupImpl lg1 = new LeaderboardGroupImpl("lg1", "LG1", /* displayGroupsInReverseOrder */ false, Collections.emptyList()); - LeaderboardGroupImpl lg2 = new LeaderboardGroupImpl("lg2", "LG2", /* displayGroupsInReverseOrder */ false, Collections.emptyList()); - LeaderboardGroupImpl lg3 = new LeaderboardGroupImpl("lg3", "LG3", /* displayGroupsInReverseOrder */ false, Collections.emptyList()); - LeaderboardGroupImpl lg4 = new LeaderboardGroupImpl("lg4", "LG4", /* displayGroupsInReverseOrder */ false, Collections.emptyList()); + LeaderboardGroupImpl lg1 = new LeaderboardGroupImpl("lg1", "LG1", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections.emptyList()); + LeaderboardGroupImpl lg2 = new LeaderboardGroupImpl("lg2", "LG2", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections.emptyList()); + LeaderboardGroupImpl lg3 = new LeaderboardGroupImpl("lg3", "LG3", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections.emptyList()); + LeaderboardGroupImpl lg4 = new LeaderboardGroupImpl("lg4", "LG4", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections.emptyList()); e.addLeaderboardGroup(lg1); Iterable lgs = e.getLeaderboardGroups(); Iterator iter = lgs.iterator(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index 1f4a70dc98f..1363731c006 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import java.util.ArrayList; import java.util.Arrays; @@ -15,6 +16,8 @@ import java.util.List; import java.util.Map; import java.util.NavigableSet; import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ExecutionException; import org.junit.Test; @@ -26,7 +29,9 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; +import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.MarkImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; @@ -37,7 +42,9 @@ import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; @@ -46,14 +53,25 @@ import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10Or8AndLastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.analyzing.impl.AdditionalScoringInformationFinder; +import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; +import com.sap.sailing.domain.racelog.impl.RaceLogEventAuthorImpl; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; +import com.sap.sailing.domain.racelog.scoring.impl.AdditionalScoringInformationEventImpl; +import com.sap.sailing.domain.racelog.state.RaceState; +import com.sap.sailing.domain.racelog.state.impl.RaceStateImpl; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; import com.sap.sailing.domain.tracking.impl.TimedComparator; import com.sap.sailing.util.impl.ArrayListNavigableSet; @@ -791,6 +809,84 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertEquals(rankedCompetitors.indexOf(c[0]), rankedCompetitors.indexOf(c[1])-1); } + @Test + public void testAdditionalScoreInformationLeadsToChangedScoreForOneColumn() throws NoWindException { + TrackedRegattaRegistry trackedRegattaRegistry = mock(TrackedRegattaRegistry.class); + Regatta dummyRegatta = new RegattaImpl(EmptyRaceLogStore.INSTANCE , "Dummy", new BoatClassImpl("Extreme40", false), trackedRegattaRegistry, new HighPointFirstGets10Or8AndLastBreaksTie(), "578876345345", new CourseAreaImpl("Humba", UUID.randomUUID())); + trackedRegattaRegistry.getOrCreateTrackedRegatta(dummyRegatta); + Competitor[] competitors = createCompetitors(10).toArray(new Competitor[0]); + TimePoint now = MillisecondsTimePoint.now(); + TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); + FlexibleLeaderboard leaderboardHighPoint10Or8AndLastBreaksTie = new FlexibleLeaderboardImpl("Test ESS Highpoint 10Or8AndLastBreaksTie", new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), + new HighPointFirstGets10Or8AndLastBreaksTie(), null); + leaderboardHighPoint10Or8AndLastBreaksTie.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(competitors), dummyRegatta), "R1", /* medalRace */ false); + assertTrue(leaderboardHighPoint10Or8AndLastBreaksTie.getScoringScheme().getScoreComparator(/* nullScoresAreBetter */ false).compare( + leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[3], later)) < 0); // c0 better than c3 + assertEquals(10, leaderboardHighPoint10Or8AndLastBreaksTie.getCompetitorsFromBestToWorst(later).size()); + assertEquals(new Double(10), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(9), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); + assertEquals(new Double(1), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + leaderboardHighPoint10Or8AndLastBreaksTie.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(competitors), dummyRegatta), "R2", /* medalRace */ false); + assertEquals(new Double(20), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); + assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + RaceLog raceLogForRace2 = leaderboardHighPoint10Or8AndLastBreaksTie.getRaceColumnByName("R2").getRaceLog(leaderboardHighPoint10Or8AndLastBreaksTie.getFleet(null)); + raceLogForRace2.add(new AdditionalScoringInformationEventImpl(now, new RaceLogEventAuthorImpl("Plopp", 1), later, "12345678", Collections.emptyList(), 0, AdditionalScoringInformationType.UNKNOWN)); + assertEquals(new Double(20), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); + assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + raceLogForRace2.add(new AdditionalScoringInformationEventImpl(now, new RaceLogEventAuthorImpl("Plopp", 1), later.plus(Duration.ONE_MINUTE), "123456789873773762", Collections.emptyList(), 0, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); + assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(16), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); + assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + leaderboardHighPoint10Or8AndLastBreaksTie.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(competitors), dummyRegatta), "R3", /* medalRace */ false); + assertEquals(new Double(28), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(25), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); + assertEquals(new Double(3), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + AdditionalScoringInformationFinder finder = new AdditionalScoringInformationFinder(raceLogForRace2); + AdditionalScoringInformationEvent event = finder.analyze(/*filterBy*/AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + assert event != null; + try { + raceLogForRace2.revokeEvent(new RaceLogEventAuthorImpl("Plopp", 1), event); + } catch (NotRevokableException e) { + e.printStackTrace(); + } + event = finder.analyze(/*filterBy*/AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + assert event == null; + assertEquals(new Double(30), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(3), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + RaceState raceStateForRace2 = RaceStateImpl.create(raceLogForRace2, new RaceLogEventAuthorImpl("Simon", 1)); + assertFalse(raceStateForRace2.isAdditionalScoringInformationEnabled(AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); + raceStateForRace2.setAdditionalScoringInformationEnabled(later.plus(Duration.ONE_MINUTE).plus(Duration.ONE_SECOND), /*enable*/true, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + assertTrue(raceStateForRace2.isAdditionalScoringInformationEnabled(AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); + assertEquals(new Double(28), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(3), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + raceStateForRace2.setAdditionalScoringInformationEnabled(later.plus(Duration.ONE_MINUTE).plus(Duration.ONE_SECOND.plus(10000)), /*enable*/false, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + assertFalse(raceStateForRace2.isAdditionalScoringInformationEnabled(AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); + assertEquals(new Double(30), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); + assertEquals(new Double(3), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); + LeaderboardDTO leaderboardDTO = null; + try { + leaderboardDTO = leaderboardHighPoint10Or8AndLastBreaksTie.getLeaderboardDTO(later.plus(Duration.ONE_HOUR), Collections.emptyList(), false, trackedRegattaRegistry, DomainFactory.INSTANCE, false); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + assert leaderboardDTO != null; + assertEquals(30.0, leaderboardDTO.rows.get(leaderboardDTO.competitors.get(0)).totalPoints, 0.000000000001); + raceStateForRace2.setAdditionalScoringInformationEnabled(later.plus(Duration.ONE_MINUTE).plus(Duration.ONE_SECOND.plus(20000)), /*enable*/true, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + try { + leaderboardDTO = leaderboardHighPoint10Or8AndLastBreaksTie.getLeaderboardDTO(later.plus(Duration.ONE_HOUR), Collections.emptyList(), false, trackedRegattaRegistry, DomainFactory.INSTANCE, false); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + assertEquals(28.0, leaderboardDTO.rows.get(leaderboardDTO.competitors.get(0)).totalPoints, 0.000000000001); + assertEquals(25.0, leaderboardDTO.rows.get(leaderboardDTO.competitors.get(1)).totalPoints, 0.000000000001); + } + @Test public void testCompetitorsRankedEleventhOrLowerGetOnePointScore() throws NoWindException { Competitor[] competitors = createCompetitors(16).toArray(new Competitor[0]); @@ -813,8 +909,8 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { false); assertEquals(16, leaderboardHighPoint.getCompetitorsFromBestToWorst(later).size()); assertEquals(new Double(16), leaderboardHighPoint.getTotalPoints(competitors[0], later)); - LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("ESS", "ESS", /* displayGroupsInReverseOrder */ false, - Arrays.asList(new Leaderboard[] { leaderboardHighPoint10LastBreaksTie })); + LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("ESS", "ESS", /* displayName */ null, + /* displayGroupsInReverseOrder */ false, Arrays.asList(new Leaderboard[] { leaderboardHighPoint10LastBreaksTie })); LeaderboardGroupMetaLeaderboard leaderboardHighPointESSOverall = new LeaderboardGroupMetaLeaderboard( leaderboardGroup, new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0])); assertEquals(16, leaderboardHighPointESSOverall.getCompetitorsFromBestToWorst(later).size()); @@ -870,7 +966,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { false); assertTrue(leaderboard3.getCompetitorsFromBestToWorst(later).indexOf(c[3]) < leaderboard3.getCompetitorsFromBestToWorst(later).indexOf(c[0])); // c3 better than c0; won last race - LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("Leaderboard Group", "Leaderboard Group", false, Arrays.asList(leaderboard1, + LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("Leaderboard Group", "Leaderboard Group", /* displayName */ null, false, Arrays.asList(leaderboard1, leaderboard2, leaderboard3)); leaderboardGroup.setOverallLeaderboard(new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0]))); @@ -923,8 +1019,8 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertEquals(4, leaderboard2.getTotalPoints(c[9], later), 0.000000001); assertEquals(3, leaderboard2.getTotalPoints(c[11], later), 0.000000001); - LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("Leaderboard Group ESS Overall", "Leaderboard Group", false, - Arrays.asList(leaderboard1, leaderboard2)); + LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("Leaderboard Group ESS Overall", "Leaderboard Group", /* displayName */ null, + false, Arrays.asList(leaderboard1, leaderboard2)); leaderboardGroup.setOverallLeaderboard(new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPointExtremeSailingSeriesOverall(), new ThresholdBasedResultDiscardingRuleImpl(new int[0]))); leaderboardGroup.getOverallLeaderboard().setSuppressed(c[c.length-1], true); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LockTraceTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LockTraceTest.java index daa6684533a..abb276740d0 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LockTraceTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LockTraceTest.java @@ -16,6 +16,7 @@ import com.sap.sailing.domain.test.measurements.MeasurementCase; import com.sap.sailing.domain.test.measurements.MeasurementXMLFile; import com.sap.sailing.util.impl.LockUtil; import com.sap.sailing.util.impl.NamedReentrantReadWriteLock; +import com.sap.sse.common.Util; public class LockTraceTest { private static class LockingThread extends Thread { @@ -47,18 +48,18 @@ public class LockTraceTest { public void testReentrantReadLocking() { NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock("testReentrantReadLocking-Lock", /* fair */ true); LockUtil.lockForRead(lock); - assertTrue(lock.getReaders().contains(Thread.currentThread())); - assertEquals(1, lock.getReaders().size()); + assertTrue(Util.contains(lock.getReaders(), Thread.currentThread())); + assertEquals(1, Util.size(lock.getReaders())); LockUtil.lockForRead(lock); - assertTrue(lock.getReaders().contains(Thread.currentThread())); - assertEquals(2, lock.getReaders().size()); + assertTrue(Util.contains(lock.getReaders(), Thread.currentThread())); + assertEquals(2, Util.size(lock.getReaders())); LockUtil.unlockAfterRead(lock); - assertTrue(lock.getReaders().contains(Thread.currentThread())); - assertEquals(1, lock.getReaders().size()); + assertTrue(Util.contains(lock.getReaders(), Thread.currentThread())); + assertEquals(1, Util.size(lock.getReaders())); LockUtil.unlockAfterRead(lock); - assertFalse(lock.getReaders().contains(Thread.currentThread())); + assertFalse(Util.contains(lock.getReaders(), Thread.currentThread())); assertEquals(0, lock.getReadHoldCount()); - assertEquals(0, lock.getReaders().size()); + assertEquals(0, Util.size(lock.getReaders())); } @Test @@ -67,15 +68,15 @@ public class LockTraceTest { LockUtil.lockForWrite(lock); assertTrue(lock.getWriter() == Thread.currentThread()); LockUtil.lockForRead(lock); // reentrant read while holding write - assertTrue(lock.getReaders().contains(Thread.currentThread())); + assertTrue(Util.contains(lock.getReaders(), Thread.currentThread())); LockUtil.lockForWrite(lock); // reentrant write assertTrue(lock.getWriter() == Thread.currentThread()); - assertTrue(lock.getReaders().contains(Thread.currentThread())); + assertTrue(Util.contains(lock.getReaders(), Thread.currentThread())); LockUtil.unlockAfterRead(lock); - assertFalse(lock.getReaders().contains(Thread.currentThread())); + assertFalse(Util.contains(lock.getReaders(), Thread.currentThread())); assertEquals(0, lock.getReadHoldCount()); assertTrue(lock.getWriter() == Thread.currentThread()); - assertFalse(lock.getReaders().contains(Thread.currentThread())); + assertFalse(Util.contains(lock.getReaders(), Thread.currentThread())); assertEquals(0, lock.getReadHoldCount()); LockUtil.unlockAfterWrite(lock); assertTrue(lock.getWriter() == Thread.currentThread()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index de167da9325..50ebffd0334 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -92,9 +92,9 @@ public class OfflineSerializationTest extends AbstractSerializationTest { DomainFactory receiverDomainFactory = new DomainFactoryImpl(); Event e = new EventImpl("Event Name", MillisecondsTimePoint.now(), MillisecondsTimePoint.now().plus( Duration.ONE_DAY.times(10)), "At Home", /* is public */true, UUID.randomUUID()); - LeaderboardGroup lg1 = new LeaderboardGroupImpl("LG1", "LG1 Description", /* displayGroupsInReverseOrder */ false, Collections. emptyList()); + LeaderboardGroup lg1 = new LeaderboardGroupImpl("LG1", "LG1 Description", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections. emptyList()); e.addLeaderboardGroup(lg1); - LeaderboardGroup lg2 = new LeaderboardGroupImpl("LG2", "LG2 Description", /* displayGroupsInReverseOrder */ false, Collections. emptyList()); + LeaderboardGroup lg2 = new LeaderboardGroupImpl("LG2", "LG2 Description", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Collections. emptyList()); e.addLeaderboardGroup(lg2); Event deserialized = cloneBySerialization(e, receiverDomainFactory); assertEquals(Util.size(e.getLeaderboardGroups()), Util.size(deserialized.getLeaderboardGroups())); @@ -118,7 +118,7 @@ public class OfflineSerializationTest extends AbstractSerializationTest { @Test public void testSerializingOverallLeaderboardWithFactorOnColumn() throws ClassNotFoundException, IOException { Leaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 5 }), new HighPoint(), new CourseAreaImpl("Alpha", UUID.randomUUID())); - LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("LeaderboardGroup", "Test Leaderboard Group", /* displayGroupsInReverseOrder */ false, Arrays.asList(new Leaderboard[] { leaderboard })); + LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("LeaderboardGroup", "Test Leaderboard Group", /* displayName */ null, /* displayGroupsInReverseOrder */ false, Arrays.asList(new Leaderboard[] { leaderboard })); final LeaderboardGroupMetaLeaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPoint(), new ThresholdBasedResultDiscardingRuleImpl(new int[0])); leaderboardGroup.setOverallLeaderboard(overallLeaderboard); final double FACTOR = 2.0; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PolarSheetGenerationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PolarSheetGenerationTest.java index dfccf777536..17d8541af65 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PolarSheetGenerationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/PolarSheetGenerationTest.java @@ -278,7 +278,7 @@ public class PolarSheetGenerationTest { } @Override - public boolean isValid() { + public boolean isValidCached() { return true; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SmartFutureCacheDeadlockTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SmartFutureCacheDeadlockTest.java index 92d1bda16f1..b03b00bd6b9 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SmartFutureCacheDeadlockTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/SmartFutureCacheDeadlockTest.java @@ -19,6 +19,7 @@ import com.sap.sailing.util.SmartFutureCache; import com.sap.sailing.util.SmartFutureCache.EmptyUpdateInterval; import com.sap.sailing.util.impl.LockUtil; import com.sap.sailing.util.impl.NamedReentrantReadWriteLock; +import com.sap.sse.common.Util; /** * When the thread reading a value from the cache holds a fair read lock, and another thread is trying to obtain the @@ -88,15 +89,15 @@ public class SmartFutureCacheDeadlockTest { @Test public void testBasicLockingAndUnlockingWithScripts() throws InterruptedException { logger.info("starting testBasicLockingAndUnlockingWithScripts"); - assertFalse(lock.getReaders().contains(readerThread)); + assertFalse(Util.contains(lock.getReaders(), readerThread)); try { reader.performAndWait(Command.LOCK_FOR_READ); - assertTrue(lock.getReaders().contains(readerThread)); + assertTrue(Util.contains(lock.getReaders(), readerThread)); writer.perform(Command.LOCK_FOR_WRITE); assertNull(lock.getWriter()); } finally { reader.performAndWait(Command.UNLOCK_AFTER_READ); - assertFalse(lock.getReaders().contains(readerThread)); + assertFalse(Util.contains(lock.getReaders(), readerThread)); writer.performAndWait(Command.UNLOCK_AFTER_WRITE); } } @@ -195,7 +196,7 @@ public class SmartFutureCacheDeadlockTest { writerThread.join(); assertFalse(reader.isRunning()); assertFalse(writer.isRunning()); - assertTrue(lock.getReaders().isEmpty()); + assertTrue(Util.isEmpty(lock.getReaders())); assertNull(lock.getWriter()); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java index c08c2a1d461..3b33a28e192 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java @@ -26,6 +26,7 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Timed; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.common.AbstractBearing; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Position; @@ -43,6 +44,7 @@ import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; import com.sap.sailing.domain.tracking.GPSFix; import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.impl.CompactGPSFixMovingImpl; import com.sap.sailing.domain.tracking.impl.DistanceCache; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; @@ -852,7 +854,7 @@ public class TrackTest { true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - DegreeBearingImpl bearing = new DegreeBearingImpl(90); + AbstractBearing bearing = new DegreeBearingImpl(90); Position position1 = new DegreePosition(1, 2); Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(1, bearing)); @@ -873,7 +875,7 @@ public class TrackTest { true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - DegreeBearingImpl bearing = new DegreeBearingImpl(90); + AbstractBearing bearing = new DegreeBearingImpl(90); Position position1 = new DegreePosition(1, 2); Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(10, bearing)); @@ -894,7 +896,7 @@ public class TrackTest { true), null), /* millisecondsOverWhichToAverage */5000, /* no smoothening */null); TimePoint now1 = MillisecondsTimePoint.now(); TimePoint now2 = addMillisToTimepoint(now1, 1000); // 1s - DegreeBearingImpl bearing = new DegreeBearingImpl(90); + AbstractBearing bearing = new DegreeBearingImpl(90); Position position1 = new DegreePosition(1, 2); Position position2 = position1.translateGreatCircle(bearing, new MeterDistance(1)); GPSFixMovingImpl myGpsFix1 = new GPSFixMovingImpl(position1, now1, new MeterPerSecondSpeedWithDegreeBearingImpl(0.1, bearing)); @@ -1053,4 +1055,33 @@ public class TrackTest { assertEquals(3, track.getAverageIntervalBetweenFixes().asMillis()); assertEquals(3, track.getAverageIntervalBetweenRawFixes().asMillis()); } + + @Test + public void testEstimatedSpeedCaching() { + GPSFixMoving originalFix = new GPSFixMovingImpl(new DegreePosition(12, 34), MillisecondsTimePoint.now(), + new KnotSpeedWithBearingImpl(9, new DegreeBearingImpl(123))); + GPSFixMoving fix = new CompactGPSFixMovingImpl(originalFix); + assertFalse(fix.isEstimatedSpeedCached()); + final KnotSpeedWithBearingImpl estimatedSpeed = new KnotSpeedWithBearingImpl(9.1, new DegreeBearingImpl(124)); + fix.cacheEstimatedSpeed(estimatedSpeed); + assertTrue(fix.isEstimatedSpeedCached()); + SpeedWithBearing cachedEstimatedSpeed = fix.getCachedEstimatedSpeed(); + assertEquals(estimatedSpeed, cachedEstimatedSpeed); + fix.invalidateEstimatedSpeedCache(); + assertFalse(fix.isEstimatedSpeedCached()); + } + + @Test + public void testEstimatedSpeedCachingOnTrack() { + GPSFixMoving compactFix3 = track.getFirstFixAtOrAfter(gpsFix3.getTimePoint()); + assertFalse(compactFix3.isEstimatedSpeedCached()); + SpeedWithBearing fix3EstimatedSpeed = track.getEstimatedSpeed(gpsFix3.getTimePoint()); + assertTrue(compactFix3.isEstimatedSpeedCached()); + assertEquals(fix3EstimatedSpeed, compactFix3.getCachedEstimatedSpeed()); + assertEquals(fix3EstimatedSpeed, track.getEstimatedSpeed(gpsFix3.getTimePoint())); // fetch again from the cache + // assuming that all test fixes are within a few milliseconds and the averaging interval is much larger than that, + // adding a single fix in the middle should invalidate the cache + track.add(new GPSFixMovingImpl(gpsFix3.getPosition(), gpsFix3.getTimePoint().plus(1), gpsFix3.getSpeed())); + assertFalse(compactFix3.isEstimatedSpeedCached()); + } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index c7aa4f8615c..aa724fefb6d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test.mock; import java.io.Serializable; +import java.util.Collections; import java.util.List; import java.util.NavigableSet; import java.util.TreeSet; @@ -617,14 +618,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Iterable getWindSources(WindSourceType type) { - // TODO Auto-generated method stub - return null; + return Collections.emptyList(); } @Override public Iterable getWindSources() { - // TODO Auto-generated method stub - return null; + return Collections.emptyList(); } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java index d1c70ee4f26..8aade6f904d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.SpeedWithConfidence; import com.sap.sailing.domain.base.Waypoint; @@ -43,11 +44,12 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRaceStatus; import com.sap.sailing.domain.tracking.TrackedRegatta; import com.sap.sailing.domain.tracking.Wind; -import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.WindWithConfidence; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; import com.sap.sse.common.Util; /** @@ -62,6 +64,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { private static final long serialVersionUID = 2708044935347796930L; private final TimePoint startTime; private final List competitorsFromBestToWorst; + private final Regatta regatta; private RaceDefinition race; /** @@ -70,7 +73,11 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { * mocked tracked race */ public MockedTrackedRaceWithStartTimeAndRanks(TimePoint startTime, List competitorsFromBestToWorst) { - super(); + this(startTime, competitorsFromBestToWorst, null); + } + + public MockedTrackedRaceWithStartTimeAndRanks(TimePoint startTime, List competitorsFromBestToWorst, Regatta regatta) { + this.regatta = regatta; this.startTime = startTime; // copies the list to make sure that later modifications to the list passed to this constructor don't affect the ranking produced by this race this.competitorsFromBestToWorst = new ArrayList(competitorsFromBestToWorst); @@ -226,14 +233,12 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public Iterable getWindSources(WindSourceType type) { - // TODO Auto-generated method stub - return null; + return Collections.emptyList(); } @Override public Iterable getWindSources() { - // TODO Auto-generated method stub - return null; + return Collections.emptyList(); } @Override @@ -328,8 +333,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public TrackedRegatta getTrackedRegatta() { - // TODO Auto-generated method stub - return null; + return new DynamicTrackedRegattaImpl(regatta); } @Override diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index cc5e8e43a74..a960e1e2d6a 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -46,8 +46,8 @@ import com.sap.sailing.domain.tractracadapter.DomainFactory; import com.sap.sailing.domain.tractracadapter.Receiver; import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants; import com.sap.sailing.domain.tractracadapter.TracTracRaceTracker; -import com.tractrac.model.lib.api.ModelLocator; import com.sap.sse.common.Util; +import com.tractrac.model.lib.api.ModelLocator; import com.tractrac.model.lib.api.event.CreateModelException; import com.tractrac.model.lib.api.event.ICompetitor; import com.tractrac.model.lib.api.event.IEvent; @@ -62,6 +62,7 @@ import com.tractrac.subscription.lib.api.competitor.ICompetitorsListener; import com.tractrac.subscription.lib.api.event.IConnectionStatusListener; import com.tractrac.subscription.lib.api.event.ILiveDataEvent; import com.tractrac.subscription.lib.api.event.IStoredDataEvent; +import com.tractrac.subscription.lib.api.race.IRacesListener; public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements IConnectionStatusListener, TracTracRaceTracker, DynamicRaceDefinitionSet { private static final Logger logger = Logger.getLogger(TracTracRaceTrackerImpl.class.getName()); @@ -343,6 +344,25 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements public void addCompetitor(ICompetitor competitor) { } }); + eventSubscriber.subscribeRaces(new IRacesListener() { + @Override public void abandonRace(UUID raceId) {} + @Override public void addRace(IRace race) {} + @Override public void deleteRace(UUID raceId) {} + @Override public void reloadRace(UUID raceId) {} + @Override public void startTracking(UUID raceId) {} + @Override + public void updateRace(IRace race) { + if (Util.equalsWithNull(race, TracTracRaceTrackerImpl.this.tractracRace)) { + int delayToLiveInMillis = race.getLiveDelay()*1000; + for (RaceDefinition raceDefinition : getRaces()) { + DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(raceDefinition); + if (trackedRace != null) { + trackedRace.setDelayToLiveInMillis(delayToLiveInMillis); + } + } + } + } + }); // Start live and stored data streams Regatta effectiveRegatta = regatta; raceSubscriber = subscriberFactory.createRaceSubscriber(tractracRace, liveURI, storedURI); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java index 2cfd6d10a98..a9bad5f525b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.base; import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import java.util.List; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; @@ -14,6 +15,9 @@ import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.dto.TrackedRaceDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; @@ -53,6 +57,9 @@ public interface DomainFactory extends SharedDomainFactory { TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); + TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn, + Fleet fleet, Collection mediatracks); + /** * @param trackedRace must not be null */ diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/BoatClassMasterdata.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/BoatClassMasterdata.java deleted file mode 100644 index 6fd246e66b2..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/BoatClassMasterdata.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.sap.sailing.domain.base.impl; - -public enum BoatClassMasterdata { - - LASER_SB3 ( "Laser SB3", 6.15 ), - EXTREME_40 ("Extreme 40", 12.2), - J80 ("J/80", 8.0, "J80"), - _49ER ("49er", 4.88), - _29ER ("29er", 4.45), - _505 ("505", 5.03), - _420 ("420", 4.2), - _470 ("470", 4.7); - - private final double hullLengthInMeter; - - private final String displayName; - - private final String[] alternativeNames; - - BoatClassMasterdata(String displayName, double hullLengthInMeter) { - this.displayName = displayName; - this.hullLengthInMeter = hullLengthInMeter; - this.alternativeNames = new String[0]; - } - - BoatClassMasterdata(String displayName, double hullLengthInMeter, String... alternativeNames) { - this.displayName = displayName; - this.hullLengthInMeter = hullLengthInMeter; - this.alternativeNames = alternativeNames; - } - - public static BoatClassMasterdata resolveBoatClass(String boatClassName) { - for(BoatClassMasterdata boatClass: values()) { - if(boatClass.displayName.toUpperCase().equals(boatClassName.toUpperCase())) { - return boatClass; - } - for(String name: boatClass.alternativeNames) { - if(name.toUpperCase().equals(boatClassName.toUpperCase())) { - return boatClass; - } - } - } - return null; - } - - public double getHullLengthInMeter() { - return hullLengthInMeter; - } - - public String getDisplayName() { - return displayName; - } -} 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 c49b68642a3..7ebe68a5235 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 @@ -3,6 +3,7 @@ package com.sap.sailing.domain.base.impl; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.logging.Logger; @@ -13,13 +14,17 @@ import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.ObjectInputStreamResolvingAgainstDomainFactory; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Placemark; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.PlacemarkDTO; @@ -28,19 +33,28 @@ import com.sap.sailing.domain.common.dto.PositionDTO; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.dto.RaceStatusDTO; import com.sap.sailing.domain.common.dto.TrackedRaceDTO; +import com.sap.sailing.domain.common.dto.TrackedRaceStatisticsDTO; +import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie; +import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10Or8AndLastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFiveIgnoringRaceCount; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; +import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSixIgnoringRaceCount; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero; import com.sap.sailing.domain.tracking.GPSFix; +import com.sap.sailing.domain.tracking.GPSFixMoving; +import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sailing.domain.tracking.impl.MarkPassingImpl; @@ -95,6 +109,10 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return new HighPointWinnerGetsFiveIgnoringRaceCount(); case HIGH_POINT_WINNER_GETS_SIX: return new HighPointWinnerGetsSix(); + case HIGH_POINT_WINNER_GETS_SIX_IGNORING_RACE_COUNT: + return new HighPointWinnerGetsSixIgnoringRaceCount(); + case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT: + return new HighPointFirstGets10Or8AndLastBreaksTie(); } throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name()); } @@ -144,6 +162,75 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return trackedRaceDTO; } + @Override + public TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, + RaceColumn raceColumn, Fleet fleet, Collection mediaTracks) { + TrackedRaceStatisticsDTO statisticsDTO = new TrackedRaceStatisticsDTO(); + + // GPS data + statisticsDTO.hasGPSData = trackedRace.hasGPSData(); + + Competitor leaderOrWinner = null; + TimePoint now = MillisecondsTimePoint.now(); + try { + if(trackedRace.isLive(now)) { + leaderOrWinner = trackedRace.getOverallLeader(now); + } else if (trackedRace.getEndOfRace() != null) { + for(Competitor competitor: leaderboard.getCompetitorsFromBestToWorst(raceColumn, now)) { + Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); + if(fleetOfCompetitor != null && fleetOfCompetitor.equals(fleet)) { + leaderOrWinner = competitor; + break; + } + } + } + if(leaderOrWinner != null) { + statisticsDTO.hasLeaderOrWinnerData = true; + statisticsDTO.leaderOrWinner = convertToCompetitorDTO(leaderOrWinner); + GPSFixTrack track = trackedRace.getTrack(leaderOrWinner); + if(track != null) { + statisticsDTO.averageGPSDataSampleInterval = track.getAverageIntervalBetweenFixes(); + } + } + } catch (NoWindException e) { + } + + // Measured wind sources data + statisticsDTO.measuredWindSourcesCount = Util.size(trackedRace.getWindSources(WindSourceType.EXPEDITION)); + statisticsDTO.hasMeasuredWindData = statisticsDTO.measuredWindSourcesCount > 0; + + // leg progress data + RaceDefinition race = trackedRace.getRace(); + if(race.getCourse() != null) { + statisticsDTO.hasLegProgressData = true; + statisticsDTO.totalLegsCount = race.getCourse().getLegs().size(); + TrackedLeg currentLeg = trackedRace.getCurrentLeg(MillisecondsTimePoint.now()); + if(currentLeg != null) { + statisticsDTO.currentLegNo = race.getCourse().getIndexOfWaypoint(currentLeg.getLeg().getFrom()); + } else { + statisticsDTO.currentLegNo = 0; + } + } + + // media data + if(mediaTracks != null) { + for(MediaTrack track: mediaTracks) { + switch(track.mimeType.mediaType) { + case audio: + statisticsDTO.hasAudioData = true; + statisticsDTO.audioTracksCount = statisticsDTO.audioTracksCount == null ? 1 : statisticsDTO.audioTracksCount++; + break; + case video: + statisticsDTO.hasVideoData = true; + statisticsDTO.videoTracksCount = statisticsDTO.videoTracksCount == null ? 1 : statisticsDTO.videoTracksCount++; + break; + } + } + } + + return statisticsDTO; + } + private PlacemarkOrderDTO getRacePlaces(TrackedRace trackedRace) { Util.Pair startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace); PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO(); 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 67f0f9dc36f..f9477ea027f 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 @@ -20,6 +20,7 @@ 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.RevokeEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; import com.sap.sailing.domain.racelog.tracking.CloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.racelog.tracking.DefineMarkEvent; import com.sap.sailing.domain.racelog.tracking.DenoteForTrackingEvent; @@ -150,4 +151,9 @@ public class RaceColumnRaceLogReplicator implements RaceLogEventVisitor, Seriali public void visit(CloseOpenEndedDeviceMappingEvent event) { notifyOnAdd(event); } + + @Override + public void visit(AdditionalScoringInformationEvent additionalScoringInformation) { + notifyOnAdd(additionalScoringInformation); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 18206de4caa..5c61a242a33 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -36,6 +36,7 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnInSeries; import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; @@ -68,6 +69,7 @@ import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCache; import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache; import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater; +import com.sap.sailing.domain.racelog.InvalidatesLeaderboardCache; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.tracking.GPSFix; @@ -83,8 +85,8 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRaceStatus; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; import com.sap.sailing.domain.tracking.Wind; -import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.util.impl.LockUtil; import com.sap.sailing.util.impl.NamedReentrantReadWriteLock; import com.sap.sailing.util.impl.RaceColumnListeners; @@ -1215,6 +1217,13 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race @Override public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) { getRaceColumnListeners().notifyListenersAboutRaceLogEventAdded(raceColumn, raceLogIdentifier, event); + if (event instanceof InvalidatesLeaderboardCache) { + // make sure to invalidate the cache as this event indicates that + // it changes values the cache could still hold + if (leaderboardDTOCache != null) { + leaderboardDTOCache.invalidate(this); + } + } } @Override @@ -1240,7 +1249,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race Map>> competitorsFromBestToWorstTasks = new HashMap<>(); for (final RaceColumn raceColumn : this.getRaceColumns()) { result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace(), - this.getScoringScheme().isValidInTotalScore(this, raceColumn, timePoint)); + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null, + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null); for (Fleet fleet : raceColumn.getFleets()) { RegattaAndRaceIdentifier raceIdentifier = null; RaceDTO race = null; @@ -1253,8 +1263,10 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } // Note: the RaceColumnDTO won't be created by the following addRace call because it has been created // above by the result.createEmptyRaceColumn call - result.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), raceColumn.getFactor(), fleetDTO, - raceColumn.isMedalRace(), raceIdentifier, race); + result.addRace(raceColumn.getName(), raceColumn.getExplicitFactor(), raceColumn.getFactor(), + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getRegatta().getName() : null, + raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null, + fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race); } FutureTask> task = new FutureTask>(new Callable>() { @Override @@ -1647,7 +1659,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race boolean waitForLatestAnalyses, Map> legRanksCache, LeaderboardDTOCalculationReuseCache cache) throws NoWindException { LegEntryDTO result; - if (trackedLeg == null || trackedLeg.getTime(timePoint) == null) { + final Duration time = trackedLeg.getTime(timePoint); + if (trackedLeg == null || time == null) { result = null; } else { result = new LegEntryDTO(); @@ -1669,7 +1682,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race Distance distanceTraveled = trackedLeg.getDistanceTraveled(timePoint); result.distanceTraveledInMeters = distanceTraveled == null ? null : distanceTraveled.getMeters(); result.estimatedTimeToNextWaypointInSeconds = trackedLeg.getEstimatedTimeToNextMarkInSeconds(timePoint, WindPositionMode.EXACT, cache); - result.timeInMilliseconds = trackedLeg.getTime(timePoint).asMillis(); + result.timeInMilliseconds = time.asMillis(); result.finished = trackedLeg.hasFinishedLeg(timePoint); result.gapToLeaderInSeconds = trackedLeg.getGapToLeaderInSeconds(timePoint, legRanksCache.get(trackedLeg.getLeg()).entrySet().iterator().next().getKey(), WindPositionMode.LEG_MIDDLE); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java new file mode 100644 index 00000000000..1ca7177aa00 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java @@ -0,0 +1,65 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.List; +import java.util.concurrent.Callable; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; +import com.sap.sailing.domain.racelog.RaceLog; +import com.sap.sailing.domain.racelog.analyzing.impl.AdditionalScoringInformationFinder; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationEvent; +import com.sap.sailing.domain.racelog.scoring.AdditionalScoringInformationType; +import com.sap.sse.common.Util; + +/** + * {@link HighPointFirstGetsFixedScore} scheme that in most cases applies + * 10 points for the winner. Iff for one race column a {@link AdditionalScoringInformationEvent} + * is found then 8 points are applied for the winner. + * + * @author Simon Marcel Pamies + */ +public class HighPointFirstGets10Or8AndLastBreaksTie extends HighPointFirstGetsFixedScore { + private static final long serialVersionUID = 1L; + + private final double SCORE_FOR_WINNER_IF_OVERWRITTEN = 8.0; + + public HighPointFirstGets10Or8AndLastBreaksTie() { + super(10.0); + } + + @Override + public ScoringSchemeType getType() { + return ScoringSchemeType.HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT; + } + + @Override + public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + return 0; + } + + @Override + public Double getScoreForRank(RaceColumn raceColumn, Competitor competitor, int rank, Callable numberOfCompetitorsInRaceFetcher, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher) { + Double effectiveScore = super.getScoreForRank(raceColumn, competitor, rank, numberOfCompetitorsInRaceFetcher, numberOfCompetitorsInLeaderboardFetcher); + return checkForOverwrittenScore(raceColumn, rank, effectiveScore); + } + + private Double checkForOverwrittenScore(RaceColumn raceColumn, int rank, Double effectiveScore) { + Double result = effectiveScore; + for (Fleet fleet : raceColumn.getFleets()) { + RaceLog raceLog = raceColumn.getRaceLog(fleet); + AdditionalScoringInformationFinder finder = new AdditionalScoringInformationFinder(raceLog); + AdditionalScoringInformationEvent event = finder.analyze(AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE); + if (event != null) { + if (rank == 0) { + result = null; + } else { + result = Math.max(getMinimumScoreFromRank(), (double) (SCORE_FOR_WINNER_IF_OVERWRITTEN - rank + 1)); + } + } + } + return result; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGetsFixedScore.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGetsFixedScore.java index 5742b5211ad..f9ef8bf135e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGetsFixedScore.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGetsFixedScore.java @@ -32,11 +32,11 @@ public abstract class HighPointFirstGetsFixedScore extends HighPoint { this.minimumScoreFromRank = minimumScoreFromRank; } - protected double getScoreForRaceWinner() { + double getScoreForRaceWinner() { return scoreForRaceWinner; } - private double getMinimumScoreFromRank() { + double getMinimumScoreFromRank() { return minimumScoreFromRank; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointWinnerGetsSixIgnoringRaceCount.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointWinnerGetsSixIgnoringRaceCount.java new file mode 100644 index 00000000000..0d8b0a82b86 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointWinnerGetsSixIgnoringRaceCount.java @@ -0,0 +1,20 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import com.sap.sailing.domain.common.ScoringSchemeType; + +public class HighPointWinnerGetsSixIgnoringRaceCount extends HighPointWinnerGetsSix { + private static final long serialVersionUID = -6974180846946052247L; + + /** + * Ignores the number of races scored, making the simple total points the first ranking criterion. + */ + @Override + public int compareByNumberOfRacesScored(int competitor1NumberOfRacesScored, int competitor2NumberOfRacesScored) { + return 0; + } + + @Override + public ScoringSchemeType getType() { + return ScoringSchemeType.HIGH_POINT_WINNER_GETS_SIX_IGNORING_RACE_COUNT; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardGroupImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardGroupImpl.java index 2e654c8ead7..7d4a5736602 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardGroupImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardGroupImpl.java @@ -31,8 +31,9 @@ public class LeaderboardGroupImpl extends LeaderboardGroupBaseImpl implements Le /** * Creates a new leaderboard group with a new UUID as its ID. */ - public LeaderboardGroupImpl(String name, String description, boolean displayGroupsInReverseOrder, List leaderboards) { - this(UUID.randomUUID(), name, description, displayGroupsInReverseOrder, leaderboards); + public LeaderboardGroupImpl(String name, String description, String displayName, + boolean displayGroupsInReverseOrder, List leaderboards) { + this(UUID.randomUUID(), name, description, displayName, displayGroupsInReverseOrder, leaderboards); } private synchronized void writeObject(ObjectOutputStream oos) throws IOException { @@ -42,8 +43,9 @@ public class LeaderboardGroupImpl extends LeaderboardGroupBaseImpl implements Le /** * Use this constructor when loading or deserializing a leaderboard group and the ID is known and is provided to the constructor. */ - public LeaderboardGroupImpl(UUID id, String name, String description, boolean displayGroupsInReverseOrder, List leaderboards) { - super(id, name, description); + public LeaderboardGroupImpl(UUID id, String name, String description, String displayName, + boolean displayGroupsInReverseOrder, List leaderboards) { + super(id, name, description, displayName); this.displayGroupsInReverseOrder = displayGroupsInReverseOrder; this.leaderboards = new ArrayList(leaderboards); this.listeners = new HashSet(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java index 5527e9ac1ed..3a4a3ee1e0a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ScoreCorrectionImpl.java @@ -296,6 +296,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection { case DNS: case DNC: case OCS: + case BFD: result = true; break; default: diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java index 61080855d20..753278e985f 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/masterdataimport/TopLevelMasterData.java @@ -73,14 +73,11 @@ public class TopLevelMasterData implements Serializable { HashSet eventSet = new HashSet(); eventsForLeaderboardGroup.put(leaderboardGroup, eventSet); for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - CourseArea courseArea = regattaLeaderboard.getRegatta().getDefaultCourseArea(); - if (courseArea != null) { - Event event = eventForCourseArea.get(courseArea); - if (event != null) { - eventSet.add(event); - } + CourseArea courseArea = leaderboard.getDefaultCourseArea(); + if (courseArea != null) { + Event event = eventForCourseArea.get(courseArea); + if (event != null) { + eventSet.add(event); } } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFix.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFix.java index f1764bdd193..673b1870980 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFix.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/GPSFix.java @@ -3,6 +3,6 @@ package com.sap.sailing.domain.tracking; import com.sap.sailing.domain.base.Timed; import com.sap.sailing.domain.common.SpeedWithBearing; -public interface GPSFix extends Positioned, Timed, WithValidityCache { +public interface GPSFix extends Positioned, Timed, WithValidityCache, WithEstimatedSpeedCache { SpeedWithBearing getSpeedAndBearingRequiredToReach(GPSFix to); } \ No newline at end of file diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 0c04c02c7ce..7ca16436693 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -397,7 +397,7 @@ public interface TrackedRace extends Serializable { /** * Computes a default wind direction based on the direction of the first leg at time at, with a default - * speed of one knot. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()} returns + * speed of zero knots. Note that this wind direction can only be used if {@link #raceIsKnownToStartUpwind()} returns * true. * * @param at diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithEstimatedSpeedCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithEstimatedSpeedCache.java new file mode 100755 index 00000000000..d439add3db6 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithEstimatedSpeedCache.java @@ -0,0 +1,17 @@ +package com.sap.sailing.domain.tracking; + +import com.sap.sailing.domain.common.SpeedWithBearing; + +public interface WithEstimatedSpeedCache { + boolean isEstimatedSpeedCached(); + + /** + * Returns a valid result if {@link #isEstimatedSpeedCached()} returns true + */ + SpeedWithBearing getCachedEstimatedSpeed(); + + void invalidateEstimatedSpeedCache(); + + void cacheEstimatedSpeed(SpeedWithBearing estimatedSpeed); + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithValidityCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithValidityCache.java index 66c1c639df4..7e73e89410d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithValidityCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WithValidityCache.java @@ -3,7 +3,10 @@ package com.sap.sailing.domain.tracking; public interface WithValidityCache { boolean isValidityCached(); - boolean isValid(); + /** + * Returns a valid result if {@link #isValidCached()} returns true + */ + boolean isValidCached(); void invalidateCache(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java index 8471cbc5d53..ff982b430db 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractGPSFixImpl.java @@ -48,14 +48,21 @@ public abstract class AbstractGPSFixImpl implements GPSFix { Speed speed = distance.inTime(to.getTimePoint().asMillis()-getTimePoint().asMillis()); return new KnotSpeedWithBearingImpl(speed.getKnots(), bearing); } - + + /** + * Subclasses overriding this method also need to override {@link #isValid} with a useful implementation. + */ @Override public boolean isValidityCached() { return false; } + /** + * Only evaluated if {@link #isValidityCached()} returns true. Therefore, subclassess that + * override {@link #isValidityCached()} also need to override this method accordingly. + */ @Override - public boolean isValid() { + public boolean isValidCached() { return false; } @@ -66,4 +73,29 @@ public abstract class AbstractGPSFixImpl implements GPSFix { @Override public void cacheValidity(boolean isValid) { } + + /** + * Subclasses overriding this method also need to override {@link #getCachedEstimatedSpeed()} with a useful implementation. + */ + @Override + public boolean isEstimatedSpeedCached() { + return false; + } + + /** + * Only evaluated if {@link #isEstimatedSpeedCached()} returns true. Therefore, subclassess that + * override {@link #isEstimatedSpeedCached()} also need to override this method accordingly. + */ + @Override + public SpeedWithBearing getCachedEstimatedSpeed() { + return null; + } + + @Override + public void invalidateEstimatedSpeedCache() { + } + + @Override + public void cacheEstimatedSpeed(SpeedWithBearing estimatedSpeed) { + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java index 77fd16a6521..1071c4b254e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CompactGPSFixImpl.java @@ -1,8 +1,12 @@ package com.sap.sailing.domain.tracking.impl; +import com.sap.sailing.domain.common.AbstractBearing; import com.sap.sailing.domain.common.AbstractPosition; +import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.AbstractSpeedWithAbstractBearingImpl; import com.sap.sailing.domain.common.impl.AbstractTimePoint; import com.sap.sailing.domain.tracking.GPSFix; @@ -19,6 +23,23 @@ import com.sap.sailing.domain.tracking.GPSFix; */ public class CompactGPSFixImpl extends AbstractGPSFixImpl { private static final long serialVersionUID = 8167588584536992501L; + + /** + * Bit mask for {@link #whatIsCached}, telling whether validity is currently cached + */ + private static final byte IS_VALIDITY_CACHED = 1<<0; + + /** + * Bit mask for {@link #whatIsCached}, telling whether the estimated speed is currently cached + */ + private static final byte IS_ESTIMATED_SPEED_CACHED = 1<<1; + + /** + * Bit mask for {@link #whatIsCached}, telling the validity of the fix; only relevant if + * {@link #whatIsCached}&{@link #IS_VALIDITY_CACHED} != 0 + */ + private static final byte VALIDITY = 1<<2; + private final double latDeg; private final double lngDeg; private final long timePointAsMillis; @@ -28,7 +49,19 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl { * needs to be invalidated as soon as fixes are added to the containing track which may have an impact * on this fix's validity. -1 means "no value"; 0 means invalid, 1 means valid. */ - private byte validityCache = -1; + private byte whatIsCached = 0; + + /** + * When {@link #whatIsCached}&{@link #IS_ESTIMATED_SPEED_CACHED} != 0, this field tells the estimated speed's + * true "bearing" (true course over ground) in degrees. + */ + private double cachedEstimatedSpeedBearingInDegrees; + + /** + * When {@link #whatIsCached}&{@link #IS_ESTIMATED_SPEED_CACHED} != 0, this field tells the estimated speed + * in knots. + */ + private double cachedEstimatedSpeedInKnots; private class CompactPosition extends AbstractPosition { private static final long serialVersionUID = 5621506820766614178L; @@ -53,6 +86,29 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl { } } + private class CompactEstimatedSpeedBearing extends AbstractBearing { + private static final long serialVersionUID = 8549231429037883121L; + + @Override + public double getDegrees() { + return cachedEstimatedSpeedBearingInDegrees; + } + } + + private class CompactEstimatedSpeed extends AbstractSpeedWithAbstractBearingImpl { + private static final long serialVersionUID = -5871855443391817248L; + + @Override + public Bearing getBearing() { + return new CompactEstimatedSpeedBearing(); + } + + @Override + public double getKnots() { + return cachedEstimatedSpeedInKnots; + } + } + public CompactGPSFixImpl(Position position, TimePoint timePoint) { latDeg = position.getLatDeg(); lngDeg = position.getLngDeg(); @@ -80,22 +136,52 @@ public class CompactGPSFixImpl extends AbstractGPSFixImpl { @Override public boolean isValidityCached() { - return validityCache != -1; + return (whatIsCached & IS_VALIDITY_CACHED) != 0; } @Override - public boolean isValid() { - return validityCache == 1; + public boolean isValidCached() { + assert isValidityCached(); + return (whatIsCached & VALIDITY) != 0; } @Override public void invalidateCache() { - validityCache = -1; + whatIsCached &= ~IS_VALIDITY_CACHED; } @Override public void cacheValidity(boolean isValid) { - validityCache = (byte) (isValid ? 1 : 0); + if (isValid) { + whatIsCached |= IS_VALIDITY_CACHED | VALIDITY; + } else { + whatIsCached |= IS_VALIDITY_CACHED; + whatIsCached &= ~VALIDITY; + } + } + + @Override + public boolean isEstimatedSpeedCached() { + return (whatIsCached & IS_ESTIMATED_SPEED_CACHED) != 0; + } + + @Override + public SpeedWithBearing getCachedEstimatedSpeed() { + assert isEstimatedSpeedCached(); + return new CompactEstimatedSpeed(); + } + + @Override + public void invalidateEstimatedSpeedCache() { + whatIsCached &= ~IS_ESTIMATED_SPEED_CACHED; + } + + @Override + public void cacheEstimatedSpeed(SpeedWithBearing estimatedSpeed) { + cachedEstimatedSpeedBearingInDegrees = estimatedSpeed.getBearing().getDegrees(); + cachedEstimatedSpeedInKnots = estimatedSpeed.getKnots(); + whatIsCached |= IS_ESTIMATED_SPEED_CACHED; } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java index f56a09c6b79..5b5ddce5a03 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CrossTrackErrorCache.java @@ -455,7 +455,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener { /** * Invalidates all cache contents for all competitors from the beginning of time */ - private void invalidate() { + public void invalidate() { final List shuffledCompetitors = new ArrayList<>(cachePerCompetitor.keySet()); Collections.shuffle(shuffledCompetitors); for (Competitor competitor : shuffledCompetitors) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicGPSFixMovingTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicGPSFixMovingTrackImpl.java index 7e9472cd8ed..9fd5fb15d0e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicGPSFixMovingTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicGPSFixMovingTrackImpl.java @@ -123,7 +123,7 @@ public class DynamicGPSFixMovingTrackImpl extends GPSFixTrackImpl extends TrackImpl private transient MaxSpeedCache maxSpeedCache; + private int estimatedSpeedCacheHits; + private int estimatedSpeedCacheMisses; + public GPSFixTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage) { this(trackedItem, millisecondsOverWhichToAverage, DEFAULT_MAX_SPEED_FOR_SMOOTHING); } @@ -230,7 +233,7 @@ public class GPSFixTrackImpl extends TrackImpl } @Override - public boolean isValid() { + public boolean isValidCached() { return false; } @@ -241,6 +244,24 @@ public class GPSFixTrackImpl extends TrackImpl @Override public void cacheValidity(boolean isValid) { } + + @Override + public boolean isEstimatedSpeedCached() { + return false; + } + + @Override + public SpeedWithBearing getCachedEstimatedSpeed() { + return null; + } + + @Override + public void invalidateEstimatedSpeedCache() { + } + + @Override + public void cacheEstimatedSpeed(SpeedWithBearing estimatedSpeed) { + } } @@ -577,12 +598,29 @@ public class GPSFixTrackImpl extends TrackImpl @Override public SpeedWithBearing getEstimatedSpeed(TimePoint at) { lockForRead(); + FixType ceil = getInternalFixes().ceiling(createDummyGPSFix(at)); try { - SpeedWithBearingWithConfidence estimatedSpeed = getEstimatedSpeed(at, getInternalFixes(), + final SpeedWithBearing result; + if (ceil != null && ceil.getTimePoint().equals(at) && ceil.isEstimatedSpeedCached()) { + estimatedSpeedCacheHits++; + result = ceil.getCachedEstimatedSpeed(); + } else { + estimatedSpeedCacheMisses++; + SpeedWithBearingWithConfidence estimatedSpeed = getEstimatedSpeed(at, getInternalFixes(), ConfidenceFactory.INSTANCE.createExponentialTimeDifferenceWeigher( // use a minimum confidence to avoid the bearing to flip to 270deg in case all is zero getMillisecondsOverWhichToAverageSpeed()/2, /* minimumConfidence */ 0.00000001)); // half confidence if half averaging interval apart - return estimatedSpeed == null ? null : estimatedSpeed.getObject(); + result = estimatedSpeed == null ? null : estimatedSpeed.getObject(); + if (estimatedSpeed != null) { + if (ceil != null && ceil.getTimePoint().equals(at)) { + ceil.cacheEstimatedSpeed(result); + } + } + } + if (logger.isLoggable(Level.FINE) && (estimatedSpeedCacheHits + estimatedSpeedCacheMisses) % 1000 == 0) { + logger.fine("estimated speed cache hits/misses: "+estimatedSpeedCacheHits+"/"+estimatedSpeedCacheMisses); + } + return result; } finally { unlockAfterRead(); } @@ -769,6 +807,9 @@ public class GPSFixTrackImpl extends TrackImpl * * But even for a track with {@link GPSFixMoving} fixes this is a good algorithm because in case the speed changes * significantly between fixes, it is important to know the next fix to understand and consider the trend. + * + * @see #getMillisecondsOverWhichToAverage() + * @see #getMillisecondsOverWhichToAverageSpeed() */ protected List getFixesRelevantForSpeedEstimation(TimePoint at, NavigableSet fixesToUseForSpeedEstimation) { lockForRead(); @@ -858,7 +899,7 @@ public class GPSFixTrackImpl extends TrackImpl } /** - * When redefining this method, make sure to redefine {@link #invalidateValidityAndDistanceCaches(GPSFix)} + * When redefining this method, make sure to redefine {@link #invalidateValidityAndEstimatedSpeedAndDistanceCaches(GPSFix)} * accordingly. This implementation checks the immediate previous and next fix for e. Therefore, when * adding a fix, only immediately adjacent fix's validity caches need to be invalidated. *

@@ -875,7 +916,7 @@ public class GPSFixTrackImpl extends TrackImpl isValid = true; } else { if (e.isValidityCached()) { - isValid = e.isValid(); + isValid = e.isValidCached(); } else { FixType previous = rawFixes.lower(e); final boolean atLeastOnePreviousFixInRange = previous != null && e.getTimePoint().asMillis() - previous.getTimePoint().asMillis() <= getMillisecondsOverWhichToAverageSpeed(); @@ -918,7 +959,7 @@ public class GPSFixTrackImpl extends TrackImpl * of the gpsFix "upwards." However, if the adjacent earlier fixes have changed their validity by the addition * of gpsFix, the distance cache must be invalidated starting with the first fix whose validity changed. */ - protected void invalidateValidityAndDistanceCaches(FixType gpsFix) { + protected void invalidateValidityAndEstimatedSpeedAndDistanceCaches(FixType gpsFix) { assertWriteLock(); TimePoint distanceCacheInvalidationStart = gpsFix.getTimePoint(); // see also bug 968: cache entries for intervals ending after the last fix need to be removed because they are @@ -930,6 +971,10 @@ public class GPSFixTrackImpl extends TrackImpl distanceCacheInvalidationStart = last.getTimePoint().plus(1); // add one millisecond to invalidate *after* the last fix only } gpsFix.invalidateCache(); + for (FixType fixOnWhichToInvalidateEstimatedSpeed : getFixesRelevantForSpeedEstimation(gpsFix.getTimePoint(), + getInternalRawFixes())) { + fixOnWhichToInvalidateEstimatedSpeed.invalidateEstimatedSpeedCache(); + } Iterable lowers = getEarlierFixesWhoseValidityMayBeAffected(gpsFix); for (FixType lower : lowers) { boolean lowerWasValid = isValid(getRawFixes(), lower); @@ -1014,7 +1059,7 @@ public class GPSFixTrackImpl extends TrackImpl try { firstFixInTrack = getRawFixes().isEmpty(); result = addWithoutLocking(fix); - invalidateValidityAndDistanceCaches(fix); + invalidateValidityAndEstimatedSpeedAndDistanceCaches(fix); } finally { unlockAfterWrite(); } 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 c7372728b4c..eccb13d321c 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 @@ -220,7 +220,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl * them. */ private transient SmartFutureCache>, EmptyUpdateInterval> maneuverCache; - + private transient Map> directionFromStartToNextMarkCache; private final ConcurrentHashMap> markTracks; @@ -234,7 +234,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl private transient Timer cacheInvalidationTimer; private transient Object cacheInvalidationTimerLock; - protected transient HashMap attachedRaceLogs; + protected transient ConcurrentHashMap attachedRaceLogs; /** * The time delay to the current point in time in milliseconds. @@ -289,7 +289,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind); shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2); locksForMarkPassings = new IdentityHashMap<>(); - attachedRaceLogs = new HashMap<>(); + attachedRaceLogs = new ConcurrentHashMap<>(); this.status = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.PREPARED, 0.0); this.statusNotifier = new Object[0]; this.loadingFromWindStoreLock = new NamedReentrantReadWriteLock("Loading from wind store lock for tracked race " @@ -467,7 +467,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl */ private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); - attachedRaceLogs = new HashMap<>(); + attachedRaceLogs = new ConcurrentHashMap<>(); markPassingsTimes = new ArrayList>>(); cacheInvalidationTimerLock = new Object(); windStore = EmptyWindStore.INSTANCE; @@ -475,7 +475,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl competitorRankingsLocks = createCompetitorRankingsLockMap(); directionFromStartToNextMarkCache = new HashMap>(); crossTrackErrorCache = new CrossTrackErrorCache(this); + crossTrackErrorCache.invalidate(); maneuverCache = createManeuverCache(); + triggerManeuverCacheRecalculationForAllCompetitors(); logger.info("Deserialized race " + getRace().getName()); shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2); } @@ -489,7 +491,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public synchronized void waitForLoadingFromGPSFixStoreToFinishRunning(RaceLog fromRaceLog) throws InterruptedException { - while (! attachedRaceLogs.containsKey(fromRaceLog.getId()) || loadingFromGPSFixStore) { + while (!attachedRaceLogs.containsKey(fromRaceLog.getId()) || loadingFromGPSFixStore) { wait(); } } @@ -504,7 +506,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } }, /* nameForLocks */"Maneuver cache for race " + getRace().getName()); } - + /** * Precondition: race has already been set, e.g., in constructor before this method is called */ @@ -1378,7 +1380,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl Position firstLegEnd = getApproximatePosition(firstLeg.getTo(), at); Position firstLegStart = getApproximatePosition(firstLeg.getFrom(), at); if (firstLegStart != null && firstLegEnd != null) { - result = new WindImpl(firstLegStart, at, new KnotSpeedWithBearingImpl(1.0, + result = new WindImpl(firstLegStart, at, new KnotSpeedWithBearingImpl(0.0, firstLegEnd.getBearingGreatCircle(firstLegStart))); } else { result = null; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/util/SmartFutureCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/util/SmartFutureCache.java index b20bd3c8809..3e11b1d5077 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/util/SmartFutureCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/util/SmartFutureCache.java @@ -576,4 +576,11 @@ public class SmartFutureCache> { return smartFutureCacheTaskReuseCounter; } + /** + * Removes the key from the cache. If any updates are still running, they may again insert the key into hte cache. + */ + public void remove(K key) { + cache(key, null); + } + } diff --git a/java/com.sap.sailing.gwt.ui.test/.classpath b/java/com.sap.sailing.gwt.ui.test/.classpath index 5cc60e2c543..d03a3fcb224 100755 --- a/java/com.sap.sailing.gwt.ui.test/.classpath +++ b/java/com.sap.sailing.gwt.ui.test/.classpath @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java index 01ed0d076e0..544c21cc430 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java @@ -1,17 +1,19 @@ package com.sap.sailing.gwt.ui.common.client; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + import org.junit.Test; import com.sap.sailing.domain.common.Duration; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; -import com.sap.sailing.gwt.ui.common.client.Countdown.CountdownListener; -import com.sap.sailing.gwt.ui.common.client.Countdown.RemainingTime; -import com.sap.sailing.gwt.ui.common.client.Countdown.Unit; - -import static org.junit.Assert.*; - -import static org.hamcrest.Matchers.*; +import com.sap.sailing.gwt.home.client.shared.Countdown; +import com.sap.sailing.gwt.home.client.shared.Countdown.CountdownListener; +import com.sap.sailing.gwt.home.client.shared.Countdown.RemainingTime; +import com.sap.sailing.gwt.home.client.shared.Countdown.Unit; public class CountdownTest { diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java index f56b53061f8..18f7842172e 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java @@ -149,7 +149,7 @@ public class GwtTestCaseColumnToggling extends GWTTestCase { @Override public void onSuccess(Void result) { System.out.println("Added column to leaderboard."); - RaceColumnDTO race = new RaceColumnDTO(/* isValidInTotalScore */ null); + RaceColumnDTO race = new RaceColumnDTO(); race.setName(COLUMN1_NAME); race.setMedalRace(false); leaderboardPanel.addColumn(leaderboardPanel.createRaceColumn(race)); diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java index 411b5379c72..6ee5c04a7c8 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java @@ -9,7 +9,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; -import com.sap.sailing.gwt.ui.leaderboard.SortableColumn; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSortableColumnWithMinMax; import com.sap.sailing.gwt.ui.leaderboard.SortedCellTable; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.useragent.UserAgentDetails; @@ -20,12 +20,12 @@ public class LeaderboardPanelMock extends LeaderboardPanel { String leaderboardName, ErrorReporter errorReporter, StringMessages stringMessages) { super(sailingService, new AsyncActionsExecutor(), LeaderboardSettingsFactory.getInstance().createNewDefaultSettings( - /* racesToShow */null, /* namesOfRacesToShow */ null, null, /* autoExpandFirstRace */ false), new CompetitorSelectionModel( + /* racesToShow */null, /* namesOfRacesToShow */ null, null, /* autoExpandFirstRace */ false, /* showRegattaRank */ true), new CompetitorSelectionModel( /* hasMultiSelection */true), leaderboardName, errorReporter, stringMessages, new UserAgentDetails("gecko1_8"), /* showRaceDetails */ true); } @Override - public void addColumn(SortableColumn column) { + public void addColumn(LeaderboardSortableColumnWithMinMax column) { // TODO Auto-generated method stub super.addColumn(column); } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java index db4b3ba8ab5..ba99ba90492 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PolarSheetGenerationServiceTest.java @@ -209,7 +209,7 @@ public class PolarSheetGenerationServiceTest { } @Override - public boolean isValid() { + public boolean isValidCached() { return true; } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java index 00113e74ea5..b828e4b4245 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java @@ -61,9 +61,9 @@ public class TestColumnSwapping { return UUID.randomUUID().toString(); } }, /* hasOverallDetails */ false); - leaderboardOriginalDTO.addRace("Race1", /* explicitFactor */ null, 2., DEFAULT_FLEET, true, null, null); - leaderboardOriginalDTO.addRace("Race3", /* explicitFactor */ null, 2., DEFAULT_FLEET, true, null, null); - leaderboardOriginalDTO.addRace("Race2", /* explicitFactor */ null, 2., DEFAULT_FLEET, true, null, null); + leaderboardOriginalDTO.addRace("Race1", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null); + leaderboardOriginalDTO.addRace("Race3", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null); + leaderboardOriginalDTO.addRace("Race2", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null); } catch (Exception e) { e.printStackTrace(); } @@ -126,9 +126,9 @@ public class TestColumnSwapping { } }, /* hasOverallDetails */ false); assertNotNull("Leaderboard != NULL", lb); - lb.addRace("1", /* explicitFactor */ null, 1., DEFAULT_FLEET, false, null, null); - lb.addRace("2", /* explicitFactor */ null, 1., DEFAULT_FLEET, false, null, null); - lb.addRace("3", /* explicitFactor */ null, 1., DEFAULT_FLEET, true, null, null); + lb.addRace("1", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, false, null, null); + lb.addRace("2", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, false, null, null); + lb.addRace("3", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null); lb.moveRaceDown("1"); String[] s = new String[] { "2", "1", "3" }; for (int i = 0; i < lb.getRaceList().size(); i++) { diff --git a/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs b/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs index 581bf904451..b7c13760e13 100755 --- a/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs +++ b/java/com.sap.sailing.gwt.ui/.settings/com.google.gwt.eclipse.core.prefs @@ -1,4 +1,3 @@ eclipse.preferences.version=1 entryPointModules= filesCopiedToWebInfLib=gwt-servlet.jar -gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgLiAtbG9jYWxXb3JrZXJzIDMgLXN0cmljdCAtbG9nTGV2ZWwgVFJBQ0UgLWNvbXBpbGVSZXBvcnQgLVhzb3ljRGV0YWlsZWRdXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDIwMjRtIC1EZ3d0LnVzZWFyY2hpdmVzPWZhbHNlXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5BZG1pbkNvbnNvbGU8L2VudHJ5LXBvaW50LW1vZHVsZT48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5zYXAuc2FpbGluZy5nd3QudWkuUmFjZUJvYXJkPC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLkxlYWRlcmJvYXJkPC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLlNwZWN0YXRvcjwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+ diff --git a/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs index 548f1163d5a..8aa4ae5d789 100755 --- a/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs +++ b/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs @@ -1,3 +1,4 @@ eclipse.preferences.version=1 +encoding//src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages_de.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties=UTF-8 diff --git a/java/com.sap.sailing.gwt.ui/AdminConsole.css b/java/com.sap.sailing.gwt.ui/AdminConsole.css index 22a9b491cb8..d87c9892dd9 100644 --- a/java/com.sap.sailing.gwt.ui/AdminConsole.css +++ b/java/com.sap.sailing.gwt.ui/AdminConsole.css @@ -151,6 +151,7 @@ fieldset legend { .gwt-Button { margin: 3px 2px 3px 5px; + outline: 0; } .gwt-Button:hover { diff --git a/java/com.sap.sailing.gwt.ui/CommonControls.css b/java/com.sap.sailing.gwt.ui/CommonControls.css old mode 100644 new mode 100755 index 23b8c26a282..68dd8edf6e6 --- a/java/com.sap.sailing.gwt.ui/CommonControls.css +++ b/java/com.sap.sailing.gwt.ui/CommonControls.css @@ -30,6 +30,8 @@ body ::-webkit-scrollbar-track { background: #b6b6b6; -webkit-border-radius: 5px; -moz-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; border-radius: 5px; overflow: hidden; border: 1px solid #aaaaaa; @@ -41,6 +43,8 @@ body ::-webkit-scrollbar-track { margin: 12px; -webkit-border-radius: 5px; -moz-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; border-radius: 5px; width: auto !important; border: 1px solid #aaaaaa; @@ -54,9 +58,13 @@ body ::-webkit-scrollbar-track { position: relative; -webkit-border-top-left-radius: 4px; -moz-border-top-left-radius: 4px; + -o-border-top-left-radius: 4px; + -ms-border-top-left-radius: 4px; border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; -moz-border-top-right-radius: 4px; + -o-border-top-right-radius: 4px; + -ms-border-top-right-radius: 4px; border-top-right-radius: 4px; } @@ -136,10 +144,6 @@ body ::-webkit-scrollbar-track { color:#A1A1A1; } -.gwt-SplitLayoutPanel-HDragger { - width: 20px; -} - .gwt-ToggleButton { background: url(images/btn-cta-orangeleft.png) center top repeat-x; padding: 8px; @@ -152,18 +156,179 @@ body ::-webkit-scrollbar-track { color: #fff; } -.gwt-SplitLayoutPanel-HDragger { - width: 12px; +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Panel { + position: absolute; + right: 10px; + top: 3px; +} + +.gwt-SplitLayoutPanel-EastToggleButton-Panel { + position: absolute; + bottom: 77px; + margin-left: -35px; +} + +.gwt-SplitLayoutPanel-EastToggleButton { + height: 40px; + background-color: white; + border: none; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + padding-right: 25px; + padding-left: 30px; + margin-left: -15px; + border-bottom: 1px solid #cecece; + border-right: 1px solid #cecece; + border-left: 1px solid #cecece; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; +} + +.gwt-SplitLayoutPanel-EastToggleButton-Open { + background: white url(images/arrows_top_black_small.png) 96% 50% no-repeat; +} + +.gwt-SplitLayoutPanel-EastToggleButton-Closed { + background: white url(images/arrows_bottom_black_small.png) 96% 50% no-repeat; +} + +.gwt-SplitLayoutPanel-EastToggleButton:hover { + background-color: #ececec; +} + +.gwt-SplitLayoutPanel-EastToggleButton:focus { + outline:0 !important; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton { + height: 33px; + background-color: #fff; + border: 1px solid #cecece; + margin-left: 5px; + padding: 2px 40px; + border-radius: 7px; + margin-top: 0px; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed { + background: white url(images/arrows_top_black_small.png) 95% 50% no-repeat; + font-weight: normal; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open { + background: white url(images/arrows_bottom_black_small.png) 95% 50% no-repeat; + font-weight: bold; + border-width: 3px; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton:focus { + outline:0 !important; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton:hover { + background-color: #ececec; } .gwt-SplitLayoutPanel-HDragger { - background: #cbcaca url(images/thumb_vertical.png) center center no-repeat; - cursor: col-resize; + position: absolute; + height: 60px !important; + width: 25px !important; + margin-left: 3px; + top: 40% !important; + background: #ffffff url(images/thumb_vertical.png) 70% 50% no-repeat; + border: 2px solid #cecece; + border-left: 0px; + cursor: col-resize; + border-top-right-radius: 25px; + border-bottom-right-radius: 25px; + z-index: 1; +} + +.SplitLayoutPanel-Divider-Horizontal { + background: #ffffff; +} + +.SplitLayoutPanel-Divider-Vertical { + background: #ffffff; + border-top: 1px solid #cecece; } .gwt-SplitLayoutPanel-VDragger { - background: #cbcaca url(images/thumb_horz.png) center center no-repeat; - cursor: row-resize; + position: absolute; + width: 60px !important; + height: 21px !important; + left: 48% !important; + top: 2px !important; + background: #ffffff url(images/thumb_horz.png) 50% 30% no-repeat; + cursor: row-resize; + border: 2px solid #cecece; + border-bottom: 0px; + border-top-left-radius: 25px; + border-top-right-radius: 25px; + opacity: .7; + z-index: 1; +} + +.gwt-SplitLayoutPanel-CloseAndSettingsButton-Panel { + position: absolute; + right: 2px; + top: 2px; + z-index: 1; +} + +.gwt-SplitLayoutPanel-CloseButton { + margin-left: 10px; + border-top-left-radius: 25px; + border-top-right-radius: 25px; + border-bottom-left-radius: 25px; + border-bottom-right-radius: 25px; + background: white url(images/close_black.png) center no-repeat; + z-index: 1; + width: 28px; + height: 28px; + cursor: pointer; +} + +.gwt-SplitLayoutPanel-CloseButton:focus { + outline:0 !important; +} + +.gwt-SplitLayoutPanel-CloseButton:hover { + background-color: #ececec; +} + +.gwt-SettingsButton { + border: none; + background: grey url(images/SAP_RV_Settings.png) center no-repeat; + z-index: 1; + width: 28px; + height: 28px; + cursor: pointer; +} + +.gwt-SettingsButton:hover { + background-color: #cecece; +} + +.gwt-SettingsButton:focus { + outline: 0 !important; +} + +.gwt-MapSettingsButton { + margin-right: 30px; + margin-top: 5px; + border-top-left-radius: 25px; + border-top-right-radius: 25px; + border-bottom-left-radius: 25px; + border-bottom-right-radius: 25px; + border: none; + background: white url(images/SAP_RV_SettingsBlack.png) center no-repeat; + z-index: 1; + width: 28px; + height: 28px; + cursor: pointer; } .gwt-ToggleButton-up-hovering, .gwt-ToggleButton-down-hovering { @@ -310,15 +475,13 @@ body ::-webkit-scrollbar-track { } .timeLinePanel { - color: #fff; + color: black; width: 100%; position: fixed; bottom: 0; z-index: 9; - background: #7c7b7c; - box-shadow: 0 0 20px #858585; - -webkit-box-shadow: 0 0 20px #858585; - -moz-box-shadow: 0 0 20px #858585; + background: #f6f6f6; + border-top: 2px solid #cecece; } .timeLineInnerBgPanel { @@ -337,8 +500,6 @@ body ::-webkit-scrollbar-track { .timePanel-controls { margin: 0; padding: 7px 12px 0 12px; - -webkit-box-shadow: 0px -7px 8px 0px rgba(84, 84, 84, 1); - box-shadow: 0px -7px 8px 0px rgba(84, 84, 84, 1); height: 29px; } @@ -352,7 +513,7 @@ body ::-webkit-scrollbar-track { .timePanel-timeslider-play { float:left; - padding: 10px; + padding: 10px 4px; height: 24px; margin: 5px 14px 5px 0; } @@ -395,7 +556,7 @@ body ::-webkit-scrollbar-track { .timePanel-controls-timeDelay { float: right; - margin: 0 10px 0 0; + margin: 0 50px 0 0; } .timePanel-controls-playmode{ @@ -421,8 +582,6 @@ body ::-webkit-scrollbar-track { } .timePanelInnerWrapper { - -webkit-box-shadow: inset 0px -7px 13px 0px rgba(84, 84, 84, 1); - box-shadow: inset 0px -7px 13px 0px rgba(84, 84, 84, 1); } @@ -438,6 +597,8 @@ body ::-webkit-scrollbar-track { box-shadow: 0 0 20px #858585; -moz-box-shadow: 0 0 20px #858585; -webkit-box-shadow: 0 0 20px #858585; + -o-box-shadow: 0 0 20px #858585; + -ms-box-shadow: 0 0 20px #858585; z-index: 1; } @@ -456,7 +617,7 @@ body ::-webkit-scrollbar-track { right:0; } -.globalNavigationLink, .globalNavigationLink:visited { +.globalNavigation-Link, .globalNavigation-Link:visited { font-family: OpenSansSemiBold, Verdana, Arial, sans-serif; border: none; display: inline-block; @@ -476,13 +637,13 @@ body ::-webkit-scrollbar-track { white-space: nowrap; } -.globalNavigationLink:active { +.globalNavigation-Link:active { top: 1px; position: relative; border: none; } -.globalNavigationLink:hover { +.globalNavigation-Link:hover { background: url(images/btn-cta-orangeleft.png) center -30px repeat-x; cursor: pointer; } @@ -537,12 +698,17 @@ body ::-webkit-scrollbar-track { .gwt-DialogBox .Caption { font-size: 14px; - padding: 14px 10px; - background: url(images/dialogBox-bg.png) 0 0 repeat-x; + padding: 8px 10px; + background-color: #cecece; + border: 1px solid #cecece; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; + -o-border-radius-topleft: 5px; + -o-border-radius-topright: 5px; + -ms-border-radius-topleft: 5px; + -ms-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; font-family: OpenSansSemiBold, Verdana, Arial, sans-serif; @@ -551,9 +717,13 @@ body ::-webkit-scrollbar-track { .gwt-DialogBox .dialogContent { background: #ffffff; padding: 10px; - border: 10px solid #a6a6a6; + border: 1px solid #cecece; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px; + -o-border-bottom-right-radius: 5px; + -o-border-bottom-left-radius: 5px; + -ms-border-bottom-right-radius: 5px; + -ms-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 5px; border-bottom-right-radius: 5px; @@ -563,23 +733,26 @@ body ::-webkit-scrollbar-track { .gwt-Button, .gwt-Button:visited { font-family: OpenSansSemiBold, Verdana, Arial, sans-serif; border: none; - - background: url(images/btn-cta-orangeleft.png) center top repeat-x; + background: url(images/btn-cta-orangeleft.png) center top repeat-x; display: inline-block; padding: 2px 10px 4px; color: #fff; text-decoration: none; -moz-border-radius: 5px; -webkit-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; border-radius: 5px; - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); cursor: pointer; height: 24px; white-space: nowrap; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); } .gwt-Button:active { @@ -600,6 +773,8 @@ body ::-webkit-scrollbar-track { border: 1px solid #919090; -moz-box-shadow: none; -webkit-box-shadow: none; + -o-box-shadow: none; + -ms-box-shadow: none; box-shadow: none; border: none; text-shadow: none; @@ -659,7 +834,6 @@ body ::-webkit-scrollbar-track { } .SettingsDialogComponent .dialogInnerHeadline { - background: url(images/settingsDialog_bg.png) repeat-x 0 0 #E5E5E5; border: 1px solid #CCCCCC; font-family: OpenSansSemiBold,Arial,Verdana,sans-serif; height: 21px; @@ -667,6 +841,8 @@ body ::-webkit-scrollbar-track { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; margin: 0 0 10px 0; } @@ -743,4 +919,49 @@ video { .pointeredLink { cursor: pointer; cursor: hand; -} \ No newline at end of file +} + +.betterCheckboxCellSelected { + margin: 0px; + height: 18px; + width: 18px; + border: 1px; + background-color: #acacac; + vertical-align: middle; +} + +.betterCheckboxCellDeselected { + margin-left: 2px; /* account for the selection border that pushes a selected checkbox to the side */ + margin-top: 0px; + margin-bottom: 0px; + margin-right: 0px; + border: 1px; + height: 18px; + width: 18px; + vertical-align: middle; +} + +.LeaderboardPanel-FilterControl-Panel { + width: 380px; + border-top: 1px solid #ececec; + margin-top: 3px; +} + +.LeaderboardPanel-FilterClear-Button { + margin-top: 2px; + font-size: 10px; + outline: 0; + height: 23px; + background-color: #fff; + border: 1px solid #cecece; + border-radius: 7px; +} + +.LeaderboardPanel-FilterClear-Button:hover { + background-color: #ececec; +} + +.LeaderboardPanel-FilterControl-StatusLabel { + padding: 8px 2px; + font-size: 10px; +} diff --git a/java/com.sap.sailing.gwt.ui/CommonGwtControls.css b/java/com.sap.sailing.gwt.ui/CommonGwtControls.css deleted file mode 100644 index e3449e68e54..00000000000 --- a/java/com.sap.sailing.gwt.ui/CommonGwtControls.css +++ /dev/null @@ -1,209 +0,0 @@ -.gwt-SplitLayoutPanel-HDragger { - width: 20px; -} - -.gwt-ToggleButton { - background: url(images/btn-cta-orangeleft.png) center top repeat-x; - padding: 8px; - margin: 0 11px 0 0; - border: 0; -} - -.gwt-ToggleButton-down { - background: url(images/btn-cta-orangeleft.png) center -30px repeat-x; - color: #fff; -} - -.gwt-SplitLayoutPanel-HDragger { - width: 12px; -} - -.gwt-SplitLayoutPanel-HDragger { - background: #cbcaca url(images/thumb_vertical.png) center center no-repeat; - cursor: col-resize; -} - -.gwt-SplitLayoutPanel-VDragger { - background: #cbcaca url(images/thumb_horz.png) center center no-repeat; - cursor: row-resize; -} - -.gwt-ToggleButton-up-hovering, .gwt-ToggleButton-down-hovering { - background: url(images/btn-cta-orangeleft-down.png) center top repeat-x; - color: #fff; -} - -.gwt-MenuBarPopup .menuPopupTopLeft { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupTopCenter { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupTopCenter { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupTopRight { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupMiddleLeft { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupMiddleRight { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupMiddleRight { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupBottomCenter { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupBottomRight { - background: none !important; -} - -.gwt-MenuBarPopup .menuPopupBottomLeft { - background: none !important; -} - -.gwt-MenuBar-vertical .gwt-MenuItem { - padding: 10px; - padding-bottom: 5px; - padding-top: 5px; -} - -.gwt-MenuBar .gwt-MenuItem-selected { - background: none repeat scroll 0 0 #efaa00; -} - -.gwt-DialogBox { - -webkit-box-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75); - -moz-box-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75); - box-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75); - line-height: 1.4; -} - -.gwt-DialogBox .Caption { - font-size: 14px; - padding: 14px 10px; - background: url(images/dialogBox-bg.png) 0 0 repeat-x; - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - font-family: UbuntuBold, Verdana, Arial, sans-serif; -} - -.gwt-DialogBox .dialogContent { - background: #ffffff; - padding: 10px; - border: 10px solid #a6a6a6; - -webkit-border-bottom-right-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomright: 5px; - -moz-border-radius-bottomleft: 5px; - border-bottom-right-radius: 5px; - border-bottom-left-radius: 5px; -} - -.gwt-Button, .gwt-Button:visited { - font-family: UbuntuBold, Verdana, Arial, sans-serif; - border: none; - - background: url(images/btn-cta-orangeleft.png) center top repeat-x; - display: inline-block; - padding: 2px 10px 4px; - color: #fff; - text-decoration: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); - border-bottom: 1px solid rgba(0, 0, 0, 0.25); - cursor: pointer; - height: 24px; - white-space: nowrap; -} - -.gwt-Button:active { - top: 1px; - position: relative; - border: none; -} - -.gwt-Button:hover { - background: url(images/btn-cta-orangeleft.png) center -30px repeat-x; - cursor: pointer; -} - -.gwt-Button[disabled] { - cursor: default; - color: #888; - background: #F1F1F1; - border: 1px solid #919090; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - border: none; - text-shadow: none; -} - -.gwt-Button[disabled]:hover { - cursor: default; - color: #888; - background: #F1F1F1; -} - -.gwt-Button[disabled]:active { - cursor: default; - color: #888; - background: #F1F1F1; - top: 0; -} - -.gwt-ButtonLarge -.gwt-ButtonMedium -.gwt-ButtonSmall - -.gwt-DialogBox .boxPanel { - padding: 0 0 10px 0; -} - -.gwt-DialogBox .boxPanel:after { - display: inline-block; - content: " "; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - -.gwt-DialogBox .settingsDialogLabel { - float: left; - padding: 3px 6px 0 0; -} - -.gwt-DialogBox .settingsDialogValue { - float: right; -} - -.gwt-DialogBox .additionalWidgets { - padding: 5px 0 0 0; - text-align: right; -} - -.gwt-DialogBox .gwt-Label { - line-height: 1.4; -} diff --git a/java/com.sap.sailing.gwt.ui/DataMining.css b/java/com.sap.sailing.gwt.ui/DataMining.css index 4fdabcb0f2e..a1e0d76ae36 100644 --- a/java/com.sap.sailing.gwt.ui/DataMining.css +++ b/java/com.sap.sailing.gwt.ui/DataMining.css @@ -80,6 +80,8 @@ table { box-shadow: 0 0 20px #858585; -moz-box-shadow: 0 0 20px #858585; -webkit-box-shadow: 0 0 20px #858585; + -o-box-shadow: 0 0 20px #858585; + -ms-box-shadow: 0 0 20px #858585; } .LogoAndTitlePanel:after { @@ -192,9 +194,13 @@ input.magnifier { text-decoration: none; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 0 0 5px; + -o-border-radius: 5px 0 0 5px; + -ms-border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); @@ -208,9 +214,12 @@ input.magnifier { height: 23px; margin: 0 12px 0 1px; -webkit-border-radius: 0px 3px 3px 0px; + -moz-border-radius: 0px 3px 3px 0px; + -o-border-radius: 0px 3px 3px 0px; + -ms-border-radius: 0px 3px 3px 0px; border-radius: 0px 3px 3px 0px; } .dataTypeLabel { font-weight: bold; -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.gwt.ui/Home.html b/java/com.sap.sailing.gwt.ui/Home.html index 319a40e0491..b834326a418 100644 --- a/java/com.sap.sailing.gwt.ui/Home.html +++ b/java/com.sap.sailing.gwt.ui/Home.html @@ -7,13 +7,14 @@ + - + diff --git a/java/com.sap.sailing.gwt.ui/Leaderboard.css b/java/com.sap.sailing.gwt.ui/Leaderboard.css index 270d817cdc7..6bdeedb1d78 100755 --- a/java/com.sap.sailing.gwt.ui/Leaderboard.css +++ b/java/com.sap.sailing.gwt.ui/Leaderboard.css @@ -134,15 +134,23 @@ body, table td, select, button { height: 8px; -moz-border-radius-topleft: 50%; -webkit-border-top-left-radius: 50%; + -o-border-top-left-radius: 50%; + -ms-border-top-left-radius: 50%; border-top-left-radius: 50%; -moz-border-radius-topright: 50%; -webkit-border-top-right-radius: 50%; + -o-border-top-right-radius: 50%; + -ms-border-top-right-radius: 50%; border-top-right-radius: 50%; -moz-border-radius-bottomleft: 50%; -webkit-border-bottom-left-radius: 50%; + -o-border-bottom-left-radius: 50%; + -ms-border-bottom-left-radius: 50%; border-bottom-left-radius: 50%; -moz-border-radius-bottomright: 50%; -webkit-border-bottom-right-radius: 50%; + -o-border-bottom-right-radius: 50%; + -ms-border-bottom-right-radius: 50%; border-bottom-right-radius: 50%; float: left; } diff --git a/java/com.sap.sailing.gwt.ui/LeaderboardNewHome.css b/java/com.sap.sailing.gwt.ui/LeaderboardNewHome.css new file mode 100644 index 00000000000..94f6c74fc11 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/LeaderboardNewHome.css @@ -0,0 +1,122 @@ +@import url(fontface.css); +@import url(CommonControls.css); +@import url(ViewerToolbar.css); + +table { + border-collapse: separate; } + +.leaderboardContent { +} + +.leaderboardContent td, .leaderboardContent th { + vertical-align: bottom; + line-height: 1.3; + padding-top: 2px; +} + +.leaderboardContent-toolbar { + +} + +.leaderboardLabel { + border-bottom: 2px solid #007dc0; + font-weight: bold; + margin: 5px; + } + +.refreshAndSettings { + background: #f8f8f8; + height: 30px; } + +.refreshAndSettings table td { + padding: 0 10px 0 0;} + +.refreshAndSettings table table td{ + padding: 0 0 0 0;} + +input.magnifier{ + display: block; + margin: 3px auto 0 auto !important; +} + +body, table td, select, button { + font-family: 'OpenSansLight', Arial, Verdana, sans-serif; + font-size: 14px; +} + +.errorLabel { + color: #FF0000; +} + +.abstractChartPanel-importantMessageOfChart { + font-family: 'OpenSansBold',Arial,Verdana,sans-serif; + font-size: 20px; + height: 70px; + margin: 0 auto; + padding: 49px 0 0 80px; + width: 300px; + color: #7c7c7c; + background: url(images/important-message.png) left center no-repeat; +} + +.LeaderboardHeader { + position: relative; + margin: 0 auto; + width: 400px; + text-align: center; + font-family: 'OpenSansRegular', Arial, Verdana, sans-serif; + font-size: 18px; + color: #fff; + margin-top: 22px; +} + +.leaderboardHeading { + font-size: 16px; + font-family: 'OpenSansRegular', Arial, Verdana, sans-serif; + font-weight: bold; +} + +.gwt-DialogBox { + z-index: 20; +} + +.bold { + font-family: "OpenSansCondensedBold", sans-serif; +} + +.trackingQuality-circle { + width: 8px; + height: 8px; + -moz-border-radius-topleft: 50%; + -webkit-border-top-left-radius: 50%; + border-top-left-radius: 50%; + -moz-border-radius-topright: 50%; + -webkit-border-top-right-radius: 50%; + border-top-right-radius: 50%; + -moz-border-radius-bottomleft: 50%; + -webkit-border-bottom-left-radius: 50%; + border-bottom-left-radius: 50%; + -moz-border-radius-bottomright: 50%; + -webkit-border-bottom-right-radius: 50%; + border-bottom-right-radius: 50%; + float: left; +} + +.circleYellow { + background: #fbba00; +} + +.circleGreen { + background: #8ab54e; +} + +.circleRed { + background: #f01010; +} + +.busyIndicator-Simple { + margin-top: 7px; +} + +.busyIndicator-Circle { +} diff --git a/java/com.sap.sailing.gwt.ui/PolarSheets.html b/java/com.sap.sailing.gwt.ui/PolarSheets.html index fdf8b1e9f87..19e100f2629 100644 --- a/java/com.sap.sailing.gwt.ui/PolarSheets.html +++ b/java/com.sap.sailing.gwt.ui/PolarSheets.html @@ -11,7 +11,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/Profile SailingGWT.launch b/java/com.sap.sailing.gwt.ui/Profile SailingGWT.launch new file mode 100755 index 00000000000..32331edf760 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/Profile SailingGWT.launch @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index f3daea67dce..86583207d0f 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -30,7 +30,7 @@ iframe {display: block; width: 100%; height: 100%; border: none; overflow-y: aut } body { - background: #ebebeb; + background: white; font-family: 'OpenSansRegular', Arial, Verdana, sans-serif; line-height: 1; font-size: 14px; @@ -68,13 +68,18 @@ table { .CombinedWindPanel { -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; border-radius: 4px; background-color: rgba(255, 255, 255, 0.75); border: 1px solid #C9CACA; } -.RaceBoardHeaderPanel { - margin: 0 12px 14px 12px; +.RaceMap-HeaderPanel { + height: 60px; + width: 100%; + background-color: #333; + opacity: .5; } .leaderboardLabel { @@ -193,6 +198,9 @@ img.openColumn { height: 23px; margin: 0 12px 0 1px; -webkit-border-radius: 0px 3px 3px 0px; + -moz-border-radius: 0px 3px 3px 0px; + -o-border-radius: 0px 3px 3px 0px; + -ms-border-radius: 0px 3px 3px 0px; border-radius: 0px 3px 3px 0px; } @@ -203,17 +211,6 @@ img.openColumn { cursor: pointer; } -.raceBoardNavigation-filterButton { - background: url(images/filter_white.png), url(images/btn-cta-orangeleft.png); - background-position: center, center 0; - background-repeat: no-repeat, repeat-x; - width: 27px; - height: 23px; - margin: 0 12px 0 1px; - -webkit-border-radius: 0px 3px 3px 0px; - border-radius: 0px 3px 3px 0px; -} - .raceBoardNavigation-filterButton:hover { background-image: url(images/filter_white.png), url(images/btn-cta-orangeleft.png); background-position: center, center -30px; @@ -236,9 +233,13 @@ img.openColumn { text-decoration: none; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 0 0 5px; + -o-border-radius: 5px 0 0 5px; + -ms-border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); @@ -271,12 +272,16 @@ img.openColumn { text-decoration: none; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); border-radius: 5px 5px 5px 5px; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 5px 5px 5px; + -o-border-radius: 5px 5px 5px 5px; + -ms-border-radius: 5px 5px 5px 5px; } .raceBoardNavigation-standaloneElement:active { @@ -298,41 +303,79 @@ img.openColumn { margin: 0 0 0 5px; } +.timePanelButton-SlowDown { + background-color: red !important; +} + +.timePanelButton-SpeedUp { + background-color: green !important; +} + .playPauseButton { padding: 0; float: left; - width: 28px; - height: 25px; - background: url(images/timeslider-play-active-icon.png) 0 0 no-repeat; + width: 32px; + height: 28px; + background: url(images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png) center no-repeat; cursor: pointer; + border: 1px solid #cecece; + border-radius: 4px; + outline: 0; } .playPauseButton:hover{ - background: url(images/playbutton-hover.png) 0 0 no-repeat !important; cursor: pointer; + background-color: #cecece; } .playPauseButtonPause { - background: url(images/timeslider-pause-icon.png) 0 0 no-repeat; + background: url(images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png) 2px 0 no-repeat; + outline: 0; + background-size: contain; } .playPauseButtonPause:hover { - background: url(images/playbuttonPause-hover.png) 0 0 no-repeat !important; cursor: pointer; } .backToLivePlayButton { - background: url(images/btn-cta-greenleft.png) center top repeat-x; - margin: 0 0 0 5px; + position: absolute; + right: 15px; + top: 8px; + width: 42px; + height: 38px; + font-size: 8px; + white-space: normal; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; + border-radius: 5px; + border: none; + cursor: pointer; +} + +.backToLivePlayButton-Inactive { + color: #6dc021; + background-color: white; + font-weight: bold; +} + +.backToLivePlayButton-Active { + background-color: #6dc021; + color: white; + font-weight: normal; } .backToLivePlayButton:hover { - background: url(images/btn-cta-greenleft.png) center -30px repeat-x; - margin: 0 0 0 5px; + border: 2px solid gray; +} + +.backToLivePlayButton:focus { + outline: 0 !important; } .dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"] { - box-shadow: 0 0 8px #424242; z-index: 10; } @@ -346,15 +389,23 @@ img.openColumn { height: 8px; -moz-border-radius-topleft: 50%; -webkit-border-top-left-radius: 50%; + -o-border-top-left-radius: 50%; + -ms-border-top-left-radius: 50%; border-top-left-radius: 50%; -moz-border-radius-topright: 50%; -webkit-border-top-right-radius: 50%; + -o-border-top-right-radius: 50%; + -ms-border-top-right-radius: 50%; border-top-right-radius: 50%; -moz-border-radius-bottomleft: 50%; -webkit-border-bottom-left-radius: 50%; + -o-border-bottom-left-radius: 50%; + -ms-border-bottom-left-radius: 50%; border-bottom-left-radius: 50%; -moz-border-radius-bottomright: 50%; -webkit-border-bottom-right-radius: 50%; + -o-border-bottom-right-radius: 50%; + -ms-border-bottom-right-radius: 50%; border-bottom-right-radius: 50%; float: left; } @@ -372,8 +423,222 @@ img.openColumn { } .busyIndicator-Simple { - margin-top: 7px; + position: absolute; + top: 0.7em; + right: 7.4em; } .busyIndicator-Circle { } + +.raceBoard-TitlePanel { + position: relative; + top: 10px; + z-index: 10; + color: #fff; + margin-left: auto; + margin-right: auto; +} + +.raceBoard-TitlePanel-RaceNameLabel { + font-size: 32px; + font-weight: bold; + padding: 7px; +} + +.raceBoard-Logo { + position: absolute; + top: 6px; + left: 10px; + z-index: 10; + cursor: pointer; +} + +.SideBySideComponentViewer-MainPanel { + top: 12px; +} + +.TimePanel-ShowExtended-Button { + width: 29px; + height: 28px; + float: left; + cursor: pointer; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + border: 1px solid #ececec; +} + +.TimePanel-ShowExtended-Button-Open { + background: white url(images/arrows_top_black.png) center no-repeat; +} + +.TimePanel-ShowExtended-Button-Closed { + background: white url(images/arrows_bottom_black.png) center no-repeat; +} + +.TimePanel-ShowExtended-Button:hover { + background-color: #cecece; +} + +.TimePanel-ShowExtended-Button:focus { + outline: 0 !important; +} + +.RaceBoard-globalNavigation-Link { + display: inline; + margin-right: 3px; +} + +.RaceBoard-globalNavigation-Link a { + color: #fff; + cursor: pointer; +} + +.RaceBoard-globalNavigation-Link+.RaceBoard-globalNavigation-Link:before { + content: ' \00bb\00a0'; +} + +.TimePanel-settingsButtonStyle { + position: absolute; + right: 0px; + z-index: 1; + border: none; +} + +.TimePanel-settingsButtonStyle:focus { + outline: 0 !important; +} + +.TimePanel-settingsButtonStyle:hover { + border: 1px solid gray; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-multiCompetitorRaceChart { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png), url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-multiCompetitorRaceChart { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png), url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-windChart { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png), url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-windChart { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png), url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png), url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png), url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-media { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-media { + background-color: white; + background-image: url(images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Small-media { + background-position: 50% 50%, 100% 50% !important; + margin-left: 0px !important; + padding: 2px 20px !important; +} + +.RegattaRaceInformation-Header { + position: relative; + left: 140px; + top: 11px; +} + +.RegattaRaceInformation-Header .RaceName-Label { + display: inline; + color: white; + margin-right: 10px; + font-size: 36px; +} + +.RegattaRaceInformation-Header .RaceSeriesAndFleet-Label { + display: inline; + color: white; + font-size: 15px; +} + +.RegattaAndRaceTime-Header { + position: absolute; + right: 10px; + top: 13px; + text-align: right; + color: white; +} + +.RegattaAndRaceTime-Header .RegattaName-Anchor { + font-size: 15px; + color: white; + text-decoration: none; + padding-left: 25px; + background-image: url(images/home.png); + background-repeat: no-repeat; + background-size: 17px; + background-position: 4px 1px; +} + +.RegattaAndRaceTime-Header .RegattaName-Anchor:hover { + text-decoration: underline; +} + +.RegattaAndRaceTime-Header .RaceTime-Label { + font-size: 15px; + margin-top: 5px; +} + +.VideoPopup-Close-Button { + border: none; +} + +.gwt-Button, .gwt-Button:visited { + background-color: #fcbb22; + background-image: none !important; + -moz-box-shadow: none; + -webkit-box-shadow: none; + -o-box-shadow: none; + -ms-box-shadow: none; + box-shadow: none; + text-shadow: none; +} + +.gwt-Button:hover { + background-color: #fcbb22 !important; +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/RegattaOverview.css b/java/com.sap.sailing.gwt.ui/RegattaOverview.css index fa4fb0cf139..87fc2aaaa64 100644 --- a/java/com.sap.sailing.gwt.ui/RegattaOverview.css +++ b/java/com.sap.sailing.gwt.ui/RegattaOverview.css @@ -80,6 +80,8 @@ table { box-shadow: 0 0 20px #858585; -moz-box-shadow: 0 0 20px #858585; -webkit-box-shadow: 0 0 20px #858585; + -o-box-shadow: 0 0 20px #858585; + -ms-box-shadow: 0 0 20px #858585; } .LogoAndTitlePanel:after { @@ -136,15 +138,23 @@ table { background: url(images/functionBar_bg.png) 0 0 repeat-x; -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; + -o-border-top-left-radius: 5px; + -ms-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; + -o-border-top-right-radius: 5px; + -ms-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; + -o-border-bottom-left-radius: 5px; + -ms-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; + -o-border-bottom-right-radius: 5px; + -ms-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; margin: 0 0 15px 0; } @@ -162,15 +172,23 @@ table { height: 10px; -moz-border-radius-topleft: 50%; -webkit-border-top-left-radius: 50%; + -o-border-top-left-radius: 50%; + -ms-border-top-left-radius: 50%; border-top-left-radius: 50%; -moz-border-radius-topright: 50%; -webkit-border-top-right-radius: 50%; + -o-border-top-right-radius: 50%; + -ms-border-top-right-radius: 50%; border-top-right-radius: 50%; -moz-border-radius-bottomleft: 50%; -webkit-border-bottom-left-radius: 50%; + -o-border-bottom-left-radius: 50%; + -ms-border-bottom-left-radius: 50%; border-bottom-left-radius: 50%; -moz-border-radius-bottomright: 50%; -webkit-border-bottom-right-radius: 50%; + -o-border-bottom-right-radius: 50%; + -ms-border-bottom-right-radius: 50%; border-bottom-right-radius: 50%; float: left; margin: 2px 6px 0 0; @@ -226,9 +244,13 @@ table { text-decoration: none; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 0 0 5px; + -o-border-radius: 5px 0 0 5px; + -ms-border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch similarity index 74% rename from java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch rename to java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch index 1b84b74772a..0b8d83049f1 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch @@ -4,7 +4,8 @@ - + + @@ -18,7 +19,7 @@ - + @@ -40,13 +41,20 @@ + + + + + + + - + - + diff --git a/java/com.sap.sailing.gwt.ui/Simulator.css b/java/com.sap.sailing.gwt.ui/Simulator.css index 35389cf3dd5..71f9f9baee2 100644 --- a/java/com.sap.sailing.gwt.ui/Simulator.css +++ b/java/com.sap.sailing.gwt.ui/Simulator.css @@ -1,385 +1,392 @@ -@import url(fontface.css); -//@import url(CommonControls.css); - -/** Add css rules here for your application. */ -/* - body #calendar:after - content: " "; - display: block; - height: 0; - clear: both; - visibility: hidden; -*/ -.clear { - clear: both; - font-size: 1px; - height: 0px; - line-height: 0px; - margin: -1px 0 0; - width: 100%; -} - -.cover { - left: -1000px; - overflow: hidden; - position: absolute; - top: -1000px; -} - -.titleLabelWrapper { - position: relative; - margin-left: auto; - margin-right: auto; - width: 50%; -} - -.titleLabel { - text-align: center; - font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; - font-size: 18px; - color: #fff; - margin: 23px 0 0 0; -} - -body { - background: #ebebeb; - font-family: 'OpenSansRegular', Arial, Verdana, sans-serif; - line-height: 1; - font-size: 14px; - font-weight: 400; - padding: 80px 0 160px 0; - margin: 0; - color: #7c7c7c; -} - -table td,select,button { - font-family: 'OpenSansLight', Arial, Verdana, sans-serif; - line-height: 1; - font-size: 14px; -} - -.contentOuterPanel { - background: #dddcdc; - margin: 0 12px 0 12px; - padding: 12px; -} - -/** Example rules used by the template application (remove for your app) */ -h1 { - font-size: 2em; - font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; - color: #777777; - margin: 40px 0px 70px; - text-align: center; -} - -table { - border-collapse: separate; -} - -/*.RaceBoardHeaderPanel { - margin: 0 12px 14px 12px; -}*/ -.sapLogo { - float: left; - margin: 13px 0 0 12px; -} - -.pioLogo { - float: right; - margin: 11px 20px 0 12px; -} - -.sailingAnalyticsLabelPanel { - margin: 10px 0 0 0; -} - -.sailingAnalyticsLabel { - float: left; - color: #fff; - font-size: 14px; - font-weight: bold; - margin: 15px 0 0 0; -} - -.timePanelSettings { - display: none; -} - -/*.leaderboardLabel { - border-bottom: 2px solid #007dc0; - padding: 0 0 6px 0; - font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; -}*/ -.refreshAndSettings { - background: #f2f2f2; - border-bottom: 2px solid #fff; - border-top: 2px solid #fff; - height: 30px; -} - -.refreshAndSettings table td { - padding: 0 10px 0 0; -} - -.refreshAndSettings table table td { - padding: 0 0 0 0; -} - -.race-name { - line-height: 1.0; -} - -input.magnifier { - display: block; - margin: 3px auto 0 auto !important; -} - -.breadcrumbPanel { - height: 30px; - margin: 0 12px 13px 12px; -} - -.mainPanel { - width: 100%; -} - -/*.raceBoardNavigation { - float: right; - margin: 26px 0 0 0; - font-family: 'OpenSansLight', Arial, Verdana, sans-serif; -} - -.raceBoardNavigation-navigationitem { - color: #dddcdc; - text-transform: uppercase; - font-weight: 500; - margin: 0 12px 0 0; - padding: 0 0 5px 0; -} - -.raceBoardNavigation-navigationitem:hover { - border-bottom: 4px solid #f0ab00; - color: #dddcdc; - text-decoration: none; -} - -.raceBoardNavigation-navigationitem:active { - border-bottom: 4px solid #f0ab00; - color: #dddcdc; - text-decoration: none; -}*/ -.abstractChartPanel-importantMessageOfChart { - font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; - font-size: 20px; - height: 70px; - margin: 0 auto; - padding: 49px 0 0 80px; - width: 300px; - color: #7c7c7c; - background: url(images/important-message.png) left center no-repeat; -} - -/*.breadcrumbPanel-NextArrow { - display: none; -}*/ -.replayPanel { - position: relative; - z-index: 10; -} - -.innerHeadline { - font-family: OpenSansSemiBold, Arial, Verdana, sans-serif; - font-size: 16px; - color: #7c7c7c; - margin: 15px 0 -} - -.sectorHeadline { - font-family: OpenSansLight, Arial, Verdana, sans-serif; - font-size: 16px; -} - -.controlPanelInnerWrapper { - margin: 0 10px; -} - -.windPanel { - width: 100%; -} - -.choosePattern { - width: 100%; - margin: 0 0 15px 0; -} - -.choosePattern td:last-child { - text-align: right; -} - -.optionsPanel { - background: url(images/simulator/panel_bg.png) 0 0 repeat-x; - border-bottom: 4px solid #7c7b7c; - padding: 0 10px; -} - -.mapOptions { - background: url(images/simulator/panel_bg.png) 0 0 repeat-x; - border-bottom: 4px solid #7c7b7c; - padding: 0 10px; -} - -.timePanelButton { - float: left; - margin: 0 0 0 5px; -} - -.playPauseButton { - padding: 0; - width: 28px; - height: 24px; - background: url(images/timeslider-play-active-icon.png) 0 0 no-repeat; - cursor: pointer; -} - -.playPauseButton:hover{ - background: url(images/playbutton-hover.png) 0 0 no-repeat !important; - cursor: pointer; -} - -.playPauseButtonPause { - background: url(images/timeslider-pause-icon.png) 0 0 no-repeat; -} - -.playPauseButtonPause:hover { - background: url(images/playbuttonPause-hover.png) 0 0 no-repeat !important; - cursor: pointer; -} - - -.backToLivePlayButton { - float: left; - padding: 3px 10px 4px; -} - - -.sliderWrapper { - float: left; - width: 100%; - margin: 0 0 7px 0; -} - -.sliderLabel { - width: 200px; - padding: 12px 0 14px 12px; -} - -/* styles for the masterPanel */ -#masterPanelLeft .gwt-SliderBar-shell { - background: url(images/simulator/slider_bg.png) 0 0 repeat-x; - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border: 1px solid #ccc; - height: 36px; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line { - border: 1px solid #919191; - background-color: #818181; - height: 4px; - width: 90%; - top: 23px; - overflow: hidden; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line-disabled { - border: 1px solid gray; -} - -/*#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-knob { - top: 14px; - width: 11px; - height: 21px; - z-index: 1; - cursor: pointer; -}*/ - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-tick { - top: 18px; - width: 1px; - height: 6pt; - background: #919191; - overflow: hidden; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-mark { - top: 21pt; - width: 6px; - height: 6pt; - background: #f0ab00; - overflow: hidden; - border-left: 4px solid #fff; - border-right: 4px solid #fff; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-tick-disabled { - background: gray; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-ticklabel { - font-size: 12px; - cursor: default; - font-family: 'OpenSansSemiBold',Arial,Verdana,sans-serif; - top: 5px; -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-markerlabel { - top: 30pt; - font-size: 12px; - color: #bc9434; - cursor: default; - font-family: 'OpenSansSemiBold',Arial,Verdana,sans-serif; -} - -#masterPanelLeft .gwt-SliderBar-shell-focused { - -} - -#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line-sliding { - cursor: pointer; -} - -.boatClassLabel { - width: 235px; - margin: 0 0 15px 0; -} - -.sailingPanel { - width: 100%; -} - -.dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"] { - box-shadow: 0 0 8px #424242; - z-index: 10; -} - -.MapDisplayOptions { - margin: 0 15px 0 0; -} - -.MapDisplayOptions label,.gwt-RadioButton label { - margin: 0 0 0 5px; -} -.MapDisplayOptions { - margin: 0 0 0 5px; -} - -.timeSliderWrapperPanel{ - -webkit-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* WebKit */ - -moz-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Firefox */ - box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Standard */ -} -.polarDiv -{background-color: white;width:100%;height:100px;border-radius: 5px; -moz-border-radius: 5px; +@import url(fontface.css); +//@import url(CommonControls.css); + +/** Add css rules here for your application. */ +/* + body #calendar:after + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; +*/ +.clear { + clear: both; + font-size: 1px; + height: 0px; + line-height: 0px; + margin: -1px 0 0; + width: 100%; +} + +.cover { + left: -1000px; + overflow: hidden; + position: absolute; + top: -1000px; +} + +.titleLabelWrapper { + position: relative; + margin-left: auto; + margin-right: auto; + width: 50%; +} + +.titleLabel { + text-align: center; + font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; + font-size: 18px; + color: #fff; + margin: 23px 0 0 0; +} + +body { + background: #ebebeb; + font-family: 'OpenSansRegular', Arial, Verdana, sans-serif; + line-height: 1; + font-size: 14px; + font-weight: 400; + padding: 80px 0 160px 0; + margin: 0; + color: #7c7c7c; +} + +table td,select,button { + font-family: 'OpenSansLight', Arial, Verdana, sans-serif; + line-height: 1; + font-size: 14px; +} + +.contentOuterPanel { + background: #dddcdc; + margin: 0 12px 0 12px; + padding: 12px; +} + +/** Example rules used by the template application (remove for your app) */ +h1 { + font-size: 2em; + font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; + color: #777777; + margin: 40px 0px 70px; + text-align: center; +} + +table { + border-collapse: separate; +} + +/*.RaceBoardHeaderPanel { + margin: 0 12px 14px 12px; +}*/ +.sapLogo { + float: left; + margin: 13px 0 0 12px; +} + +.pioLogo { + float: right; + margin: 11px 20px 0 12px; +} + +.sailingAnalyticsLabelPanel { + margin: 10px 0 0 0; +} + +.sailingAnalyticsLabel { + float: left; + color: #fff; + font-size: 14px; + font-weight: bold; + margin: 15px 0 0 0; +} + +.timePanelSettings { + display: none; +} + +/*.leaderboardLabel { + border-bottom: 2px solid #007dc0; + padding: 0 0 6px 0; + font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; +}*/ +.refreshAndSettings { + background: #f2f2f2; + border-bottom: 2px solid #fff; + border-top: 2px solid #fff; + height: 30px; +} + +.refreshAndSettings table td { + padding: 0 10px 0 0; +} + +.refreshAndSettings table table td { + padding: 0 0 0 0; +} + +.race-name { + line-height: 1.0; +} + +input.magnifier { + display: block; + margin: 3px auto 0 auto !important; +} + +.breadcrumbPanel { + height: 30px; + margin: 0 12px 13px 12px; +} + +.mainPanel { + width: 100%; +} + +/*.raceBoardNavigation { + float: right; + margin: 26px 0 0 0; + font-family: 'OpenSansLight', Arial, Verdana, sans-serif; +} + +.raceBoardNavigation-navigationitem { + color: #dddcdc; + text-transform: uppercase; + font-weight: 500; + margin: 0 12px 0 0; + padding: 0 0 5px 0; +} + +.raceBoardNavigation-navigationitem:hover { + border-bottom: 4px solid #f0ab00; + color: #dddcdc; + text-decoration: none; +} + +.raceBoardNavigation-navigationitem:active { + border-bottom: 4px solid #f0ab00; + color: #dddcdc; + text-decoration: none; +}*/ +.abstractChartPanel-importantMessageOfChart { + font-family: 'OpenSansSemiBold', Arial, Verdana, sans-serif; + font-size: 20px; + height: 70px; + margin: 0 auto; + padding: 49px 0 0 80px; + width: 300px; + color: #7c7c7c; + background: url(images/important-message.png) left center no-repeat; +} + +/*.breadcrumbPanel-NextArrow { + display: none; +}*/ +.replayPanel { + position: relative; + z-index: 10; +} + +.innerHeadline { + font-family: OpenSansSemiBold, Arial, Verdana, sans-serif; + font-size: 16px; + color: #7c7c7c; + margin: 15px 0 +} + +.sectorHeadline { + font-family: OpenSansLight, Arial, Verdana, sans-serif; + font-size: 16px; +} + +.controlPanelInnerWrapper { + margin: 0 10px; +} + +.windPanel { + width: 100%; +} + +.choosePattern { + width: 100%; + margin: 0 0 15px 0; +} + +.choosePattern td:last-child { + text-align: right; +} + +.optionsPanel { + background: url(images/simulator/panel_bg.png) 0 0 repeat-x; + border-bottom: 4px solid #7c7b7c; + padding: 0 10px; +} + +.mapOptions { + background: url(images/simulator/panel_bg.png) 0 0 repeat-x; + border-bottom: 4px solid #7c7b7c; + padding: 0 10px; +} + +.timePanelButton { + float: left; + margin: 0 0 0 5px; +} + +.playPauseButton { + padding: 0; + width: 28px; + height: 24px; + background: url(images/timeslider-play-active-icon.png) 0 0 no-repeat; + cursor: pointer; +} + +.playPauseButton:hover{ + background: url(images/playbutton-hover.png) 0 0 no-repeat !important; + cursor: pointer; +} + +.playPauseButtonPause { + background: url(images/timeslider-pause-icon.png) 0 0 no-repeat; +} + +.playPauseButtonPause:hover { + background: url(images/playbuttonPause-hover.png) 0 0 no-repeat !important; + cursor: pointer; +} + + +.backToLivePlayButton { + float: left; + padding: 3px 10px 4px; +} + + +.sliderWrapper { + float: left; + width: 100%; + margin: 0 0 7px 0; +} + +.sliderLabel { + width: 200px; + padding: 12px 0 14px 12px; +} + +/* styles for the masterPanel */ +#masterPanelLeft .gwt-SliderBar-shell { + background: url(images/simulator/slider_bg.png) 0 0 repeat-x; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -o-border-radius: 3px; + -ms-border-radius: 3px; + border: 1px solid #ccc; + height: 36px; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line { + border: 1px solid #919191; + background-color: #818181; + height: 4px; + width: 90%; + top: 23px; + overflow: hidden; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line-disabled { + border: 1px solid gray; +} + +/*#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-knob { + top: 14px; + width: 11px; + height: 21px; + z-index: 1; + cursor: pointer; +}*/ + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-tick { + top: 18px; + width: 1px; + height: 6pt; + background: #919191; + overflow: hidden; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-mark { + top: 21pt; + width: 6px; + height: 6pt; + background: #f0ab00; + overflow: hidden; + border-left: 4px solid #fff; + border-right: 4px solid #fff; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-tick-disabled { + background: gray; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-ticklabel { + font-size: 12px; + cursor: default; + font-family: 'OpenSansSemiBold',Arial,Verdana,sans-serif; + top: 5px; +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-markerlabel { + top: 30pt; + font-size: 12px; + color: #bc9434; + cursor: default; + font-family: 'OpenSansSemiBold',Arial,Verdana,sans-serif; +} + +#masterPanelLeft .gwt-SliderBar-shell-focused { + +} + +#masterPanelLeft .gwt-SliderBar-shell .gwt-SliderBar-line-sliding { + cursor: pointer; +} + +.boatClassLabel { + width: 235px; + margin: 0 0 15px 0; +} + +.sailingPanel { + width: 100%; +} + +.dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"] { + box-shadow: 0 0 8px #424242; + z-index: 10; +} + +.MapDisplayOptions { + margin: 0 15px 0 0; +} + +.MapDisplayOptions label,.gwt-RadioButton label { + margin: 0 0 0 5px; +} +.MapDisplayOptions { + margin: 0 0 0 5px; +} + +.timeSliderWrapperPanel{ + -webkit-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* WebKit */ + -moz-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Firefox */ + -o-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Firefox */ + -ms-box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Firefox */ + box-shadow: inset 0px 5px 10px 0px rgba(0, 0, 0, 0.15); /* Standard */ +} +.polarDiv +{background-color: white;width:100%;height:100px;border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border: 1px solid #177980;} + -moz-border-radius: 5px; border: 1px solid #177980;} + -o-border-radius: 5px; border: 1px solid #177980;} + -ms-border-radius: 5px; border: 1px solid #177980;} diff --git a/java/com.sap.sailing.gwt.ui/Simulator.html b/java/com.sap.sailing.gwt.ui/Simulator.html index a90d4a20796..5e66810b126 100644 --- a/java/com.sap.sailing.gwt.ui/Simulator.html +++ b/java/com.sap.sailing.gwt.ui/Simulator.html @@ -14,7 +14,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/Spectator.css b/java/com.sap.sailing.gwt.ui/Spectator.css index c45f733f108..1afd3de0213 100644 --- a/java/com.sap.sailing.gwt.ui/Spectator.css +++ b/java/com.sap.sailing.gwt.ui/Spectator.css @@ -80,6 +80,8 @@ table { box-shadow: 0 0 20px #858585; -moz-box-shadow: 0 0 20px #858585; -webkit-box-shadow: 0 0 20px #858585; + -o-box-shadow: 0 0 20px #858585; + -ms-box-shadow: 0 0 20px #858585; } .LogoAndTitlePanel:after { @@ -210,6 +212,8 @@ input.magnifier { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; } .leaderboardGroupPanel-ActiveRace, .leaderboardGroupPanel-InactiveRace, .leaderboardGroupPanel-LegendTracked { @@ -220,6 +224,8 @@ input.magnifier { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; background: url("images/btn-cta-blueleft.png") repeat-x -10px 0 #e7e7e7; text-decoration: none; color: #fff; @@ -235,6 +241,8 @@ input.magnifier { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; background: url("images/btn-cta-greenleft.png") repeat-x -10px 0 #e7e7e7; text-decoration: none; color: #fff; @@ -250,6 +258,8 @@ input.magnifier { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; background: url("images/btn-cta-orangeleft.png") repeat-x -10px 0 #e7e7e7; text-decoration: none; color: #fff; @@ -262,6 +272,8 @@ input.magnifier { border-radius: 4px; -moz-border-radius: 4px; -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; background: url("images/btn-cta-blueleft.png") repeat-x 0px 0 #e7e7e7; text-decoration: none; color: #fff; diff --git a/java/com.sap.sailing.gwt.ui/ViewerToolbar.css b/java/com.sap.sailing.gwt.ui/ViewerToolbar.css index dcea3a8a731..3fd42f875f5 100644 --- a/java/com.sap.sailing.gwt.ui/ViewerToolbar.css +++ b/java/com.sap.sailing.gwt.ui/ViewerToolbar.css @@ -41,6 +41,9 @@ height: 23px; margin: 0 12px 0 1px; -webkit-border-radius: 0px 3px 3px 0px; + -moz-border-radius: 0px 3px 3px 0px; + -o-border-radius: 0px 3px 3px 0px; + -ms-border-radius: 0px 3px 3px 0px; border-radius: 0px 3px 3px 0px; } @@ -78,9 +81,13 @@ text-decoration: none; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 0 0 5px; + -o-border-radius: 5px 0 0 5px; + -ms-border-radius: 5px 0 0 5px; border-radius: 5px 0 0 5px; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); @@ -113,12 +120,16 @@ text-decoration: none; -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); border-bottom: 1px solid rgba(0, 0, 0, 0.25); border-radius: 5px 5px 5px 5px; -moz-border-radius: 5px 0 0 5px; -webkit-border-radius: 5px 5px 5px 5px; + -o-border-radius: 5px 5px 5px 5px; + -ms-border-radius: 5px 5px 5px 5px; } .viewerToolbar-standaloneElement:active { diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index 3e0c785617a..6e4fd18d28b 100755 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -7,6 +7,7 @@ bin.includes = META-INF/,\ AdminConsole.css,\ AdminConsole.html,\ Leaderboard.css,\ + LeaderboardNewHome.css,\ Leaderboard.html,\ LeaderboardEditing.html,\ UserManagement.html,\ @@ -46,7 +47,6 @@ bin.includes = META-INF/,\ PolarSheets.css,\ PolarSheets.html,\ ViewerToolbar.css,\ - CommonGwtControls.css,\ com.sap.sailing.gwt.ui.DataMining/,\ DataMining.css,\ DataMining.html,\ diff --git a/java/com.sap.sailing.gwt.ui/images/SAP_RV_Settings.png b/java/com.sap.sailing.gwt.ui/images/SAP_RV_Settings.png new file mode 100644 index 00000000000..fbe4d7d99d8 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/SAP_RV_Settings.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/SAP_RV_SettingsBlack.png b/java/com.sap.sailing.gwt.ui/images/SAP_RV_SettingsBlack.png new file mode 100644 index 00000000000..9b63ce60c98 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/SAP_RV_SettingsBlack.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black.png b/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black.png new file mode 100644 index 00000000000..824b928db71 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black_small.png b/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black_small.png new file mode 100644 index 00000000000..5d06cf1589f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/arrows_bottom_black_small.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/arrows_right_black.png b/java/com.sap.sailing.gwt.ui/images/arrows_right_black.png new file mode 100644 index 00000000000..274a9f0c8d1 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/arrows_right_black.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/arrows_top_black.png b/java/com.sap.sailing.gwt.ui/images/arrows_top_black.png new file mode 100644 index 00000000000..02d02e1cde6 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/arrows_top_black.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/arrows_top_black_small.png b/java/com.sap.sailing.gwt.ui/images/arrows_top_black_small.png new file mode 100644 index 00000000000..4eddabb57b9 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/arrows_top_black_small.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/close_black.png b/java/com.sap.sailing.gwt.ui/images/close_black.png new file mode 100644 index 00000000000..188969f926f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/close_black.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home.png b/java/com.sap.sailing.gwt.ui/images/home.png new file mode 100644 index 00000000000..5b13eae6506 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/busy_indicator.gif b/java/com.sap.sailing.gwt.ui/images/home/busy_indicator.gif new file mode 100644 index 00000000000..ed72b117dd9 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/busy_indicator.gif differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/location-icon.png b/java/com.sap.sailing.gwt.ui/images/home/location-icon.png new file mode 100644 index 00000000000..737b6e4e2d0 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/location-icon.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/reload.png b/java/com.sap.sailing.gwt.ui/images/home/reload.png new file mode 100644 index 00000000000..a333086fa24 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/reload.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/settings.png b/java/com.sap.sailing.gwt.ui/images/home/settings.png new file mode 100644 index 00000000000..1f16ed08149 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/settings.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/social-icons.png b/java/com.sap.sailing.gwt.ui/images/home/social-icons.png new file mode 100644 index 00000000000..f9566384566 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/social-icons.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/sap_logo_header.png b/java/com.sap.sailing.gwt.ui/images/sap_logo_header.png new file mode 100644 index 00000000000..e5d2daf91f3 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/sap_logo_header.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/settings_black.png b/java/com.sap.sailing.gwt.ui/images/settings_black.png new file mode 100644 index 00000000000..a1969e23b01 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/settings_black.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/SAP_RV_TweekSprite_a00.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/SAP_RV_TweekSprite_a00.png new file mode 100755 index 00000000000..8ffc474113f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/SAP_RV_TweekSprite_a00.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_ACTIVE.png new file mode 100755 index 00000000000..73f224bde91 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png new file mode 100755 index 00000000000..cdaa4261f8d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png new file mode 100755 index 00000000000..e123081fc31 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_CHECKED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_CHECKED.png new file mode 100755 index 00000000000..fb678245b17 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_CHECKED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_UNCHECKED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_UNCHECKED.png new file mode 100755 index 00000000000..66dbf06d92c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Checkbox_UNCHECKED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Clear.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Clear.png new file mode 100755 index 00000000000..c9a92b7a63a Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Clear.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_ACTIVE.png new file mode 100755 index 00000000000..8a38e267534 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png new file mode 100755 index 00000000000..188192c8e81 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png new file mode 100755 index 00000000000..c58f87ba96d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_ACTIVE.png new file mode 100755 index 00000000000..0d3d9c1ca44 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_GHOSTED.png new file mode 100755 index 00000000000..194c13de49a Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_INACTIVE.png new file mode 100755 index 00000000000..a689e2101bc Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_CompetitorsFilter_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_ACTIVE.png new file mode 100755 index 00000000000..fb0fc5e8d68 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png new file mode 100755 index 00000000000..73bd5698fa8 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png new file mode 100755 index 00000000000..a933b3dc3c4 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_ACTIVE.png new file mode 100755 index 00000000000..eaf9e9ccfe2 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_GHOSTED.png new file mode 100755 index 00000000000..954a80eb32a Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_INACTIVE.png new file mode 100755 index 00000000000..6795ac0f02e Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_LivePlay_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_ACTIVE.png new file mode 100755 index 00000000000..12811f5881c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_GHOSTED.png new file mode 100755 index 00000000000..f8a0fd719fd Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_INACTIVE.png new file mode 100755 index 00000000000..d35eb30aa6b Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Map_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_PlaySpeed.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_PlaySpeed.png new file mode 100755 index 00000000000..128d31c2151 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_PlaySpeed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_ACTIVE.png new file mode 100755 index 00000000000..e4edff8cbde Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_GHOSTED.png new file mode 100755 index 00000000000..2c1285bc534 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png new file mode 100755 index 00000000000..2144eacf6c8 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Search.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Search.png new file mode 100755 index 00000000000..22698de84ad Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Search.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Settings.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Settings.png new file mode 100755 index 00000000000..fbe4d7d99d8 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Settings.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_29.jpg b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_29.jpg new file mode 100755 index 00000000000..46323c6c6c3 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_29.jpg differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_32.jpg b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_32.jpg new file mode 100755 index 00000000000..3d258927a58 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_TweekSprite_a00_32.jpg differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_ACTIVE.png new file mode 100755 index 00000000000..110f48efada Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_GHOSTED.png new file mode 100755 index 00000000000..9d326fb2e37 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_INACTIVE.png new file mode 100755 index 00000000000..746b9b37f3f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@1x/img/SAP_RV_Wind_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/SAP_RV_TweekSprite_a00.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/SAP_RV_TweekSprite_a00.png new file mode 100755 index 00000000000..9f2f9ff5ab2 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/SAP_RV_TweekSprite_a00.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_ACTIVE.png new file mode 100755 index 00000000000..44d1bbb626d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_GHOSTED.png new file mode 100755 index 00000000000..c924f99480d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_INACTIVE.png new file mode 100755 index 00000000000..e7c4026d648 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_AudioVideo_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_CHECKED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_CHECKED.png new file mode 100755 index 00000000000..65b76a26fd3 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_CHECKED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_UNCHECKED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_UNCHECKED.png new file mode 100755 index 00000000000..de9eedc724e Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Checkbox_UNCHECKED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Clear.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Clear.png new file mode 100755 index 00000000000..2108ec5b9a1 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Clear.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_ACTIVE.png new file mode 100755 index 00000000000..38890afa4cc Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_GHOSTED.png new file mode 100755 index 00000000000..68d21fcc689 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_INACTIVE.png new file mode 100755 index 00000000000..37412eabfc9 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorCharts_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_ACTIVE.png new file mode 100755 index 00000000000..7a015ebfca0 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_GHOSTED.png new file mode 100755 index 00000000000..561a34f9c0c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_INACTIVE.png new file mode 100755 index 00000000000..0a050a30305 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_CompetitorsFilter_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_ACTIVE.png new file mode 100755 index 00000000000..1e24f619098 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_GHOSTED.png new file mode 100755 index 00000000000..d8d0d7fc441 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_INACTIVE.png new file mode 100755 index 00000000000..ff1f70ee98c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Leaderboard_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_ACTIVE.png new file mode 100755 index 00000000000..2202da0998f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_GHOSTED.png new file mode 100755 index 00000000000..be3e1ffc961 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_INACTIVE.png new file mode 100755 index 00000000000..4b305220449 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_LivePlay_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_ACTIVE.png new file mode 100755 index 00000000000..49b2f6a7b91 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_GHOSTED.png new file mode 100755 index 00000000000..449e081eb2a Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_INACTIVE.png new file mode 100755 index 00000000000..a736707b684 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Map_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png new file mode 100644 index 00000000000..f38f74c7ad1 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_PlaySpeed.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_PlaySpeed.png new file mode 100755 index 00000000000..bc5b691963c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_PlaySpeed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_ACTIVE.png new file mode 100755 index 00000000000..8ca76b0b44d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_GHOSTED.png new file mode 100755 index 00000000000..e4f8256df5d Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_INACTIVE.png new file mode 100755 index 00000000000..09d9f3da798 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Play_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Search.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Search.png new file mode 100755 index 00000000000..c294f7f2ead Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Search.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Settings.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Settings.png new file mode 100755 index 00000000000..3b35b62d820 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Settings.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_29.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_29.png new file mode 100755 index 00000000000..92ceb496a7e Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_29.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_32.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_32.png new file mode 100755 index 00000000000..e230cfb16db Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_TweekSprite_a00_32.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_ACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_ACTIVE.png new file mode 100755 index 00000000000..32816de58b5 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_ACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_GHOSTED.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_GHOSTED.png new file mode 100755 index 00000000000..8e61221881f Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_GHOSTED.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_INACTIVE.png b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_INACTIVE.png new file mode 100755 index 00000000000..ddc63c21bd7 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/viewicons/@2x/img/SAP_RV_Wind_INACTIVE.png differ diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index 33ae1e4bfce..c9c3330cc12 100644 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -84,7 +84,7 @@ - -Dgwt.persistentunitcache=false + -Dgwt.persistentunitcache=false -Xmx4096m @@ -109,8 +109,10 @@ 3 ${basedir} ${basedir}/src/main/resources - + compile diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResolver.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResolver.java new file mode 100644 index 00000000000..a8f1fd84cc1 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResolver.java @@ -0,0 +1,71 @@ +package com.sap.sailing.gwt.home.client; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gwt.resources.client.ImageResource; +import com.sap.sailing.domain.common.BoatClassMasterdata; + +public class BoatClassImageResolver { + private static Map boatClassIconsMap; + private static BoatClassImageResources imageResources = BoatClassImageResources.INSTANCE; + + static { + boatClassIconsMap = new HashMap(); + + boatClassIconsMap.put(BoatClassMasterdata._12M.getDisplayName(), imageResources._12mRIcon()); + boatClassIconsMap.put(BoatClassMasterdata._2_4M.getDisplayName(), imageResources._2_4mIcon()); + boatClassIconsMap.put(BoatClassMasterdata._29ER.getDisplayName(), imageResources._29erIcon()); + boatClassIconsMap.put(BoatClassMasterdata._29ERXX.getDisplayName(), imageResources._29erIcon()); + boatClassIconsMap.put(BoatClassMasterdata._420.getDisplayName(), imageResources._420Icon()); + boatClassIconsMap.put(BoatClassMasterdata._470.getDisplayName(), imageResources._470Icon()); + boatClassIconsMap.put(BoatClassMasterdata._49ERFX.getDisplayName(), imageResources._49erFXIcon()); + boatClassIconsMap.put(BoatClassMasterdata._49ER.getDisplayName(), imageResources._49erIcon()); + boatClassIconsMap.put(BoatClassMasterdata._5O5.getDisplayName(), imageResources._505mIcon()); + boatClassIconsMap.put(BoatClassMasterdata.A_CAT.getDisplayName(), imageResources.A_CatIcon()); + boatClassIconsMap.put(BoatClassMasterdata.ALBIN_EXPRESS.getDisplayName(), imageResources.AlbinExpressIcon()); + boatClassIconsMap.put(BoatClassMasterdata.B_ONE.getDisplayName(), imageResources.BOne()); + boatClassIconsMap.put(BoatClassMasterdata.CONTENDER.getDisplayName(), imageResources.ContenderIcon()); + boatClassIconsMap.put(BoatClassMasterdata.DRAGON_INT.getDisplayName(), imageResources.DragonIcon()); + boatClassIconsMap.put(BoatClassMasterdata.EUROPE_INT.getDisplayName(), imageResources.EuropeIcon()); + boatClassIconsMap.put(BoatClassMasterdata.EXTREME_40.getDisplayName(), imageResources.Extreme40Icon()); + boatClassIconsMap.put(BoatClassMasterdata.F_16.getDisplayName(), imageResources.F16Icon()); + boatClassIconsMap.put(BoatClassMasterdata.F_18.getDisplayName(), imageResources.F18Icon()); + boatClassIconsMap.put(BoatClassMasterdata.FARR_30.getDisplayName(), imageResources.Farr30Icon()); + boatClassIconsMap.put(BoatClassMasterdata.FINN.getDisplayName(), imageResources.FinnIcon()); + boatClassIconsMap.put(BoatClassMasterdata.FLYING_DUTCHMAN.getDisplayName(), imageResources.FlyingDutchmanIcon()); + boatClassIconsMap.put(BoatClassMasterdata.FOLKBOAT.getDisplayName(), imageResources.FolkBoatIcon()); + boatClassIconsMap.put(BoatClassMasterdata.H_BOAT.getDisplayName(), imageResources.H_BoatIcon()); + boatClassIconsMap.put(BoatClassMasterdata.HOBIE_16.getDisplayName(), imageResources.HobieIcon()); + boatClassIconsMap.put(BoatClassMasterdata.HOBIE_TIGER.getDisplayName(), imageResources.HobieIcon()); + boatClassIconsMap.put(BoatClassMasterdata.HOBIE_WILD_CAT.getDisplayName(), imageResources.HobieIcon()); + boatClassIconsMap.put(BoatClassMasterdata.J24.getDisplayName(), imageResources.J24Icon()); + boatClassIconsMap.put(BoatClassMasterdata.J70.getDisplayName(), imageResources.J70Icon()); + boatClassIconsMap.put(BoatClassMasterdata.J80.getDisplayName(), imageResources.J80Icon()); + boatClassIconsMap.put(BoatClassMasterdata.LASER_SB3.getDisplayName(), imageResources.LaserSB3Icon()); + boatClassIconsMap.put(BoatClassMasterdata.LASER_INT.getDisplayName(), imageResources.LaserIcon()); + boatClassIconsMap.put(BoatClassMasterdata.LASER_4_7.getDisplayName(), imageResources.LaserIcon()); + boatClassIconsMap.put(BoatClassMasterdata.LASER_RADIAL.getDisplayName(), imageResources.LaserIcon()); + boatClassIconsMap.put(BoatClassMasterdata.MELGES_24.getDisplayName(), imageResources.Melges24Icon()); + boatClassIconsMap.put(BoatClassMasterdata.MINI_TRANSAT.getDisplayName(), imageResources.MiniTransatIcon()); + boatClassIconsMap.put(BoatClassMasterdata.MUSTO_SKIFF.getDisplayName(), imageResources.MustoSkiffIcon()); + boatClassIconsMap.put(BoatClassMasterdata.NACRA_17.getDisplayName(), imageResources.Nacra17Icon()); + boatClassIconsMap.put(BoatClassMasterdata.OK.getDisplayName(), imageResources.OKIcon()); + boatClassIconsMap.put(BoatClassMasterdata.OPTIMIST.getDisplayName(), imageResources.OptimistIcon()); + boatClassIconsMap.put(BoatClassMasterdata.PLATU_25.getDisplayName(), imageResources.Platu25Icon()); + boatClassIconsMap.put(BoatClassMasterdata.RS_X.getDisplayName(), imageResources.RSXIcon()); + boatClassIconsMap.put(BoatClassMasterdata.SONAR.getDisplayName(), imageResources.SonarIcon()); + boatClassIconsMap.put(BoatClassMasterdata.STAR.getDisplayName(), imageResources.StarIcon()); + boatClassIconsMap.put(BoatClassMasterdata.STREAMLINE.getDisplayName(), imageResources.StreamlineIcon()); + boatClassIconsMap.put(BoatClassMasterdata.SWAN_45.getDisplayName(), imageResources.Swan45Icon()); + boatClassIconsMap.put(BoatClassMasterdata.TORNADO.getDisplayName(), imageResources.TornadoIcon()); + boatClassIconsMap.put(BoatClassMasterdata.X_99.getDisplayName(), imageResources.X99Icon()); + boatClassIconsMap.put(BoatClassMasterdata.INTERNATIONAL_14.getDisplayName(), imageResources.International14Icon()); + boatClassIconsMap.put(BoatClassMasterdata.DYAS.getDisplayName(), imageResources.DyasIcon()); + boatClassIconsMap.put(BoatClassMasterdata.OPEN_BIC.getDisplayName(), imageResources.OpenBicIcon()); + } + + public static ImageResource getBoatClassIconResource(String displayName) { + return boatClassIconsMap.get(displayName); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResources.java new file mode 100644 index 00000000000..2a962a2ed5a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/BoatClassImageResources.java @@ -0,0 +1,147 @@ +package com.sap.sailing.gwt.home.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +public interface BoatClassImageResources extends ClientBundle { + public static final BoatClassImageResources INSTANCE = GWT.create(BoatClassImageResources.class); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/GENERIC_BOATCLASS.png") + ImageResource genericBoatClass(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/12MR.png") + ImageResource _12mRIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/2_4M.png") + ImageResource _2_4mIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/29ER.png") + ImageResource _29erIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/420.png") + ImageResource _420Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/470.png") + ImageResource _470Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/49ER_FX.png") + ImageResource _49erFXIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/49ER.png") + ImageResource _49erIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/505.png") + ImageResource _505mIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/A_CAT.png") + ImageResource A_CatIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/ALBIN_EXPRESS.png") + ImageResource AlbinExpressIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/B_ONE.png") + ImageResource BOne(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/CONTENDER.png") + ImageResource ContenderIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/DRAGON.png") + ImageResource DragonIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/EUROPE.png") + ImageResource EuropeIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/EXTREME40.png") + ImageResource Extreme40Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/F16.png") + ImageResource F16Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/F18.png") + ImageResource F18Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/FARR_30.png") + ImageResource Farr30Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/FINN.png") + ImageResource FinnIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/FLYING_DUTCHMAN.png") + ImageResource FlyingDutchmanIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/FOLKBOAT.png") + ImageResource FolkBoatIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/H_BOAT.png") + ImageResource H_BoatIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/HOBIE.png") + ImageResource HobieIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/J24.png") + ImageResource J24Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/J70.png") + ImageResource J70Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/J80.png") + ImageResource J80Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/LASER_SB3.png") + ImageResource LaserSB3Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/LASER.png") + ImageResource LaserIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/MELGES_24.png") + ImageResource Melges24Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/MINI_TRANSAT.png") + ImageResource MiniTransatIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/MUSTO_SKIFF.png") + ImageResource MustoSkiffIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/NACRA_17.png") + ImageResource Nacra17Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/OK.png") + ImageResource OKIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/OPTIMIST.png") + ImageResource OptimistIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/PLATU_25.png") + ImageResource Platu25Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/RS_X.png") + ImageResource RSXIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/SONAR.png") + ImageResource SonarIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/STAR.png") + ImageResource StarIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/STREAMLINE.png") + ImageResource StreamlineIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/SWAN_45.png") + ImageResource Swan45Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/TORNADO.png") + ImageResource TornadoIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/X_99.png") + ImageResource X99Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/DYAS.png") + ImageResource DyasIcon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/INTERNATIONAL_14.png") + ImageResource International14Icon(); + + @Source("com/sap/sailing/gwt/ui/client/images/boatclass/OPENBIC.png") + ImageResource OpenBicIcon(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationActivityMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationActivityMapper.java index 9bf6fac4580..ef42d84a558 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationActivityMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationActivityMapper.java @@ -11,6 +11,8 @@ import com.sap.sailing.gwt.home.client.place.event.EventActivityProxy; import com.sap.sailing.gwt.home.client.place.event.EventPlace; import com.sap.sailing.gwt.home.client.place.events.EventsActivityProxy; import com.sap.sailing.gwt.home.client.place.events.EventsPlace; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardActivityProxy; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardPlace; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultActivityProxy; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.client.place.solutions.SolutionsActivityProxy; @@ -44,6 +46,8 @@ public class ApplicationActivityMapper implements ActivityMapper { return new SponsoringActivityProxy((SponsoringPlace) place, clientFactory); } else if (place instanceof SolutionsPlace) { return new SolutionsActivityProxy((SolutionsPlace) place, clientFactory); + } else if (place instanceof LeaderboardPlace) { + return new LeaderboardActivityProxy((LeaderboardPlace) place, clientFactory); } else if (place instanceof SearchResultPlace) { return new SearchResultActivityProxy((SearchResultPlace) place, clientFactory); } else { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationClientFactory.java index 5269aff0492..3cb19e535f6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationClientFactory.java @@ -4,12 +4,14 @@ import com.sap.sailing.gwt.home.client.place.aboutus.AboutUsClientFactory; import com.sap.sailing.gwt.home.client.place.contact.ContactClientFactory; import com.sap.sailing.gwt.home.client.place.event.EventClientFactory; import com.sap.sailing.gwt.home.client.place.events.EventsClientFactory; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardClientFactory; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultClientFactory; import com.sap.sailing.gwt.home.client.place.solutions.SolutionsClientFactory; import com.sap.sailing.gwt.home.client.place.sponsoring.SponsoringClientFactory; import com.sap.sailing.gwt.home.client.place.start.StartClientFactory; public interface ApplicationClientFactory extends AboutUsClientFactory, ContactClientFactory, EventClientFactory, - EventsClientFactory, StartClientFactory, SponsoringClientFactory, SolutionsClientFactory, SearchResultClientFactory { + EventsClientFactory, StartClientFactory, SponsoringClientFactory, SolutionsClientFactory, SearchResultClientFactory, + LeaderboardClientFactory { PlaceNavigator getPlaceNavigator(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationHistoryMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationHistoryMapper.java index d3fe642da21..72f4ab48c09 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationHistoryMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/ApplicationHistoryMapper.java @@ -6,8 +6,14 @@ import com.sap.sailing.gwt.home.client.place.aboutus.AboutUsPlace; import com.sap.sailing.gwt.home.client.place.contact.ContactPlace; import com.sap.sailing.gwt.home.client.place.event.EventPlace; import com.sap.sailing.gwt.home.client.place.events.EventsPlace; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardPlace; +import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultPlace; +import com.sap.sailing.gwt.home.client.place.solutions.SolutionsPlace; +import com.sap.sailing.gwt.home.client.place.sponsoring.SponsoringPlace; import com.sap.sailing.gwt.home.client.place.start.StartPlace; -@WithTokenizers({ AboutUsPlace.Tokenizer.class, ContactPlace.Tokenizer.class, EventPlace.Tokenizer.class, EventsPlace.Tokenizer.class, StartPlace.Tokenizer.class }) +@WithTokenizers({ AboutUsPlace.Tokenizer.class, ContactPlace.Tokenizer.class, EventPlace.Tokenizer.class, EventsPlace.Tokenizer.class, + SolutionsPlace.Tokenizer.class, SponsoringPlace.Tokenizer.class, SearchResultPlace.Tokenizer.class, StartPlace.Tokenizer.class, + LeaderboardPlace.Tokenizer.class}) public interface ApplicationHistoryMapper extends PlaceHistoryMapper { } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigator.java index e0cff6053bb..ca3f7d1acf9 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigator.java @@ -2,8 +2,9 @@ package com.sap.sailing.gwt.home.client.app; public interface PlaceNavigator { void goToHome(); - void goToEvent(String eventUuidAsString, String baseUrl); - void goToRegattaOfEvent(String eventUuidAsString, String regattaIdAsNameString, String baseUrl); + void goToEvent(String eventUuidAsString, String baseUrl, boolean isOnRemoteServer); + void goToRegattaOfEvent(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl, boolean isOnRemoteServer); + void goToLeaderboard(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl, boolean isOnRemoteServer); void goToSearchResult(String searchQuery); void goToEvents(); void goToAboutUs(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigatorImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigatorImpl.java index f506a658504..3731da8fd75 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigatorImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/PlaceNavigatorImpl.java @@ -7,7 +7,9 @@ import com.google.gwt.user.client.Window; import com.sap.sailing.gwt.home.client.place.aboutus.AboutUsPlace; import com.sap.sailing.gwt.home.client.place.contact.ContactPlace; import com.sap.sailing.gwt.home.client.place.event.EventPlace; +import com.sap.sailing.gwt.home.client.place.event.EventPlace.NavigationTabs; import com.sap.sailing.gwt.home.client.place.events.EventsPlace; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardPlace; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.client.place.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.client.place.sponsoring.SponsoringPlace; @@ -15,7 +17,8 @@ import com.sap.sailing.gwt.home.client.place.start.StartPlace; public class PlaceNavigatorImpl implements PlaceNavigator { private final PlaceController placeController; - private final static String SAPSAILING_DOMAIN = "www.sapsailing.com"; + private final static String DEFAULT_SAPSAILING_SERVER = "www.sapsailing.com"; + private final static String DEFAULT_SAPSAILING_SERVER_URL = "http://" + DEFAULT_SAPSAILING_SERVER; protected PlaceNavigatorImpl(PlaceController placeController) { super(); @@ -24,79 +27,88 @@ public class PlaceNavigatorImpl implements PlaceNavigator { @Override public void goToHome() { - gotoPlace(new StartPlace(), new StartPlace.Tokenizer()); + gotoPlace(getLocationURL(), new StartPlace(), new StartPlace.Tokenizer()); } @Override - public void goToEvent(String eventUuidAsString, String baseUrl) { - EventPlace eventPlace = new EventPlace(eventUuidAsString, null); - if(isLocationOnLocalhost() || baseUrl.contains(SAPSAILING_DOMAIN)) { - placeController.goTo(eventPlace); - } else { - String remoteEventUrl = buildRemotePlaceUrl(baseUrl, eventPlace, new EventPlace.Tokenizer()); - Window.Location.replace(remoteEventUrl); - } + public void goToEvent(String eventUuidAsString, String baseUrl, boolean isOnRemoteServer) { + EventPlace eventPlace = new EventPlace(eventUuidAsString, NavigationTabs.Regattas, null); + gotoPlace(baseUrl, isOnRemoteServer, eventPlace, new EventPlace.Tokenizer()); } @Override - public void goToRegattaOfEvent(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl) { - EventPlace eventPlace = new EventPlace(eventUuidAsString, leaderboardIdAsNameString); - if(isLocationOnLocalhost() || baseUrl.contains(SAPSAILING_DOMAIN)) { - placeController.goTo(eventPlace); - } else { - String remoteEventUrl = buildRemotePlaceUrl(baseUrl, eventPlace, new EventPlace.Tokenizer()); - Window.Location.replace(remoteEventUrl); - } + public void goToRegattaOfEvent(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl, boolean isOnRemoteServer) { + EventPlace eventPlace = new EventPlace(eventUuidAsString, NavigationTabs.Regatta, leaderboardIdAsNameString); + gotoPlace(baseUrl, isOnRemoteServer, eventPlace, new EventPlace.Tokenizer()); + } + + @Override + public void goToLeaderboard(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl, boolean isOnRemoteServer) { + LeaderboardPlace leaderboardPlace = new LeaderboardPlace(eventUuidAsString, leaderboardIdAsNameString, true, true); + gotoPlace(baseUrl, isOnRemoteServer, leaderboardPlace, new LeaderboardPlace.Tokenizer()); } @Override public void goToSearchResult(String searchQuery) { - gotoPlace(new SearchResultPlace(searchQuery), new SearchResultPlace.Tokenizer()); + gotoPlace(getLocationURL(), new SearchResultPlace(searchQuery), new SearchResultPlace.Tokenizer()); } @Override public void goToEvents() { - gotoPlace(new EventsPlace(), new EventsPlace.Tokenizer()); + gotoPlace(getLocationURL(), new EventsPlace(), new EventsPlace.Tokenizer()); } @Override public void goToAboutUs() { - gotoPlace(new AboutUsPlace(), new AboutUsPlace.Tokenizer()); + gotoPlace(getLocationURL(), new AboutUsPlace(), new AboutUsPlace.Tokenizer()); } @Override public void goToContact() { - gotoPlace(new ContactPlace(), new ContactPlace.Tokenizer()); + gotoPlace(getLocationURL(), new ContactPlace(), new ContactPlace.Tokenizer()); } @Override public void goToSolutions() { - gotoPlace(new SolutionsPlace(), new SolutionsPlace.Tokenizer()); + gotoPlace(getLocationURL(), new SolutionsPlace(), new SolutionsPlace.Tokenizer()); } @Override public void goToSponsoring() { - gotoPlace(new SponsoringPlace(), new SponsoringPlace.Tokenizer()); + gotoPlace(getLocationURL(), new SponsoringPlace(), new SponsoringPlace.Tokenizer()); } - private void gotoPlace(T destinationPlace, PlaceTokenizer tokenizer) { - if(isLocationOnLocalhost() || isLocationOnSapSailingCom()) { + private void gotoPlace(String baseUrl, T destinationPlace, PlaceTokenizer tokenizer) { + if(isLocationOnLocalhost(baseUrl) || isLocationOnDefaultSapSailingServer(baseUrl)) { placeController.goTo(destinationPlace); } else { - String homeUrl = buildRemotePlaceUrl("http://" + SAPSAILING_DOMAIN, destinationPlace, tokenizer); + String homeUrl = buildRemotePlaceUrl(DEFAULT_SAPSAILING_SERVER_URL, destinationPlace, tokenizer); Window.Location.replace(homeUrl); } } + + private void gotoPlace(String baseUrl, boolean isOnRemoteServer, T destinationPlace, PlaceTokenizer tokenizer) { + if((baseUrl != null && isLocationOnLocalhost(baseUrl)) || !isOnRemoteServer) { + placeController.goTo(destinationPlace); + } else { + String homeUrl = buildRemotePlaceUrl(baseUrl, destinationPlace, tokenizer); + Window.Location.replace(homeUrl); + } + } + + private String getLocationURL() { + return Window.Location.getProtocol() + "//" + Window.Location.getHostName(); + } private String buildRemotePlaceUrl(String baseUrl, T destinationPlace, PlaceTokenizer tokenizer) { return baseUrl + "/gwt/Home.html#" + destinationPlace.getClass().getSimpleName() + ":" + tokenizer.getToken(destinationPlace); } - - private boolean isLocationOnSapSailingCom() { - return Window.Location.getHostName().contains(SAPSAILING_DOMAIN); + + private boolean isLocationOnDefaultSapSailingServer(String urlToCheck) { + return urlToCheck.contains(DEFAULT_SAPSAILING_SERVER); } - private boolean isLocationOnLocalhost() { - return Window.Location.getHostName().contains("localhost") || Window.Location.getHostName().contains("127.0.0.1"); + private boolean isLocationOnLocalhost(String urlToCheck) { + return urlToCheck.contains("localhost") || urlToCheck.contains("127.0.0.1"); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/SmartphoneApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/SmartphoneApplicationClientFactory.java index ab5e46d4bf8..d7f9018888a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/SmartphoneApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/SmartphoneApplicationClientFactory.java @@ -5,11 +5,16 @@ import java.util.List; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; import com.google.web.bindery.event.shared.EventBus; +import com.sap.sailing.gwt.home.client.place.error.TabletAndDesktopErrorView; import com.sap.sailing.gwt.home.client.place.event.EventView; +import com.sap.sailing.gwt.home.client.place.event.EventWithoutRegattasView; import com.sap.sailing.gwt.home.client.place.event.TabletAndDesktopEventView; +import com.sap.sailing.gwt.home.client.place.event.TabletAndDesktopEventWithoutRegattasView; import com.sap.sailing.gwt.home.client.place.events.EventsActivity; import com.sap.sailing.gwt.home.client.place.events.EventsView; import com.sap.sailing.gwt.home.client.place.events.TabletAndDesktopEventsView; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardView; +import com.sap.sailing.gwt.home.client.place.leaderboard.TabletAndDesktopLeaderboardView; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultView; import com.sap.sailing.gwt.home.client.place.searchresult.TabletAndDesktopSearchResultView; import com.sap.sailing.gwt.home.client.place.solutions.SolutionsActivity; @@ -35,12 +40,17 @@ public class SmartphoneApplicationClientFactory extends AbstractApplicationClien } private SmartphoneApplicationClientFactory(EventBus eventBus, PlaceController placeController) { - super(new SmartphoneApplicationView(new PlaceNavigatorImpl(placeController)), eventBus, placeController); + super(new TabletAndDesktopApplicationView(new PlaceNavigatorImpl(placeController)), eventBus, placeController); } @Override public EventView createEventView(EventDTO event, List raceGroups, String leaderboardName, Timer timerForClientServerOffset) { - return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset); + return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset, getPlaceNavigator()); + } + + @Override + public EventWithoutRegattasView createEventWithoutRegattasView(EventDTO event) { + return new TabletAndDesktopEventWithoutRegattasView(getSailingService(), event); } @Override @@ -48,10 +58,14 @@ public class SmartphoneApplicationClientFactory extends AbstractApplicationClien return new TabletAndDesktopEventsView(getPlaceNavigator()); } + @Override + public TabletAndDesktopErrorView createErrorView(String errorMessage, Throwable errorReason) { + return new TabletAndDesktopErrorView(errorMessage, errorReason); + } + @Override public StartView createStartView() { return new TabletAndDesktopStartView(getPlaceNavigator()); -// return new SmartphoneStartView(getPlaceNavigator()); } @Override @@ -64,8 +78,13 @@ public class SmartphoneApplicationClientFactory extends AbstractApplicationClien return new TabletAndDesktopSolutionsView(); } + @Override + public LeaderboardView createLeaderboardView(EventDTO event, String leaderboardName, Timer timerForClientServerOffset) { + return new TabletAndDesktopLeaderboardView(event, leaderboardName, timerForClientServerOffset, getPlaceNavigator()); + } + @Override public SearchResultView createSearchResultView() { - return new TabletAndDesktopSearchResultView(getPlaceNavigator(), getEventBus()); + return new TabletAndDesktopSearchResultView(getPlaceNavigator()); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationClientFactory.java index c58a34f6f62..6100a0d2510 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationClientFactory.java @@ -5,11 +5,16 @@ import java.util.List; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; import com.google.web.bindery.event.shared.EventBus; +import com.sap.sailing.gwt.home.client.place.error.TabletAndDesktopErrorView; import com.sap.sailing.gwt.home.client.place.event.EventView; +import com.sap.sailing.gwt.home.client.place.event.EventWithoutRegattasView; import com.sap.sailing.gwt.home.client.place.event.TabletAndDesktopEventView; +import com.sap.sailing.gwt.home.client.place.event.TabletAndDesktopEventWithoutRegattasView; import com.sap.sailing.gwt.home.client.place.events.EventsActivity; import com.sap.sailing.gwt.home.client.place.events.EventsView; import com.sap.sailing.gwt.home.client.place.events.TabletAndDesktopEventsView; +import com.sap.sailing.gwt.home.client.place.leaderboard.LeaderboardView; +import com.sap.sailing.gwt.home.client.place.leaderboard.TabletAndDesktopLeaderboardView; import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultView; import com.sap.sailing.gwt.home.client.place.searchresult.TabletAndDesktopSearchResultView; import com.sap.sailing.gwt.home.client.place.solutions.SolutionsActivity; @@ -40,7 +45,17 @@ public class TabletAndDesktopApplicationClientFactory extends AbstractApplicatio @Override public EventView createEventView(EventDTO event, List raceGroups, String leaderboardName, Timer timerForClientServerOffset) { - return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset); + return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset, getPlaceNavigator()); + } + + @Override + public TabletAndDesktopErrorView createErrorView(String errorMessage, Throwable errorReason) { + return new TabletAndDesktopErrorView(errorMessage, errorReason); + } + + @Override + public EventWithoutRegattasView createEventWithoutRegattasView(EventDTO event) { + return new TabletAndDesktopEventWithoutRegattasView(getSailingService(), event); } @Override @@ -63,8 +78,13 @@ public class TabletAndDesktopApplicationClientFactory extends AbstractApplicatio return new TabletAndDesktopSolutionsView(); } + @Override + public LeaderboardView createLeaderboardView(EventDTO event, String leaderboardName, Timer timerForClientServerOffset) { + return new TabletAndDesktopLeaderboardView(event, leaderboardName, timerForClientServerOffset, getPlaceNavigator()); + } + @Override public SearchResultView createSearchResultView() { - return new TabletAndDesktopSearchResultView(getPlaceNavigator(), getEventBus()); + return new TabletAndDesktopSearchResultView(getPlaceNavigator()); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.java index 915f726ee10..ae32e3212eb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.java @@ -1,8 +1,6 @@ package com.sap.sailing.gwt.home.client.app; import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.AcceptsOneWidget; @@ -31,9 +29,6 @@ public class TabletAndDesktopApplicationView extends Composite implements Applic @UiField SimplePanel mainContentPanel; - @UiField - Element loadingMessage; - public TabletAndDesktopApplicationView(PlaceNavigator navigator) { headerPanel = new Header(navigator); initWidget(uiBinder.createAndBindUi(this)); @@ -45,7 +40,6 @@ public class TabletAndDesktopApplicationView extends Composite implements Applic } @Override - public void showLoading(boolean visibile) { - loadingMessage.getStyle().setVisibility(visibile ? Visibility.VISIBLE : Visibility.HIDDEN); + public void showLoading(boolean visible) { } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.ui.xml index c53727b7ab3..c0926ee297e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/app/TabletAndDesktopApplicationView.ui.xml @@ -2,14 +2,9 @@ - -

Loading...
- - - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.java index dfe7d0e5e92..c0431620b40 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.java @@ -1,8 +1,11 @@ package com.sap.sailing.gwt.home.client.i18n; +import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.Messages; public interface TextMessages extends Messages { + public static final TextMessages INSTANCE = GWT.create(TextMessages.class); + String chooseALanguage(); String home(); String events(); @@ -10,20 +13,36 @@ public interface TextMessages extends Messages { String contact(); String sponsoring(); String solutions(); - String search(); String german(); String english(); String fullEventSchedule(); + String officalEventWebsite(); + String leg(); + String races(); + String moreInfo(); + String viewAnalysis(); + String overallLeaderboard(); + String pleaseEnterASearchTerm(); + String pleaseTryAgain(); + String reloadPage(); + String errorMessageLoadingData(); + String errorMessageNoSuchLeaderboard(); + String raceNotScheduled(); + String regattaDetails(); String countdownDays(); String countdownHours(); String countdownMinutes(); String countdownSeconds(); + String countdownDay(); + String countdownHour(); + String countdownMinute(); + String countdownSecond(); String live(); String finished(); String watchNow(); String lastUpdate(); - String leaderBoard(); + String leaderboard(); String boxNewsUpdateMoreLink(); String boxNewsUpdateTitle(); String boxUpcomingRacesCountdownStarted1(); @@ -158,4 +177,5 @@ public interface TextMessages extends Messages { String solutionsSimulatorNav(); String solutionsSimulatorHeadline(); String solutionsSimulatorText(); + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.properties index 8e11127cf20..0f8ea69634d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages.properties @@ -5,20 +5,36 @@ aboutUs=About us contact=Contact sponsoring=Sponsoring solutions=Solutions -search=Search german=Deutsch english=English fullEventSchedule=Full event schedule +officalEventWebsite=Official event website +leg=Leg +races=Races +moreInfo=More info +viewAnalysis=View analysis +overallLeaderboard=Overall leaderboard +pleaseEnterASearchTerm=Please enter a search term. +pleaseTryAgain=Please try again... +reloadPage=Reload page +errorMessageLoadingData=An error occured while loading the data for this page. +errorMessageNoSuchLeaderboard=Could not find a leaderboard with this name. +raceNotScheduled=Not scheduled. +regattaDetails=Regatta details countdownDays=Days -countdownHours=Hours -countdownMinutes=Mins -countdownSeconds=Secs +countdownHours=Hrs +countdownMinutes=Min +countdownSeconds=Sec +countdownDay=Day +countdownHour=Hour +countdownMinute=Min +countdownSecond=Sec live=Live finished=Finished watchNow=Watch now lastUpdate=Last Update -leaderBoard=LeaderBoard +leaderboard=Leaderboard boxNewsUpdateMoreLink=Report news boxNewsUpdateTitle=News Update boxUpcomingRacesCountdownStarted1=Started @@ -75,8 +91,8 @@ eventRegattaRaceStarted=Started at: eventRegattaRaceScheduled=Scheduled for: eventRegattaRaceRace=Race eventRegattaRaceWind=Wind Strength: -eventRegattaRaceWinner=Winner: -eventRegattaRaceLeader=Leader: +eventRegattaRaceWinner=Winner +eventRegattaRaceLeader=Leader eventRegattaRacesLegendGps=Tracking eventRegattaRacesLegendWind=Wind Data eventRegattaRacesLegendVideo=Video Stream @@ -91,7 +107,7 @@ headerEvents=Events headerHome=Home headerLogo=SAP Sailing Analytics headerSearch=Search -headerSearchPlaceholder=Search +headerSearchPlaceholder=Search SAPSailing.com headerSolutions=Solutions headerSponsoring=Sponsoring latestRaceResultsHeadline=Latest Official Race Results @@ -123,15 +139,15 @@ regattaStartedAt=Started at regattasResultsTitle=Winner and Results searchResultHeaderButton=Search searchResultHeaderLabel=Your Search -searchResultHeaderPlaceholder=Suchbegriff eingeben +searchResultHeaderPlaceholder=Type in your searchkey searchResultMore=More searchResultSearch=Search searchResultSearchAgain=Search again searchResultSortLabel=Sort by -searchResultSortNewest=Neueste -searchResultSortOldest=Älteste +searchResultSortNewest=Recent +searchResultSortOldest=Oldest searchResultSortRelevance=Relevance -searchResultCount=About 2,450 reslts where found for 'Schnitzel' +searchResultCount=About 2,450 results where found for 'Schnitzel' sharingEmail=Send an email sharingFacebook=Share on Facebook sharingTwitter=Tweet about it diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages_de.properties index 799ed153233..248856f4317 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/i18n/TextMessages_de.properties @@ -1,155 +1,171 @@ -chooseALanguage=Wähle eine Sprache +chooseALanguage=Wähle eine Sprache events=Veranstaltungen home=Startseite -aboutUs=Über uns +aboutUs=Über uns contact=Kontakt sponsoring=Sponsoring -solutions=Lösungen -search=Suche +solutions=Lösungen german=Deutsch english=English -fullEventSchedule=Full event schedule +fullEventSchedule=Gesamter Veranstaltungsplan +officalEventWebsite=Offizielle Internetseite +leg=Schenkel +races=Rennen +moreInfo=Weitere Informationen +viewAnalysis=Analyzen ansehen +overallLeaderboard=Gesamtergebnis +pleaseEnterASearchTerm=Bitte gebe einen Suchbegriff ein. +pleaseTryAgain=Bitte versuchen sie es erneut... +reloadPage=Seite neu laden +errorMessageLoadingData=Beim Laden der Daten für diese Seite ist ein Fehler aufgetreten. +errorMessageNoSuchLeaderboard=Es wurde keine Ergebnisliste mit diesem Namen gefunden. +raceNotScheduled=Keine Startzeit bekannt +regattaDetails=Regatta anzeigen -countdownDays=Days -countdownHours=Hours -countdownMinutes=Mins -countdownSeconds=Secs +countdownDays=Tage +countdownHours=Std. +countdownMinutes=Min. +countdownSeconds=Sek. +countdownDay=Tag +countdownHour=Std. +countdownMinute=Min. +countdownSecond=Sek. live=Live -finished=Finished -watchNow=Watch now -lastUpdate=Last Update -leaderBoard=LeaderBoard -boxNewsUpdateMoreLink=Report news +finished=Beendet +watchNow=Jetzt mitverfolgen +lastUpdate=Letztes Update +leaderboard=Ergebnisliste +boxNewsUpdateMoreLink=Neuigkeiten berichten boxNewsUpdateTitle=News Update -boxUpcomingRacesCountdownStarted1=Started -boxUpcomingRacesCountdownStarted2=hrs and -boxUpcomingRacesCountdownStarted3=minutes ago -boxUpcomingRacesCountdownStarting1=Starting in -boxUpcomingRacesCountdownStarting2=hrs and -boxUpcomingRacesCountdownStarting3=minutes -boxUpcomingRacesMoreLink=Event Schedule -boxUpcomingRacesTitle=Upcoming Races Today -boxWeather=Weather -boxWeatherUnit=KTS +boxUpcomingRacesCountdownStarted1=Gestartet +boxUpcomingRacesCountdownStarted2=Std. und +boxUpcomingRacesCountdownStarted3=Minuten vorbei +boxUpcomingRacesCountdownStarting1=Startet in +boxUpcomingRacesCountdownStarting2=Std. in +boxUpcomingRacesCountdownStarting3=Minuten +boxUpcomingRacesMoreLink=Veranstaltungszeitplan +boxUpcomingRacesTitle=Kommende Rennen heute +boxWeather=Wetter +boxWeatherUnit=KTN defaultTitle=SAP Sailing Analytics eventHeaderMedia=Media -eventHeaderOverview=Overview -eventHeaderRaces=Schedule -eventHeaderRegattas=Regattas -seriesHeaderOverview=About the Series -seriesHeaderUpcoming=Upcoming Events -seriesHeaderRecent=Recent Events -seriesHeaderLeaderboard=Leaderboard -seriesOverviewHeaderRecent=Latest Series Events -seriesOverviewReadMore=More -eventsOverviewRecentEvents=Events -eventsOverviewRecentCountries=Countries -eventsOverviewRecentSailors=Sailors -eventsOverviewRecentTrackedRaces=Tracked Races -eventResultsHeadline=Winners and Results -eventResultsBoatClassesDropDown=All Boat Classes -eventOverviewMoreEvents=More Events -eventOverviewRecentEvents=Recent Events -eventOverviewUpcomingDate=Date -eventOverviewUpcomingEvent=Event -eventOverviewUpcomingLocation=Location -eventOverviewUpcomingSchedule=Upcoming Schedule -eventOverviewUpcomingSeries=Series -eventOverviewUpcomingTeaser=More Events To Be Announced Soon! -eventQuickfinderTitle=Event Quick-Finder -eventRegattaHeaderLeaderboard=Leaderboard -eventRegattaHeaderRaceRaces=Races -eventRegattaListAllBoatClasses=All boat classes -eventRegattaLeaderboardCompetitor=Competitor -eventRegattaLeaderboardExtendLeaderboard=Extend Leaderboard -eventRegattaLeaderboardFinishedMessage=No more races -eventRegattaLeaderboardLastScoreUpdate=Last Score Update +eventHeaderOverview=Übersicht +eventHeaderRaces=Zeitplan +eventHeaderRegattas=Regatten +seriesHeaderOverview=Über die Serie +seriesHeaderUpcoming=Noch kommende Veranstaltungen +seriesHeaderRecent=Letzte Veranstaltungen +seriesHeaderLeaderboard=Ergebnisliste +seriesOverviewHeaderRecent=Letzte Serienveranstaltungen +seriesOverviewReadMore=Mehr +eventsOverviewRecentEvents=Veranstaltungen +eventsOverviewRecentCountries=Länder +eventsOverviewRecentSailors=Segler +eventsOverviewRecentTrackedRaces=mitverfolgte Rennen +eventResultsHeadline=Gewinner und Ergebnisse +eventResultsBoatClassesDropDown=Alle Bootklassen +eventOverviewMoreEvents=Mehr Veranstaltungen +eventOverviewRecentEvents=Letzte Veranstaltungen +eventOverviewUpcomingDate=Datum +eventOverviewUpcomingEvent=Veranstaltungen +eventOverviewUpcomingLocation=Ort +eventOverviewUpcomingSchedule=Kommendes Programm +eventOverviewUpcomingSeries=Serien +eventOverviewUpcomingTeaser=Mehr Veranstaltungen werden bald veröffentlicht +eventQuickfinderTitle=Veranstaltung Schnellsuche +eventRegattaHeaderLeaderboard=Ergebnisliste +eventRegattaHeaderRaceRaces=Rennen +eventRegattaListAllBoatClasses=Alle Bootklassen +eventRegattaLeaderboardCompetitor=Teilnehmer +eventRegattaLeaderboardExtendLeaderboard=Erweitere Ergebnisliste +eventRegattaLeaderboardFinishedMessage=Keine weiteren rennen +eventRegattaLeaderboardLastScoreUpdate=Letztes Ergebnisupdate eventRegattaLeaderboardName=Name -eventRegattaLeaderboardRegattaRank=Regatta Rank -eventRegattaLeaderboardTotalPoints=Total Points -eventRegattaRaceWatch=Watch live -eventRegattaRaceAnalyse=Analyze Race -eventRegattaRaceNotTracked=Not Tracked -eventRegattaRaceFinished=Finished at: -eventRegattaRaceStarted=Started at: -eventRegattaRaceScheduled=Scheduled for: -eventRegattaRaceRace=Race -eventRegattaRaceWind=Wind Strength: -eventRegattaRaceWinner=Winner: -eventRegattaRaceLeader=Leader: +eventRegattaLeaderboardRegattaRank=Platz in der Regatta +eventRegattaLeaderboardTotalPoints=Gesamtpunkte +eventRegattaRaceWatch=Live ansehen +eventRegattaRaceAnalyse=Rennen analysieren +eventRegattaRaceNotTracked=Nicht getracked +eventRegattaRaceFinished=Beendet um: +eventRegattaRaceStarted=Gestartet um: +eventRegattaRaceScheduled=Geplant um: +eventRegattaRaceRace=Rennen +eventRegattaRaceWind=Windstärke: +eventRegattaRaceWinner=Gewinner +eventRegattaRaceLeader=Führender eventRegattaRacesLegendGps=Tracking -eventRegattaRacesLegendWind=Wind Data +eventRegattaRacesLegendWind=Winddaten eventRegattaRacesLegendVideo=Video Stream eventRegattaRacesLegendAudio=Audio Stream -eventSponsorsTitle=Event Sponsorships +eventSponsorsTitle=Veranstaltungssponsoren footerCopyright=\u00A9 2014 SAP Sailing Analytics -footerLanguage=SAP Sailing offered in -footerLegal=Legal Disclosure -footerPrivacy=Privacy +footerLanguage=SAP Sailing in +footerLegal=Impressum +footerPrivacy=Datenschutz footerFeedback=Feedback -headerEvents=Events -headerHome=Home +headerEvents=Veranstaltungen +headerHome=Startseite headerLogo=SAP Sailing Analytics -headerSearch=Search -headerSearchPlaceholder=Search -headerSolutions=Solutions -headerSponsoring=Sponsoring -latestRaceResultsHeadline=Latest Official Race Results -latestRaceResultsIsNew=New -latestRaceResultsIsUpdated=Updated -latestRaceResultsRaceCountLabel=Result after -latestRaceResultsRaceCountUnit=races -latestRaceResultsRefresh=refresh -leaderboardQuickAccessLabel=Leaderboard Quick Access -mainEventShowAll=Show All Events -mainEventTitle=Latest Events from the Sailing World -mainMediaSubtitle=Get lost in the latest and most beautiful impressions from your favorite sailing event. -mainMediaTitle=Sailing loves Photography -mainMediaVideosSubtitle=Immerse yourself in the world of sailing and check out our latest events for more videos. -mainMediaVideosTitle=Recent Video Entries -mainSponsorsReadMore=Read More -mediaTeaserPhotosTitle=Photos +headerSearch=Suche in SAPSailing.com +headerSearchPlaceholder=Suche +headerSolutions=Lösungen +headerSponsoring=Sponsoren +latestRaceResultsHeadline=Letzten ofiziellen Ergebnisse +latestRaceResultsIsNew=Neu +latestRaceResultsIsUpdated=Aktualisiert +latestRaceResultsRaceCountLabel=Ergebnis nach +latestRaceResultsRaceCountUnit=Rennen +latestRaceResultsRefresh=aktualisieren +leaderboardQuickAccessLabel=Ergebnisliste Schnellzugang +mainEventShowAll=Zeige alle Veranstaltungen +mainEventTitle=Die letzten Veranstaltungen aus der Segelwelt +mainMediaSubtitle=Hier gibt es die aktuellsten und schönsten Impressionen aus deiner beliebtesten Segelveranstaltung. +mainMediaTitle=Segeln liebt Fotographie +mainMediaVideosSubtitle=Tauche ein in die Welt des Segelns und besuche auch die anderen Veranstaltungen für mehr Videos. +mainMediaVideosTitle= Die Letzten Videoeinträge +mainSponsorsReadMore=Lese mehr +mediaTeaserPhotosTitle=Fotos mediaTeaserVideosTitle=Videos -regattaCompetitors=Competitors -regattaRaces=Races -regattaTracked=Tracked -regattaRegattaStarts=Regatta will start -regattaPts=Pts. -regattaCourse=Course -regattaArea=Area -regattaFinishedAt=Finished at -regattaScheduledAt=Scheduled at -regattaStartedAt=Started at -regattasResultsTitle=Winner and Results -searchResultHeaderButton=Search -searchResultHeaderLabel=Your Search +regattaCompetitors=Teilnehmer +regattaRaces=Rennen +regattaTracked=Getracked +regattaRegattaStarts=Regatta wird starten +regattaPts=Pkt. +regattaCourse=Kurs +regattaArea=Regattabahn +regattaFinishedAt=Beendet um +regattaScheduledAt=Geplant um +regattaStartedAt=Gestartet um +regattasResultsTitle=Gewinner und Ergebnisse +searchResultHeaderButton=Suche +searchResultHeaderLabel=Deine Suche searchResultHeaderPlaceholder=Suchbegriff eingeben -searchResultMore=More -searchResultSearch=Search -searchResultSearchAgain=Search again -searchResultSortLabel=Sort by +searchResultMore=Mehr +searchResultSearch=Suche +searchResultSearchAgain=Noch einmal suchen +searchResultSortLabel=Sortiert nach searchResultSortNewest=Neueste -searchResultSortOldest=Älteste -searchResultSortRelevance=Relevance -searchResultCount=About 2,450 reslts where found for 'Schnitzel' -sharingEmail=Send an email -sharingFacebook=Share on Facebook -sharingTwitter=Tweet about it -socialFooterShare=Share this on -socialFooterTitle=Recommend SAP Sailing Analytics +searchResultSortOldest=Älteste +searchResultSortRelevance=Relevanz +searchResultCount=Um die 2.450 Ergebnisse wurden gefunden für "Schnitzel" +sharingEmail=Email versenden +sharingFacebook=Auf Facebook teilen +sharingTwitter=Twittern +socialFooterShare=Teile es auf +socialFooterTitle=Empfehle SAP Sailing Analytics solutionsSAPNav=SAP Sailing Analytics solutionsSAPHeadline=SAP Sailing Analytics -solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing. -solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere. +solutionsSAPText1=Bei Echtzeitanalysen rund um Rennplätze, Schnelligkeit, Manöver, Verhalten etc., SAP hilf dabei zu vereinfachen und den Mythos von der Komplexität des Segelns zu nehmen. +solutionsSAPText2=SAP Sailing Analytics ermöglicht Einsichten und Transparenz in die Welt des Segelns durch Nutzung der Cloud und In-Memory Technologien, Erheben von GPS und Windmessungen in echtzeit und den Inhalt auf verschiedenen Oberflächen von überall zu visualisieren. solutionsRaceNav=Race Committee App solutionsRaceHeadline=Race Committee App -solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter. -solutionsPostNav=Post-Race Analytics -solutionsPostHeadline=Post-Race Analytics -solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.
SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas. -solutionsTrainingNav=Training Diary -solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary -solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel. -solutionsSimulatorNav=Strategy Simulator -solutionsSimulatorHeadline=Strategy Simulator -solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions. +solutionsRaceText=Die SAP Race Committee App bietet mehr Effizienz und Kontrolle für die Rennleiter durch Automatisieren und vereinfachen der manuellen Aufgaben und der Kommunikation während laufender Segelregatten. Die Race Committee App hilft Aufgaben zu vereinfachen und Segelveranstaltungen zu leiten, um das Segel Komitee besser Handeln zu lassen. +solutionsPostNav=Nachträgliche Rennen Analyse. +solutionsPostHeadline=Nachträgliche Rennen Analyse +solutionsPostText=Zugang zu gesammelten Daten bei Segelveranstaltungen geben Seglern die Möglichkeit die eigene Performance zu beurteilen und zu analysieren, um Strategien zu entwickeln und besser zu segeln.
SAP Business Analytics Lösungen stellen Seglern, Trainern, Fans und Medien Tools zu verfügung, um die historischen Daten über mehrere Regatten und Rennen anzusehen und zu analysieren. SAP HANA erlaubt es ihnen über Verhaltensmuster, Tendenzen und Segelprofilen in einem einfachen, schnellen und effizienten Weg zu erlernen, damit sie ihre Performance und Entwicklung der Strategien in zukünftigen Regatten zu optimieren. +solutionsTrainingNav=Training Tagebuch +solutionsTrainingHeadline=SAP Segelt Besser \u2013 STG Training Tagebuch +solutionsTrainingText=Das STG Trainingstagebuch unterstützt die tägliche Dokumentation und Analyse von der physischen Kondition und Trainingserfolge eines Athleten in Wassertraining, physischen Training, Boot Arbeiten, Theorie und andere Aufgaben wie Bildung oder Reisen. +solutionsSimulatorNav=Strategie Simulator +solutionsSimulatorHeadline=Strategie Simulator +solutionsSimulatorText=Die richtige Strategie zu wählen kann einen großen Vorteil während eines Rennens bringen. Der Strategie Simulator vereinfacht ausschlaggebend die besten Segelstrategien für verschiedene Windkonditionen und Wasserströmungen. Seit dem der Wind und die Strömung während der Simulation direkt geändert werden kann, kann die Strategie sogar für unsichere Wetterverhältnisse einfach bewertet werden. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivity.java new file mode 100644 index 00000000000..189b6a60a33 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivity.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.home.client.place.error; + +import com.google.gwt.activity.shared.AbstractActivity; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.user.client.ui.AcceptsOneWidget; + +public class ErrorActivity extends AbstractActivity { + + public ErrorActivity(ErrorPlace place, ErrorClientFactory clientFactory) { + } + + @Override + public void start(AcceptsOneWidget panel, EventBus eventBus) { + // TODO: the error place should get the error message from the place + panel.setWidget(new TabletAndDesktopErrorView(null, null)); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivityProxy.java new file mode 100644 index 00000000000..99ee5c0ecfe --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorActivityProxy.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.home.client.place.error; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; + +public class ErrorActivityProxy extends AbstractActivityProxy { + + private final ErrorClientFactory clientFactory; + private final ErrorPlace place; + + public ErrorActivityProxy(ErrorPlace place, ErrorClientFactory clientFactory) { + this.place = place; + this.clientFactory = clientFactory; + } + + @Override + protected void startAsync() { + GWT.runAsync(new AbstractRunAsyncCallback() { + @Override + public void onSuccess() { + super.onSuccess(new ErrorActivity(place, clientFactory)); + } + }); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorClientFactory.java new file mode 100644 index 00000000000..2be2c58653c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorClientFactory.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.client.place.error; + +import com.sap.sailing.gwt.ui.client.SailingClientFactory; + +public interface ErrorClientFactory extends SailingClientFactory { + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorPlace.java new file mode 100644 index 00000000000..75e36136479 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/ErrorPlace.java @@ -0,0 +1,19 @@ +package com.sap.sailing.gwt.home.client.place.error; + +import com.google.gwt.place.shared.PlaceTokenizer; +import com.sap.sailing.gwt.home.client.AbstractBasePlace; + +public class ErrorPlace extends AbstractBasePlace { + + public static class Tokenizer implements PlaceTokenizer { + @Override + public String getToken(ErrorPlace place) { + return null; + } + + @Override + public ErrorPlace getPlace(String token) { + return new ErrorPlace(); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.java new file mode 100644 index 00000000000..f36be64b41d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.java @@ -0,0 +1,24 @@ +package com.sap.sailing.gwt.home.client.place.error; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.shared.error.ErrorMessage; +import com.sap.sse.gwt.client.mvp.ErrorView; + +public class TabletAndDesktopErrorView extends Composite implements ErrorView { + private static ErrorViewUiBinder uiBinder = GWT.create(ErrorViewUiBinder.class); + + interface ErrorViewUiBinder extends UiBinder { + } + + @UiField(provided=true) ErrorMessage errorMessage; + + public TabletAndDesktopErrorView(String errorMessageText, Throwable errorReason) { + errorMessage = new ErrorMessage(errorMessageText, errorReason); + + initWidget(uiBinder.createAndBindUi(this)); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.ui.xml new file mode 100644 index 00000000000..6672708ed5c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/error/TabletAndDesktopErrorView.ui.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/AbstractEventComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/AbstractEventComposite.java new file mode 100644 index 00000000000..d34b2cb7cb5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/AbstractEventComposite.java @@ -0,0 +1,27 @@ +package com.sap.sailing.gwt.home.client.place.event; + +import com.google.gwt.user.client.ui.Composite; +import com.sap.sailing.gwt.ui.shared.EventDTO; + +/** + * A base class for a content composite related to an sailing event + * @author Frank + * + */ +public class AbstractEventComposite extends Composite { + private final EventDTO event; + private final EventPageNavigator pageNavigator; + + public AbstractEventComposite(EventDTO event, EventPageNavigator pageNavigator) { + this.event = event; + this.pageNavigator = pageNavigator; + } + + public EventDTO getEvent() { + return event; + } + + public EventPageNavigator getPageNavigator() { + return pageNavigator; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventActivity.java index 4c47059a9ef..f9e1fdbf044 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventActivity.java @@ -9,12 +9,14 @@ import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.client.shared.placeholder.Placeholder; import com.sap.sailing.gwt.ui.regattaoverview.RegattaRaceStatesSettings; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; +import com.sap.sse.gwt.client.mvp.ErrorView; import com.sap.sse.gwt.client.player.TimeListener; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; @@ -30,35 +32,47 @@ public class EventActivity extends AbstractActivity { private final RegattaRaceStatesSettings raceStatesSettings; private EventView view; + private EventDTO event; public EventActivity(EventPlace place, EventClientFactory clientFactory) { this.clientFactory = clientFactory; this.eventPlace = place; + this.view = null; + this.event = null; + timerForClientServerOffset = new Timer(PlayModes.Replay); serverUpdateTimer = new Timer(PlayModes.Live, serverUpdateRateInMs); raceStatesSettings = new RegattaRaceStatesSettings(); - serverUpdateTimer.addTimeListener(new TimeListener() { - - @Override - public void timeChanged(Date newTime, Date oldTime) { - // loadAndUpdateEventRaceStatesLog(); - } - }); } @Override public void start(final AcceptsOneWidget panel, final EventBus eventBus) { + panel.setWidget(new Placeholder()); + final long clientTimeWhenRequestWasSent = System.currentTimeMillis(); UUID eventUUID = UUID.fromString(eventPlace.getEventUuidAsString()); - clientFactory.getSailingService().getEventById(eventUUID, new AsyncCallback() { + clientFactory.getSailingService().getEventById(eventUUID, true, new AsyncCallback() { @Override public void onSuccess(final EventDTO event) { - - clientFactory.getSailingService().getRegattaStructureForEvent(event.id, new AsyncCallback>() { - @Override - public void onSuccess(List raceGroups) { + loadRegattaStructure(panel, clientTimeWhenRequestWasSent, event); + } + + @Override + public void onFailure(Throwable caught) { + createErrorView("Error while loading the event with service getEventById()", caught, panel); + } + }); + } + + private void loadRegattaStructure(final AcceptsOneWidget panel, final long clientTimeWhenRequestWasSent, final EventDTO event) { + this.event = event; + if(event.getLeaderboardGroups().size() > 0) { + clientFactory.getSailingService().getRegattaStructureOfEvent(event.id, new AsyncCallback>() { + @Override + public void onSuccess(List raceGroups) { + if(raceGroups.size() > 0) { for(LeaderboardGroupDTO leaderboardGroupDTO: event.getLeaderboardGroups()) { final long clientTimeWhenResponseWasReceived = System.currentTimeMillis(); if (leaderboardGroupDTO.getAverageDelayToLiveInMillis() != null) { @@ -66,51 +80,76 @@ public class EventActivity extends AbstractActivity { } timerForClientServerOffset.adjustClientServerOffset(clientTimeWhenRequestWasSent, leaderboardGroupDTO.getCurrentServerTime(), clientTimeWhenResponseWasReceived); } - - view = clientFactory.createEventView(event, raceGroups, eventPlace.getLeaderboardIdAsNameString(), timerForClientServerOffset); - panel.setWidget(view.asWidget()); - } - - @Override - public void onFailure(Throwable caught) { - Window.alert("Shit happens at getRegattaStructureForEvent()"); - } - }); - } + createEventView(event, raceGroups, panel); - @Override - public void onFailure(Throwable caught) { - Window.alert("Shit happens at getRegattaStructureForEvent()"); - } - }); + if(event.isRunning()) { + // create update time for race states only for running events + serverUpdateTimer.addTimeListener(new TimeListener() { + @Override + public void timeChanged(Date newTime, Date oldTime) { + loadAndUpdateEventRaceStatesLog(); + } + }); + } + + } else { + createEventWithoutRegattasView(event, panel); + } + } + + @Override + public void onFailure(Throwable caught) { + createErrorView("Error while loading the regatta structure with service getRegattaStructureOfEvent()", caught, panel); + } + }); + } else { + createEventWithoutRegattasView(event, panel); + } + } + + private void createErrorView(String errorMessage, Throwable errorReason, AcceptsOneWidget panel) { + ErrorView view = clientFactory.createErrorView(errorMessage, errorReason); + panel.setWidget(view.asWidget()); + } + + private void createEventView(EventDTO event, List raceGroups, AcceptsOneWidget panel) { + view = clientFactory.createEventView(event, raceGroups, eventPlace.getLeaderboardIdAsNameString(), timerForClientServerOffset); + panel.setWidget(view.asWidget()); } + private void createEventWithoutRegattasView(EventDTO event, AcceptsOneWidget panel) { + // no leaderboard groups defined yet -> show a teaser page + EventWithoutRegattasView view = clientFactory.createEventWithoutRegattasView(event); + panel.setWidget(view.asWidget()); + } + protected void loadAndUpdateEventRaceStatesLog() { - final long clientTimeWhenRequestWasSent = System.currentTimeMillis(); - UUID eventUUID = UUID.fromString(eventPlace.getEventUuidAsString()); + if(view != null && event != null) { + final long clientTimeWhenRequestWasSent = System.currentTimeMillis(); - clientFactory.getSailingService().getRaceStateEntriesForRaceGroup(eventUUID, raceStatesSettings.getVisibleCourseAreas(), - raceStatesSettings.getVisibleRegattas(), raceStatesSettings.isShowOnlyCurrentlyRunningRaces(), raceStatesSettings.isShowOnlyRacesOfSameDay(), - new MarkedAsyncCallback>( - new AsyncCallback>() { - @Override - public void onFailure(Throwable cause) { - Window.alert("Shit happens at getRaceStateEntriesForRaceGroup()"); - } - - @Override - public void onSuccess(List result) { - final long clientTimeWhenResponseWasReceived = System.currentTimeMillis(); - Date serverTimeDuringRequest = null; - for (RegattaOverviewEntryDTO entryDTO : result) { - if (entryDTO.currentServerTime != null) { - serverTimeDuringRequest = entryDTO.currentServerTime; - } + clientFactory.getSailingService().getRaceStateEntriesForRaceGroup(event.id, raceStatesSettings.getVisibleCourseAreas(), + raceStatesSettings.getVisibleRegattas(), raceStatesSettings.isShowOnlyCurrentlyRunningRaces(), raceStatesSettings.isShowOnlyRacesOfSameDay(), + new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onFailure(Throwable cause) { + Window.setStatus("Error while loading the race states with service getRaceStateEntriesForRaceGroup()"); } - view.updateEventRaceStates(result); - timerForClientServerOffset.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); - } - })); + + @Override + public void onSuccess(List result) { + final long clientTimeWhenResponseWasReceived = System.currentTimeMillis(); + Date serverTimeDuringRequest = null; + for (RegattaOverviewEntryDTO entryDTO : result) { + if (entryDTO.currentServerTime != null) { + serverTimeDuringRequest = entryDTO.currentServerTime; + } + } + view.updateEventRaceStates(result); + timerForClientServerOffset.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived); + } + })); + } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventClientFactory.java index 7d07e0c4625..6d79fe73c60 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventClientFactory.java @@ -9,4 +9,6 @@ import com.sap.sse.gwt.client.player.Timer; public interface EventClientFactory extends SailingClientFactory { EventView createEventView(EventDTO event, List raceGroups, String leaderboardName, Timer timerForClientServerOffset); + + EventWithoutRegattasView createEventWithoutRegattasView(EventDTO event); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPageNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPageNavigator.java index 24fdcdaccc1..f61b6f9234d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPageNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPageNavigator.java @@ -10,7 +10,8 @@ public interface EventPageNavigator { void goToRegattas(); void goToSchedule(); void goToMedia(); - void goToRegattaRaces(RaceGroupDTO raceGroup, StrippedLeaderboardDTO leaderboard); + void goToRegattaRaces(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard, RaceGroupDTO raceGroup); void openRaceViewer(StrippedLeaderboardDTO leaderboard, RaceDTO race); + void openOverallLeaderboardViewer(LeaderboardGroupDTO leaderboardGroup); void openLeaderboardViewer(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPlace.java index 81c9450c1ad..3a90c9bb2e5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventPlace.java @@ -6,16 +6,30 @@ import com.sap.sailing.gwt.home.client.AbstractBasePlace; public class EventPlace extends AbstractBasePlace { private final String eventUuidAsString; private final String leaderboardIdAsNameString; + private final NavigationTabs navigationTab; + + private final static String PARAM_EVENTID = "eventId"; + private final static String PARAM_LEADEROARD_NAME = "leaderboardName"; + private final static String PARAM_NAVIGATION_TAB = "navigationTab"; + + public enum NavigationTabs { Overview, Regattas, Regatta, Media, Schedule }; public EventPlace(String url) { super(url); - eventUuidAsString = getParameter("eventId"); - leaderboardIdAsNameString = getParameter("leaderboardName"); + eventUuidAsString = getParameter(PARAM_EVENTID); + leaderboardIdAsNameString = getParameter(PARAM_LEADEROARD_NAME); + String paramNavTab = getParameter(PARAM_NAVIGATION_TAB); + if(paramNavTab != null) { + navigationTab = NavigationTabs.valueOf(paramNavTab); + } else { + navigationTab = NavigationTabs.Regattas; + } } - public EventPlace(String eventUuidAsString, String leaderboardIdAsNameString) { - super("eventId", eventUuidAsString, "leaderboardName", leaderboardIdAsNameString); + public EventPlace(String eventUuidAsString, NavigationTabs navigationTab, String leaderboardIdAsNameString) { + super(PARAM_EVENTID, eventUuidAsString, PARAM_NAVIGATION_TAB, navigationTab.name(), PARAM_LEADEROARD_NAME, leaderboardIdAsNameString); this.eventUuidAsString = eventUuidAsString; + this.navigationTab = navigationTab; this.leaderboardIdAsNameString = leaderboardIdAsNameString; } @@ -27,6 +41,10 @@ public class EventPlace extends AbstractBasePlace { return leaderboardIdAsNameString; } + public NavigationTabs getNavigationTab() { + return navigationTab; + } + public static class Tokenizer implements PlaceTokenizer { @Override public String getToken(EventPlace place) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventWithoutRegattasView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventWithoutRegattasView.java new file mode 100644 index 00000000000..24eacd20417 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/EventWithoutRegattasView.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.client.place.event; + +import com.google.gwt.user.client.ui.Widget; + +public interface EventWithoutRegattasView { + Widget asWidget(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventView.java index adc9629fa21..73d7a3d87fe 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventView.java @@ -6,13 +6,19 @@ import java.util.List; import java.util.Map; import com.google.gwt.core.client.GWT; +import com.google.gwt.place.shared.Place; +import com.google.gwt.place.shared.PlaceTokenizer; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.History; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.gwt.home.client.place.event.EventPlace.NavigationTabs; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.place.event.header.EventHeader; import com.sap.sailing.gwt.home.client.place.event.media.EventMedia; import com.sap.sailing.gwt.home.client.place.event.overview.EventOverview; @@ -28,7 +34,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; import com.sap.sse.gwt.client.player.Timer; public class TabletAndDesktopEventView extends Composite implements EventView, EventPageNavigator { @@ -47,62 +53,45 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E @UiField EventSponsors eventSponsors; private final List pageElements; - private final Map> leaderboardsWithLeaderboardGroup; + private final EventDTO event; public TabletAndDesktopEventView(SailingServiceAsync sailingService, EventDTO event, List raceGroups, String leaderboardName, - Timer timerForClientServerOffset) { - leaderboardsWithLeaderboardGroup = new HashMap>(); - for(LeaderboardGroupDTO leaderboardGroup: event.getLeaderboardGroups()) { - for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) { - leaderboardsWithLeaderboardGroup.put(leaderboard.name, new Pair(leaderboard, leaderboardGroup)); - } - } - + Timer timerForClientServerOffset, PlaceNavigator navigator) { + this.event = event; + Map> regattaStructure = getRegattaStructure(event, raceGroups); + eventHeader = new EventHeader(event, this); - eventRegattaList = new EventRegattaList(event, raceGroups, leaderboardsWithLeaderboardGroup, timerForClientServerOffset, this); - eventRegattaRaces = new EventRegattaRaces(event, timerForClientServerOffset, this); - eventOverview = new EventOverview(event); - eventSchedule = new EventSchedule(event); - eventMedia = new EventMedia(event); + eventRegattaList = new EventRegattaList(event, regattaStructure, timerForClientServerOffset, navigator, this); + eventRegattaRaces = new EventRegattaRaces(event, timerForClientServerOffset, navigator, this); + eventOverview = new EventOverview(event, this); + eventSchedule = new EventSchedule(event, this); + eventMedia = new EventMedia(event, this); initWidget(uiBinder.createAndBindUi(this)); pageElements = Arrays.asList(new Widget[] { eventOverview, eventRegattaList, eventRegattaRaces, eventMedia, eventSchedule }); - int leaderboardsCount = raceGroups.size(); - if(leaderboardsCount == 0) { - Window.alert("There is no data available for this event."); + Triple selectedRegatta = null; + if(leaderboardName != null) { + selectedRegatta = regattaStructure.get(leaderboardName); + } + + // in case we only have one regatta/leaderboard we go directly to the 'races' page + if(selectedRegatta == null && regattaStructure.size() == 1) { + selectedRegatta = regattaStructure.get(0); + } + + if(selectedRegatta != null && !event.isFakeSeries()) { + goToRegattaRaces(selectedRegatta.getC(), selectedRegatta.getB(), selectedRegatta.getA()); } else { - RaceGroupDTO selectedRaceGroup = null; - - // find the preselected leaderboard (if one exist) - if (leaderboardName != null) { - for (RaceGroupDTO raceGroup : raceGroups) { - if(raceGroup.getName().equals(leaderboardName)) { - selectedRaceGroup = raceGroup; - break; - } - } - } - - // in case we only have one regatta/leaderboard we go directly to the 'races' page - if(selectedRaceGroup == null && leaderboardsCount == 1) { - selectedRaceGroup = raceGroups.get(0); - } - - if(selectedRaceGroup != null) { - goToRegattaRaces(selectedRaceGroup, leaderboardsWithLeaderboardGroup.get(selectedRaceGroup.getName()).getA()); - } else { - goToRegattas(); - } - if(event.getSponsorImageURLs() != null && event.getSponsorImageURLs().size() > 0) { - eventSponsors.setVisible(false); - eventSponsors.setEventSponsors(event.getSponsorImageURLs()); - } else { - eventSponsors.setVisible(false); - eventSponsors.setEventSponsors(null); - } - + goToRegattas(); + } + if(event.getSponsorImageURLs() != null && event.getSponsorImageURLs().size() > 0) { + eventSponsors.setVisible(false); + eventSponsors.setEventSponsors(event.getSponsorImageURLs()); + } else { + eventSponsors.setVisible(false); + eventSponsors.setEventSponsors(null); } } @@ -115,31 +104,46 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E public void goToOverview() { setVisibleEventElement(eventOverview); eventHeader.setDataNavigationType("normal"); + + EventPlace place = new EventPlace(event.id.toString(), NavigationTabs.Overview, null); + pushPlaceToHistoryStack(place, new EventPlace.Tokenizer()); } @Override public void goToRegattas() { setVisibleEventElement(eventRegattaList); eventHeader.setDataNavigationType("normal"); + + EventPlace place = new EventPlace(event.id.toString(), NavigationTabs.Regattas, null); + pushPlaceToHistoryStack(place, new EventPlace.Tokenizer()); } @Override - public void goToRegattaRaces(RaceGroupDTO raceGroup, StrippedLeaderboardDTO leaderboard) { - eventRegattaRaces.setRacesFromRaceGroup(raceGroup, leaderboard); + public void goToRegattaRaces(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard, RaceGroupDTO raceGroup) { + eventRegattaRaces.setRaces(leaderboardGroup, false, leaderboard, raceGroup); eventHeader.setDataNavigationType("compact"); setVisibleEventElement(eventRegattaRaces); + + EventPlace place = new EventPlace(event.id.toString(), NavigationTabs.Regatta, leaderboard.name); + pushPlaceToHistoryStack(place, new EventPlace.Tokenizer()); } @Override public void goToSchedule() { setVisibleEventElement(eventSchedule); eventHeader.setDataNavigationType("normal"); + + EventPlace place = new EventPlace(event.id.toString(), NavigationTabs.Schedule, null); + pushPlaceToHistoryStack(place, new EventPlace.Tokenizer()); } @Override public void goToMedia() { setVisibleEventElement(eventMedia); eventHeader.setDataNavigationType("normal"); + + EventPlace place = new EventPlace(event.id.toString(), NavigationTabs.Media, null); + pushPlaceToHistoryStack(place, new EventPlace.Tokenizer()); } @Override @@ -155,11 +159,31 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E Window.open(link, "_blank", ""); } + @Override + public void openOverallLeaderboardViewer(LeaderboardGroupDTO leaderboardGroup) { + String link = EntryPointLinkFactory.createLeaderboardLink(createOverallLeaderboardLinkParameters(leaderboardGroup)); + Window.open(link, "_blank", ""); + } + + private Map createOverallLeaderboardLinkParameters(LeaderboardGroupDTO leaderboardGroup) { + Map linkParams = new HashMap(); + linkParams.put("eventId", event.id.toString()); + linkParams.put("name", leaderboardGroup.getName() + " " + LeaderboardNameConstants.OVERALL); + linkParams.put("showRaceDetails", "true"); + if(leaderboardGroup.getDisplayName() != null) { + linkParams.put("displayName", leaderboardGroup.getDisplayName()); + } + linkParams.put("leaderboardGroupName", leaderboardGroup.getName()); + return linkParams; + } + private Map createRaceBoardLinkParameters(String leaderboardName, RegattaAndRaceIdentifier raceIdentifier) { Map linkParams = new HashMap(); + linkParams.put("eventId", event.id.toString()); linkParams.put("leaderboardName", leaderboardName); linkParams.put("raceName", raceIdentifier.getRaceName()); - linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true"); + // TODO this must only be forwarded if there is a logged-on user +// linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true"); linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, "true"); linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_NAVIGATION_PANEL, "true"); linkParams.put("regattaName", raceIdentifier.getRegattaName()); @@ -168,9 +192,9 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E private Map createLeaderboardLinkParameters(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard) { Map linkParams = new HashMap(); + linkParams.put("eventId", event.id.toString()); linkParams.put("name", leaderboard.name); linkParams.put("showRaceDetails", "true"); - linkParams.put("embedded", "true"); if (leaderboard.displayName != null) { linkParams.put("displayName", leaderboard.displayName); } @@ -186,4 +210,26 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E } } + private Map> getRegattaStructure(EventDTO event, List raceGroups) { + Map> result = new HashMap<>(); + Map raceGroupsMap = new HashMap<>(); + for (RaceGroupDTO raceGroup: raceGroups) { + raceGroupsMap.put(raceGroup.getName(), raceGroup); + } + + for (LeaderboardGroupDTO leaderboardGroup : event.getLeaderboardGroups()) { + for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) { + String leaderboardName = leaderboard.name; + result.put(leaderboardName, new Triple(raceGroupsMap.get(leaderboardName), + leaderboard, leaderboardGroup)); + } + } + return result; + } + + private void pushPlaceToHistoryStack(T destinationPlace, PlaceTokenizer tokenizer) { + String placeHistoryToken = destinationPlace.getClass().getSimpleName() + ":" + tokenizer.getToken(destinationPlace); + History.newItem(placeHistoryToken, false); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.java new file mode 100644 index 00000000000..f140e40cbc6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.home.client.place.event; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.place.event.header.EventHeader; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.shared.EventDTO; + +public class TabletAndDesktopEventWithoutRegattasView extends Composite implements EventWithoutRegattasView { + private static EventViewUiBinder uiBinder = GWT.create(EventViewUiBinder.class); + + interface EventViewUiBinder extends UiBinder { + } + + @UiField(provided=true) EventHeader eventHeader; + + public TabletAndDesktopEventWithoutRegattasView(SailingServiceAsync sailingService, EventDTO event) { + eventHeader = new EventHeader(event); + + initWidget(uiBinder.createAndBindUi(this)); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.ui.xml new file mode 100644 index 00000000000..35264d68afd --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/TabletAndDesktopEventWithoutRegattasView.ui.xml @@ -0,0 +1,21 @@ + + + + + .infoPanel { + height: 300px; + padding-top: 2em; + } + + + +
+
+ There is no information available about the regattas of this event yet. +
+
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.java new file mode 100644 index 00000000000..80ca5dac1ad --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.java @@ -0,0 +1,95 @@ +package com.sap.sailing.gwt.home.client.place.event.header; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.ImageElement; +import com.google.gwt.dom.client.SpanElement; +import com.google.gwt.dom.client.StyleInjector; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; + +public class CompactEventHeader extends Composite { + private static CompactHeaderUiBinder uiBinder = GWT.create(CompactHeaderUiBinder.class); + + interface CompactHeaderUiBinder extends UiBinder { + } + + @UiField Anchor regattaLink; + @UiField Anchor regattaLink2; + @UiField ImageElement eventLogo; + @UiField SpanElement eventNameSpan; + + private final EventDTO event; + private final PlaceNavigator placeNavigator; + private final String leaderboardName; + + private final String defaultLogoUrl = "http://static.sapsailing.com/ubilabsimages/default/default_event_logo.jpg"; + + public CompactEventHeader(EventDTO event, String leaderboardName, PlaceNavigator placeNavigator) { + this.event = event; + this.leaderboardName = leaderboardName; + this.placeNavigator = placeNavigator; + + EventHeaderResources.INSTANCE.css().ensureInjected(); + StyleInjector.injectAtEnd("@media (min-width: 50em) { "+EventHeaderResources.INSTANCE.largeCss().getText()+"}"); + + initWidget(uiBinder.createAndBindUi(this)); + updateUI(); + } + + private StrippedLeaderboardDTO findLeaderboardWithSameCourseArea(EventDTO event) { + for(LeaderboardGroupDTO leaderboardGroup: event.getLeaderboardGroups()) { + for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) { + for(CourseAreaDTO courseArea: event.venue.getCourseAreas()) { + if(leaderboard.defaultCourseAreaId != null && leaderboard.defaultCourseAreaId.equals(courseArea.id)) { + return leaderboard; + } + } + } + } + return null; + } + + private void updateUI() { + boolean isSeries = event.isFakeSeries(); + + String eventName = event.getName(); + if(isSeries) { + LeaderboardGroupDTO leaderboardGroupDTO = event.getLeaderboardGroups().get(0); + eventName = leaderboardGroupDTO.getDisplayName() != null ? leaderboardGroupDTO.getDisplayName() : leaderboardGroupDTO.getName(); + + StrippedLeaderboardDTO leaderboardFittingToEvent = findLeaderboardWithSameCourseArea(event); + if(leaderboardFittingToEvent != null) { + } else { + } + } else { + } + eventNameSpan.setInnerText(eventName); + String logoUrl = event.getLogoImageURL() != null ? event.getLogoImageURL() : defaultLogoUrl; + eventLogo.setSrc(logoUrl); + } + + @UiHandler("regattaLink") + void gotoRegattaClicked(ClickEvent event) { + showRegattaOfEvent(); + } + + @UiHandler("regattaLink2") + void gotoRegatta2Clicked(ClickEvent event) { + showRegattaOfEvent(); + } + + private void showRegattaOfEvent() { + placeNavigator.goToRegattaOfEvent(event.id.toString(), leaderboardName, event.getBaseURL(), event.isOnRemoteServer()); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml new file mode 100644 index 00000000000..f9f591e74e7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/CompactEventHeader.ui.xml @@ -0,0 +1,24 @@ + + + + + + + + +
+
+
+ + + + + + +
+
+
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.css index d39b7c45b44..222152e00aa 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.css @@ -1,10 +1,7 @@ -/** - * The header of the pages to an event - */ .dropdown { - font-size: 16px; + font-size: 15px; font-size: 1rem; - width: 18.75em; + width: 20em; max-width: 100%; display: inline-block; text-align: left; @@ -17,9 +14,9 @@ cursor: pointer; background: #f8f8f8; color: #666; - height: 2.5625em; - line-height: 2.5em; - padding-left: 0.9375em; + height: 2.733333333333333em; + line-height: 2.666666666666667em; + padding-left: 1em; font-weight: 700; } .dropdown_head_titlebutton { @@ -30,18 +27,18 @@ z-index: 1; background: #f6f9fc; display: none; - width: 18.75em; + width: 20em; height: auto; - max-height: 21.875em; + max-height: 23.333333333333332em; overflow: auto; - -webkit-box-shadow: 0 0.0625em 0.25em #ccc; - box-shadow: 0 0.0625em 0.25em #ccc; + -webkit-box-shadow: 0 0.066666666666667em 0.266666666666667em #ccc; + box-shadow: 0 0.066666666666667em 0.266666666666667em #ccc; border-bottom: solid 1px #ccc; } .dropdown_content_link { display: block; cursor: pointer; - padding: 1.25em 0.9375em; + padding: 1.333333333333333em 1em; border-bottom: 1px solid #ddd; } .dropdown_content_link:hover, @@ -57,19 +54,19 @@ color: #008fcc; display: block; font-weight: 700; - font-size: 1.125em; + font-size: 1.2em; } .dropdown_content_link_subtitle { color: #666; - font-size: 1em; + font-size: 1.066666666666667em; } .leaderboardquickaccess { - font-size: 16px; + font-size: 15px; font-size: 1rem; text-align: right; } .eventheaderwrapper { - font-size: 16px; + font-size: 15px; font-size: 1rem; } .eventheaderwrapper[data-navigationtype='compact'] .eventheader, @@ -87,35 +84,43 @@ transition: top 0.4s; } .eventheader { - font-size: 16px; + font-size: 15px; font-size: 1rem; background: #f2f2f2; - padding: 1.875em 0; + padding: 2em 0; + border-bottom: 1px solid darkgray; } .eventheader_intro { - padding-left: 9.6875em; - min-height: 8.75em; + padding-left: 10.333333333333334em; + min-height: 9.333333333333334em; position: relative; } .eventheader_intro_description { - font-size: 16px; + font-size: 15px; font-size: 1rem; } .eventheader_intro_logo { - border: solid 5px #fff; -webkit-box-shadow: 0 0 5px rgba(204,204,204,0.25); box-shadow: 0 0 5px rgba(204,204,204,0.25); position: absolute; top: 0; left: 0; + max-width: 140px; + max-height: 140px; + width: auto; + height: auto; +} +.eventheader_intro_logo_image { + border: solid 5px #fff; + max-height: 100%; } .eventheader_intro_name { display: inline-block; - margin: 0 0.3125em 0 0; + margin: 0 0.333333333333333em 0 0; } .eventheader_intro_details { - margin-bottom: 0.625em; - padding-bottom: 0.625em; + margin-bottom: 0.666666666666667em; + padding-bottom: 0.666666666666667em; border-bottom: 1px solid #ddd; font-weight: 600; color: #333; @@ -123,8 +128,8 @@ .eventheader_intro_details_item { display: inline-block; border-right: 1px solid #ddd; - padding: 0.25em 0.625em 0.25em 0; - margin-right: 0.625em; + padding: 0.266666666666667em 0.666666666666667em 0.266666666666667em 0; + margin-right: 0.666666666666667em; } .eventheader_intro_details_itemlink { color: inherit; @@ -146,9 +151,9 @@ } .eventheader_sharing_item { display: inline-block; - height: 2.5em; - width: 2.5em; - margin-left: 0.3125em; + height: 2.666666666666667em; + width: 2.666666666666667em; + margin-left: 0.333333333333333em; background-position: center center; background-repeat: no-repeat; } @@ -156,22 +161,59 @@ background-color: #f0ab00; background-image: url("images/home/email-icon.png"); } +.eventheader_sharing_itememail:hover, +.eventheader_sharing_itememail:focus { + background-color: #d89a00; +} .eventheader_sharing_itemtwitter { background-color: #32b5e2; background-image: url("images/home/twitter-icon.png"); } +.eventheader_sharing_itemtwitter:hover, +.eventheader_sharing_itemtwitter:focus { + background-color: #1faada; +} .eventheader_sharing_itemfacebook { background-color: #3b5998; background-image: url("images/home/facebook-icon.png"); } +.eventheader_sharing_itemfacebook:hover, +.eventheader_sharing_itemfacebook:focus { + background-color: #355089; +} .locationicon { vertical-align: text-bottom; - margin-right: 0.3125em; + margin-right: 0.333333333333333em; } .eventnavigation { - font-size: 16px; + font-size: 15px; font-size: 1rem; - padding: 1.875em 0; +} +.eventnavigationnormal { + position: relative; +} +.eventnavigationcompact, +.eventnavigationcompactfloating { + background: #f2f2f2; + margin: 0; + padding: 1em 0; +} +.eventnavigationcompact_logo, +.eventnavigationcompactfloating_logo { + border: solid 2px #fff; + -webkit-box-shadow: 0 0 5px rgba(204,204,204,0.25); + box-shadow: 0 0 5px rgba(204,204,204,0.25); + margin-right: 0.666666666666667em; +} +.eventnavigationcompactfloating { + position: fixed; + top: -8em; + left: 0; + right: 0; + z-index: 5; +} +.eventnavigationcompactfloating.eventnavigationfixed { + top: 0; } .eventnavigation_link { text-transform: uppercase; @@ -188,30 +230,4 @@ .eventnavigation_linkactive:hover, .eventnavigation_linkactive:focus { background-color: #d89a00; -} -.eventnavigationnormal { - border-bottom: 1px solid #f2f2f2; -} -.eventnavigationcompact, -.eventnavigationcompactfloating { - background: #f2f2f2; - margin: 0; - padding: 0.9375em 0; -} -.eventnavigationcompact_logo, -.eventnavigationcompactfloating_logo { - border: solid 2px #fff; - -webkit-box-shadow: 0 0 5px rgba(204,204,204,0.25); - box-shadow: 0 0 5px rgba(204,204,204,0.25); - margin-right: 0.625em; -} -.eventnavigationcompactfloating { - position: fixed; - top: -5em; - left: 0; - right: 0; - z-index: 5; -} -.eventnavigationcompactfloating.eventnavigationfixed { - top: 0; -} +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.java index 8039adc309a..8a9e58dff39 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.java @@ -4,25 +4,30 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.ImageElement; import com.google.gwt.dom.client.SpanElement; +import com.google.gwt.dom.client.Style.Display; +import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil; +import com.sap.sailing.gwt.ui.shared.CourseAreaDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -public class EventHeader extends Composite { +public class EventHeader extends AbstractEventComposite { private static EventHeaderUiBinder uiBinder = GWT.create(EventHeaderUiBinder.class); interface EventHeaderUiBinder extends UiBinder { } - private final EventDTO event; - // @UiField Anchor overviewLink; @UiField Anchor regattasLink; // @UiField Anchor scheduleLink; @@ -37,34 +42,37 @@ public class EventHeader extends Composite { // @UiField Anchor regattasLink3; // @UiField Anchor scheduleLink3; // @UiField Anchor mediaLink3; - + @UiField Anchor officalWebsiteAnchor; + @UiField Anchor twitterAnchor; + @UiField Anchor facebookAnchor; + @UiField DivElement seriesLeaderboardDiv; + @UiField Anchor seriesLeaderboardAnchor; + @UiField DivElement eventHeaderWrapperDiv; - @UiField SpanElement eventName; - @UiField SpanElement eventName2; + @UiField DivElement regattaNameInSeriesDiv; + @UiField SpanElement eventNameSpan; + @UiField SpanElement eventName2Span; // @UiField SpanElement eventName3; - @UiField SpanElement eventDate; - @UiField SpanElement eventDescription; - @UiField SpanElement venueName; - @UiField SpanElement eventWebsite; + @UiField DivElement eventDateDiv; + @UiField DivElement eventDescriptionDiv; + @UiField SpanElement venueNameSpan; + @UiField DivElement isLiveDiv; + @UiField DivElement isFinishedDiv; @UiField ImageElement eventLogo; @UiField ImageElement eventLogo2; // @UiField ImageElement eventLogo3; - private final String defaultLogoUrl = "http://static.sapsailing.com/newhome/default_event_logo.png"; + private final String defaultLogoUrl = "http://static.sapsailing.com/ubilabsimages/default/default_event_logo.jpg"; // private final List links1; // private final List links2; // private final List links3; - - private final EventPageNavigator pageNavigator; public EventHeader(EventDTO event, EventPageNavigator pageNavigator) { - this.event = event; - this.pageNavigator = pageNavigator; + super(event, pageNavigator); - EventHeaderResources.INSTANCE.css().ensureInjected(); - initWidget(uiBinder.createAndBindUi(this)); + initResources(); // links1 = Arrays.asList(new Anchor[] { overviewLink, regattasLink, scheduleLink, mediaLink }); // links2 = Arrays.asList(new Anchor[] { overviewLink2, regattasLink2, scheduleLink2, mediaLink2 }); @@ -73,26 +81,118 @@ public class EventHeader extends Composite { // setActiveLink(links2, overviewLink2); // setActiveLink(links3, overviewLink3); + if(event.isRunning()) { + isFinishedDiv.getStyle().setDisplay(Display.NONE); + } else if (event.isFinished()) { + isLiveDiv.getStyle().setDisplay(Display.NONE); + } else { + isFinishedDiv.getStyle().setDisplay(Display.NONE); + isLiveDiv.getStyle().setDisplay(Display.NONE); + } + setDataNavigationType("normal"); updateUI(); } + + public EventHeader(EventDTO event) { + super(event, null); + + initResources(); + + isFinishedDiv.getStyle().setDisplay(Display.NONE); + isLiveDiv.getStyle().setDisplay(Display.NONE); + + setDataNavigationType("normal"); + updateUI(); + } + + public EventHeader(EventDTO event, PlaceNavigator placeNavigator) { + super(event, null); + + initResources(); + + isFinishedDiv.getStyle().setDisplay(Display.NONE); + isLiveDiv.getStyle().setDisplay(Display.NONE); + + setDataNavigationType("normal"); + updateUI(); + } + + private void initResources() { + EventHeaderResources.INSTANCE.css().ensureInjected(); + StyleInjector.injectAtEnd("@media (min-width: 50em) { "+EventHeaderResources.INSTANCE.largeCss().getText()+"}"); + + initWidget(uiBinder.createAndBindUi(this)); + } public void setDataNavigationType(String dataNavigationType) { eventHeaderWrapperDiv.setAttribute("data-navigationtype", dataNavigationType); } + + private StrippedLeaderboardDTO findLeaderboardWithSameCourseArea(EventDTO event) { + for(LeaderboardGroupDTO leaderboardGroup: event.getLeaderboardGroups()) { + for(StrippedLeaderboardDTO leaderboard: leaderboardGroup.getLeaderboards()) { + for(CourseAreaDTO courseArea: event.venue.getCourseAreas()) { + if(leaderboard.defaultCourseAreaId != null && leaderboard.defaultCourseAreaId.equals(courseArea.id)) { + return leaderboard; + } + } + } + } + return null; + } private void updateUI() { - eventName.setInnerHTML(event.getName()); - eventName2.setInnerHTML(event.getName()); + EventDTO event = getEvent(); + boolean isSeries = event.isFakeSeries(); + + String eventName = event.getName(); + if(isSeries) { + LeaderboardGroupDTO leaderboardGroupDTO = event.getLeaderboardGroups().get(0); + eventName = leaderboardGroupDTO.getDisplayName() != null ? leaderboardGroupDTO.getDisplayName() : leaderboardGroupDTO.getName(); + + StrippedLeaderboardDTO leaderboardFittingToEvent = findLeaderboardWithSameCourseArea(event); + if(leaderboardFittingToEvent != null) { + regattaNameInSeriesDiv.setInnerText(leaderboardFittingToEvent.displayName); + } else { + regattaNameInSeriesDiv.getStyle().setDisplay(Display.NONE); + } + } else { + seriesLeaderboardDiv.getStyle().setDisplay(Display.NONE); + regattaNameInSeriesDiv.getStyle().setDisplay(Display.NONE); + } + + eventNameSpan.setInnerHTML(eventName); + eventName2Span.setInnerHTML(eventName); // eventName3.setInnerHTML(event.getName()); - venueName.setInnerHTML(event.venue.getName()); - eventDate.setInnerHTML(EventDatesFormatterUtil.formatDateRangeWithYear(event.startDate, event.endDate)); + venueNameSpan.setInnerHTML(event.venue.getName()); + eventDateDiv.setInnerHTML(EventDatesFormatterUtil.formatDateRangeWithYear(event.startDate, event.endDate)); if(event.getDescription() != null) { - eventDescription.setInnerHTML(event.getDescription()); + eventDescriptionDiv.setInnerHTML(event.getDescription()); } if(event.getOfficialWebsiteURL() != null) { - eventWebsite.setInnerHTML(event.getOfficialWebsiteURL()); + String title = event.getOfficialWebsiteURL(); + if(title.startsWith("http://")) { + title = title.substring("http://".length(), title.length()); + } + if(title.length() > 35) { + title = TextMessages.INSTANCE.officalEventWebsite(); + } + officalWebsiteAnchor.setText(title); + officalWebsiteAnchor.setHref(event.getOfficialWebsiteURL()); + } else { + officalWebsiteAnchor.setVisible(false); + } + if(event.getTwitterURL() != null) { + twitterAnchor.setHref(event.getTwitterURL()); + } else { + twitterAnchor.setVisible(false); + } + if(event.getFacebookURL() != null) { + facebookAnchor.setHref(event.getFacebookURL()); + } else { + facebookAnchor.setVisible(false); } String logoUrl = event.getLogoImageURL() != null ? event.getLogoImageURL() : defaultLogoUrl; @@ -133,13 +233,20 @@ public class EventHeader extends Composite { showRegattas(); } + @UiHandler("seriesLeaderboardAnchor") + void seriesLeaderboardClicked(ClickEvent clickevent) { + if(getEvent().isFakeSeries()) { + getPageNavigator().openOverallLeaderboardViewer(getEvent().getLeaderboardGroups().get(0)); + } + } + // @UiHandler("regattasLink3") // void regattas3Clicked(ClickEvent event) { // showRegattas(); // } // private void showRegattas() { - pageNavigator.goToRegattas(); + getPageNavigator().goToRegattas(); // setActiveLink(links1, regattasLink); // setActiveLink(links2, regattasLink2); // setActiveLink(links3, regattasLink3); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.ui.xml index a3f9dab8703..f02e2b9342d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeader.ui.xml @@ -5,6 +5,23 @@ + + .action { + float: right; + text-align: center; + text-transform: uppercase; + cursor: pointer; + margin-top: 0.5em; + margin-bottom: 0.5em; + } + .action_link { + background-color: #008FCC; + color: white; + } + .action_link:hover { + background-color: #0177ab; + } + @@ -12,29 +29,45 @@
-
-

-
+
+
+

+
+
-
-
-
+
+
+
+ + +
+
-
+
-
+
+ + +
+
+
+ +
+
- + - + + +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderLarge.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderLarge.css new file mode 100644 index 00000000000..3b8bede771c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderLarge.css @@ -0,0 +1,42 @@ +.eventheader_intro_details_item:nth-child\(2\) { + border-right: 1px solid #ddd; +} +.eventheader_intro_details_item:last-child { + display: inline-block; +} +.dropdown {} +.dropdown_head {} +.dropdown_head_title {} +.dropdown_head_titlebutton {} +.dropdown_content {} +.dropdown_content_link {} +.dropdown_content_link_title {} +.dropdown_content_link_subtitle {} +.leaderboardquickaccess {} +.eventheaderwrapper {} +.eventheader {} +.eventheader_intro {} +.eventheader_intro_description {} +.eventheader_intro_logo {} +.eventheader_intro_logo_image {} +.eventheader_intro_name {} +.eventheader_intro_details {} +.eventheader_intro_details_item {} +.eventheader_intro_details_itemlink {} +.eventheader_sharing {} +.eventheader_sharing_item {} +.eventheader_sharing_itememail {} +.eventheader_sharing_itemtwitter {} +.eventheader_sharing_itemfacebook {} +.locationicon {} +.eventnavigation {} +.eventnavigationnormal {} +.eventnavigationcompact, +.eventnavigationcompactfloating {} +.eventnavigationcompact_logo, +.eventnavigationcompactfloating_logo {} +.eventnavigationcompactfloating {} +.eventnavigationcompactfloating.eventnavigationfixed {} +.eventnavigation_link {} +.eventnavigation_linkactive {} + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderResources.java index 26b03780885..a737137fa0c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/header/EventHeaderResources.java @@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.event.header; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.CssResource.Shared; public interface EventHeaderResources extends ClientBundle { public static final EventHeaderResources INSTANCE = GWT.create(EventHeaderResources.class); @@ -10,6 +11,13 @@ public interface EventHeaderResources extends ClientBundle { @Source("com/sap/sailing/gwt/home/client/place/event/header/EventHeader.css") LocalCss css(); + public interface MinWidth50emCss extends LocalCss { + } + + @Source("com/sap/sailing/gwt/home/client/place/event/header/EventHeaderLarge.css") + MinWidth50emCss largeCss(); + + @Shared public interface LocalCss extends CssResource { String dropdown(); String dropdown_head(); @@ -28,6 +36,7 @@ public interface EventHeaderResources extends ClientBundle { String eventheader_intro(); String eventheader_intro_description(); String eventheader_intro_logo(); + String eventheader_intro_logo_image(); String eventheader_intro_name(); String eventheader_intro_details(); String eventheader_intro_details_item(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/media/EventMedia.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/media/EventMedia.java index ade11aa8a5f..4f046441b8c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/media/EventMedia.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/media/EventMedia.java @@ -2,21 +2,19 @@ package com.sap.sailing.gwt.home.client.place.event.media; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; +import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.ui.shared.EventDTO; -public class EventMedia extends Composite { +public class EventMedia extends AbstractEventComposite { private static EventMediaUiBinder uiBinder = GWT.create(EventMediaUiBinder.class); interface EventMediaUiBinder extends UiBinder { } - @SuppressWarnings("unused") - private final EventDTO event; - - public EventMedia(EventDTO event) { - this.event = event; + public EventMedia(EventDTO event, EventPageNavigator placeNavigator) { + super(event, placeNavigator); EventMediaResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.css index c2ac3b6301c..e9deba83975 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.css @@ -381,7 +381,7 @@ background: #000; opacity: 0.4; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; - filter: alpha(opacity=40); + filter: literal("alpha(opacity=40)"); position: absolute; bottom: 0px; height: 5em; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.java index dcf1d2d48b0..4e5f644b9af 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/overview/EventOverview.java @@ -2,21 +2,19 @@ package com.sap.sailing.gwt.home.client.place.event.overview; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; +import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.ui.shared.EventDTO; -public class EventOverview extends Composite { +public class EventOverview extends AbstractEventComposite { private static EventOverviewUiBinder uiBinder = GWT.create(EventOverviewUiBinder.class); interface EventOverviewUiBinder extends UiBinder { } - @SuppressWarnings("unused") - private final EventDTO event; - - public EventOverview(EventDTO event) { - this.event = event; + public EventOverview(EventDTO event, EventPageNavigator pageNavigator) { + super(event, pageNavigator); EventOverviewResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.css index 914afb8559f..3be9d68d82a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.css @@ -85,11 +85,11 @@ padding-bottom: 0.666666666666667em; } .regatta_intro_phases_phase { - display: inline-block; + display: block; margin-right: 1.333333333333333em; padding: 0.133333333333333em 1.333333333333333em 0.133333333333333em 0; min-height: 2.666666666666667em; - border-right: 1px solid #ccc; + } .regatta_intro_phases_phase_name { font-size: 0.866666666666667em; @@ -102,6 +102,7 @@ background-color: #ccc; height: 0.666666666666667em; width: 1.333333333333333em; + margin-right: 3px; } .regatta_intro_phases_phase_races_race[data-status='live'] { background-color: #f00; @@ -110,16 +111,18 @@ background-color: #f0ab00; } .regatta_intro_phases_leaderboardlink { - font-size: 0.933333333333333em; - font-weight: 700; - border: 1px solid #ccc; - padding: 0.714285714285714em 0.928571428571429em; text-transform: uppercase; z-index: 2; position: absolute; top: 0; right: 0; + background-color: #008FCC; + color: white; } +.regatta_intro_phases_leaderboardlink:hover { + background-color: #0177ab; +} + .regatta_intro_scheduled { padding-top: 0.8em; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.java index 2a2302b7a28..68539c84c6b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.java @@ -1,20 +1,28 @@ package com.sap.sailing.gwt.home.client.place.event.regatta; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.HeadingElement; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.dom.client.Style.Visibility; -import com.google.gwt.dom.client.TableElement; -import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.uibinder.client.UiHandler; -import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.BoatClassImageResolver; +import com.sap.sailing.gwt.home.client.BoatClassImageResources; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; +import com.sap.sailing.gwt.home.client.shared.LongNamesUtil; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; @@ -28,116 +36,155 @@ public class Regatta extends Composite { interface RegattaUiBinder extends UiBinder { } - @SuppressWarnings("unused") private final EventDTO event; private final Timer timerForClientServerOffset; private final EventPageNavigator pageNavigator; + @SuppressWarnings("unused") + private final PlaceNavigator placeNavigator; private StrippedLeaderboardDTO leaderboard; private RaceGroupDTO raceGroup; - - @SuppressWarnings("unused") + private final List phasesElements; private LeaderboardGroupDTO leaderboardGroup; + private final boolean isSingleView; - @UiField SpanElement regattaName1; - @UiField SpanElement regattaName2; + @UiField DivElement regattaDiv; + @UiField HeadingElement regattaNameHeading; @UiField DivElement leaderboardGroupName; - @UiField SpanElement scheduledStart; + @UiField DivElement leaderboardGroupNameDiv; +// @UiField SpanElement scheduledStart; @UiField DivElement regattaPhasesPanel; + @UiField DivElement regattaPhasesInfoDiv; + @UiField SpanElement competitorsCount; + @UiField DivElement competitorsCountDiv; @UiField SpanElement racesCount; @UiField SpanElement trackedRacesCount; @UiField DivElement isLiveDiv; - @UiField TableElement isLiveDiv2; - @UiField DivElement isFinishedDiv; - @UiField DivElement isFinishedDiv2; - @UiField DivElement isScheduledDiv; - @UiField Anchor leaderboardLink; - @UiField HTMLPanel liveRaceInfosPerFleetPanel; - @UiField(provided=true) RegattaCompetitor competitorWithRank1; - @UiField(provided=true) RegattaCompetitor competitorWithRank2; - @UiField(provided=true) RegattaCompetitor competitorWithRank3; +// @UiField TableElement isLiveDiv2; +// @UiField DivElement isFinishedDiv; +// @UiField DivElement isFinishedDiv2; +// @UiField DivElement isScheduledDiv; +// @UiField AnchorElement leaderboardLink; +// @UiField DivElement liveRaceInfosPerFleetPanel; +// @UiField(provided=true) RegattaCompetitor competitorWithRank1; +// @UiField(provided=true) RegattaCompetitor competitorWithRank2; +// @UiField(provided=true) RegattaCompetitor competitorWithRank3; + + @UiField AnchorElement regattaDetailsLink; + @UiField AnchorElement leaderboardLink; - @UiField HTMLPanel regattaImage; - @UiField Anchor regattaImageWithLink; - - @UiField HTMLPanel regattaNameDiv; - @UiField Anchor regattaNameWithLink; - - public Regatta(EventDTO event, boolean isNavigatable, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) { + @UiField Image boatClassImage; + + public Regatta(EventDTO event, Timer timerForClientServerOffset, boolean isSingleView, PlaceNavigator placeNavigator, EventPageNavigator pageNavigator) { this.event = event; this.timerForClientServerOffset = timerForClientServerOffset; + this.isSingleView = isSingleView; + this.placeNavigator = placeNavigator; this.pageNavigator = pageNavigator; - competitorWithRank1 = new RegattaCompetitor(1, null); - competitorWithRank2 = new RegattaCompetitor(2, null); - competitorWithRank3 = new RegattaCompetitor(3, null); + phasesElements = new ArrayList(); + +// competitorWithRank1 = new RegattaCompetitor(1, null); +// competitorWithRank2 = new RegattaCompetitor(2, null); +// competitorWithRank3 = new RegattaCompetitor(3, null); RegattaResources.INSTANCE.css().ensureInjected(); - initWidget(uiBinder.createAndBindUi(this)); - - regattaImageWithLink.getElement().setAttribute("data-rendermode", "link"); - regattaImageWithLink.setVisible(isNavigatable); - regattaImage.setVisible(!isNavigatable); + StyleInjector.injectAtEnd("@media (min-width: 50em) { "+RegattaResources.INSTANCE.largeCss().getText()+"}"); - regattaNameWithLink.getElement().setAttribute("data-rendermode", "link"); - regattaNameWithLink.setVisible(isNavigatable); - regattaNameDiv.setVisible(!isNavigatable); + initWidget(uiBinder.createAndBindUi(this)); } - public void setData(RaceGroupDTO raceGroup, StrippedLeaderboardDTO leaderboard, LeaderboardGroupDTO leaderboardGroup) { + public void setData(LeaderboardGroupDTO leaderboardGroup, boolean hasMultipleLeaderboardGroups, StrippedLeaderboardDTO leaderboard, + RaceGroupDTO raceGroup) { this.raceGroup = raceGroup; this.leaderboard = leaderboard; this.leaderboardGroup = leaderboardGroup; - + + registerEvents(leaderboardGroup); + boolean hasLiveRace = leaderboard.hasLiveRace(timerForClientServerOffset.getLiveTimePointInMillis()); - isLiveDiv.setAttribute("data-labeltype", hasLiveRace ? "live" : ""); + if(!hasLiveRace) { + isLiveDiv.getStyle().setDisplay(Display.NONE); + } - boolean isFinished = !hasLiveRace; - if(!isFinished) { - isFinishedDiv.getStyle().setDisplay(Display.NONE); + // boolean isFinished... TODO + if(raceGroup.boatClass != null) { + boatClassImage.setResource(BoatClassImageResolver.getBoatClassIconResource(raceGroup.boatClass)); + } else { + boatClassImage.setResource(BoatClassImageResources.INSTANCE.genericBoatClass()); } String regattaDisplayName = leaderboard.displayName != null ? leaderboard.displayName : leaderboard.name; - regattaName1.setInnerText(regattaDisplayName); - regattaName2.setInnerText(regattaDisplayName); - if(raceGroup.leaderboardGroupName != null) { - leaderboardGroupName.setInnerText(raceGroup.leaderboardGroupName); + regattaNameHeading.setInnerText(regattaDisplayName); + if(hasMultipleLeaderboardGroups && leaderboardGroup.getName() != null) { + leaderboardGroupName.setInnerText(LongNamesUtil.shortenLeaderboardGroupName(event.getName(), leaderboardGroup.getName())); leaderboardGroupName.setAttribute("data-labeltype", "group1"); } else { - leaderboardGroupName.getStyle().setDisplay(Display.NONE); + leaderboardGroupNameDiv.getStyle().setDisplay(Display.NONE); } - if(leaderboard.rows != null) { - competitorsCount.setInnerText(String.valueOf(leaderboard.rows.size())); + if(leaderboard.competitorsCount > 0) { + competitorsCount.setInnerText(String.valueOf(leaderboard.competitorsCount)); } else { - competitorsCount.getStyle().setVisibility(Visibility.HIDDEN); + competitorsCountDiv.getStyle().setDisplay(Display.NONE); + } + setRegattaProgress(leaderboard); + } + + private void setRegattaProgress(StrippedLeaderboardDTO leaderboard) { + // clear first + regattaPhasesPanel.removeAllChildren(); + phasesElements.clear(); + + if(raceGroup != null) { + if(raceGroup.getSeries().size() == 0) { + regattaPhasesInfoDiv.getStyle().setDisplay(Display.NONE); + } else { + for(RaceGroupSeriesDTO series: raceGroup.getSeries()) { + RegattaPhase regattaPhase = new RegattaPhase(series, leaderboardGroup, + leaderboard, raceGroup, pageNavigator, timerForClientServerOffset); + regattaPhasesPanel.appendChild(regattaPhase.getElement()); + phasesElements.add(regattaPhase); + } + } } - racesCount.setInnerText("tbd"); - trackedRacesCount.setInnerText("tbd"); -// regattaPhasesPanel.add(xxx); - setRegattaProgress(); + racesCount.setInnerText(String.valueOf(leaderboard.getRacesCount())); + trackedRacesCount.setInnerText(String.valueOf(leaderboard.getTrackedRacesCount())); } - - private void setRegattaProgress() { - for(RaceGroupSeriesDTO series: raceGroup.getSeries()) { - RegattaPhase regattaPhase = new RegattaPhase(series); - regattaPhasesPanel.appendChild(regattaPhase.getElement()); + + private void registerEvents(final LeaderboardGroupDTO leaderboardGroup) { + if(isSingleView) { + regattaDetailsLink.getStyle().setDisplay(Display.NONE); + + Event.sinkEvents(leaderboardLink, Event.ONCLICK); + Event.setEventListener(leaderboardLink, new EventListener() { + @Override + public void onBrowserEvent(Event browserEvent) { + switch (DOM.eventGetType(browserEvent)) { + case Event.ONCLICK: + pageNavigator.openLeaderboardViewer(leaderboardGroup, leaderboard); + + // the new leaderboard view integrated into the new design + //placeNavigator.goToLeaderboard(event.id.toString(), leaderboard.name, event.getBaseURL(), event.isOnRemoteServer()); + break; + } + } + }); + } else { + leaderboardLink.getStyle().setDisplay(Display.NONE); + + Event.sinkEvents(regattaDetailsLink, Event.ONCLICK); + Event.setEventListener(regattaDetailsLink, new EventListener() { + @Override + public void onBrowserEvent(Event browserEvent) { + switch (DOM.eventGetType(browserEvent)) { + case Event.ONCLICK: + pageNavigator.goToRegattaRaces(leaderboardGroup, leaderboard, raceGroup); + break; + } + } + }); } } - - @UiHandler("leaderboardLink") - public void goToLeaderboard(ClickEvent e) { - pageNavigator.openLeaderboardViewer(null, leaderboard); - } - - @UiHandler("regattaImageWithLink") - public void goToRegattaRaces(ClickEvent e) { - pageNavigator.goToRegattaRaces(raceGroup, leaderboard); - } - - @UiHandler("regattaNameWithLink") - public void goToRegattaRaces2(ClickEvent e) { - pageNavigator.goToRegattaRaces(raceGroup, leaderboard); - } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.ui.xml index c991e11dabe..796f9e94b52 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.ui.xml @@ -6,48 +6,41 @@ - -
+
- - - - - - +
+ +
- -

-
- -

-
+

+
-
 
+
 
 
 
-
+
-
+
-
- -
+ +
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaLarge.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaLarge.css new file mode 100644 index 00000000000..72dd98d48f4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaLarge.css @@ -0,0 +1,33 @@ +.regatta_intro_phases_phase { + display: inline-block; + border-right: 1px solid #ccc; +} +.regatta {} +.regatta_intro {} +.regatta_intro_image {} +.regatta_intro_header {} +.regatta_intro_header_name {} +.regatta_intro_header_namelink:hover, +.regatta_intro_header_namelink:focus {} +.regatta_intro_header_details {} +.regatta_intro_header_details_item {} +.regatta_intro_header_details_item_value {} +.regatta_intro_header_details_label {} +.regatta_intro_phases {} +.regatta_intro_phases_phase_name {} +.regatta_intro_phases_phase_races {} +.regatta_intro_phases_phase_races_race {} +.regatta_intro_phases_leaderboardlink {} +.regatta_intro_scheduled {} +.regatta_intro_results {} +.regatta_intro_results_competitor {} +.regatta_intro_results_competitor_name {} +.regatta_intro_fleets {} +.regatta_intro_fleets_fleet {} +.regatta_intro_fleets_fleet:last-child {} +.regatta_intro_fleets_fleet_item {} +.regatta_intro_fleets_fleet_itemfirst {} +.regatta_intro_fleets_fleet_item_value {} +.regatta_intro_fleets_fleet_item_flag {} +.regatta_intro_fleets_fleet_live {} +.regatta_intro_details_itemhideoncompact {} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.java index f2259db96b1..0d75a10f947 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.java @@ -1,12 +1,23 @@ package com.sap.sailing.gwt.home.client.place.event.regatta; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.domain.common.LeaderboardNameConstants; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sse.gwt.client.player.Timer; public class RegattaPhase extends UIObject { private static RegattaPhaseUiBinder uiBinder = GWT.create(RegattaPhaseUiBinder.class); @@ -15,17 +26,46 @@ public class RegattaPhase extends UIObject { } @UiField SpanElement phaseName; - @UiField DivElement phaseRacesPanel; + @UiField DivElement phaseRacesDiv; + @UiField AnchorElement phaseRacesAnchor; - public RegattaPhase(RaceGroupSeriesDTO series) { + public RegattaPhase(RaceGroupSeriesDTO series, final LeaderboardGroupDTO leaderboardGroup, + final StrippedLeaderboardDTO leaderboard, final RaceGroupDTO raceGroup, final EventPageNavigator pageNavigator, Timer timerForClientServerOffset) { + RegattaResources.INSTANCE.css().ensureInjected(); + setElement(uiBinder.createAndBindUi(this)); + + if(LeaderboardNameConstants.DEFAULT_SERIES_NAME.equals(series.getName())) { + phaseName.setInnerText("Races"); + } else { + phaseName.setInnerText(series.getName()); + } + + for(RaceColumnDTO raceColumn: series.getRaceColumns()) { + // the raceColumn from the RaceGroupSeriesDTO does not contain all required information for the race state. + // therefore we take it from the LeaderboardDTO + // TODO: try to have only one RaceColumnDTO + RaceColumnDTO raceColumn2 = leaderboard.getRaceColumnByName(raceColumn.getName()); + RegattaPhaseRace race = new RegattaPhaseRace(raceColumn2, timerForClientServerOffset); + phaseRacesDiv.appendChild(race.getElement()); + + Event.sinkEvents(phaseRacesAnchor, Event.ONCLICK); + Event.setEventListener(phaseRacesAnchor, new EventListener() { + @Override + public void onBrowserEvent(Event browserEvent) { + switch (DOM.eventGetType(browserEvent)) { + case Event.ONCLICK: + pageNavigator.goToRegattaRaces(leaderboardGroup, leaderboard, raceGroup); + break; + } + } + }); + } + } + + public RegattaPhase() { RegattaResources.INSTANCE.css().ensureInjected(); setElement(uiBinder.createAndBindUi(this)); - phaseName.setInnerText(series.getName()); - - for(int i = 0; i < 5; i++) { - RegattaPhaseRace race = new RegattaPhaseRace(); - phaseRacesPanel.appendChild(race.getElement()); - } + phaseName.setInnerText("No series defined yet."); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.ui.xml index 5378ec65da4..67224964e3d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhase.ui.xml @@ -6,7 +6,9 @@
-
-
+
+ + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhaseRace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhaseRace.java index 771ffee0f25..c0ba7b96fdc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhaseRace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaPhaseRace.java @@ -5,6 +5,8 @@ import com.google.gwt.dom.client.DivElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sse.gwt.client.player.Timer; public class RegattaPhaseRace extends UIObject { private static RegattaPhaseRaceUiBinder uiBinder = GWT.create(RegattaPhaseRaceUiBinder.class); @@ -13,11 +15,30 @@ public class RegattaPhaseRace extends UIObject { } @UiField DivElement raceStatus; - - public RegattaPhaseRace() { + + private enum DataStatusEnum { + FINISHED ("finished"), LIVE("live"), SCHEDULED("scheduled"); + + private final String attributeValue; + private static final String ATTRIBUTE_NAME = "data-status"; + + DataStatusEnum(String attributeValue) { + this.attributeValue = attributeValue; + } + } + + public RegattaPhaseRace(RaceColumnDTO raceColumn, Timer timerForClientServerOffset) { RegattaResources.INSTANCE.css().ensureInjected(); setElement(uiBinder.createAndBindUi(this)); - - raceStatus.setAttribute("data-status", "raceStatus"); + + DataStatusEnum dataStatus; + if(raceColumn.hasLiveRaces(timerForClientServerOffset.getLiveTimePointInMillis())) { + dataStatus = DataStatusEnum.LIVE; + } else if (raceColumn.hasTrackedRaces()) { + dataStatus = DataStatusEnum.FINISHED; + } else { + dataStatus = DataStatusEnum.SCHEDULED; + } + raceStatus.setAttribute(DataStatusEnum.ATTRIBUTE_NAME, dataStatus.attributeValue); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaResources.java index 72e848dd155..d976e611cf2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regatta/RegattaResources.java @@ -3,13 +3,20 @@ package com.sap.sailing.gwt.home.client.place.event.regatta; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.CssResource.Shared; public interface RegattaResources extends ClientBundle { public static final RegattaResources INSTANCE = GWT.create(RegattaResources.class); @Source("com/sap/sailing/gwt/home/client/place/event/regatta/Regatta.css") LocalCss css(); + public interface MinWidth50emCss extends LocalCss { + } + @Source("com/sap/sailing/gwt/home/client/place/event/regatta/RegattaLarge.css") + MinWidth50emCss largeCss(); + + @Shared public interface LocalCss extends CssResource { String regatta(); String regatta_intro_details_itemhideoncompact(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css new file mode 100644 index 00000000000..8d8535fded2 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css @@ -0,0 +1,181 @@ +.leaderboardcompetitor { + line-height: 1.75; + padding: 0.466666666666667em 0; + border-bottom: 1px solid #ddd; +} +.leaderboardcompetitorshort[datarank='3'] { + border-bottom: 0; +} +.leaderboardcompetitor[datarank='1'] .leaderboardcompetitor_rank, +.leaderboardcompetitor[datarank='2'] .leaderboardcompetitor_rank, +.leaderboardcompetitor[datarank='3'] .leaderboardcompetitor_rank { + display: inline-block; + border-radius: 50%; + color: #fff; + font-weight: 700; + line-height: 2em; + height: 2em; + width: 2em; + padding: 0; +} +.leaderboardcompetitor[datarank='1'] .leaderboardcompetitor_rank { + background: #de8a2e; +} +.leaderboardcompetitor[datarank='2'] .leaderboardcompetitor_rank { + background: #c0c0c0; +} +.leaderboardcompetitor[datarank='3'] .leaderboardcompetitor_rank { + background: #8c7953; +} +.leaderboardcompetitor_image { + vertical-align: middle; +} +.leaderboardcompetitor_nationality { + vertical-align: middle; + margin-right: 0.8em; +} +.leaderboardcompetitor_itemcenter { + text-align: center; +} +.eventregattaleaderboard_table { + padding: 0 1rem; +} +.eventregattaleaderboard { + font-size: 15px; + font-size: 1rem; + width: 100%; +} +.eventregattaleaderboard_meta { + margin: 2.333333333333333em auto; +} +.eventregattaleaderboard_meta_title { + margin-bottom: 0; +} +.eventregattaleaderboard_meta_update { + font-weight: 600; + color: #999; +} +.eventregattaleaderboard_meta_button { + float: right; + margin-top: 1em; +} +.eventregattaleaderboard_meta_reload { + float: right; + width: 39px; + height: 39px; + margin: 0 0 10px 0; + background-color: #f0ab00; + background-image: url("images/home/reload.png"); + background-repeat: no-repeat; + background-position: center center; +} +.eventregattaleaderboard_meta_reload:hover { + background-color: #d89a00; +} +.eventregattaleaderboard_meta_settings { + float: right; + width: 39px; + height: 39px; + margin: 0 0 10px 0; + background-color: #f0ab00; + background-image: url("images/home/settings.png"); + background-repeat: no-repeat; + background-position: center center; +} +.eventregattaleaderboard_meta_settings:hover { + background-color: #d89a00; +} + +.eventregattaleaderboard_header { + background: #f2f2f2; + color: #008fcc; + text-transform: uppercase; + font-weight: 600; + padding: 2.333333333333333em 0; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} +.eventregattaleaderboard_header_item { + margin: 0; + padding: 2.333333333333333em 0 2.333333333333333em 1.666666666666667em; + font-weight: 600; +} +.eventregattaleaderboard_header_itemrank { + min-width: 12rem; + text-align: center; +} +.eventregattaleaderboard_header_itemcompetitor { + min-width: 16rem; +} +.eventregattaleaderboard_header_itemname { + min-width: 16rem; +} +.eventregattaleaderboard_header_itemdata { + min-width: 24rem; +} +.eventregattaleaderboard_header_itemdata_element, +.eventregattaleaderboard_header_itemdata_elementascending, +.eventregattaleaderboard_header_itemdata_elementdescending { + width: 50px; + text-align: right; +} +.eventregattaleaderboard_header_itempoints { + min-width: 12rem; + text-align: center; +} +.eventregattaleaderboard_header_item_name, +.eventregattaleaderboard_header_itemdata_element_name { + display: inline-block; +} +.eventregattaleaderboard_header_itemdescending:before, +.eventregattaleaderboard_header_itemdata_elementdescending:before { + content: ''; + display: inline-block; + width: 12px; + height: 12px; + line-height: 20px; + margin-right: 5px; + background-repeat: no-repeat; + background-position: center center; + background-image: url("images/home/arrow-down-yellow.png"); +} +.eventregattaleaderboard_header_itemascending:before, +.eventregattaleaderboard_header_itemdata_elementascending:before { + content: ''; + display: inline-block; + width: 12px; + height: 12px; + line-height: 20px; + margin-right: 5px; + background-repeat: no-repeat; + background-position: center center; + background-image: url("images/home/arrow-up-yellow.png"); +} +.eventregattaleaderboard_header_table { + width: 100%; + table-layout: fixed; +} +.eventregattaleaderboard_body { + width: 100%; + max-width: 100%; +} +.eventregattaleaderboard_data_element { + width: 50px; + text-align: right; +} +.leaderboardcompetitor:last-child { + border: 0; +} +.leaderboardcompetitor_item, +.leaderboardcompetitor_itemcenter { + padding-left: 1.666666666666667em; +} +.leaderboardcompetitor_itemcenter, +.leaderboardcompetitor_itemcentercenter { + text-align: center; +} +.leaderboardcompetitor_item_table, +.leaderboardcompetitor_itemcenter_table { + width: 100%; + table-layout: fixed; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.ui.xml new file mode 100644 index 00000000000..d58c6aade51 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.ui.xml @@ -0,0 +1,36 @@ + + + + + + + + +
+
+

{leaderboard.scoringComment}{#if navigation.isFinished}{/if navigation.isFinished} +

+
:   {leaderboard.lastScoringUpdate}
+
+
+
+
+ + + + + + + + {#each competitor in leaderboard.competitors}{/each leaderboard.competitors} +
+ + {#each columnName in leaderboard.columnNames}{/each leaderboard.columnNames} + +
+
+
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboardResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboardResources.java new file mode 100644 index 00000000000..8284bec3b8a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboardResources.java @@ -0,0 +1,50 @@ +package com.sap.sailing.gwt.home.client.place.event.regattaleaderboard; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; + +public interface EventRegattaLeaderboardResources extends ClientBundle { + public static final EventRegattaLeaderboardResources INSTANCE = GWT.create(EventRegattaLeaderboardResources.class); + + @Source("com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/EventRegattaLeaderboard.css") + LocalCss css(); + + public interface LocalCss extends CssResource { + String leaderboardcompetitor(); + String leaderboardcompetitor_rank(); + String leaderboardcompetitor_image(); + String leaderboardcompetitor_nationality(); + String leaderboardcompetitor_itemcenter(); + String eventregattaleaderboard_table(); + String eventregattaleaderboard(); + String eventregattaleaderboard_meta(); + String eventregattaleaderboard_meta_title(); + String eventregattaleaderboard_meta_update(); + String eventregattaleaderboard_meta_button(); + String eventregattaleaderboard_meta_reload(); + String eventregattaleaderboard_meta_settings(); + String eventregattaleaderboard_header(); + String eventregattaleaderboard_header_item(); + String eventregattaleaderboard_header_itemrank(); + String eventregattaleaderboard_header_itemcompetitor(); + String eventregattaleaderboard_header_itemname(); + String eventregattaleaderboard_header_itemdata(); + String eventregattaleaderboard_header_itemdata_element(); + String eventregattaleaderboard_header_itemdata_elementascending(); + String eventregattaleaderboard_header_itemdata_elementdescending(); + String eventregattaleaderboard_header_itempoints(); + String eventregattaleaderboard_header_item_name(); + String eventregattaleaderboard_header_itemdata_element_name(); + String eventregattaleaderboard_header_itemdescending(); + String eventregattaleaderboard_header_itemascending(); + String eventregattaleaderboard_header_table(); + String eventregattaleaderboard_body(); + String eventregattaleaderboard_data_element(); + String leaderboardcompetitor_item(); + String leaderboardcompetitor_itemcentercenter(); + String leaderboardcompetitor_item_table(); + String leaderboardcompetitor_itemcenter_table(); + String leaderboardcompetitorshort(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitor.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitor.ui.xml new file mode 100644 index 00000000000..06c5d72a78e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitor.ui.xml @@ -0,0 +1,23 @@ + + + + + + + + + {competitor.rank} + {competitor.nationality}{competitor.sailID} + {competitor.name} + + + {#each raceScore in competitor.raceScores}{/each competitor.raceScores} + +
+ + {competitor.totalPoints} + +
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitorRaceScore.ui.xml similarity index 60% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.ui.xml rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitorRaceScore.ui.xml index f9772e70697..80f39316687 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardCompetitorRaceScore.ui.xml @@ -4,5 +4,9 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"> - + + + +{raceScore.totalPoints} + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/recentevent/RecentEvents.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardHeaderColumn.ui.xml similarity index 52% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/recentevent/RecentEvents.ui.xml rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardHeaderColumn.ui.xml index e56e5b3d333..07d1962a879 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/recentevent/RecentEvents.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaleaderboard/RegattaLeaderboardHeaderColumn.ui.xml @@ -4,17 +4,9 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"> - + -
-
- -

- - - - -

-
+ +{columnName}
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.java index 9f45168686f..4109c098c99 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.java @@ -1,51 +1,138 @@ package com.sap.sailing.gwt.home.client.place.event.regattalist; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.SpanElement; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.HomeResources; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.home.client.place.event.regatta.Regatta; +import com.sap.sailing.gwt.home.client.shared.LongNamesUtil; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; import com.sap.sse.gwt.client.player.Timer; -public class EventRegattaList extends Composite { +public class EventRegattaList extends AbstractEventComposite { private static EventRegattaHeaderUiBinder uiBinder = GWT.create(EventRegattaHeaderUiBinder.class); interface EventRegattaHeaderUiBinder extends UiBinder { } +// @UiField DivElement seriesLeaderboardDiv; +// @UiField AnchorElement seriesLeaderboardAnchor; + @UiField DivElement regattaGroupsNavigationPanel; - @UiField DivElement regattaListNavgiationDiv; - @UiField HTMLPanel regattaListItemPanel; - @UiField AnchorElement allRegattasLink; - - public EventRegattaList(EventDTO event, List raceGroups, - Map> leaderboardsWithLeaderboardGroup, - Timer timerForClientServerOffset, EventPageNavigator pageNavigator) { + @UiField DivElement regattaListNavigationDiv; + @UiField DivElement regattaListItemsDiv; + @UiField AnchorElement filterNoLeaderboardGroupsAnchor; + @UiField SpanElement allBoatClassesSelected; + + private final Map> regattaElementsByLeaderboardGroup; + + public EventRegattaList(EventDTO event, Map> regattaStructure, + Timer timerForClientServerOffset, PlaceNavigator placeNavigator, EventPageNavigator pageNavigator) { + super(event, pageNavigator); + EventRegattaListResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); - regattaListNavgiationDiv.getStyle().setDisplay(Display.NONE); + regattaElementsByLeaderboardGroup = new HashMap<>(); + + boolean isSeries = event.isFakeSeries(); + boolean hasMultipleLeaderboardGroups = event.getLeaderboardGroups().size() > 1; - for (RaceGroupDTO raceGroup: raceGroups) { - Regatta regatta = new Regatta(event, true, timerForClientServerOffset, pageNavigator); - Pair leaderboardWithLeaderboardGroup = leaderboardsWithLeaderboardGroup.get(raceGroup.getName()); - regatta.setData(raceGroup, leaderboardWithLeaderboardGroup != null ? leaderboardWithLeaderboardGroup.getA() : null, - leaderboardWithLeaderboardGroup != null ? leaderboardWithLeaderboardGroup.getB() : null); - regattaListItemPanel.add(regatta); + if(isSeries) { + regattaListNavigationDiv.getStyle().setDisplay(Display.NONE); + } else { + if(hasMultipleLeaderboardGroups) { + // fill the navigation panel + registerFilterLeaderboardGroupEvent(filterNoLeaderboardGroupsAnchor, null); + for(LeaderboardGroupDTO leaderboardGroup: event.getLeaderboardGroups()) { + AnchorElement filterLeaderboardGroupAnchor = Document.get().createAnchorElement(); + filterLeaderboardGroupAnchor.setClassName(HomeResources.INSTANCE.mainCss().navbar_button()); + filterLeaderboardGroupAnchor.setHref("javascript:;"); + + String leaderboardGroupName = LongNamesUtil.shortenLeaderboardGroupName(event.getName(), leaderboardGroup.getName()); + filterLeaderboardGroupAnchor.setInnerText(leaderboardGroupName); + regattaGroupsNavigationPanel.appendChild(filterLeaderboardGroupAnchor); + + registerFilterLeaderboardGroupEvent(filterLeaderboardGroupAnchor, leaderboardGroup); + } + } else { + regattaListNavigationDiv.getStyle().setDisplay(Display.NONE); + } + } + + for (LeaderboardGroupDTO leaderboardGroup : event.getLeaderboardGroups()) { + for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.getLeaderboards()) { + Triple r = regattaStructure.get(leaderboard.name); + if (r != null) { + Regatta regatta = new Regatta(event, timerForClientServerOffset, false, placeNavigator, pageNavigator); + regatta.setData(r.getC(), hasMultipleLeaderboardGroups, r.getB(), r.getA()); + regattaListItemsDiv.appendChild(regatta.getElement()); + List regattaElements = regattaElementsByLeaderboardGroup.get(leaderboardGroup.getName()); + if (regattaElements == null) { + regattaElements = new ArrayList(); + regattaElementsByLeaderboardGroup.put(leaderboardGroup.getName(), regattaElements); + } + regattaElements.add(regatta); + } + } + } + } + + private void registerFilterLeaderboardGroupEvent(AnchorElement filterLeaderboardGroupAnchor, final LeaderboardGroupDTO leaderboardGroup) { + Event.sinkEvents(filterLeaderboardGroupAnchor, Event.ONCLICK); + Event.setEventListener(filterLeaderboardGroupAnchor, new EventListener() { + @Override + public void onBrowserEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONCLICK: + filterRegattaListByLeaderboardGroup(leaderboardGroup); + break; + } + } + }); + } + + private void filterRegattaListByLeaderboardGroup(LeaderboardGroupDTO leaderboardGroup) { + if (leaderboardGroup != null) { + allBoatClassesSelected.getStyle().setDisplay(Display.NONE); + // hide all regattas of the not selected leaderboardgroup + for (LeaderboardGroupDTO lg : getEvent().getLeaderboardGroups()) { + boolean isVisible = leaderboardGroup.getName().equals(lg.getName()); + List regattaElements = regattaElementsByLeaderboardGroup.get(lg.getName()); + for (Regatta regatta : regattaElements) { + regatta.setVisible(isVisible); + } + } + } else { + // make all regattas visible + allBoatClassesSelected.getStyle().setDisplay(Display.INLINE_BLOCK); + for (LeaderboardGroupDTO lg : getEvent().getLeaderboardGroups()) { + List regattaElements = regattaElementsByLeaderboardGroup.get(lg.getName()); + for (Regatta regatta : regattaElements) { + regatta.setVisible(true); + } + } } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.ui.xml index ba3fb0f4f79..64a280b6c3d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaList.ui.xml @@ -8,15 +8,14 @@
-
+
-
- -
+
+ ✓ 
- +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.java deleted file mode 100644 index aa4ab30ca37..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattalist/EventRegattaListNavigationButton.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sap.sailing.gwt.home.client.place.event.regattalist; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.dom.client.AnchorElement; -import com.google.gwt.dom.client.DivElement; -import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.UIObject; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; - -public class EventRegattaListNavigationButton extends UIObject { - private static EventRegattaListNavigationButtonUiBinder uiBinder = GWT.create(EventRegattaListNavigationButtonUiBinder.class); - - interface EventRegattaListNavigationButtonUiBinder extends UiBinder { - } - - @UiField AnchorElement regattaGroupLink; - - public EventRegattaListNavigationButton(LeaderboardGroup leaderboardGroup) { - EventRegattaListResources.INSTANCE.css().ensureInjected(); - - setElement(uiBinder.createAndBindUi(this)); - - regattaGroupLink.setInnerText(leaderboardGroup.getName()); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.css index a1eaad80e4d..cfd3dddf088 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.css @@ -69,7 +69,7 @@ .eventregattaraces_legend_item:before { content: ' '; position: absolute; - top: -0.2em; + top: literal("-0.2em"); left: 0.666666666666667em; width: 1.733333333333333em; height: 1.733333333333333em; @@ -130,7 +130,7 @@ display: block; float: none; margin-right: 0.555555555555556em; - margin-top: -0.194444444444444em; + margin-top: literal("-0.194444444444444em"); font-size: 2.4em; color: #ccc; font-weight: 700; @@ -229,17 +229,26 @@ .eventregattarace_featuregps { background-position: 0 0; } +.eventregattarace_featuregps.eventregattarace_featureunavailable { + background-position: 0 100%; +} .eventregattarace_featurewind { background-position: 33% 0; } +.eventregattarace_featurewind.eventregattarace_featureunavailable { + background-position: 33% 100%; +} .eventregattarace_featurevideo { background-position: 66% 0; } +.eventregattarace_featurevideo.eventregattarace_featureunavailable { + background-position: 66% 100%; +} .eventregattarace_featureaudio { background-position: 100% 0; } -.eventregattarace_featureunavailable { - background-position-y: 100%; +.eventregattarace_featureaudio.eventregattarace_featureunavailable { + background-position: 100% 100%; } .regattanavigation { font-size: 15px; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.java index 554a1ab883b..fd6dd47e5b4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.java @@ -1,20 +1,26 @@ package com.sap.sailing.gwt.home.client.place.event.regattaraces; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.home.client.place.event.regatta.Regatta; import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.gwt.client.player.Timer; -public class EventRegattaRaces extends Composite { +public class EventRegattaRaces extends AbstractEventComposite { private static EventRegattaRacesUiBinder uiBinder = GWT.create(EventRegattaRacesUiBinder.class); interface EventRegattaRacesUiBinder extends UiBinder { @@ -22,36 +28,44 @@ public class EventRegattaRaces extends Composite { @UiField(provided=true) Regatta regatta; @UiField HTMLPanel regattaPhasesNavigationPanel; - @UiField HTMLPanel regattaPhasesPanel; - - @SuppressWarnings("unused") - private final EventDTO event; + @UiField HTMLPanel regattaPhasesPanel; + @UiField HTMLPanel rootPanel; private final Timer timerForClientServerOffset; - private final EventPageNavigator pageNavigator; + private final List phaseElements; - public EventRegattaRaces(EventDTO event, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) { - this.event = event; + public EventRegattaRaces(EventDTO event, Timer timerForClientServerOffset, PlaceNavigator placeNavigator, EventPageNavigator pageNavigator) { + super(event, pageNavigator); this.timerForClientServerOffset = timerForClientServerOffset; - this.pageNavigator = pageNavigator; - regatta = new Regatta(event, false, timerForClientServerOffset, pageNavigator); + phaseElements = new ArrayList(); + + regatta = new Regatta(event, timerForClientServerOffset, true, placeNavigator, pageNavigator); EventRegattaRacesResources.INSTANCE.css().ensureInjected(); + StyleInjector.injectAtEnd("@media (min-width: 25em) { "+EventRegattaRacesResources.INSTANCE.mediumCss().getText()+"}"); initWidget(uiBinder.createAndBindUi(this)); } - public void setRacesFromRaceGroup(RaceGroupDTO raceGroup, StrippedLeaderboardDTO leaderboard) { - regatta.setData(raceGroup, leaderboard, null); + public void setRaces(LeaderboardGroupDTO leaderboardGroup, boolean hasMultipleLeaderboardGroups, StrippedLeaderboardDTO leaderboard, RaceGroupDTO raceGroup) { + // clear all existing child elements first + regattaPhasesPanel.getElement().removeAllChildren(); + phaseElements.clear(); + + regatta.setData(leaderboardGroup, hasMultipleLeaderboardGroups, leaderboard, raceGroup); int regattaPhases = raceGroup.getSeries().size(); if(regattaPhases > 1) { for(RaceGroupSeriesDTO series: raceGroup.getSeries()) { - EventRegattaRacesPhase regattaPhase = new EventRegattaRacesPhase(leaderboard, series, timerForClientServerOffset, pageNavigator); + EventRegattaRacesPhase regattaPhase = new EventRegattaRacesPhase(leaderboard, series, timerForClientServerOffset, getPageNavigator()); regattaPhasesPanel.getElement().appendChild(regattaPhase.getElement()); + phaseElements.add(regattaPhase); } } else { - + RaceGroupSeriesDTO raceGroupSeriesDTO = raceGroup.getSeries().get(0); + EventRegattaRacesPhase regattaPhase = new EventRegattaRacesPhase(leaderboard, raceGroupSeriesDTO, timerForClientServerOffset, getPageNavigator()); + regattaPhasesPanel.getElement().appendChild(regattaPhase.getElement()); + phaseElements.add(regattaPhase); } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.ui.xml index e25fd50f512..2a2bd48b6c3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.ui.xml @@ -5,7 +5,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleet.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleet.java index 8c74a36ca30..fb7091b32d7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleet.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleet.java @@ -2,13 +2,13 @@ package com.sap.sailing.gwt.home.client.place.event.regattaraces; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.UIObject; import com.sap.sailing.domain.common.dto.FleetDTO; -public class EventRegattaRacesFleet { +public class EventRegattaRacesFleet extends UIObject { private static EventRegattaRacesFleetUiBinder uiBinder = GWT.create(EventRegattaRacesFleetUiBinder.class); interface EventRegattaRacesFleetUiBinder extends UiBinder { @@ -16,21 +16,17 @@ public class EventRegattaRacesFleet { @UiField SpanElement fleetName; @UiField DivElement fleetCountAndColor; - - private DivElement root; - public EventRegattaRacesFleet(FleetDTO fleet) { + public EventRegattaRacesFleet(FleetDTO fleet, int maxNumberOfCompetitorsInFleetRace) { EventRegattaRacesResources.INSTANCE.css().ensureInjected(); - root = uiBinder.createAndBindUi(this); + setElement(uiBinder.createAndBindUi(this)); fleetName.setInnerText(fleet.getName()); if(fleet.getColor() != null) { fleetCountAndColor.getStyle().setBackgroundColor(fleet.getColor().getAsHtml()); } - fleetCountAndColor.setInnerText("tbd."); - } - - public Element getElement() { - return root; + if(maxNumberOfCompetitorsInFleetRace > 0) { + fleetCountAndColor.setInnerText(String.valueOf(maxNumberOfCompetitorsInFleetRace)); + } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.java index e91d069f878..046bf2e3256 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.home.client.place.event.regattaraces; import java.util.ArrayList; +import java.util.Date; import java.util.List; import com.google.gwt.core.client.GWT; @@ -13,6 +14,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; +import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil; import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.gwt.client.player.Timer; @@ -24,6 +26,7 @@ public class EventRegattaRacesFleetGroup extends Composite { } @UiField DivElement fleetsPanel; + @UiField DivElement racesFromToDate; @UiField DivElement racesFleetPanel; public EventRegattaRacesFleetGroup(StrippedLeaderboardDTO leaderboard, RaceGroupSeriesDTO series, List fleetsToShow, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) { @@ -31,15 +34,10 @@ public class EventRegattaRacesFleetGroup extends Composite { initWidget(uiBinder.createAndBindUi(this)); for(FleetDTO fleet: fleetsToShow) { - EventRegattaRacesFleet eventRegattaRacesFleet = new EventRegattaRacesFleet(fleet); + EventRegattaRacesFleet eventRegattaRacesFleet = new EventRegattaRacesFleet(fleet, 0); fleetsPanel.appendChild(eventRegattaRacesFleet.getElement()); - - List racesOfFleet = getRacesOfFleet(leaderboard, series, fleet); - for(RaceColumnDTO raceColumn: racesOfFleet) { - RaceColumnDTO raceColumnFromLeaderboard = leaderboard.getRaceColumnByName(raceColumn.getName()); - EventRegattaRacesRace race = new EventRegattaRacesRace(leaderboard, fleet, raceColumnFromLeaderboard, timerForClientServerOffset, pageNavigator); - racesFleetPanel.appendChild(race.getElement()); - } + + updateFleetRacesUI(leaderboard, series, fleet, timerForClientServerOffset, pageNavigator); } } @@ -48,13 +46,36 @@ public class EventRegattaRacesFleetGroup extends Composite { initWidget(uiBinder.createAndBindUi(this)); fleetsPanel.getStyle().setDisplay(Display.NONE); - + FleetDTO defaultFleet = series.getFleets().get(0); - List racesOfFleet = getRacesOfFleet(leaderboard, series, defaultFleet); + updateFleetRacesUI(leaderboard, series, defaultFleet, timerForClientServerOffset, pageNavigator); + } + + private void updateFleetRacesUI(StrippedLeaderboardDTO leaderboard, RaceGroupSeriesDTO series, FleetDTO fleet, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) { + Date fromDate = null; + Date toDate = null; + + List racesOfFleet = getRacesOfFleet(leaderboard, series, fleet); for(RaceColumnDTO raceColumn: racesOfFleet) { RaceColumnDTO raceColumnFromLeaderboard = leaderboard.getRaceColumnByName(raceColumn.getName()); - EventRegattaRacesRace race = new EventRegattaRacesRace(leaderboard, defaultFleet, raceColumnFromLeaderboard, timerForClientServerOffset, pageNavigator); + EventRegattaRacesRace race = new EventRegattaRacesRace(leaderboard, fleet, raceColumnFromLeaderboard, timerForClientServerOffset, pageNavigator); racesFleetPanel.appendChild(race.getElement()); + + Date startDate = raceColumnFromLeaderboard.getStartDate(fleet); + if(startDate != null) { + if(fromDate == null || startDate.before(fromDate)) { + fromDate = startDate; + } + if(toDate == null || startDate.after(toDate)) { + toDate = startDate; + } + } + } + if(fromDate != null && toDate != null) { + racesFromToDate.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(fromDate, toDate)); + } else { + // no single race with a date + racesFromToDate.getStyle().setDisplay(Display.NONE); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.ui.xml index 5a5fddf7aaa..9e763849cff 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesFleetGroup.ui.xml @@ -7,6 +7,7 @@
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesMedium.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesMedium.css new file mode 100644 index 00000000000..eef89812601 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesMedium.css @@ -0,0 +1,50 @@ +.eventregattarace_nameshort { + float: left; +} +.eventregattarace_flag { + display: inline-block; +} +.eventregattaraces {} +.eventregattaraces_phase {} +.eventregattaraces_phase_name {} +.eventregattaraces_phase_day {} +.eventregattaraces_phase_races {} +.eventregattaraces_phase_fleets {} +.eventregattaraces_phase_fleet {} +.eventregattaraces_phase_fleet_name {} +.eventregattaraces_phase_fleet_count {} +.eventregattaraces_legend {} +.eventregattaraces_legend_item {} +.eventregattarace {} +.eventregattarace_fleetindicator {} +.eventregattarace_details {} +.eventregattarace_name {} +.eventregattarace_flag {} +.eventregattarace_wind {} +.eventregattarace_wind_strength {} +.eventregattarace_leader {} +.eventregattarace_leader_name {} +.eventregattarace_features, +.eventregattarace_legs {} +.eventregattarace_features_list, +.eventregattarace_legs_list {} +.eventregattarace_features {} +.eventregattarace_legs_leg {} +.eventregattarace_action {} +.eventregattarace_action_watch, +.eventregattarace_action_analyze {} +.eventregattarace_action_watch {} +.eventregattarace_actiondisabled {} +.eventregattarace_feature {} +.eventregattarace_featuregps {} +.eventregattarace_featurewind {} +.eventregattarace_featurevideo {} +.eventregattarace_featureaudio {} +.eventregattarace_featureunavailable {} +.regattanavigation {} +.regattanavigation_link {} +.regattanavigation_linkactive {} +.eventregattaraces_legend_itemgps {} +.eventregattaraces_legend_itemwind {} +.eventregattaraces_legend_itemvideo {} +.eventregattaraces_legend_itemaudio {} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesPhase.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesPhase.java index a9ec4ffc8ab..41cd0f686f3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesPhase.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesPhase.java @@ -9,7 +9,9 @@ import com.google.gwt.dom.client.SpanElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; @@ -28,7 +30,11 @@ public class EventRegattaRacesPhase extends UIObject { EventRegattaRacesResources.INSTANCE.css().ensureInjected(); setElement(uiBinder.createAndBindUi(this)); - phaseName.setInnerText(series.getName()); + if(series.getName().equals(LeaderboardNameConstants.DEFAULT_SERIES_NAME)) { + phaseName.setInnerText(TextMessages.INSTANCE.races()); + } else { + phaseName.setInnerText(series.getName()); + } int numberOfFleets = series.getFleets().size(); if(numberOfFleets > 1) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.java index a26e5dc7561..3f9f7f4d4e6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.java @@ -7,11 +7,14 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Visibility; +import com.google.gwt.i18n.shared.DateTimeFormat; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.dto.RaceDTO; @@ -22,19 +25,20 @@ import com.sap.sse.gwt.client.player.Timer; public class EventRegattaRacesRace extends UIObject { private static EventRegattaRacesRaceUiBinder uiBinder = GWT.create(EventRegattaRacesRaceUiBinder.class); - private enum SimpleRaceStates { NOT_TRACKED, TRACKED_AND_NOT_LIVE, TRACKED_AND_LIVE }; + private enum SimpleRaceStates { NOT_TRACKED, TRACKED, TRACKED_AND_LIVE, TRACKED_BUT_NOT_SCHEDULED }; interface EventRegattaRacesRaceUiBinder extends UiBinder { } @UiField DivElement fleetColor; @UiField SpanElement raceName; -// @UiField SpanElement raceName2; -// @UiField SpanElement raceState; -// @UiField SpanElement raceTime; + @UiField SpanElement raceName2; + @UiField SpanElement raceState; + @UiField SpanElement raceTime; @UiField SpanElement averageRaceWind; @UiField DivElement raceNotTrackedDiv; + @UiField DivElement raceNotScheduledDiv; @UiField DivElement watchRaceDiv; @UiField DivElement analyzeRaceDiv; @UiField AnchorElement watchRaceLink; @@ -55,14 +59,15 @@ public class EventRegattaRacesRace extends UIObject { @UiField DivElement featureAudio; @UiField DivElement featureVideo; - // local_res.css.eventregattarace_featureunavailable + @UiField SpanElement currentLegNo; + @UiField SpanElement totalLegsCount; -// private final DateTimeFormat raceTimeFormat = DateTimeFormat.getFormat("EEE, h:mm a"); -// private final TextMessages textMessages = GWT.create(TextMessages.class); + private final DateTimeFormat raceTimeFormat = DateTimeFormat.getFormat("EEE, h:mm a"); private final StrippedLeaderboardDTO leaderboard; private final FleetDTO fleet; private final RaceColumnDTO raceColumn; + private final RaceDTO race; private final EventPageNavigator pageNavigator; private final Timer timerForClientServerOffset; @@ -74,11 +79,12 @@ public class EventRegattaRacesRace extends UIObject { this.raceColumn = raceColumn; this.pageNavigator = pageNavigator; this.timerForClientServerOffset = timerForClientServerOffset; + race = raceColumn.getRace(fleet); EventRegattaRacesResources.INSTANCE.css().ensureInjected(); setElement(uiBinder.createAndBindUi(this)); - allConditionalElements = new Element[] {raceWinnerDiv, raceLeaderDiv, watchRaceDiv, analyzeRaceDiv, raceNotTrackedDiv, + allConditionalElements = new Element[] {raceWinnerDiv, raceLeaderDiv, watchRaceDiv, analyzeRaceDiv, raceNotTrackedDiv, raceNotScheduledDiv, raceFeaturesDiv, legProgressDiv, raceFlagDiv, windStatusDiv }; if(fleet.getColor() != null) { @@ -86,7 +92,7 @@ public class EventRegattaRacesRace extends UIObject { } raceName.setInnerText(raceColumn.getName()); -// raceName2.setInnerText(raceColumn.getName()); + raceName2.setInnerText(raceColumn.getName()); registerEvents(); updateUI(); @@ -97,7 +103,11 @@ public class EventRegattaRacesRace extends UIObject { Event.setEventListener(analyzeRaceLink, new EventListener() { @Override public void onBrowserEvent(Event event) { - openRaceViewer(); + switch (DOM.eventGetType(event)) { + case Event.ONCLICK: + openRaceViewer(); + break; + } } }); @@ -105,7 +115,11 @@ public class EventRegattaRacesRace extends UIObject { Event.setEventListener(watchRaceLink, new EventListener() { @Override public void onBrowserEvent(Event event) { - openRaceViewer(); + switch (DOM.eventGetType(event)) { + case Event.ONCLICK: + openRaceViewer(); + break; + } } }); } @@ -113,10 +127,14 @@ public class EventRegattaRacesRace extends UIObject { private SimpleRaceStates getSimpleRaceState() { SimpleRaceStates simpleRaceState = SimpleRaceStates.NOT_TRACKED; - RaceDTO race = raceColumn.getRace(fleet); if(race != null && race.trackedRace != null) { - simpleRaceState = isLive() ? SimpleRaceStates.TRACKED_AND_LIVE : SimpleRaceStates.TRACKED_AND_NOT_LIVE; -// String startOfTrackingTime = raceTimeFormat.format(race.trackedRace.startOfTracking); + simpleRaceState = SimpleRaceStates.TRACKED; + if(isLive()) { + simpleRaceState = SimpleRaceStates.TRACKED_AND_LIVE; + if(race.startOfRace == null) { + simpleRaceState = SimpleRaceStates.TRACKED_BUT_NOT_SCHEDULED; + } + } } return simpleRaceState; } @@ -136,19 +154,70 @@ public class EventRegattaRacesRace extends UIObject { case NOT_TRACKED: showElement(raceNotTrackedDiv); break; + case TRACKED_BUT_NOT_SCHEDULED: + showElement(raceNotScheduledDiv); + break; case TRACKED_AND_LIVE: showElement(watchRaceDiv); - showElement(raceLeaderDiv); - showElement(legProgressDiv); + + if(race.startOfRace != null) { + raceTime.setInnerText(raceTimeFormat.format(race.startOfRace)); + } + if(race.trackedRaceStatistics.hasLegProgressData) { + showElement(legProgressDiv); + currentLegNo.setInnerText(String.valueOf(race.trackedRaceStatistics.currentLegNo)); + totalLegsCount.setInnerText(String.valueOf(race.trackedRaceStatistics.totalLegsCount)); + } + if(race.trackedRaceStatistics.hasLeaderOrWinnerData && race.trackedRaceStatistics.leaderOrWinner != null) { + showElement(raceLeaderDiv); + updateWinnerOrLeader(raceLeader, race.trackedRaceStatistics.leaderOrWinner); + } + break; - case TRACKED_AND_NOT_LIVE: + case TRACKED: showElement(analyzeRaceDiv); - showElement(raceWinnerDiv); + + if(race.trackedRaceStatistics.hasLeaderOrWinnerData && race.trackedRaceStatistics.leaderOrWinner != null) { + showElement(raceWinnerDiv); + updateWinnerOrLeader(raceWinner, race.trackedRaceStatistics.leaderOrWinner); + } + if(race.startOfRace != null) { + raceTime.setInnerText(raceTimeFormat.format(race.startOfRace)); + } showElement(raceFeaturesDiv); + updateRaceFeatures(); + break; } } + private void updateWinnerOrLeader(SpanElement winnerOrLeaderElement, CompetitorDTO winnerOrLeader) { + String winnerOrLeaderName = winnerOrLeader.getName(); + if(winnerOrLeader.getThreeLetterIocCountryCode() != null) { + winnerOrLeaderName += " (" + winnerOrLeader.getThreeLetterIocCountryCode() + ")"; + } + winnerOrLeaderElement.setInnerText(winnerOrLeaderName); + } + + private void updateRaceFeatures() { + if(!race.trackedRaceStatistics.hasGPSData) { + featureGPS.addClassName(EventRegattaRacesResources.INSTANCE.css().eventregattarace_featureunavailable()); + } + if(!race.trackedRaceStatistics.hasMeasuredWindData) { + featureWind.addClassName(EventRegattaRacesResources.INSTANCE.css().eventregattarace_featureunavailable()); + } + if(!race.trackedRaceStatistics.hasVideoData) { + featureVideo.addClassName(EventRegattaRacesResources.INSTANCE.css().eventregattarace_featureunavailable()); + } else { + featureVideo.setTitle(String.valueOf(race.trackedRaceStatistics.videoTracksCount)); + } + if(!race.trackedRaceStatistics.hasAudioData) { + featureAudio.addClassName(EventRegattaRacesResources.INSTANCE.css().eventregattarace_featureunavailable()); + } else { + featureAudio.setTitle(String.valueOf(race.trackedRaceStatistics.audioTracksCount)); + } + } + private void hideElement(Element el) { el.getStyle().setVisibility(Visibility.HIDDEN); el.getStyle().setDisplay(Display.NONE); @@ -160,7 +229,6 @@ public class EventRegattaRacesRace extends UIObject { } private void openRaceViewer() { - RaceDTO race = raceColumn.getRace(fleet); if(race != null && race.trackedRace != null) { pageNavigator.openRaceViewer(leaderboard, race); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.ui.xml index 9837731999b..69bc2435f9e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRace.ui.xml @@ -10,10 +10,8 @@
-
@@ -24,12 +22,12 @@
-

-   +

- Leader:

-   +

-
Leg (race.leg of race.totalLegs): +
 /
@@ -43,6 +41,9 @@
+
+ +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRaceday.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRaceday.java index 7f2df8dba55..9a2430eeac1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRaceday.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesRaceday.java @@ -9,6 +9,11 @@ import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.ui.shared.RaceGroupSeriesDTO; +/** + * Not used yet + * @author Frank + * + */ public class EventRegattaRacesRaceday extends Composite { private static EventRegattaRacesRacedayUiBinder uiBinder = GWT.create(EventRegattaRacesRacedayUiBinder.class); @@ -19,7 +24,6 @@ public class EventRegattaRacesRaceday extends Composite { @UiField HTMLPanel racesPanel; public EventRegattaRacesRaceday(RaceGroupSeriesDTO series) { -// private final EventPageNavigator pageNavigator; EventRegattaRacesResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesResources.java index e0907f95721..4e4f4e4e35c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesResources.java @@ -3,13 +3,21 @@ package com.sap.sailing.gwt.home.client.place.event.regattaraces; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.CssResource.Shared; public interface EventRegattaRacesResources extends ClientBundle { public static final EventRegattaRacesResources INSTANCE = GWT.create(EventRegattaRacesResources.class); + public interface MinWidth25emCss extends LocalCss { + } + + @Source("com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRacesMedium.css") + MinWidth25emCss mediumCss(); + @Source("com/sap/sailing/gwt/home/client/place/event/regattaraces/EventRegattaRaces.css") LocalCss css(); + @Shared public interface LocalCss extends CssResource { String eventregattaraces(); String eventregattaraces_phase(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/schedule/EventSchedule.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/schedule/EventSchedule.java index 20c88876c70..059faf76134 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/schedule/EventSchedule.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/schedule/EventSchedule.java @@ -2,21 +2,19 @@ package com.sap.sailing.gwt.home.client.place.event.schedule; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.place.event.AbstractEventComposite; +import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator; import com.sap.sailing.gwt.ui.shared.EventDTO; -public class EventSchedule extends Composite { +public class EventSchedule extends AbstractEventComposite { private static EventScheduleUiBinder uiBinder = GWT.create(EventScheduleUiBinder.class); interface EventScheduleUiBinder extends UiBinder { } - - @SuppressWarnings("unused") - private final EventDTO event; - public EventSchedule(EventDTO event) { - this.event = event; + public EventSchedule(EventDTO event, EventPageNavigator placeNavigator) { + super(event, placeNavigator); EventScheduleResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/AbstractEventsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/AbstractEventsView.java index 3b843f1430c..78ecd1a27fc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/AbstractEventsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/AbstractEventsView.java @@ -23,9 +23,9 @@ public abstract class AbstractEventsView extends Composite implements EventsView @Override public void setEvents(List events) { for(EventBaseDTO event: events) { - if(event.startDate != null) { - if(DateUtil.isDayInPast(event.startDate)) { - // recent event + if(event.startDate != null && event.endDate != null) { + if(DateUtil.isDayInPast(event.startDate) || event.isRunning()) { + // recent event or live event int year = DateUtil.getYear(event.startDate); List eventsOfYear = recentEventsOrderedByYear.get(year); if(eventsOfYear == null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/EventsActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/EventsActivity.java index fb1d33e130e..dd8bfe889af 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/EventsActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/EventsActivity.java @@ -4,10 +4,11 @@ import java.util.List; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.client.shared.placeholder.Placeholder; import com.sap.sailing.gwt.ui.shared.EventBaseDTO; +import com.sap.sse.gwt.client.mvp.ErrorView; public class EventsActivity extends AbstractActivity { @@ -19,17 +20,21 @@ public class EventsActivity extends AbstractActivity { @Override public void start(final AcceptsOneWidget panel, EventBus eventBus) { - final EventsView eventsView = clientFactory.createEventsView(EventsActivity.this); - panel.setWidget(eventsView.asWidget()); + panel.setWidget(new Placeholder()); + clientFactory.getSailingService().getPublicEventsOfAllSailingServers(new AsyncCallback>() { @Override public void onSuccess(List events) { + final EventsView eventsView = clientFactory.createEventsView(EventsActivity.this); + panel.setWidget(eventsView.asWidget()); + eventsView.setEvents(events); } @Override public void onFailure(Throwable caught) { - Window.alert("Shit happens"); + final ErrorView view = clientFactory.createErrorView("Error while loading the sailing server instances with service getPublicEventsOfAllSailingServers()", caught); + panel.setWidget(view.asWidget()); } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/TabletAndDesktopEventsView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/TabletAndDesktopEventsView.ui.xml index e19a810e021..8a059ed0abc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/TabletAndDesktopEventsView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/TabletAndDesktopEventsView.ui.xml @@ -3,6 +3,7 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:p="urn:import:com.sap.sailing.gwt.home.client.place.events" xmlns:g="urn:import:com.google.gwt.user.client.ui"> + .eventsoverviewnavigation { @@ -20,16 +21,14 @@
- - + +
- - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecent.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecent.css index d7258c42961..34c5bc4815b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecent.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecent.css @@ -3,6 +3,7 @@ font-size: 1rem; text-align: center; width: 100%; + height: 24em; } .eventteaser { font-size: 15px; @@ -52,7 +53,6 @@ .eventsoverviewrecent { font-size: 15px; font-size: 1rem; - padding-top: 2em; } .eventsoverviewrecent_year { border-bottom: 1px solid #ccc; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.java index ce1b4840166..0c63b70eef2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.java @@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.events.recent; import java.util.List; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -27,7 +28,7 @@ public class EventsOverviewRecentYear extends Composite { // @UiField SpanElement countriesCount; // @UiField SpanElement sailorsCount; // @UiField SpanElement trackedRacesCount; - @UiField HTMLPanel recentEventsTeaserPanel; + @UiField DivElement recentEventsTeaserPanel; @UiField HTMLPanel contentDiv; @UiField HTMLPanel headerDiv; @@ -46,7 +47,7 @@ public class EventsOverviewRecentYear extends Composite { for(EventBaseDTO eventDTO: events) { RecentEvent recentEvent = new RecentEvent(navigator); recentEvent.setEvent(eventDTO); - recentEventsTeaserPanel.add(recentEvent); + recentEventsTeaserPanel.appendChild(recentEvent.getElement()); } isContentVisible = true; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.ui.xml index d3513d36850..521c7c3d6e3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/recent/EventsOverviewRecentYear.ui.xml @@ -38,8 +38,7 @@
-
- +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.java index a6f54560d21..1f67bca5991 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.java @@ -38,11 +38,10 @@ public class EventsOverviewUpcoming extends Composite { upcomingEventComposites.clear(); for(EventBaseDTO event: events) { - UpcomingEvent upcomingEvent = new UpcomingEvent(navigator); + UpcomingEvent upcomingEvent = new UpcomingEvent(event, navigator); - upcomingEvent.setEvent(event); upcomingEventComposites.add(upcomingEvent); - eventsPlaceholder.add(upcomingEvent); + eventsPlaceholder.getElement().appendChild(upcomingEvent.getElement()); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.ui.xml index 0b755dcc8bb..54964bc4411 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/EventsOverviewUpcoming.ui.xml @@ -12,15 +12,15 @@
-

Coming soon

+

-
Date
-
Event
-
Location
-
Series
+
+
+
+
@@ -29,7 +29,7 @@
-
More Events To Be Announced Soon!
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.java index 37d1d91cdba..705b1d27a95 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.java @@ -1,48 +1,55 @@ package com.sap.sailing.gwt.home.client.place.events.upcoming; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.AnchorElement; +import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.SpanElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; +import com.google.gwt.user.client.ui.UIObject; import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil; import com.sap.sailing.gwt.ui.shared.EventBaseDTO; -public class UpcomingEvent extends Composite { +public class UpcomingEvent extends UIObject { @UiField SpanElement eventName; @UiField SpanElement seriesName; @UiField SpanElement venueName; @UiField SpanElement eventStartDate; + @UiField AnchorElement eventOverviewLink; @SuppressWarnings("unused") private final PlaceNavigator navigator; - private EventBaseDTO event; - - - interface UpcomingEventUiBinder extends UiBinder { + interface UpcomingEventUiBinder extends UiBinder { } private static UpcomingEventUiBinder uiBinder = GWT.create(UpcomingEventUiBinder.class); - public UpcomingEvent(PlaceNavigator navigator) { + public UpcomingEvent(final EventBaseDTO event, final PlaceNavigator navigator) { this.navigator = navigator; EventsOverviewUpcomingResources.INSTANCE.css().ensureInjected(); - initWidget(uiBinder.createAndBindUi(this)); - } - - public void setEvent(EventBaseDTO event) { - this.event = event; - updateUI(); - } + setElement(uiBinder.createAndBindUi(this)); + + Event.sinkEvents(eventOverviewLink, Event.ONCLICK); + Event.setEventListener(eventOverviewLink, new EventListener() { + @Override + public void onBrowserEvent(Event browserEvent) { + switch (DOM.eventGetType(browserEvent)) { + case Event.ONCLICK: + navigator.goToEvent(event.id.toString(), event.getBaseURL(), event.isOnRemoteServer()); + break; + } + } + }); - private void updateUI() { eventName.setInnerText(event.getName()); venueName.setInnerText(event.venue.getName()); eventStartDate.setInnerText(EventDatesFormatterUtil.formatDateRangeWithoutYear(event.startDate, event.endDate)); - } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.ui.xml index bc8dec1a699..b7867cdda5a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/events/upcoming/UpcomingEvent.ui.xml @@ -5,16 +5,14 @@ - - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivity.java new file mode 100644 index 00000000000..1b7050b0952 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivity.java @@ -0,0 +1,239 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import com.google.gwt.activity.shared.AbstractActivity; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.domain.common.DetailType; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.client.shared.placeholder.Placeholder; +import com.sap.sailing.gwt.ui.client.ErrorReporter; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardUrlSettings; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sse.common.Util; +import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; +import com.sap.sse.gwt.client.mvp.ErrorView; +import com.sap.sse.gwt.client.player.Timer; +import com.sap.sse.gwt.client.player.Timer.PlayModes; +import com.sap.sse.gwt.client.player.Timer.PlayStates; +import com.sap.sse.gwt.client.useragent.UserAgentDetails; +import com.sap.sse.gwt.shared.GwtHttpRequestUtils; + +public class LeaderboardActivity extends AbstractActivity implements ErrorReporter { + private final LeaderboardClientFactory clientFactory; + private final LeaderboardPlace leaderboardPlace; + private final Timer timerForClientServerOffset; + + private final UserAgentDetails userAgent = new UserAgentDetails(Window.Navigator.getUserAgent()); + + public LeaderboardActivity(LeaderboardPlace place, LeaderboardClientFactory clientFactory) { + this.clientFactory = clientFactory; + this.leaderboardPlace = place; + + timerForClientServerOffset = new Timer(PlayModes.Replay); + } + + @Override + public void start(final AcceptsOneWidget panel, EventBus eventBus) { + panel.setWidget(new Placeholder()); + + UUID eventUUID = UUID.fromString(leaderboardPlace.getEventUuidAsString()); + final String leaderboardName = leaderboardPlace.getLeaderboardIdAsNameString(); + final boolean showRaceDetails = leaderboardPlace.getShowRaceDetails(); + + clientFactory.getSailingService().getEventById(eventUUID, true, new AsyncCallback() { + @Override + public void onSuccess(final EventDTO event) { + if (leaderboardName != null) { + clientFactory.getSailingService().checkLeaderboardName(leaderboardName, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(Util.Pair leaderboardNameAndType) { + if (leaderboardNameAndType != null && leaderboardName.equals(leaderboardNameAndType.getA())) { + createLeaderboardViewer(panel, event, leaderboardNameAndType.getA(), leaderboardNameAndType.getB(), showRaceDetails); + } else { + createErrorView(TextMessages.INSTANCE.errorMessageNoSuchLeaderboard(), null, panel); + } + } + + @Override + public void onFailure(Throwable caught) { + createErrorView("Error while checking the leaderboard name with service checkLeaderboardName()", caught, panel); + } + })); + } else { + createErrorView(TextMessages.INSTANCE.errorMessageNoSuchLeaderboard(), null, panel); + } + } + + @Override + public void onFailure(Throwable caught) { + createErrorView("Error while loading the event with service getEventById()", caught, panel); + } + }); + } + + private void createLeaderboardViewer(AcceptsOneWidget panel, EventDTO event, String leaderboardName, LeaderboardType leaderboardType, boolean showRaceDetails) { + String leaderboardDisplayName = Window.Location.getParameter("displayName"); + if (leaderboardDisplayName == null || leaderboardDisplayName.isEmpty()) { + leaderboardDisplayName = leaderboardName; + } + + long delayBetweenAutoAdvancesInMilliseconds = 3000l; + final RaceIdentifier preselectedRace = getPreselectedRace(Window.Location.getParameterMap()); + // make a single live request as the default but don't continue to play by default + Timer timer = new Timer(PlayModes.Live, PlayStates.Paused, delayBetweenAutoAdvancesInMilliseconds); + final LeaderboardSettings leaderboardSettings = createLeaderboardSettingsFromURLParameters(Window.Location.getParameterMap()); + if (leaderboardSettings.getDelayBetweenAutoAdvancesInMilliseconds() != null) { + timer.setPlayMode(PlayModes.Live); // the leaderboard, viewed via the entry point, goes "live" and "playing" if an auto-refresh + } // interval has been specified + boolean autoExpandLastRaceColumn = GwtHttpRequestUtils.getBooleanParameter(LeaderboardUrlSettings.PARAM_AUTO_EXPAND_LAST_RACE_COLUMN, false); + boolean showOverallLeaderboard = GwtHttpRequestUtils.getBooleanParameter(LeaderboardUrlSettings.PARAM_SHOW_OVERALL_LEADERBOARD, false); + boolean showSeriesLeaderboards = GwtHttpRequestUtils.getBooleanParameter(LeaderboardUrlSettings.PARAM_SHOW_SERIES_LEADERBOARDS, false); + + LeaderboardView leaderboardView = clientFactory.createLeaderboardView(event, leaderboardName, timerForClientServerOffset); + + if (leaderboardType.isMetaLeaderboard()) { + leaderboardView.createMetaLeaderboardViewer(clientFactory.getSailingService(), new AsyncActionsExecutor(), + timer, leaderboardSettings, null, preselectedRace, "leaderboardGroupName", leaderboardName, this, StringMessages.INSTANCE, + userAgent, showRaceDetails, autoExpandLastRaceColumn, showSeriesLeaderboards); + } else { + leaderboardView.createLeaderboardViewer(clientFactory.getSailingService(), new AsyncActionsExecutor(), + timer, leaderboardSettings, preselectedRace, "leaderboardGroupName", leaderboardName, this, StringMessages.INSTANCE, + userAgent, showRaceDetails, autoExpandLastRaceColumn, showOverallLeaderboard); + } + + panel.setWidget(leaderboardView.asWidget()); + } + + /** + * Constructs {@link LeaderboardSettings} from the URL parameters found + */ + private LeaderboardSettings createLeaderboardSettingsFromURLParameters(Map> parameterMap) { + LeaderboardSettings result; + Long refreshIntervalMillis = parameterMap.containsKey(LeaderboardUrlSettings.PARAM_REFRESH_INTERVAL_MILLIS) ? Long + .valueOf(parameterMap.get(LeaderboardUrlSettings.PARAM_REFRESH_INTERVAL_MILLIS).get(0)) : null; + RaceColumnSelectionStrategies raceColumnSelectionStrategy; + final Integer numberOfLastRacesToShow; + if (parameterMap.containsKey(LeaderboardUrlSettings.PARAM_NAME_LAST_N)) { + raceColumnSelectionStrategy = RaceColumnSelectionStrategies.LAST_N; + numberOfLastRacesToShow = Integer.valueOf(parameterMap.get(LeaderboardUrlSettings.PARAM_NAME_LAST_N).get(0)); + } else if (isSmallWidth()) { + raceColumnSelectionStrategy = RaceColumnSelectionStrategies.LAST_N; + int width = Window.getClientWidth(); + numberOfLastRacesToShow = (width-275)/40; + } else { + raceColumnSelectionStrategy = RaceColumnSelectionStrategies.EXPLICIT; + numberOfLastRacesToShow = null; + } + if (parameterMap.containsKey(LeaderboardUrlSettings.PARAM_RACE_NAME) || parameterMap.containsKey(LeaderboardUrlSettings.PARAM_RACE_DETAIL) || + parameterMap.containsKey(LeaderboardUrlSettings.PARAM_LEG_DETAIL) || parameterMap.containsKey(LeaderboardUrlSettings.PARAM_MANEUVER_DETAIL) || + parameterMap.containsKey(LeaderboardUrlSettings.PARAM_OVERALL_DETAIL) || parameterMap.containsKey(LeaderboardUrlSettings.PARAM_SHOW_ADDED_SCORES) || + parameterMap.containsKey(LeaderboardUrlSettings.PARAM_SHOW_OVERALL_COLUMN_WITH_NUMBER_OF_RACES_COMPLETED)) { + List maneuverDetails = getDetailTypeListFromParamValue(parameterMap.get(LeaderboardUrlSettings.PARAM_MANEUVER_DETAIL)); + List raceDetails = getDetailTypeListFromParamValue(parameterMap.get(LeaderboardUrlSettings.PARAM_RACE_DETAIL)); + List overallDetails = getDetailTypeListFromParamValue(parameterMap.get(LeaderboardUrlSettings.PARAM_OVERALL_DETAIL)); + List legDetails = getDetailTypeListFromParamValue(parameterMap.get(LeaderboardUrlSettings.PARAM_LEG_DETAIL)); + List namesOfRacesToShow = getStringListFromParamValue(parameterMap.get(LeaderboardUrlSettings.PARAM_RACE_NAME)); + boolean showAddedScores = parameterMap.containsKey(LeaderboardUrlSettings.PARAM_SHOW_ADDED_SCORES) ? + Boolean.valueOf(parameterMap.get(LeaderboardUrlSettings.PARAM_SHOW_ADDED_SCORES).get(0)) : false; + boolean showOverallColumnWithNumberOfRacesSailedPerCompetitor = parameterMap.containsKey(LeaderboardUrlSettings.PARAM_SHOW_OVERALL_COLUMN_WITH_NUMBER_OF_RACES_COMPLETED) ? + Boolean.valueOf(parameterMap.get(LeaderboardUrlSettings.PARAM_SHOW_OVERALL_COLUMN_WITH_NUMBER_OF_RACES_COMPLETED).get(0)) : false; + boolean autoExpandPreSelectedRace = parameterMap.containsKey(LeaderboardUrlSettings.PARAM_AUTO_EXPAND_PRESELECTED_RACE) ? + Boolean.valueOf(parameterMap.get(LeaderboardUrlSettings.PARAM_AUTO_EXPAND_PRESELECTED_RACE).get(0)) : + (namesOfRacesToShow != null && namesOfRacesToShow.size() == 1); + result = new LeaderboardSettings(maneuverDetails, legDetails, raceDetails, overallDetails, + /* namesOfRaceColumnsToShow */ null, + namesOfRacesToShow, numberOfLastRacesToShow, + autoExpandPreSelectedRace, refreshIntervalMillis, /* sort by column */ (namesOfRacesToShow != null && !namesOfRacesToShow.isEmpty()) ? + namesOfRacesToShow.get(0) : null, + /* ascending */ true, /* updateUponPlayStateChange */ raceDetails.isEmpty() && legDetails.isEmpty(), + raceColumnSelectionStrategy, showAddedScores, showOverallColumnWithNumberOfRacesSailedPerCompetitor); + + } else { + final List overallDetails = Collections.emptyList(); + result = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, + /* overallDetails */ overallDetails, null, + /* autoExpandFirstRace */false, refreshIntervalMillis, numberOfLastRacesToShow, + raceColumnSelectionStrategy); + } + return result; + } + + private RaceIdentifier getPreselectedRace(Map> parameterMap) { + RaceIdentifier result; + if (parameterMap.containsKey(LeaderboardUrlSettings.PARAM_RACE_NAME) && parameterMap.get(LeaderboardUrlSettings.PARAM_RACE_NAME).size() == 1 && + parameterMap.containsKey(LeaderboardUrlSettings.PARAM_REGATTA_NAME) && parameterMap.get(LeaderboardUrlSettings.PARAM_REGATTA_NAME).size() == 1) { + result = new RegattaNameAndRaceName(parameterMap.get(LeaderboardUrlSettings.PARAM_REGATTA_NAME).get(0), parameterMap.get(LeaderboardUrlSettings.PARAM_RACE_NAME).get(0)); + } else { + result = null; + } + return result; + } + + private List getDetailTypeListFromParamValue(List list) { + List result = new ArrayList(); + if (list != null) { + for (String entry : list) { + try { + result.add(DetailType.valueOf(entry)); + } catch (IllegalArgumentException e) { + } + } + } + return result; + } + + private List getStringListFromParamValue(List list) { + List result = new ArrayList(); + if (list != null) { + result.addAll(list); + } + return result; + } + + private void createErrorView(String errorMessage, Throwable errorReason, AcceptsOneWidget panel) { + ErrorView view = clientFactory.createErrorView(errorMessage, errorReason); + panel.setWidget(view.asWidget()); + } + + public boolean isSmallWidth() { + int width = Window.getClientWidth(); + return width <= 720; + } + + @Override + public void reportError(String message) { + Window.alert(message); + } + + @Override + public void reportError(String message, boolean silentMode) { + if (silentMode) { + Window.setStatus(message); + } else { + reportError(message); + } + } + + @Override + public void reportPersistentInformation(String message) { + Window.setStatus(message); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivityProxy.java new file mode 100644 index 00000000000..9d186021e7c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardActivityProxy.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import com.google.gwt.core.client.GWT; +import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; + +public class LeaderboardActivityProxy extends AbstractActivityProxy { + + private final LeaderboardClientFactory clientFactory; + private final LeaderboardPlace place; + + public LeaderboardActivityProxy(LeaderboardPlace place, LeaderboardClientFactory clientFactory) { + this.place = place; + this.clientFactory = clientFactory; + } + + @Override + protected void startAsync() { + GWT.runAsync(new AbstractRunAsyncCallback() { + @Override + public void onSuccess() { + super.onSuccess(new LeaderboardActivity(place, clientFactory)); + } + }); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardClientFactory.java new file mode 100644 index 00000000000..a45201dccb5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardClientFactory.java @@ -0,0 +1,9 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import com.sap.sailing.gwt.ui.client.SailingClientFactory; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sse.gwt.client.player.Timer; + +public interface LeaderboardClientFactory extends SailingClientFactory { + LeaderboardView createLeaderboardView(EventDTO event, String leaderboardName, Timer timerForClientServerOffset); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardPlace.java new file mode 100644 index 00000000000..9835d705db4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardPlace.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import com.google.gwt.place.shared.PlaceTokenizer; +import com.sap.sailing.gwt.home.client.AbstractBasePlace; + +public class LeaderboardPlace extends AbstractBasePlace { + private final String eventUuidAsString; + private final String leaderboardIdAsNameString; + private final Boolean showRaceDetails; + private final Boolean showSettings; + + private final static String PARAM_EVENTID = "eventId"; + private final static String PARAM_LEADERBOARD_NAME = "leaderboardName"; + private final static String PARAM_SHOW_RACE_DETAILS = "showRaceDetails"; + private final static String PARAM_SHOW_SETTINGS = "showSettings"; + + public LeaderboardPlace(String url) { + super(url); + eventUuidAsString = getParameter(PARAM_EVENTID); + leaderboardIdAsNameString = getParameter(PARAM_LEADERBOARD_NAME); + showRaceDetails = Boolean.valueOf(getParameter(PARAM_SHOW_RACE_DETAILS)); + showSettings = Boolean.valueOf(getParameter(PARAM_SHOW_SETTINGS)); + } + + public LeaderboardPlace(String eventUuidAsString, String leaderboardIdAsNameString, Boolean showRaceDetails, Boolean showSettings) { + super(PARAM_EVENTID, eventUuidAsString, PARAM_LEADERBOARD_NAME, leaderboardIdAsNameString, + PARAM_SHOW_RACE_DETAILS, String.valueOf(showRaceDetails), PARAM_SHOW_SETTINGS, String.valueOf(showSettings)); + this.eventUuidAsString = eventUuidAsString; + this.leaderboardIdAsNameString = leaderboardIdAsNameString; + this.showRaceDetails = showRaceDetails; + this.showSettings = showSettings; + } + + public String getEventUuidAsString() { + return eventUuidAsString; + } + + public String getLeaderboardIdAsNameString() { + return leaderboardIdAsNameString; + } + + public Boolean getShowRaceDetails() { + return showRaceDetails; + } + + public Boolean getShowSettings() { + return showSettings; + } + + public static class Tokenizer implements PlaceTokenizer { + @Override + public String getToken(LeaderboardPlace place) { + return place.getParametersAsToken(); + } + + @Override + public LeaderboardPlace getPlace(String url) { + return new LeaderboardPlace(url); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardView.java new file mode 100644 index 00000000000..a278ac15cb9 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/LeaderboardView.java @@ -0,0 +1,27 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.RaceIdentifier; +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.leaderboard.LeaderboardSettings; +import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.player.Timer; +import com.sap.sse.gwt.client.useragent.UserAgentDetails; + +public interface LeaderboardView { + Widget asWidget(); + + void createLeaderboardViewer(final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor, + final Timer timer, final LeaderboardSettings leaderboardSettings, final RaceIdentifier preselectedRace, + final String leaderboardGroupName, String leaderboardName, final ErrorReporter errorReporter, + final StringMessages stringMessages, final UserAgentDetails userAgent, boolean showRaceDetails, + boolean autoExpandLastRaceColumn, boolean showOverallLeaderboard); + + void createMetaLeaderboardViewer(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, + Timer timer, LeaderboardSettings leaderboardSettings, String preselectedLeaderboardName, RaceIdentifier preselectedRace, + String leaderboardGroupName, String metaLeaderboardName, ErrorReporter errorReporter, + StringMessages stringMessages, UserAgentDetails userAgent, boolean showRaceDetails, + boolean autoExpandLastRaceColumn, boolean showSeriesLeaderboards); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.java new file mode 100644 index 00000000000..004239b1abc --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.java @@ -0,0 +1,105 @@ +package com.sap.sailing.gwt.home.client.place.leaderboard; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.HeadingElement; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.client.place.event.header.CompactEventHeader; +import com.sap.sailing.gwt.home.client.place.event.regattaleaderboard.EventRegattaLeaderboardResources; +import com.sap.sailing.gwt.home.client.shared.leaderboard.AbstractLeaderboardViewer; +import com.sap.sailing.gwt.home.client.shared.leaderboard.LeaderboardViewer; +import com.sap.sailing.gwt.home.client.shared.leaderboard.MetaLeaderboardViewer; +import com.sap.sailing.gwt.ui.client.DebugIdHelper; +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.client.shared.components.SettingsDialog; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; +import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.player.Timer; +import com.sap.sse.gwt.client.useragent.UserAgentDetails; + +public class TabletAndDesktopLeaderboardView extends Composite implements LeaderboardView { + private static LeaderboardPageViewUiBinder uiBinder = GWT.create(LeaderboardPageViewUiBinder.class); + + interface LeaderboardPageViewUiBinder extends UiBinder { + } + + @UiField HTMLPanel leaderboardPanel; + @UiField(provided=true) CompactEventHeader eventHeader; + + // temp fields --> will be moved to a leaderboard partial later on + @UiField HeadingElement title; + @UiField Anchor settingsAnchor; + @UiField Anchor reloadAnchor; + + private AbstractLeaderboardViewer leaderboardViewer; + + public TabletAndDesktopLeaderboardView(EventDTO event, String leaderboardName, Timer timerForClientServerOffset, PlaceNavigator placeNavigator) { + eventHeader = new CompactEventHeader(event, leaderboardName, placeNavigator); + + EventRegattaLeaderboardResources.INSTANCE.css().ensureInjected(); + + initWidget(uiBinder.createAndBindUi(this)); + + reloadAnchor.setVisible(false); + title.setInnerText(TextMessages.INSTANCE.leaderboard() + ": " + leaderboardName); + } + + public void createLeaderboardViewer(final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor, + final Timer timer, final LeaderboardSettings leaderboardSettings, final RaceIdentifier preselectedRace, + final String leaderboardGroupName, String leaderboardName, final ErrorReporter errorReporter, + final StringMessages stringMessages, final UserAgentDetails userAgent, boolean showRaceDetails, + boolean autoExpandLastRaceColumn, boolean showOverallLeaderboard) { + leaderboardViewer = new LeaderboardViewer(sailingService, new AsyncActionsExecutor(), + timer, leaderboardSettings, preselectedRace, leaderboardGroupName, leaderboardName, errorReporter, stringMessages, + userAgent, showRaceDetails, autoExpandLastRaceColumn, showOverallLeaderboard); + + ScrollPanel contentScrollPanel = new ScrollPanel(); + contentScrollPanel.setWidget(leaderboardViewer); + leaderboardPanel.add(contentScrollPanel); + } + + public void createMetaLeaderboardViewer(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, + Timer timer, LeaderboardSettings leaderboardSettings, String preselectedLeaderboardName, RaceIdentifier preselectedRace, + String leaderboardGroupName, String metaLeaderboardName, ErrorReporter errorReporter, + StringMessages stringMessages, UserAgentDetails userAgent, boolean showRaceDetails, + boolean autoExpandLastRaceColumn, boolean showSeriesLeaderboards) { + leaderboardViewer = new MetaLeaderboardViewer(sailingService, new AsyncActionsExecutor(), + timer, leaderboardSettings, null, preselectedRace, leaderboardGroupName, metaLeaderboardName, errorReporter, stringMessages, + userAgent, showRaceDetails, autoExpandLastRaceColumn, showSeriesLeaderboards); + + ScrollPanel contentScrollPanel = new ScrollPanel(); + contentScrollPanel.setWidget(leaderboardViewer); + leaderboardPanel.add(contentScrollPanel); + } + + @UiHandler("reloadAnchor") + void reloadClicked(ClickEvent event) { + } + + @UiHandler("settingsAnchor") + void settingsClicked(ClickEvent event) { + LeaderboardPanel leaderboardComponent = leaderboardViewer.getLeaderboardPanel(); + + final String componentName = leaderboardComponent.getLocalizedShortName(); + final String debugIdPrefix = DebugIdHelper.createDebugId(componentName); + + SettingsDialog dialog = new SettingsDialog(leaderboardComponent, + StringMessages.INSTANCE); + dialog.ensureDebugId(debugIdPrefix + "SettingsDialog"); + dialog.show(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.ui.xml new file mode 100644 index 00000000000..af92d04d783 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/leaderboard/TabletAndDesktopLeaderboardView.ui.xml @@ -0,0 +1,36 @@ + + + + + + + .leaderboardPanel { + background-color:#f8f8f8; + padding: 0 10px 10px 10px; + } + + + + +
+
+

+

+ +
+
+ + +
+
+ + +
+
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/SearchResultActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/SearchResultActivity.java index 87c0a0d1485..fbacfa52c14 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/SearchResultActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/SearchResultActivity.java @@ -2,11 +2,12 @@ package com.sap.sailing.gwt.home.client.place.searchresult; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.client.shared.placeholder.Placeholder; import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; import com.sap.sse.common.search.KeywordQuery; +import com.sap.sse.gwt.client.mvp.ErrorView; public class SearchResultActivity extends AbstractActivity { private final SearchResultClientFactory clientFactory; @@ -14,6 +15,7 @@ public class SearchResultActivity extends AbstractActivity { private final SearchResultPlace searchResultPlace; private SearchResultView view; + private AcceptsOneWidget panel; public SearchResultActivity(SearchResultPlace place, SearchResultClientFactory clientFactory) { this.clientFactory = clientFactory; @@ -25,13 +27,18 @@ public class SearchResultActivity extends AbstractActivity { private void bindEvents() { clientFactory.getEventBus().addHandler(SearchEvent.TYPE, new SearchEventHandler() { public void onDoSearch(SearchEvent event) { - doSearch(event.getSearchText()); + if(view != null) { + doSearch(event.getSearchText()); + } } }); } @Override public void start(final AcceptsOneWidget panel, final EventBus eventBus) { + this.panel = panel; + panel.setWidget(new Placeholder()); + view = clientFactory.createSearchResultView(); panel.setWidget(view.asWidget()); doSearch(searchResultPlace.getSearchText()); @@ -47,7 +54,8 @@ public class SearchResultActivity extends AbstractActivity { @Override public void onFailure(Throwable caught) { - Window.alert("Shit happens"); + final ErrorView view = clientFactory.createErrorView("Error while seaching with service search()", caught); + panel.setWidget(view.asWidget()); } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/TabletAndDesktopSearchResultView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/TabletAndDesktopSearchResultView.java index 42ac68387b0..4f09e948d86 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/TabletAndDesktopSearchResultView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/searchresult/TabletAndDesktopSearchResultView.java @@ -5,7 +5,6 @@ import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; -import com.google.web.bindery.event.shared.EventBus; import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.shared.searchresult.SearchResult; import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; @@ -18,8 +17,8 @@ public class TabletAndDesktopSearchResultView extends Composite implements Searc @UiField(provided=true) SearchResult searchResult; - public TabletAndDesktopSearchResultView(PlaceNavigator navigator, EventBus eventBus) { - searchResult = new SearchResult(navigator, eventBus); + public TabletAndDesktopSearchResultView(PlaceNavigator navigator) { + searchResult = new SearchResult(navigator); initWidget(uiBinder.createAndBindUi(this)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.java index c19df307ee4..ad0ef1935c4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.java @@ -11,10 +11,9 @@ import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.shared.mainevents.MainEvents; import com.sap.sailing.gwt.home.client.shared.mainmedia.MainMedia; import com.sap.sailing.gwt.home.client.shared.mainsponsors.MainSponsors; -import com.sap.sailing.gwt.home.client.shared.socialfooter.SocialFooter; import com.sap.sailing.gwt.home.client.shared.stage.Stage; import com.sap.sailing.gwt.home.client.shared.stage.StageEventType; -import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sse.common.Util.Pair; public class SmartphoneStartView extends Composite implements StartView { @@ -27,7 +26,6 @@ public class SmartphoneStartView extends Composite implements StartView { @UiField(provided=true) MainSponsors mainSponsors; @UiField(provided=true) MainEvents mainEvents; @UiField(provided=true) MainMedia mainMedia; - @UiField SocialFooter socialFooter; public SmartphoneStartView(PlaceNavigator navigator) { stage = new Stage(navigator); @@ -38,12 +36,12 @@ public class SmartphoneStartView extends Composite implements StartView { } @Override - public void setFeaturedEvents(List> featuredEvents) { + public void setFeaturedEvents(List> featuredEvents) { stage.setFeaturedEvents(featuredEvents); } @Override - public void setRecentEvents(List recentEvents) { + public void setRecentEvents(List recentEvents) { mainEvents.setRecentEvents(recentEvents); mainMedia.setRecentEvents(recentEvents); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.ui.xml index 750f7d032ac..b7e1ef6bbb3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/SmartphoneStartView.ui.xml @@ -9,7 +9,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartActivity.java index 912c438e8b3..13a0adddae2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartActivity.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.home.client.place.start; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.List; @@ -8,8 +10,9 @@ import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.client.shared.placeholder.Placeholder; import com.sap.sailing.gwt.home.client.shared.stage.StageEventType; -import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sse.common.Util.Pair; public class StartActivity extends AbstractActivity { @@ -20,13 +23,15 @@ public class StartActivity extends AbstractActivity { } @Override - public void start(AcceptsOneWidget panel, EventBus eventBus) { - final StartView view = clientFactory.createStartView(); - panel.setWidget(view.asWidget()); + public void start(final AcceptsOneWidget panel, EventBus eventBus) { + panel.setWidget(new Placeholder()); - clientFactory.getSailingService().getEvents(new AsyncCallback>() { + clientFactory.getSailingService().getPublicEventsOfAllSailingServers(new AsyncCallback>() { @Override - public void onSuccess(List result) { + public void onSuccess(List result) { + final StartView view = clientFactory.createStartView(); + panel.setWidget(view.asWidget()); + fillStartPageEvents(view, result); } @@ -37,22 +42,21 @@ public class StartActivity extends AbstractActivity { } @SuppressWarnings("deprecation") - protected void fillStartPageEvents(StartView view, List events) { - List> featuredEvents = new ArrayList>(); + protected void fillStartPageEvents(StartView view, List events) { + List> featuredEvents = new ArrayList>(); - List recentEventsOfSameYear = new ArrayList(); - List upcomingSoonEvents = new ArrayList(); - List popularEvents = new ArrayList(); + List recentEventsOfSameYear = new ArrayList(); + List upcomingSoonEvents = new ArrayList(); + List popularEvents = new ArrayList(); Date now = new Date(); int currentYear = now.getYear(); - final int MAX_STAGE_EVENTS = 2; + final int MAX_STAGE_EVENTS = 4; final long FOUR_WEEK_IN_MS = 4L * (1000 * 60 * 60 * 24 * 7); - for(EventDTO event: events) { - // ignore events with no start and end date + for(EventBaseDTO event: events) { if(event.startDate != null && event.endDate != null) { if (now.after(event.startDate) && now.before(event.endDate)) { - featuredEvents.add(new Pair(StageEventType.RUNNING, event)); + featuredEvents.add(new Pair(StageEventType.RUNNING, event)); } else if (event.startDate.after(now) && event.startDate.getTime() - now.getTime() < FOUR_WEEK_IN_MS) { upcomingSoonEvents.add(event); } else if (event.endDate.before(now) && event.endDate.getYear() == currentYear) { @@ -72,15 +76,38 @@ public class StartActivity extends AbstractActivity { fillingUpEventsList(MAX_STAGE_EVENTS, featuredEvents, StageEventType.POPULAR, recentEventsOfSameYear); } + Collections.sort(featuredEvents, new FeaturedEventsComparator()); + view.setFeaturedEvents(featuredEvents); view.setRecentEvents(recentEventsOfSameYear); } - private void fillingUpEventsList(int maxAmountOfElements, List> resultList, StageEventType type, List listToTakeElementsFrom) { + private void fillingUpEventsList(int maxAmountOfElements, List> resultList, StageEventType type, List listToTakeElementsFrom) { int maxElementsToFill = maxAmountOfElements - resultList.size(); int elementsToTransfer = listToTakeElementsFrom.size() > maxElementsToFill ? maxElementsToFill : listToTakeElementsFrom.size(); for(int i = 0; i < elementsToTransfer; i++) { - resultList.add(new Pair(type, listToTakeElementsFrom.get(i))); + resultList.add(new Pair(type, listToTakeElementsFrom.get(i))); } } + + /** + * Comparator for sorting a pair of event and stageType first by order number of stage type and then by event start date. + * @author Frank + * + */ + private class FeaturedEventsComparator implements Comparator> { + + @Override + public int compare(Pair eventAndStageType1, Pair eventAndStageType2) { + int result; + if(eventAndStageType1.getA().ordinal() == eventAndStageType2.getA().ordinal()) { + result = eventAndStageType1.getB().startDate.compareTo(eventAndStageType2.getB().startDate); + } else { + result = eventAndStageType1.getA().ordinal() - eventAndStageType2.getA().ordinal(); + } + + return result; + } + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartView.java index 1a22a8e509c..89ef4422020 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/StartView.java @@ -4,13 +4,13 @@ import java.util.List; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.home.client.shared.stage.StageEventType; -import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sse.common.Util.Pair; public interface StartView { Widget asWidget(); - void setFeaturedEvents(List> featuredEvents); + void setFeaturedEvents(List> featuredEvents); - void setRecentEvents(List recentEvents); + void setRecentEvents(List recentEvents); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.java index bdfa661fb0a..1e31a33b428 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.java @@ -10,10 +10,9 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.home.client.app.PlaceNavigator; import com.sap.sailing.gwt.home.client.shared.mainevents.MainEvents; import com.sap.sailing.gwt.home.client.shared.mainmedia.MainMedia; -import com.sap.sailing.gwt.home.client.shared.socialfooter.SocialFooter; import com.sap.sailing.gwt.home.client.shared.stage.Stage; import com.sap.sailing.gwt.home.client.shared.stage.StageEventType; -import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sse.common.Util.Pair; public class TabletAndDesktopStartView extends Composite implements StartView { @@ -26,8 +25,7 @@ public class TabletAndDesktopStartView extends Composite implements StartView { // @UiField(provided=true) MainSponsors mainSponsors; @UiField(provided=true) MainEvents mainEvents; @UiField(provided=true) MainMedia mainMedia; - @UiField SocialFooter socialFooter; - + public TabletAndDesktopStartView(PlaceNavigator navigator) { stage = new Stage(navigator); // mainSponsors = new MainSponsors(navigator); @@ -38,13 +36,15 @@ public class TabletAndDesktopStartView extends Composite implements StartView { } @Override - public void setFeaturedEvents(List> featuredEvents) { + public void setFeaturedEvents(List> featuredEvents) { stage.setFeaturedEvents(featuredEvents); + mainMedia.setFeaturedEvents(featuredEvents); } @Override - public void setRecentEvents(List recentEvents) { + public void setRecentEvents(List recentEvents) { mainEvents.setRecentEvents(recentEvents); mainMedia.setRecentEvents(recentEvents); } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.ui.xml index fe17dfbe93c..51dee5455b0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/start/TabletAndDesktopStartView.ui.xml @@ -6,10 +6,12 @@ - + - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/Countdown.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/Countdown.java similarity index 77% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/Countdown.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/Countdown.java index c5835ab2a97..0cab44564f9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/Countdown.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/Countdown.java @@ -1,9 +1,11 @@ -package com.sap.sailing.gwt.ui.common.client; +package com.sap.sailing.gwt.home.client.shared; +import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Timer; import com.sap.sailing.domain.common.Duration; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; /** * A countdown notifying about changes in the two most significant time units. I.e. days+hours or hours+minutes or minutes+seconds or seconds only. @@ -24,6 +26,7 @@ public class Countdown { public enum Unit {DAYS, HOURS, MINUTES, SECONDS} public static class RemainingTime { + private static TextMessages i18n = GWT.create(TextMessages.class); public RemainingTime(long value, Unit unit) { this.value = value; this.unit = unit; @@ -31,6 +34,38 @@ public class Countdown { public final long value; public final Unit unit; + public String unitI18n() { + if (value == 1) { + switch (unit) { + case DAYS: + return i18n.countdownDay(); + case HOURS: + return i18n.countdownHour(); + case MINUTES: + return i18n.countdownMinute(); + case SECONDS: + return i18n.countdownSecond(); + default: + return "UNKNOWN"; + + } + } else { + switch (unit) { + case DAYS: + return i18n.countdownDays(); + case HOURS: + return i18n.countdownHours(); + case MINUTES: + return i18n.countdownMinutes(); + case SECONDS: + return i18n.countdownSeconds(); + default: + return "UNKNOWN"; + } + + } + } + public static boolean equal(RemainingTime t1, RemainingTime t2) { if (t1 == null) { if (t2 == null) { @@ -62,7 +97,7 @@ public class Countdown { * @param zeroDate * @param countdownListener */ - Countdown(TimePoint zeroDate, CountdownListener countdownListener, boolean dontSchedule) { + public Countdown(TimePoint zeroDate, CountdownListener countdownListener, boolean dontSchedule) { this.zeroDate = zeroDate; this.countdownListener = countdownListener; update(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/EventDatesFormatterUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/EventDatesFormatterUtil.java index add95120f06..d3c52128a10 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/EventDatesFormatterUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/EventDatesFormatterUtil.java @@ -15,11 +15,19 @@ public class EventDatesFormatterUtil { private final static DateTimeFormat monthFormat = DateTimeFormat.getFormat("MMMM"); private final static DateTimeFormat yearFormat = DateTimeFormat.getFormat("yyyy"); + private final static int ONE_DAY = 24 * 60 * 60 * 1000; + @SuppressWarnings("deprecation") public static String formatDateRangeWithYear(Date from, Date to) { String result = ""; if(from.getMonth() == to.getMonth()) { - result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to) + ", " + yearFormat.format(from); + // same month + if(from.getDay() == to.getDay() && to.getTime() - to.getTime() <= ONE_DAY) { + // same day + result = monthFormat.format(from) + " " + dayFormat.format(from) + ", " + yearFormat.format(from); + } else { + result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to) + ", " + yearFormat.format(from); + } } else { result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to) + ", " + yearFormat.format(from); } @@ -31,7 +39,13 @@ public class EventDatesFormatterUtil { public static String formatDateRangeWithoutYear(Date from, Date to) { String result = ""; if(from.getMonth() == to.getMonth()) { - result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to); + // same month + if(from.getDay() == to.getDay() && to.getTime() - to.getTime() <= ONE_DAY) { + // same day + result = monthFormat.format(from) + " " + dayFormat.format(from); + } else { + result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to); + } } else { result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/LongNamesUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/LongNamesUtil.java new file mode 100644 index 00000000000..03a7eb6a7cb --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/LongNamesUtil.java @@ -0,0 +1,59 @@ +package com.sap.sailing.gwt.home.client.shared; + +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; + +/** + * A utility class for handling long names + * @author Frank + * + */ +public class LongNamesUtil { + private static String NAME_SPLIT_RULE1 = " - "; + + public static String shortenLongName(String name, int maxLength) { + String result = name; + if (name.length() > maxLength) { + name = name.substring(0, maxLength - 3) + "..."; + } + return result; + } + + public static SafeHtml breakLongName(String name) { + SafeHtmlBuilder builder = new SafeHtmlBuilder(); + if(name != null) { + if (name.contains(NAME_SPLIT_RULE1)) { + String[] splittedName = name.split(NAME_SPLIT_RULE1); + for (int i = 0; i < splittedName.length; i++) { + builder.appendEscaped(splittedName[i]); + if (i != splittedName.length - 1) { + builder.appendHtmlConstant("
"); + } + } + } else { + builder.appendEscaped(name); + } + } else { + builder.appendEscaped(""); + } + return builder.toSafeHtml(); + } + + /** + * Temp -> remove as soon as we have a display name for a leaderboardGroup + */ + public static String shortenLeaderboardGroupName(String eventName, String leaderboardGroupName) { + String result = leaderboardGroupName; + if (result.startsWith(eventName) && !eventName.equals(leaderboardGroupName)) { + result = result.substring(eventName.length(), result.length()); + result = result.trim(); + + if (result.startsWith("-") || result.startsWith("/")) { + result = result.substring(1, result.length()); + result = result.trim(); + } + } + return result; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.css new file mode 100644 index 00000000000..797f79e0d8b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.css @@ -0,0 +1,15 @@ +.error_content { + margin-top: 3em; + margin-bottom: 3em; +} +.error_message { + font-weight: bold; + font-size: 20px; +} +.error_message_detail { + font-size: 15px; +} +.reload_page_message { + font-size: 20px; + margin-right: 20px; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.java new file mode 100644 index 00000000000..f07a833007f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.java @@ -0,0 +1,40 @@ +package com.sap.sailing.gwt.home.client.shared.error; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; + +public class ErrorMessage extends Composite { + + interface ErrorUiBinder extends UiBinder { + } + + private static ErrorUiBinder uiBinder = GWT.create(ErrorUiBinder.class); + + @UiField DivElement errorMessage; + @UiField DivElement errorMessageDetail; + @UiField Anchor reloadPageAnchor; + + public ErrorMessage(String detailMessage, Throwable errorReason) { + ErrorMessageResources.INSTANCE.css().ensureInjected(); + initWidget(uiBinder.createAndBindUi(this)); + + this.setHeight(Window.getClientHeight() + "px"); + errorMessage.setInnerText(TextMessages.INSTANCE.errorMessageLoadingData()); + + Window.setStatus(detailMessage); + } + + @UiHandler("reloadPageAnchor") + void reloadPage(ClickEvent e) { + Window.Location.reload(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.ui.xml new file mode 100644 index 00000000000..17cfbe94034 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.ui.xml @@ -0,0 +1,22 @@ + + + + + + +
+
+
+
+
+
+
+ + +
+
+
+
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessageResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessageResources.java new file mode 100644 index 00000000000..f995675cd40 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/error/ErrorMessageResources.java @@ -0,0 +1,19 @@ +package com.sap.sailing.gwt.home.client.shared.error; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; + +public interface ErrorMessageResources extends ClientBundle { + public static final ErrorMessageResources INSTANCE = GWT.create(ErrorMessageResources.class); + + @Source("com/sap/sailing/gwt/home/client/shared/error/ErrorMessage.css") + LocalCss css(); + + public interface LocalCss extends CssResource { + String error_content(); + String error_message(); + String error_message_detail(); + String reload_page_message(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.java index 31eae3acd14..df38170fa80 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.Map.Entry; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.http.client.UrlBuilder; @@ -22,6 +24,7 @@ public class Footer extends Composite { private static FooterPanelUiBinder uiBinder = GWT.create(FooterPanelUiBinder.class); @UiField Anchor changeLanguageLink; + @UiField DivElement languageSelectionDiv; private final Map localeAndLanguages; @@ -40,6 +43,7 @@ public class Footer extends Composite { initWidget(uiBinder.createAndBindUi(this)); + languageSelectionDiv.getStyle().setDisplay(Display.NONE); updateUI(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.ui.xml index b3cbffafd8d..df25806aa4a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/footer/Footer.ui.xml @@ -23,7 +23,9 @@
- : +
+ : +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.java index 1716c150233..8bd856a6fce 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.List; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.KeyCodes; @@ -12,6 +13,9 @@ import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Button; @@ -19,11 +23,13 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.home.client.app.PlaceNavigator; +import com.sap.sailing.gwt.home.client.i18n.TextMessages; public class Header extends Composite { @UiField Anchor startPageLink; @UiField Anchor eventsPageLink; @UiField Anchor solutionsPageLink; + @UiField AnchorElement homeLink; // @UiField Anchor sponsoringPageLink; @UiField TextBox searchText; @@ -37,7 +43,7 @@ public class Header extends Composite { private static HeaderUiBinder uiBinder = GWT.create(HeaderUiBinder.class); - public Header(PlaceNavigator navigator) { + public Header(final PlaceNavigator navigator) { this.navigator = navigator; HeaderResources.INSTANCE.css().ensureInjected(); @@ -46,7 +52,7 @@ public class Header extends Composite { initWidget(uiBinder.createAndBindUi(this)); links = Arrays.asList(new Anchor[] { startPageLink, eventsPageLink, solutionsPageLink }); - searchText.getElement().setAttribute("placeholder", "Search SAPSailing.com"); + searchText.getElement().setAttribute("placeholder", TextMessages.INSTANCE.headerSearchPlaceholder()); searchText.addKeyPressHandler(new KeyPressHandler() { @Override public void onKeyPress(KeyPressEvent event) { @@ -55,6 +61,18 @@ public class Header extends Composite { } } }); + + Event.sinkEvents(homeLink, Event.ONCLICK); + Event.setEventListener(homeLink, new EventListener() { + @Override + public void onBrowserEvent(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONCLICK: + navigator.goToHome(); + break; + } + } + }); } @UiHandler("startPageLink") @@ -66,11 +84,13 @@ public class Header extends Composite { @UiHandler("eventsPageLink") public void goToEvents(ClickEvent e) { navigator.goToEvents(); + setActiveLink(eventsPageLink); } @UiHandler("solutionsPageLink") public void goToSolutions(ClickEvent e) { navigator.goToSolutions(); + setActiveLink(solutionsPageLink); } // @UiHandler("sponsoringPageLink") @@ -81,7 +101,7 @@ public class Header extends Composite { @UiHandler("searchButton") void searchButtonClick(ClickEvent event) { if(searchText.getText().isEmpty()) { - Window.alert("Please enter a search term."); + Window.alert(TextMessages.INSTANCE.pleaseEnterASearchTerm()); } else { navigator.goToSearchResult(searchText.getText()); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.ui.xml index d63fc69e7ed..d0360d6214b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/shared/header/Header.ui.xml @@ -9,10 +9,11 @@
- + + +

Sailing Analytics

-