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 e117299b99d..b5da9872f5a 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 @@ -5,5 +5,5 @@ public enum ScoringSchemeType { LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL,HIGH_POINT_ESS_OVERALL_12, 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_EIGHT, HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION, HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT, HIGH_POINT_FIRST_GETS_TWELVE_OR_EIGHT, LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07, - LOW_POINT_LEAGUE_OVERALL + LOW_POINT_LEAGUE_OVERALL, HIGH_POINT_MATCH_RACING } diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/LiveDataConnection.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/LiveDataConnection.java index ebe5c82d488..a3bd992018b 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/LiveDataConnection.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/LiveDataConnection.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.igtimiadapter; +import java.net.InetSocketAddress; + public interface LiveDataConnection { /** * Disconnects this connection. Afterwards, the connection will no longer feed live data to its listener(s). @@ -18,4 +20,6 @@ public interface LiveDataConnection { void addListener(BulkFixReceiver listener); void removeListener(BulkFixReceiver listener); + + InetSocketAddress getRemoteAddress(); } diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/IgtimiConnectionFactoryImpl.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/IgtimiConnectionFactoryImpl.java index 9ea016cf818..9d7c3f12d43 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/IgtimiConnectionFactoryImpl.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/IgtimiConnectionFactoryImpl.java @@ -132,6 +132,10 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory { return new ArrayList(accountsByEmail.values()); } + public IgtimiConnection getConnectionOfAccount(Account account) { + return connectionsByAccount.get(account); + } + @Override public IgtimiConnection connect(Account account) { IgtimiConnection connection; diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/LiveDataConnectionWrapper.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/LiveDataConnectionWrapper.java index d7ed43cc9a7..d61c41d3658 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/LiveDataConnectionWrapper.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/LiveDataConnectionWrapper.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.igtimiadapter.websocket; +import java.net.InetSocketAddress; + import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver; import com.sap.sailing.domain.igtimiadapter.LiveDataConnection; @@ -45,4 +47,9 @@ public class LiveDataConnectionWrapper implements LiveDataConnection { LiveDataConnection getActualConnection() { return actualConnection; } + + @Override + public InetSocketAddress getRemoteAddress() { + return actualConnection.getRemoteAddress(); + } } diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketConnectionManager.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketConnectionManager.java index cfecaa610cd..451d94a9ea8 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketConnectionManager.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/websocket/WebSocketConnectionManager.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.igtimiadapter.websocket; import java.io.IOException; +import java.net.InetSocketAddress; import java.net.URI; import java.util.ArrayList; import java.util.List; @@ -150,7 +151,7 @@ public class WebSocketConnectionManager extends WebSocketAdapter implements Live public com.sap.sse.common.Util.Pair getIgtimiServerTimePointAndWhenItWasReceived() { return new com.sap.sse.common.Util.Pair(igtimiServerTimepoint, localTimepointWhenServerTimepointWasReceived); } - + @Override public void addListener(BulkFixReceiver listener) { listeners.put(listener, listener); @@ -250,4 +251,9 @@ public class WebSocketConnectionManager extends WebSocketAdapter implements Live throw lastException; } } + + @Override + public InetSocketAddress getRemoteAddress() { + return getSession().getRemoteAddress(); + } } 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 6c8d7fb4e58..a4c2ffa6b72 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 @@ -510,6 +510,34 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { } } + @Test + public void testHighPointMatchRacingScoringScheme() throws NoWindException { + List competitors = createCompetitors(2); + Competitor c1 = competitors.get(0); + Competitor c2 = competitors.get(1); + Regatta regatta = createSimpleRegatta(3, "Match Racing Test", + DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", /* typicallyStartsUpwind */false), + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT_MATCH_RACING)); + Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]); + TimePoint now = MillisecondsTimePoint.now(); + TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); + RaceColumn r1Column = series.get(0).getRaceColumnByName("R1"); + TrackedRace r1 = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors); + r1Column.setTrackedRace(r1Column.getFleetByName("Default"), r1); + + assertEquals(1, r1Column.getTrackedRace(c1).getRank(c1, later)); + assertEquals(1, leaderboard.getTrackedRank(c1, r1Column, later)); + assertEquals(1, leaderboard.getTotalPoints(c1, r1Column, later), 0.00000001); + + assertEquals(2, r1Column.getTrackedRace(c2).getRank(c2, later)); + assertEquals(2, leaderboard.getTrackedRank(c2, r1Column, later)); + assertEquals(0, leaderboard.getTotalPoints(c2, r1Column, later), 0.00000001); + + List rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later); + assertSame(c1, rankedCompetitors.get(0)); + assertSame(c2, rankedCompetitors.get(1)); + } + @Test public void testDistributionAcrossFinalFleetsWithDifferentScores() throws NoWindException { List competitors = createCompetitors(10); @@ -1814,6 +1842,25 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { return result; } + private Regatta createSimpleRegatta(final int numberOfRaces, final String regattaName, BoatClass boatClass, ScoringScheme scoringScheme) { + series = new ArrayList(); + List fleets = new ArrayList(); + fleets.add(new FleetImpl("Default")); + + List raceColumnNames = new ArrayList(); + for (int i = 1; i <= numberOfRaces; i++) { + raceColumnNames.add("R" + i); + } + Series defaultSeries = new SeriesImpl("Default", /* isMedal */false, /* isFleetsCanRunInParallel */true, + fleets, raceColumnNames, /* trackedRegattaRegistry */null); + series.add(defaultSeries); + + Regatta regatta = new RegattaImpl(RegattaImpl.getDefaultName(regattaName, boatClass.getName()), boatClass, + /* startDate */null, /* endDate */null, series, /* persistent */false, scoringScheme, "123", null, + OneDesignRankingMetric::new); + return regatta; + } + private Regatta createRegatta(final int numberOfQualifyingRaces, String[] qualifyingFleetNames, final int numberOfFinalRaces, String[] finalFleetNames, boolean medalRaceAndSeries, final int numberOfMedalRaces, final String regattaBaseName, BoatClass boatClass, ScoringScheme scoringScheme) { series = new ArrayList(); 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 85eebcdb4e8..90d57f6d567 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 @@ -48,6 +48,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEight; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterpolation; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; +import com.sap.sailing.domain.leaderboard.impl.HighPointMatchRacing; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; import com.sap.sailing.domain.leaderboard.impl.LowPoint; import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard; @@ -114,6 +115,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return new HighPointWinnerGetsSix(); case HIGH_POINT_WINNER_GETS_EIGHT: return new HighPointWinnerGetsEight(); + case HIGH_POINT_MATCH_RACING: + return new HighPointMatchRacing(); case HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION: return new HighPointWinnerGetsEightAndInterpolation(); case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT: diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java new file mode 100644 index 00000000000..e6f9cd9b0bf --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointMatchRacing.java @@ -0,0 +1,32 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.concurrent.Callable; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; +import com.sap.sse.common.TimePoint; + +/** + * Scoring system indented to by used for match racing where the winner gets 1 points and the loser gets 0 points + */ +public class HighPointMatchRacing extends HighPoint { + private static final long serialVersionUID = 9124974081268072297L; + + public HighPointMatchRacing() { + } + + @Override + public ScoringSchemeType getType() { + return ScoringSchemeType.HIGH_POINT_MATCH_RACING; + } + + @Override + public Double getScoreForRank(Leaderboard leaderboard, RaceColumn raceColumn, Competitor competitor, int rank, + Callable numberOfCompetitorsInRaceFetcher, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher, TimePoint timePoint) { + return rank == 1 ? 1.0 : 0.0; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 8dd16dfdf5d..05c6e7e0d75 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -419,6 +419,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String scoringSchemeWinnerGetsFive(); String scoringSchemeWinnerGetsSix(); String scoringSchemeWinnerGetsEight(); + String scoringSchemeHighPointMatchRacing(); + String scoringSchemeHighPointMatchRacingDescription(); String scoringSchemeWinnerGetsEightAndInterpolation(); String scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07(); String scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 0d85bcee37f..67be96789a4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -434,6 +434,8 @@ scoringSchemeLowPointWinnerGetsZero=Low Point System, Winner Gets Zero scoringSchemeWinnerGetsFive=High Point System, Winner Gets 5 Points scoringSchemeWinnerGetsSix=High Point System, Winner Gets 6 Points scoringSchemeWinnerGetsEight=High Point System, Winner Gets 8 Points +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=The winner of the match race gets 1 point, the loser gets 0 points scoringSchemeWinnerGetsEightAndInterpolation=High Point System, Winner 8 Points, Interpolated scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point with Eliminations and Rounds, Winner Gets 0.7 Points scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=A variant of the low-point scoring scheme, using eliminations consisting of rounds.\nEach round shall be modeled as a series in the regatta, and the fleet ordering counts backwards\nstarting with the highest number for the first round.\nIf a final and losers final take place, use 1 and 2 as their ordering. Start with 3 for the semi-final round. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 932fac11601..3f549d7ef2b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -434,6 +434,8 @@ scoringSchemeLowPointWinnerGetsZero=Low Point System, Gewinner erhält 0 Punkte scoringSchemeWinnerGetsFive=High Point System, Gewinner erhält 5 Punkte scoringSchemeWinnerGetsSix=High Point System, Gewinner erhält 6 Punkte scoringSchemeWinnerGetsEight=High Point System, Gewinner erhält 8 Punkte +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=Der Gewinner erhält 1 Punkt, der Verlierer 0 Punkte scoringSchemeWinnerGetsEightAndInterpolation=High Point System, Gewinner erhält 8 Punkte, interpoliert scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point System mit K.O.-Runden, Gewinner erhält 0,7 Punkte scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=Eine Variante des Low Point Systems mit mehreren K.O.-Wertungen.\nJede Runde einer Wertung wird als "Serie" in der Regatta modelliert, und die Gruppen-Ordnung wird rückwärts zählend verwendet, mit der größten Zahl für die erste Runde.\nWenn die Final-Runde in großes und kleines Finale unterteilt ist, soll das große Finale mit Ordnungszahl 1 und das kleine mit Ordnungszahl 2 modelliert werden. Das Halbfinale verwendet dann 3, usw. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties index a641cf8676b..904856768e5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties @@ -432,6 +432,8 @@ scoringSchemeLowPointWinnerGetsZero=低得点方式、1 位が 0 点 scoringSchemeWinnerGetsFive=高得点方式、1 位が 5 点 scoringSchemeWinnerGetsSix=高得点方式、1 位が 6 点 scoringSchemeWinnerGetsEight=高得点方式、1 位が 8 点 +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=The winner of the match race gets 1 point, the loser gets 0 points scoringSchemeWinnerGetsEightAndInterpolation=高得点方式、1 位が 8 点、補間 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=低得点方式、予選およびラウンドあり、1 位が 0.7 点 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=ラウンドから構成される予選を用いた低得点方式のバリエーションです。\n各ラウンドがレガッタ内のシリーズとして形成されることになり、フリート順序は\n最初のラウンドで最も大きい数から開始してカウントダウンします。\n決勝や最下位決定戦が行われる場合は、その順序として 1 および 2 を使用します。準決勝ラウンドは 3 から始めます。 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index cab02205b46..44b9e603913 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -432,6 +432,8 @@ scoringSchemeLowPointWinnerGetsZero=Система низких баллов, п scoringSchemeWinnerGetsFive=Система высоких баллов, победитель получает 5 баллов scoringSchemeWinnerGetsSix=Система высоких баллов, победитель получает 6 баллов scoringSchemeWinnerGetsEight=Система высоких баллов, победитель получает 8 баллов +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=The winner of the match race gets 1 point, the loser gets 0 points scoringSchemeWinnerGetsEightAndInterpolation=Система высоких баллов, победитель 8 баллов, интерполяция scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Низкий балл с турами на выбывание, победитель получает 0,7 балла scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=Вариант схемы оценки с низкими баллами, использующий туры на выбывание.\nКаждый тур моделируется как серия в регате, и суда ранжируются в обратном порядке,\nначиная с наибольшего числа за первый раунд.\nВ финале и при определении 3-го места используйте ранги 1 и 2. Для полуфинального тура начните с 3. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 49ddd575af3..f5c35461710 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -432,6 +432,8 @@ scoringSchemeLowPointWinnerGetsZero=低分系统,获胜者得零分 scoringSchemeWinnerGetsFive=高分系统,获胜者得 5 分 scoringSchemeWinnerGetsSix=高分系统,获胜者得 6 分 scoringSchemeWinnerGetsEight=高分系统,获胜者得 8 分 +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=The winner of the match race gets 1 point, the loser gets 0 points scoringSchemeWinnerGetsEightAndInterpolation=高分系统,获胜者 8 分,内插 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=采用多轮淘汰制的低分系统,获胜者得 0.7 分 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=低分记分系统的一种,采用多轮淘汰制。\n每一轮应作为比赛系列,船队顺序\n从第一轮的最高数向后计。\n如果有最终一支舰队和最终败者,则使用 1 和 2 排序。 半决赛从第 3 位开始。 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties index 49ddd575af3..f5c35461710 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh_CN.properties @@ -432,6 +432,8 @@ scoringSchemeLowPointWinnerGetsZero=低分系统,获胜者得零分 scoringSchemeWinnerGetsFive=高分系统,获胜者得 5 分 scoringSchemeWinnerGetsSix=高分系统,获胜者得 6 分 scoringSchemeWinnerGetsEight=高分系统,获胜者得 8 分 +scoringSchemeHighPointMatchRacing=High Point System, Match Racing +scoringSchemeHighPointMatchRacingDescription=The winner of the match race gets 1 point, the loser gets 0 points scoringSchemeWinnerGetsEightAndInterpolation=高分系统,获胜者 8 分,内插 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=采用多轮淘汰制的低分系统,获胜者得 0.7 分 scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=低分记分系统的一种,采用多轮淘汰制。\n每一轮应作为比赛系列,船队顺序\n从第一轮的最高数向后计。\n如果有最终一支舰队和最终败者,则使用 1 和 2 排序。 半决赛从第 3 位开始。 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java index b3093483023..704bcec0811 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java @@ -28,6 +28,8 @@ public class ScoringSchemeTypeFormatter { return stringMessages.scoringSchemeWinnerGetsSix(); case HIGH_POINT_WINNER_GETS_EIGHT: return stringMessages.scoringSchemeWinnerGetsEight(); + case HIGH_POINT_MATCH_RACING: + return stringMessages.scoringSchemeHighPointMatchRacing(); case HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION: return stringMessages.scoringSchemeWinnerGetsEightAndInterpolation(); case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT: @@ -56,6 +58,8 @@ public class ScoringSchemeTypeFormatter { return stringMessages.scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description(); case LOW_POINT_LEAGUE_OVERALL: return stringMessages.scoringSchemeLowPointForLeagueOverallLeaderboardDescription(); + case HIGH_POINT_MATCH_RACING: + return stringMessages.scoringSchemeHighPointMatchRacingDescription(); default: return format(scoringSchemeType, stringMessages); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java index dde74376cdb..bcf7a5e8f2a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusHtmlServlet.java @@ -8,6 +8,7 @@ import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.Map.Entry; import javax.servlet.ServletException; @@ -16,6 +17,7 @@ import javax.servlet.http.HttpServletResponse; import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver; import com.sap.sailing.domain.igtimiadapter.IgtimiWindListener; +import com.sap.sailing.domain.igtimiadapter.LiveDataConnection; import com.sap.sse.common.TimePoint; /** @@ -43,6 +45,18 @@ public class WindStatusHtmlServlet extends WindStatusServlet implements IgtimiWi out.println(""); out.println("

Reload wind connectors with parameter reloadWindReceiver=true. This will force a connection reset and a reloading of the wind receivers.

"); out.println("

Igtimi Wind Status ("+getIgtimiMessagesRawCount()+" raw messages received)

"); + Map igtimiConnections = getIgtimiConnections(); + if (!igtimiConnections.isEmpty()) { + out.println("

Igtimi accounts used

"); + for (Map.Entry entry: igtimiConnections.entrySet()) { + IgtimiConnectionInfo igtimiConnectionInfo = entry.getValue(); + int deviceCount = igtimiConnectionInfo.deviceIDs.size(); + out.println("Account " + igtimiConnectionInfo.accountName + "
"); + out.println(deviceCount + " devices " + igtimiConnectionInfo.deviceIDs.toString() + "
"); + out.println("Connection used is " + igtimiConnectionInfo.remoteAddress.toString() + "

"); + } + out.println("
"); + } if (getLastIgtimiMessages() != null && !getLastIgtimiMessages().isEmpty()) { for(Entry> deviceAndMessagesList: getLastIgtimiMessages().entrySet()) { final Deque copyOfLastIgtimiMessages; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusServlet.java index 6fb443229e8..c9564519981 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/WindStatusServlet.java @@ -1,7 +1,6 @@ package com.sap.sailing.server.gateway.impl; -import java.io.IOException; -import java.io.PrintWriter; +import java.net.InetSocketAddress; import java.net.SocketException; import java.text.DateFormat; import java.text.DecimalFormat; @@ -10,15 +9,9 @@ import java.util.ArrayList; import java.util.Date; import java.util.Deque; import java.util.HashMap; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; -import java.util.Map.Entry; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.osgi.util.tracker.ServiceTracker; @@ -37,7 +30,7 @@ import com.sap.sailing.expeditionconnector.ExpeditionMessage; import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory; import com.sap.sailing.expeditionconnector.UDPExpeditionReceiver; import com.sap.sailing.server.gateway.SailingServerHttpServlet; -import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; /** * Shows the state of wind receivers regardless of them being attached to a race. Currently Expedition and Igtimi are supported. @@ -45,7 +38,7 @@ import com.sap.sse.common.TimePoint; * @author Simon Marcel Pamies * */ -public class WindStatusServlet extends SailingServerHttpServlet implements IgtimiWindListener, BulkFixReceiver { +public abstract class WindStatusServlet extends SailingServerHttpServlet implements IgtimiWindListener, BulkFixReceiver { private static final long serialVersionUID = -6791613843435003810L; protected static final String PARAM_RELOAD_WIND_RECEIVER="reloadWindReceiver"; @@ -64,8 +57,8 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim private static int igtimiRawMessageCount; private static Map> lastIgtimiMessages; private static IgtimiWindReceiver igtimiWindReceiver; - private static LiveDataConnection liveDataConnection; - + private static Map igtimiConnections; + private static boolean isExpeditionListenerRegistered; private static boolean isIgtimiListenerRegistered; @@ -73,6 +66,7 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim super(); isExpeditionListenerRegistered = false; isIgtimiListenerRegistered = false; + igtimiConnections = new LinkedHashMap<>(); } protected int getIgtimiMessagesRawCount() { @@ -97,14 +91,21 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim synchronized (lock) { if (!isIgtimiListenerRegistered || reinitialize) { if (reinitialize) { - try { - if (liveDataConnection != null) { - liveDataConnection.stop(); - liveDataConnection.removeListener(igtimiWindReceiver); - liveDataConnection.removeListener(this); + if (!igtimiConnections.isEmpty()) { + for (Map.Entry entry: igtimiConnections.entrySet()) { + LiveDataConnection igtimiConnection = entry.getKey(); + try { + if (igtimiConnection != null) { + igtimiConnection.stop(); + igtimiConnection.removeListener(igtimiWindReceiver); + igtimiConnection.removeListener(this); + + } + } catch (Exception e) { + e.printStackTrace(); + } } - } catch (Exception e) { - e.printStackTrace(); + igtimiConnections.clear(); } } isIgtimiListenerRegistered = registerIgtimiListener(); @@ -114,77 +115,6 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim } } - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String reinitializeWindReceiverParameter = req.getParameter(PARAM_RELOAD_WIND_RECEIVER); - initializeWindReceiver(reinitializeWindReceiverParameter != null && reinitializeWindReceiverParameter.equalsIgnoreCase("true")); - resp.setContentType("text/html"); - PrintWriter out = resp.getWriter(); - out.println(""); - out.println(""); - out.println("Wind Status"); - out.println(""); - out.println(""); - out.println(""); - out.println("

Reload wind connectors with parameter reloadWindReceiver=true. This will force a connection reset and a reloading of the wind receivers.

"); - out.println("

Igtimi Wind Status ("+igtimiRawMessageCount+" raw messages received)

"); - if (lastIgtimiMessages != null && !lastIgtimiMessages.isEmpty()) { - for(Entry> deviceAndMessagesList: lastIgtimiMessages.entrySet()) { - final Deque copyOfLastIgtimiMessages; - synchronized (deviceAndMessagesList.getValue()) { - copyOfLastIgtimiMessages = new ArrayDeque<>(deviceAndMessagesList.getValue()); - } - out.println("Windbot: " + deviceAndMessagesList.getKey() + ""); - if(copyOfLastIgtimiMessages.size() > 0) { - TimePoint latestTimePoint = copyOfLastIgtimiMessages.peek().wind.getTimePoint(); - long lastFixDiffInMs = System.currentTimeMillis() - latestTimePoint.asMillis(); - out.println("    Last fix:"); - if(lastFixDiffInMs / 1000 < 60) { - out.println(lastFixDiffInMs / 1000 +"s ago"); - } else { - out.println("" + lastFixDiffInMs / 1000 +"min ago"); - } - } - out.println("
"); - Iterator messageIt = copyOfLastIgtimiMessages.iterator(); - while (messageIt.hasNext()){ - IgtimiMessageInfo message = messageIt.next(); - out.println(message); - out.println("
"); - } - out.println("
"); - } - } else { - if (igtimiRawMessageCount == 0) { - out.println("No Igtimi messages received so far!"); - } else { - out.println(""+igtimiRawMessageCount+" Igtimi message bunch has been received but not enough messages to generate wind information."); - } - } - out.println("

Expedition Wind Status

"); - if (lastExpeditionMessages != null && !lastExpeditionMessages.isEmpty()) { - final List copyOfLastExpeditionMessages; - synchronized (lastExpeditionMessages) { - copyOfLastExpeditionMessages = new ArrayList<>(WindStatusServlet.lastExpeditionMessages); - } - int expeditionMsgCounter = 0; - for (ListIterator iterator = copyOfLastExpeditionMessages.listIterator(copyOfLastExpeditionMessages.size()); iterator.hasPrevious();) { - expeditionMsgCounter++; - ExpeditionMessageInfo message = iterator.previous(); - out.println(message); - out.println("
"); - if (expeditionMsgCounter >= NUMBER_OF_MESSAGES_TO_SHOW) { - break; - } - } - } else { - out.println("No Expedition messages received so far!"); - } - out.println(""); - out.println(""); - out.close(); - } - private boolean registerIgtimiListener() { boolean result = false; ServiceTracker igtimiServiceTracker = new ServiceTracker(getContext(), IgtimiConnectionFactory.class, null); @@ -196,9 +126,16 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim if (account.getUser() != null) { IgtimiConnection igtimiConnection = igtimiConnectionFactory.connect(account); try { - liveDataConnection = igtimiConnection.getOrCreateLiveConnection(igtimiConnection.getWindDevices()); - liveDataConnection.addListener(igtimiWindReceiver); - liveDataConnection.addListener(this); + LiveDataConnection newIgtimiConnection = igtimiConnection.getOrCreateLiveConnection(igtimiConnection.getWindDevices()); + newIgtimiConnection.addListener(igtimiWindReceiver); + newIgtimiConnection.addListener(this); + + IgtimiConnectionInfo newIgtimiConnectionInfo = new IgtimiConnectionInfo(); + newIgtimiConnectionInfo.remoteAddress = newIgtimiConnection.getRemoteAddress(); + newIgtimiConnectionInfo.accountName = account.getUser().getEmail(); + Util.addAll(igtimiConnection.getWindDevices(), newIgtimiConnectionInfo.deviceIDs); + igtimiConnections.put(newIgtimiConnection, newIgtimiConnectionInfo); + result = true; } catch (Exception e) { e.printStackTrace(); @@ -236,7 +173,13 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim } return result; } - + + protected class IgtimiConnectionInfo { + InetSocketAddress remoteAddress; + String accountName; + List deviceIDs = new ArrayList<>(); + } + protected class ExpeditionMessageInfo { Integer boatID; ExpeditionMessage message; @@ -296,20 +239,24 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim @Override public void destroy() { - if (liveDataConnection != null) { + for (Map.Entry entry: igtimiConnections.entrySet()) { + LiveDataConnection igtimiConnection = entry.getKey(); try { - liveDataConnection.stop(); + igtimiConnection.stop(); } catch (Exception e) { e.printStackTrace(); - } finally { - liveDataConnection = null; - isIgtimiListenerRegistered = false; } } + igtimiConnections.clear(); + isIgtimiListenerRegistered = false; } @Override public void received(Iterable fixes) { igtimiRawMessageCount += 1; } + + public static Map getIgtimiConnections() { + return igtimiConnections; + } }