From f4686bbe852a4722f114900f457d07b85d44ad81 Mon Sep 17 00:00:00 2001 From: Benjamin Barth Date: Wed, 2 Dec 2015 17:56:12 +0100 Subject: [PATCH] Added LeaderboardType calculation to set it in LeaderboardDTOs --- .../impl/AbstractSimpleLeaderboardImpl.java | 5 + .../impl/FlexibleLeaderboardImpl.java | 678 +++++++++--------- .../impl/RegattaLeaderboardImpl.java | 240 ++++--- .../meta/FlexibleMetaLeaderboard.java | 134 ++-- .../meta/LeaderboardGroupMetaLeaderboard.java | 190 ++--- 5 files changed, 638 insertions(+), 609 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index bdf437fe905..08d5fe903d9 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 @@ -42,6 +42,7 @@ 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; +import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.MaxPointsReason; @@ -1218,6 +1219,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race this.getScoreCorrection() == null ? null : this.getScoreCorrection().getComment(), this.getScoringScheme() == null ? null : this.getScoringScheme().getType(), this .getScoringScheme().isHigherBetter(), new UUIDGenerator(), addOverallDetails); + result.type = getLeaderboardType(); result.competitors = new ArrayList(); result.name = this.getName(); result.competitorDisplayNames = new HashMap(); @@ -1929,4 +1931,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race public NumberOfCompetitorsInLeaderboardFetcher getNumberOfCompetitorsInLeaderboardFetcher() { return new NumberOfCompetitorsFetcherImpl(); } + + protected abstract LeaderboardType getLeaderboardType(); + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index ab37c03d57d..62d50860e6a 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -1,336 +1,342 @@ -package com.sap.sailing.domain.leaderboard.impl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.impl.AbstractRaceExecutionOrderProvider; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; -import com.sap.sailing.domain.regattalike.BaseRegattaLikeImpl; -import com.sap.sailing.domain.regattalike.FlexibleLeaderboardAsRegattaLikeIdentifier; -import com.sap.sailing.domain.regattalike.IsRegattaLike; -import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; -import com.sap.sailing.domain.regattalike.RegattaLikeListener; -import com.sap.sailing.domain.regattalog.RegattaLogStore; -import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; -import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.Duration; - -/** - * A leaderboard implementation that allows users to flexibly configure which columns exist. No constraints need to be observed regarding - * the columns belonging to the same regatta or even boat class.

- * - * The flexible leaderboard listens as {@link RaceColumnListener} on all its {@link RaceColumn}s and forwards all events to - * all {@link RaceColumnListener}s subscribed with this leaderboard. - * - * @author Axel Uhl (D043530) - * - */ -public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements FlexibleLeaderboard { - private static Logger logger = Logger.getLogger(FlexibleLeaderboardImpl.class.getName()); - - protected static final DefaultFleetImpl defaultFleet = new DefaultFleetImpl(); - private static final long serialVersionUID = -5708971849158747846L; - private final List races; - private final ScoringScheme scoringScheme; - private String name; - private transient RaceLogStore raceLogStore; - private CourseArea courseArea; - private RaceExecutionOrderProvider raceExecutionOrderProvider; - - /** - * @see RegattaLog for the reason why the leaderboard manages a {@code RegattaLog} - */ - private final IsRegattaLike regattaLikeHelper; - - public FlexibleLeaderboardImpl(String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, - ScoringScheme scoringScheme, CourseArea courseArea) { - this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, - name, resultDiscardingRule, scoringScheme, courseArea); - } - - public FlexibleLeaderboardImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, - String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, - ScoringScheme scoringScheme, CourseArea courseArea) { - super(resultDiscardingRule); - this.scoringScheme = scoringScheme; - if (name == null) { - throw new IllegalArgumentException("A leaderboard's name must not be null"); - } - this.name = name; - this.races = new ArrayList<>(); - this.raceLogStore = raceLogStore; - this.courseArea = courseArea; - this.regattaLikeHelper = new BaseRegattaLikeImpl(new FlexibleLeaderboardAsRegattaLikeIdentifier(this), regattaLogStore) { - private static final long serialVersionUID = 4082392360832548953L; - - @Override - public RaceColumn getRaceColumnByName(String raceColumnName) { - return getRaceColumnByName(raceColumnName); - } - }; - this.raceExecutionOrderProvider = new RaceExecutionOrderCache(); - } - - /** - * Deserialization has to be maintained in lock-step with {@link #writeObject(ObjectOutputStream) serialization}. - * When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an - * {@link EmptyRaceLogStore} is used for the de-serialized instance. A new {@link RaceLogInformation} is - * assembled for this empty race log and applied to all columns. - */ - private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { - ois.defaultReadObject(); - raceLogStore = EmptyRaceLogStore.INSTANCE; - for (RaceColumn column : getRaceColumns()) { - column.setRaceLogInformation(raceLogStore, new FlexibleLeaderboardAsRegattaLikeIdentifier(this)); - } - } - - protected Object readResolve() throws ObjectStreamException { - raceExecutionOrderProvider.triggerUpdate(); - return this; - } - - @Override - public String getName() { - return name; - } - - /** - * @param newName must not be null - */ - public void setName(String newName) { - if (newName == null) { - throw new IllegalArgumentException("A leaderboard's name must not be null"); - } - this.name = newName; - } - - @Override - public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace) { - FlexibleRaceColumn column = addRaceColumn(columnName, medalRace, /* logAlreadyExistingColumn */false); - column.setTrackedRace(defaultFleet, race); // triggers listeners because this object was registered above as - // race column listener on the column - return column; - } - - @Override - public FlexibleRaceColumn addRaceColumn(String name, boolean medalRace) { - return addRaceColumn(name, medalRace, /* logAlreadyExistingColumn */true); - } - - private FlexibleRaceColumn addRaceColumn(String name, boolean medalRace, boolean logAlreadyExistingColumn) { - FlexibleRaceColumn column = getRaceColumnByName(name); - if (column != null) { - if (logAlreadyExistingColumn) { - final String msg = "Trying to create race column with duplicate name " + name + " in leaderboard " + getName(); - logger.severe(msg); - } - } else { - column = createRaceColumn(name, medalRace); - column.addRaceColumnListener(this); - races.add(column); - column.setRaceLogInformation(raceLogStore, new FlexibleLeaderboardAsRegattaLikeIdentifier(this)); - getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(column); - } - return column; - } - - @Override - public FlexibleRaceColumn getRaceColumnByName(String columnName) { - return (FlexibleRaceColumn) super.getRaceColumnByName(columnName); - } - - @Override - public Fleet getFleet(String fleetName) { - Fleet result; - if (fleetName == null) { - result = defaultFleet; - } else { - result = super.getFleet(fleetName); - } - return result; - } - - @Override - public void removeRaceColumn(String columnName) { - final FlexibleRaceColumn raceColumn = getRaceColumnByName(columnName); - if (raceColumn != null) { - for (Fleet fleet : raceColumn.getFleets()) { - raceLogStore.removeRaceLog(raceColumn.getRaceLogIdentifier(fleet)); - if (raceColumn.getTrackedRace(fleet) != null) { - raceColumn.getTrackedRace(fleet).detachRaceExecutionOrderProvider(raceExecutionOrderProvider); - } - } - races.remove(raceColumn); - getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn); - raceColumn.removeRaceColumnListener(this); - } - } - - @Override - public Iterable getRaceColumns() { - final Iterable result; - if (races != null) { - result = Collections.unmodifiableCollection(new ArrayList(races)); - } else { - result = null; - } - return result; - } - - protected RaceColumnImpl createRaceColumn(String column, boolean medalRace) { - return new RaceColumnImpl(column, medalRace, raceExecutionOrderProvider); - } - - protected Iterable turnNullOrEmptyFleetsIntoDefaultFleet(Fleet... fleets) { - Iterable theFleets; - if (fleets == null || fleets.length == 0) { - Fleet defaultfleetCasted = defaultFleet; - theFleets = Collections.singleton(defaultfleetCasted); - } else { - theFleets = Arrays.asList(fleets); - } - return theFleets; - } - - @Override - public void moveRaceColumnUp(String name) { - FlexibleRaceColumn race = null; - for (FlexibleRaceColumn r : races) { - if (r.getName().equals(name)) { - race = r; - } - } - if (race != null) { - int index = 0; - index = races.lastIndexOf(race); - index--; - if (index >= 0) { - races.remove(race); - races.add(index, race); - getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(race, index); - } - } - } - - @Override - public void moveRaceColumnDown(String name) { - FlexibleRaceColumn race = null; - for (FlexibleRaceColumn r : races) { - if (r.getName().equals(name)) { - race = r; - } - } - if (race != null) { - int index = 0; - index = races.lastIndexOf(race); - if (index != -1) { - index++; - if (index < races.size()) { - races.remove(race); - races.add(index, race); - getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(race, index); - } - } - } - } - - @Override - public void updateIsMedalRace(String raceName, boolean isMedalRace) { - FlexibleRaceColumn race = null; - for (FlexibleRaceColumn r : races) { - if (r.getName().equals(raceName)) - race = r; - } - if (race != null) { - race.setIsMedalRace(isMedalRace); - } - } - - @Override - public ScoringScheme getScoringScheme() { - return scoringScheme; - } - - @Override - public CourseArea getDefaultCourseArea() { - return courseArea; - } - - @Override - public void setDefaultCourseArea(CourseArea newCourseArea) { - this.courseArea = newCourseArea; - } - - @Override - public IsRegattaLike getRegattaLike() { - return regattaLikeHelper; - } - - @Override - public RegattaLog getRegattaLog() { - return regattaLikeHelper.getRegattaLog(); - } - - @Override - public RegattaLikeIdentifier getRegattaLikeIdentifier() { - return regattaLikeHelper.getRegattaLikeIdentifier(); - } - - @Override - public void addListener(RegattaLikeListener listener) { - regattaLikeHelper.addListener(listener); - } - - @Override - public void removeListener(RegattaLikeListener listener) { - regattaLikeHelper.removeListener(listener); - } - - @Override - public Double getTimeOnTimeFactor(Competitor competitor) { - return regattaLikeHelper.getTimeOnTimeFactor(competitor); - } - - @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { - return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor); - } - - private class RaceExecutionOrderCache extends AbstractRaceExecutionOrderProvider { - private static final long serialVersionUID = 652833386555762661L; - - public RaceExecutionOrderCache() { - super(); - addRaceColumnListener(this); - } - - @Override - protected Map> getRaceColumnsOfSeries() { - final Map> result = new HashMap<>(); - result.put(FlexibleLeaderboardImpl.defaultFleet, getRaceColumns()); - return result; - } - } -} +package com.sap.sailing.domain.leaderboard.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.impl.AbstractRaceExecutionOrderProvider; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore; +import com.sap.sailing.domain.regattalike.BaseRegattaLikeImpl; +import com.sap.sailing.domain.regattalike.FlexibleLeaderboardAsRegattaLikeIdentifier; +import com.sap.sailing.domain.regattalike.IsRegattaLike; +import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; +import com.sap.sailing.domain.regattalike.RegattaLikeListener; +import com.sap.sailing.domain.regattalog.RegattaLogStore; +import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore; +import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Duration; + +/** + * A leaderboard implementation that allows users to flexibly configure which columns exist. No constraints need to be observed regarding + * the columns belonging to the same regatta or even boat class.

+ * + * The flexible leaderboard listens as {@link RaceColumnListener} on all its {@link RaceColumn}s and forwards all events to + * all {@link RaceColumnListener}s subscribed with this leaderboard. + * + * @author Axel Uhl (D043530) + * + */ +public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements FlexibleLeaderboard { + private static Logger logger = Logger.getLogger(FlexibleLeaderboardImpl.class.getName()); + + protected static final DefaultFleetImpl defaultFleet = new DefaultFleetImpl(); + private static final long serialVersionUID = -5708971849158747846L; + private final List races; + private final ScoringScheme scoringScheme; + private String name; + private transient RaceLogStore raceLogStore; + private CourseArea courseArea; + private RaceExecutionOrderProvider raceExecutionOrderProvider; + + /** + * @see RegattaLog for the reason why the leaderboard manages a {@code RegattaLog} + */ + private final IsRegattaLike regattaLikeHelper; + + public FlexibleLeaderboardImpl(String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, + ScoringScheme scoringScheme, CourseArea courseArea) { + this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, + name, resultDiscardingRule, scoringScheme, courseArea); + } + + public FlexibleLeaderboardImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, + String name, ThresholdBasedResultDiscardingRule resultDiscardingRule, + ScoringScheme scoringScheme, CourseArea courseArea) { + super(resultDiscardingRule); + this.scoringScheme = scoringScheme; + if (name == null) { + throw new IllegalArgumentException("A leaderboard's name must not be null"); + } + this.name = name; + this.races = new ArrayList<>(); + this.raceLogStore = raceLogStore; + this.courseArea = courseArea; + this.regattaLikeHelper = new BaseRegattaLikeImpl(new FlexibleLeaderboardAsRegattaLikeIdentifier(this), regattaLogStore) { + private static final long serialVersionUID = 4082392360832548953L; + + @Override + public RaceColumn getRaceColumnByName(String raceColumnName) { + return getRaceColumnByName(raceColumnName); + } + }; + this.raceExecutionOrderProvider = new RaceExecutionOrderCache(); + } + + /** + * Deserialization has to be maintained in lock-step with {@link #writeObject(ObjectOutputStream) serialization}. + * When de-serializing, a possibly remote {@link #raceLogStore} is ignored because it is transient. Instead, an + * {@link EmptyRaceLogStore} is used for the de-serialized instance. A new {@link RaceLogInformation} is + * assembled for this empty race log and applied to all columns. + */ + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + raceLogStore = EmptyRaceLogStore.INSTANCE; + for (RaceColumn column : getRaceColumns()) { + column.setRaceLogInformation(raceLogStore, new FlexibleLeaderboardAsRegattaLikeIdentifier(this)); + } + } + + protected Object readResolve() throws ObjectStreamException { + raceExecutionOrderProvider.triggerUpdate(); + return this; + } + + @Override + public String getName() { + return name; + } + + /** + * @param newName must not be null + */ + public void setName(String newName) { + if (newName == null) { + throw new IllegalArgumentException("A leaderboard's name must not be null"); + } + this.name = newName; + } + + @Override + public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace) { + FlexibleRaceColumn column = addRaceColumn(columnName, medalRace, /* logAlreadyExistingColumn */false); + column.setTrackedRace(defaultFleet, race); // triggers listeners because this object was registered above as + // race column listener on the column + return column; + } + + @Override + public FlexibleRaceColumn addRaceColumn(String name, boolean medalRace) { + return addRaceColumn(name, medalRace, /* logAlreadyExistingColumn */true); + } + + private FlexibleRaceColumn addRaceColumn(String name, boolean medalRace, boolean logAlreadyExistingColumn) { + FlexibleRaceColumn column = getRaceColumnByName(name); + if (column != null) { + if (logAlreadyExistingColumn) { + final String msg = "Trying to create race column with duplicate name " + name + " in leaderboard " + getName(); + logger.severe(msg); + } + } else { + column = createRaceColumn(name, medalRace); + column.addRaceColumnListener(this); + races.add(column); + column.setRaceLogInformation(raceLogStore, new FlexibleLeaderboardAsRegattaLikeIdentifier(this)); + getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(column); + } + return column; + } + + @Override + public FlexibleRaceColumn getRaceColumnByName(String columnName) { + return (FlexibleRaceColumn) super.getRaceColumnByName(columnName); + } + + @Override + public Fleet getFleet(String fleetName) { + Fleet result; + if (fleetName == null) { + result = defaultFleet; + } else { + result = super.getFleet(fleetName); + } + return result; + } + + @Override + public void removeRaceColumn(String columnName) { + final FlexibleRaceColumn raceColumn = getRaceColumnByName(columnName); + if (raceColumn != null) { + for (Fleet fleet : raceColumn.getFleets()) { + raceLogStore.removeRaceLog(raceColumn.getRaceLogIdentifier(fleet)); + if (raceColumn.getTrackedRace(fleet) != null) { + raceColumn.getTrackedRace(fleet).detachRaceExecutionOrderProvider(raceExecutionOrderProvider); + } + } + races.remove(raceColumn); + getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn); + raceColumn.removeRaceColumnListener(this); + } + } + + @Override + public Iterable getRaceColumns() { + final Iterable result; + if (races != null) { + result = Collections.unmodifiableCollection(new ArrayList(races)); + } else { + result = null; + } + return result; + } + + protected RaceColumnImpl createRaceColumn(String column, boolean medalRace) { + return new RaceColumnImpl(column, medalRace, raceExecutionOrderProvider); + } + + protected Iterable turnNullOrEmptyFleetsIntoDefaultFleet(Fleet... fleets) { + Iterable theFleets; + if (fleets == null || fleets.length == 0) { + Fleet defaultfleetCasted = defaultFleet; + theFleets = Collections.singleton(defaultfleetCasted); + } else { + theFleets = Arrays.asList(fleets); + } + return theFleets; + } + + @Override + public void moveRaceColumnUp(String name) { + FlexibleRaceColumn race = null; + for (FlexibleRaceColumn r : races) { + if (r.getName().equals(name)) { + race = r; + } + } + if (race != null) { + int index = 0; + index = races.lastIndexOf(race); + index--; + if (index >= 0) { + races.remove(race); + races.add(index, race); + getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(race, index); + } + } + } + + @Override + public void moveRaceColumnDown(String name) { + FlexibleRaceColumn race = null; + for (FlexibleRaceColumn r : races) { + if (r.getName().equals(name)) { + race = r; + } + } + if (race != null) { + int index = 0; + index = races.lastIndexOf(race); + if (index != -1) { + index++; + if (index < races.size()) { + races.remove(race); + races.add(index, race); + getRaceColumnListeners().notifyListenersAboutRaceColumnMoved(race, index); + } + } + } + } + + @Override + public void updateIsMedalRace(String raceName, boolean isMedalRace) { + FlexibleRaceColumn race = null; + for (FlexibleRaceColumn r : races) { + if (r.getName().equals(raceName)) + race = r; + } + if (race != null) { + race.setIsMedalRace(isMedalRace); + } + } + + @Override + public ScoringScheme getScoringScheme() { + return scoringScheme; + } + + @Override + public CourseArea getDefaultCourseArea() { + return courseArea; + } + + @Override + public void setDefaultCourseArea(CourseArea newCourseArea) { + this.courseArea = newCourseArea; + } + + @Override + public IsRegattaLike getRegattaLike() { + return regattaLikeHelper; + } + + @Override + public RegattaLog getRegattaLog() { + return regattaLikeHelper.getRegattaLog(); + } + + @Override + public RegattaLikeIdentifier getRegattaLikeIdentifier() { + return regattaLikeHelper.getRegattaLikeIdentifier(); + } + + @Override + public void addListener(RegattaLikeListener listener) { + regattaLikeHelper.addListener(listener); + } + + @Override + public void removeListener(RegattaLikeListener listener) { + regattaLikeHelper.removeListener(listener); + } + + @Override + public Double getTimeOnTimeFactor(Competitor competitor) { + return regattaLikeHelper.getTimeOnTimeFactor(competitor); + } + + @Override + public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { + return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor); + } + + private class RaceExecutionOrderCache extends AbstractRaceExecutionOrderProvider { + private static final long serialVersionUID = 652833386555762661L; + + public RaceExecutionOrderCache() { + super(); + addRaceColumnListener(this); + } + + @Override + protected Map> getRaceColumnsOfSeries() { + final Map> result = new HashMap<>(); + result.put(FlexibleLeaderboardImpl.defaultFleet, getRaceColumns()); + return result; + } + } + + @Override + protected LeaderboardType getLeaderboardType() { + return LeaderboardType.FlexibleLeaderboard; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index a6df854049f..d5af239cf6a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -1,117 +1,123 @@ -package com.sap.sailing.domain.leaderboard.impl; - -import java.util.ArrayList; -import java.util.List; - -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnInSeries; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.regattalike.IsRegattaLike; -import com.sap.sailing.domain.tracking.TrackedRace; - -/** - * A leaderboard that is based on the definition of a {@link Regatta} with its {@link Series} and {@link Fleet}. The regatta - * leaderboard listens to its {@link Regatta} as a {@link RaceColumnListener} and forwards all link/unlink events for - * {@link TrackedRace}s being linked to / unlinked from race columns to all {@link RaceColumnListener}s subscribed with - * this leaderboard. - * - * @author Axel Uhl (D043530) - * - */ -public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements RegattaLeaderboard { - private static final long serialVersionUID = 2370461218294770084L; - private final Regatta regatta; - - public RegattaLeaderboardImpl(Regatta regatta, ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(resultDiscardingRule); - this.regatta = regatta; - regatta.addRaceColumnListener(this); - } - - /** - * Updates the display name of this regatta leaderboard so that the regatta's name is no longer used as the default name. - */ - @Override - public void setName(String newName) { - setDisplayName(newName); - } - - @Override - public Regatta getRegatta() { - return regatta; - } - - @Override - public String getName() { - return getRegatta().getName(); - } - - @Override - public Iterable getRaceColumns() { - List result = new ArrayList(); - for (Series series : getRegatta().getSeries()) { - for (RaceColumn raceColumn : series.getRaceColumns()) { - result.add(raceColumn); - } - } - return result; - } - - @Override - public RaceColumnInSeries getRaceColumnByName(String columnName) { - return (RaceColumnInSeriesImpl) super.getRaceColumnByName(columnName); - } - - @Override - public ScoringScheme getScoringScheme() { - return regatta.getScoringScheme(); - } - - @Override - public CourseArea getDefaultCourseArea() { - return regatta.getDefaultCourseArea(); - } - - /** - * If the regatta' series {@link Regatta#definesSeriesDiscardThresholds() define} their own result discarding rules, this leaderboard uses - * a composite result discarding rule of type {@link PerSeriesResultDiscardingRuleImpl} that contains discards within each series according - * to the series' discarding rules. Otherwise, the default cross-leaderboard result discarding rule is obtained from the super class - * implementation. - */ - @Override - public ResultDiscardingRule getResultDiscardingRule() { - if (regatta.definesSeriesDiscardThresholds()) { - return new PerSeriesResultDiscardingRuleImpl(regatta); - } else { - return super.getResultDiscardingRule(); - } - } - - /** - * Delegates to {@link Regatta#getAllCompetitors()} which is expected to deliver all competitors from this - * leaderboard's regatta which includes those belonging to {@link RaceDefinition races} - * {@link Regatta#getAllRaces() belonging to the regatta} as well as competitors listed on the regatta's - * {@link RegattaLog}. - */ - @Override - public Iterable getAllCompetitors() { - return regatta.getAllCompetitors(); - } - - @Override - public IsRegattaLike getRegattaLike() { - return regatta; - } -} +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.ArrayList; +import java.util.List; + +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnInSeries; +import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.regattalike.IsRegattaLike; +import com.sap.sailing.domain.tracking.TrackedRace; + +/** + * A leaderboard that is based on the definition of a {@link Regatta} with its {@link Series} and {@link Fleet}. The regatta + * leaderboard listens to its {@link Regatta} as a {@link RaceColumnListener} and forwards all link/unlink events for + * {@link TrackedRace}s being linked to / unlinked from race columns to all {@link RaceColumnListener}s subscribed with + * this leaderboard. + * + * @author Axel Uhl (D043530) + * + */ +public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements RegattaLeaderboard { + private static final long serialVersionUID = 2370461218294770084L; + private final Regatta regatta; + + public RegattaLeaderboardImpl(Regatta regatta, ThresholdBasedResultDiscardingRule resultDiscardingRule) { + super(resultDiscardingRule); + this.regatta = regatta; + regatta.addRaceColumnListener(this); + } + + /** + * Updates the display name of this regatta leaderboard so that the regatta's name is no longer used as the default name. + */ + @Override + public void setName(String newName) { + setDisplayName(newName); + } + + @Override + public Regatta getRegatta() { + return regatta; + } + + @Override + public String getName() { + return getRegatta().getName(); + } + + @Override + public Iterable getRaceColumns() { + List result = new ArrayList(); + for (Series series : getRegatta().getSeries()) { + for (RaceColumn raceColumn : series.getRaceColumns()) { + result.add(raceColumn); + } + } + return result; + } + + @Override + public RaceColumnInSeries getRaceColumnByName(String columnName) { + return (RaceColumnInSeriesImpl) super.getRaceColumnByName(columnName); + } + + @Override + public ScoringScheme getScoringScheme() { + return regatta.getScoringScheme(); + } + + @Override + public CourseArea getDefaultCourseArea() { + return regatta.getDefaultCourseArea(); + } + + /** + * If the regatta' series {@link Regatta#definesSeriesDiscardThresholds() define} their own result discarding rules, this leaderboard uses + * a composite result discarding rule of type {@link PerSeriesResultDiscardingRuleImpl} that contains discards within each series according + * to the series' discarding rules. Otherwise, the default cross-leaderboard result discarding rule is obtained from the super class + * implementation. + */ + @Override + public ResultDiscardingRule getResultDiscardingRule() { + if (regatta.definesSeriesDiscardThresholds()) { + return new PerSeriesResultDiscardingRuleImpl(regatta); + } else { + return super.getResultDiscardingRule(); + } + } + + /** + * Delegates to {@link Regatta#getAllCompetitors()} which is expected to deliver all competitors from this + * leaderboard's regatta which includes those belonging to {@link RaceDefinition races} + * {@link Regatta#getAllRaces() belonging to the regatta} as well as competitors listed on the regatta's + * {@link RegattaLog}. + */ + @Override + public Iterable getAllCompetitors() { + return regatta.getAllCompetitors(); + } + + @Override + public IsRegattaLike getRegattaLike() { + return regatta; + } + + @Override + protected LeaderboardType getLeaderboardType() { + return LeaderboardType.RegattaLeaderboard; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/FlexibleMetaLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/FlexibleMetaLeaderboard.java index a7de5eb4c40..e7f9c04de2d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/FlexibleMetaLeaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/FlexibleMetaLeaderboard.java @@ -1,64 +1,70 @@ -package com.sap.sailing.domain.leaderboard.meta; - -import java.util.ArrayList; -import java.util.List; - -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sse.concurrent.LockUtil; -import com.sap.sse.concurrent.NamedReentrantReadWriteLock; - -public class FlexibleMetaLeaderboard extends AbstractMetaLeaderboard { - private static final long serialVersionUID = 789076326144062944L; - - private final List leaderboards; - - private final NamedReentrantReadWriteLock leaderboardsLock; - - public FlexibleMetaLeaderboard(String name, ScoringScheme scoringScheme, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(name, scoringScheme, resultDiscardingRule); - leaderboards = new ArrayList(); - leaderboardsLock = new NamedReentrantReadWriteLock("leaderboards collection of "+FlexibleMetaLeaderboard.class.getSimpleName()+" "+getName(), - /* fair */ false); - } - - @Override - public Iterable getLeaderboards() { - LockUtil.lockForRead(leaderboardsLock); - try { - return new ArrayList(leaderboards); - } finally { - LockUtil.unlockAfterRead(leaderboardsLock); - } - } - - public void addLeaderboard(Leaderboard leaderboard) { - LockUtil.lockForWrite(leaderboardsLock); - try { - leaderboards.add(leaderboard); - registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); - getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(getColumnForLeaderboard(leaderboard)); - } finally { - LockUtil.unlockAfterWrite(leaderboardsLock); - } - } - - public void removeLeaderboard(Leaderboard leaderboard) { - LockUtil.lockForWrite(leaderboardsLock); - try { - leaderboards.remove(leaderboard); - getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(getColumnForLeaderboard(leaderboard)); - unregisterScoreCorrectionChangeForwarder(leaderboard); - } finally { - LockUtil.unlockAfterWrite(leaderboardsLock); - } - } - - @Override - public CourseArea getDefaultCourseArea() { - return null; - } -} +package com.sap.sailing.domain.leaderboard.meta; + +import java.util.ArrayList; +import java.util.List; + +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sse.concurrent.LockUtil; +import com.sap.sse.concurrent.NamedReentrantReadWriteLock; + +public class FlexibleMetaLeaderboard extends AbstractMetaLeaderboard { + private static final long serialVersionUID = 789076326144062944L; + + private final List leaderboards; + + private final NamedReentrantReadWriteLock leaderboardsLock; + + public FlexibleMetaLeaderboard(String name, ScoringScheme scoringScheme, + ThresholdBasedResultDiscardingRule resultDiscardingRule) { + super(name, scoringScheme, resultDiscardingRule); + leaderboards = new ArrayList(); + leaderboardsLock = new NamedReentrantReadWriteLock("leaderboards collection of "+FlexibleMetaLeaderboard.class.getSimpleName()+" "+getName(), + /* fair */ false); + } + + @Override + public Iterable getLeaderboards() { + LockUtil.lockForRead(leaderboardsLock); + try { + return new ArrayList(leaderboards); + } finally { + LockUtil.unlockAfterRead(leaderboardsLock); + } + } + + public void addLeaderboard(Leaderboard leaderboard) { + LockUtil.lockForWrite(leaderboardsLock); + try { + leaderboards.add(leaderboard); + registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); + getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(getColumnForLeaderboard(leaderboard)); + } finally { + LockUtil.unlockAfterWrite(leaderboardsLock); + } + } + + public void removeLeaderboard(Leaderboard leaderboard) { + LockUtil.lockForWrite(leaderboardsLock); + try { + leaderboards.remove(leaderboard); + getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(getColumnForLeaderboard(leaderboard)); + unregisterScoreCorrectionChangeForwarder(leaderboard); + } finally { + LockUtil.unlockAfterWrite(leaderboardsLock); + } + } + + @Override + public CourseArea getDefaultCourseArea() { + return null; + } + + @Override + protected LeaderboardType getLeaderboardType() { + return LeaderboardType.FlexibleMetaLeaderboard; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/LeaderboardGroupMetaLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/LeaderboardGroupMetaLeaderboard.java index 73860657959..673e1ee5120 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/LeaderboardGroupMetaLeaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/LeaderboardGroupMetaLeaderboard.java @@ -1,92 +1,98 @@ -package com.sap.sailing.domain.leaderboard.meta; - -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.impl.TrackedRaces; -import com.sap.sailing.domain.common.LeaderboardNameConstants; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.LeaderboardGroupListener; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.tracking.TrackedRace; - -/** - * A meta leaderboard which considers all regular leaderboards of a {@link LeaderboardGroup}. To stay up to date, this - * meta leaderboard registers itself as a {@link LeaderboardGroupListener} on the leaderboard group it represents. This - * way, whenever a leaderboard is added to or removed from the group, this meta leaderboard can in turn inform its - * {@link RaceColumnListener}s about the impact this change has on the set of {@link TrackedRaces} and therefore the - * competitors attached to this meta leaderboard. - *

- * - * After an object of this type has been de-serialized, and after all objects referenced by it (leaderboard, leaderboard - * group) have been initialized, {@link #registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards()} must be called to - * ensure that score corrections are propagated as desired. This is because score correction listeners are "transient" - * and are as such not serialized. Note: calling {@link #registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards()} - * during readObject or readResolve is not possible because the object graph hasn't been fully - * initialized yet when those methods are called. Hence, the structures for registering the score correction listeners - * are not yet in place at that time. - * - * @author Axel Uhl (d043530) - * - */ -public class LeaderboardGroupMetaLeaderboard extends AbstractMetaLeaderboard implements LeaderboardGroupListener, RaceColumnListener { - private static final long serialVersionUID = 8087872002175528002L; - - private final LeaderboardGroup leaderboardGroup; - - public LeaderboardGroupMetaLeaderboard(LeaderboardGroup leaderboardGroup, ScoringScheme scoringScheme, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(leaderboardGroup.getName() + " " + LeaderboardNameConstants.OVERALL, scoringScheme, resultDiscardingRule); - this.leaderboardGroup = leaderboardGroup; - leaderboardGroup.addLeaderboardGroupListener(this); - registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards(); - } - - public void registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards() { - for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); - } - } - - @Override - public Iterable getLeaderboards() { - return leaderboardGroup.getLeaderboards(); - } - - @Override - public void leaderboardAdded(LeaderboardGroup group, Leaderboard leaderboard) { - registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - if (trackedRace != null) { - getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(raceColumn, fleet, trackedRace); - } - } - } - getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(getColumnForLeaderboard(leaderboard)); - } - - @Override - public void leaderboardRemoved(LeaderboardGroup group, Leaderboard leaderboard) { - leaderboard.removeRaceColumnListener(this); - unregisterScoreCorrectionChangeForwarder(leaderboard); - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - if (trackedRace != null) { - getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(raceColumn, fleet, trackedRace); - } - } - } - getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(getColumnForLeaderboard(leaderboard)); - } - - @Override - public CourseArea getDefaultCourseArea() { - return null; - } -} +package com.sap.sailing.domain.leaderboard.meta; + +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnListener; +import com.sap.sailing.domain.base.impl.TrackedRaces; +import com.sap.sailing.domain.common.LeaderboardNameConstants; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.LeaderboardGroupListener; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.tracking.TrackedRace; + +/** + * A meta leaderboard which considers all regular leaderboards of a {@link LeaderboardGroup}. To stay up to date, this + * meta leaderboard registers itself as a {@link LeaderboardGroupListener} on the leaderboard group it represents. This + * way, whenever a leaderboard is added to or removed from the group, this meta leaderboard can in turn inform its + * {@link RaceColumnListener}s about the impact this change has on the set of {@link TrackedRaces} and therefore the + * competitors attached to this meta leaderboard. + *

+ * + * After an object of this type has been de-serialized, and after all objects referenced by it (leaderboard, leaderboard + * group) have been initialized, {@link #registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards()} must be called to + * ensure that score corrections are propagated as desired. This is because score correction listeners are "transient" + * and are as such not serialized. Note: calling {@link #registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards()} + * during readObject or readResolve is not possible because the object graph hasn't been fully + * initialized yet when those methods are called. Hence, the structures for registering the score correction listeners + * are not yet in place at that time. + * + * @author Axel Uhl (d043530) + * + */ +public class LeaderboardGroupMetaLeaderboard extends AbstractMetaLeaderboard implements LeaderboardGroupListener, RaceColumnListener { + private static final long serialVersionUID = 8087872002175528002L; + + private final LeaderboardGroup leaderboardGroup; + + public LeaderboardGroupMetaLeaderboard(LeaderboardGroup leaderboardGroup, ScoringScheme scoringScheme, + ThresholdBasedResultDiscardingRule resultDiscardingRule) { + super(leaderboardGroup.getName() + " " + LeaderboardNameConstants.OVERALL, scoringScheme, resultDiscardingRule); + this.leaderboardGroup = leaderboardGroup; + leaderboardGroup.addLeaderboardGroupListener(this); + registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards(); + } + + public void registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards() { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); + } + } + + @Override + public Iterable getLeaderboards() { + return leaderboardGroup.getLeaderboards(); + } + + @Override + public void leaderboardAdded(LeaderboardGroup group, Leaderboard leaderboard) { + registerScoreCorrectionAndRaceColumnChangeForwarder(leaderboard); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + if (trackedRace != null) { + getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(raceColumn, fleet, trackedRace); + } + } + } + getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(getColumnForLeaderboard(leaderboard)); + } + + @Override + public void leaderboardRemoved(LeaderboardGroup group, Leaderboard leaderboard) { + leaderboard.removeRaceColumnListener(this); + unregisterScoreCorrectionChangeForwarder(leaderboard); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + if (trackedRace != null) { + getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(raceColumn, fleet, trackedRace); + } + } + } + getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(getColumnForLeaderboard(leaderboard)); + } + + @Override + public CourseArea getDefaultCourseArea() { + return null; + } + + @Override + protected LeaderboardType getLeaderboardType() { + return LeaderboardType.RegattaMetaLeaderboard; + } +}