Skip to content

Commit 5f55022

Browse files
authored
Merge pull request #783 from allanjoseph98/tiebreak-returned
Tiebreak: add lastRoundId to Tournament for ForeBuchholz
2 parents 8ba86cb + ecc845a commit 5f55022

File tree

5 files changed

+42
-32
lines changed

5 files changed

+42
-32
lines changed

bench/src/main/scala/benchmarks/TiebreakBench.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class TiebreakBench:
2424

2525
@Setup
2626
def setup(): Unit =
27-
tournament = Tournament(Helper.games("FWWRC.pgn"))
27+
val games = Helper.games("FWWRC.pgn")
28+
val lastRoundId = Helper.lastRoundId(games)
29+
tournament = Tournament(games, lastRoundId)
2830

2931
@Benchmark
3032
def averageOfOpponentsBuchholz(bh: Blackhole) =

test-kit/src/test/scala/tiebreak/Helper.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,6 @@ object Helper:
4747
.groupBy(_._1)
4848
.map: (player, games) =>
4949
player.id -> PlayerWithGames(player, games.map(_._2))
50+
51+
def lastRoundId(gamesMap: Map[String, PlayerWithGames]): Option[String] =
52+
gamesMap.values.maxByOption(_.games.size).flatMap(_.games.lastOption.flatMap(_.roundId))

test-kit/src/test/scala/tiebreak/TiebreakSnapshotTest.scala

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,48 +9,54 @@ import Helper.*
99
class TiebreakSnapshotTest extends MunitExtensions with SnapshotAssertions:
1010

1111
test("tiebreak games snapshot") {
12+
val gamesMap = games("FWWRC.pgn")
1213
val result = Tiebreak
1314
.compute(
14-
games("FWWRC.pgn"),
15+
gamesMap,
1516
List(
1617
AverageOfOpponentsBuchholz,
1718
AveragePerfectPerformanceOfOpponents,
1819
DirectEncounter,
1920
PerfectTournamentPerformance,
2021
SonnebornBerger(CutModifier.None)
21-
)
22+
),
23+
lastRoundId(gamesMap)
2224
)
2325
.mkString("\n")
2426
assertFileSnapshot(result, "tiebreak/tournament.txt")
2527
}
2628

2729
// https://chess-results.com/tnr1074691.aspx?lan=1&art=1&flag=30
2830
test("Women's world rapid championship") {
31+
val gamesMap = games("FWWRC.pgn")
2932
val result = Tiebreak
3033
.compute(
31-
games("FWWRC.pgn"),
34+
gamesMap,
3235
List(
3336
Buchholz(CutModifier.Cut1),
3437
Buchholz(CutModifier.None),
3538
AverageRatingOfOpponents(CutModifier.Cut1)
36-
)
39+
),
40+
lastRoundId(gamesMap)
3741
)
3842
.mkString("\n")
3943
assertFileSnapshot(result, "tiebreak/official_tournament.txt")
4044
}
4145

4246
// https://chess-results.com/tnr1175851.aspx?art=1
4347
test("Uzchess Cup"):
48+
val gamesMap = games("uzchesscup.pgn")
4449
val result = Tiebreak
4550
.compute(
46-
games("uzchesscup.pgn"),
51+
gamesMap,
4752
List(
4853
DirectEncounter,
4954
SonnebornBerger(CutModifier.None),
5055
NbWins,
5156
NbBlackWins,
5257
KoyaSystem(LimitModifier.default)
53-
)
58+
),
59+
lastRoundId(gamesMap)
5460
)
5561
.mkString("\n")
5662
assertFileSnapshot(result, "tiebreak/uzchesscup.txt")

test-kit/src/test/scala/tiebreak/TiebreakTest.scala

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ class TiebreakTest extends ChessTest:
3939
playerA.draws(playerC, "2"),
4040
playerA.loses(playerD, "3"),
4141
playerA.beats(playerE, "4"),
42-
playerB.beats(playerC, "1"),
43-
playerB.draws(playerD, "2"),
44-
playerB.loses(playerE, "3"),
45-
playerC.beats(playerD, "1"),
46-
playerC.draws(playerE, "2"),
47-
playerD.beats(playerE, "1")
42+
playerB.beats(playerC, "2"),
43+
playerB.draws(playerD, "3"),
44+
playerB.loses(playerE, "4"),
45+
playerC.beats(playerD, "3"),
46+
playerC.draws(playerE, "4"),
47+
playerD.beats(playerE, "4")
4848
)
4949

5050
def povGames(player: Player): Seq[Game] =
@@ -60,13 +60,15 @@ class TiebreakTest extends ChessTest:
6060
val playerE_Games = PlayerWithGames(playerE, povGames(playerE))
6161
val allGames =
6262
Seq(playerA_Games, playerB_Games, playerC_Games, playerD_Games, playerE_Games).mapBy(_.player.id)
63+
val lastRoundId =
64+
allGames.values.maxByOption(_.games.size).flatMap(_.games.lastOption).flatMap(_.roundId)
6365

6466
def computeTournamentPoints(
6567
allGames: Map[PlayerId, PlayerWithGames],
6668
player: Player,
6769
tiebreak: Tiebreak
6870
): Option[TiebreakPoint] =
69-
Tournament(allGames)
71+
Tournament(allGames, lastRoundId)
7072
.compute(List(tiebreak))
7173
.find(_.player.id == player.id)
7274
.flatMap(_.tiebreakPoints.headOption)
@@ -183,11 +185,11 @@ class TiebreakTest extends ChessTest:
183185
)
184186

185187
val points1 = DirectEncounter
186-
.compute(Tournament(allGames), previousPoints)
188+
.compute(Tournament(allGames, lastRoundId), previousPoints)
187189
.get(playerA.id)
188190
.flatMap(_.lift(1))
189191
val points2 = DirectEncounter
190-
.compute(Tournament(allGames), previousPoints)
192+
.compute(Tournament(allGames, lastRoundId), previousPoints)
191193
.get(playerD.id)
192194
.flatMap(_.lift(1))
193195
assertEquals(points1, Some(TiebreakPoint(0f)))
@@ -201,11 +203,11 @@ class TiebreakTest extends ChessTest:
201203
)
202204

203205
val points1 = DirectEncounter
204-
.compute(Tournament(allGames), previousPoints)
206+
.compute(Tournament(allGames, lastRoundId), previousPoints)
205207
.get(playerA.id)
206208
.flatMap(_.lift(1))
207209
val points2 = DirectEncounter
208-
.compute(Tournament(allGames), previousPoints)
210+
.compute(Tournament(allGames, lastRoundId), previousPoints)
209211
.get(playerD.id)
210212
.flatMap(_.lift(1))
211213
assertEquals(points1, Some(TiebreakPoint(0f)))
@@ -235,15 +237,15 @@ class TiebreakTest extends ChessTest:
235237
.mapBy(_.player.id)
236238

237239
val points1 = DirectEncounter
238-
.compute(Tournament(allGamesWithPartial), previousPoints)
240+
.compute(Tournament(allGamesWithPartial, None), previousPoints)
239241
.get(playerA.id)
240242
.flatMap(_.lift(1))
241243
val points2 = DirectEncounter
242-
.compute(Tournament(allGamesWithPartial), previousPoints)
244+
.compute(Tournament(allGamesWithPartial, None), previousPoints)
243245
.get(playerD.id)
244246
.flatMap(_.lift(1))
245247
val pointsX = DirectEncounter
246-
.compute(Tournament(allGamesWithPartial), previousPoints)
248+
.compute(Tournament(allGamesWithPartial, None), previousPoints)
247249
.get(playerX_Games.player.id)
248250
.flatMap(_.lift(1))
249251
assertEquals(points1, Some(TiebreakPoint(0f)))

tiebreak/src/main/scala/Tiebreak.scala

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ trait Tournament:
258258
def toPlayerGames: Map[PlayerId, Tiebreak.PlayerWithGames]
259259
def opponentsOf: PlayerId => List[Player]
260260
def scoreOf: PlayerId => TournamentScore
261+
def lastRoundId: Option[String]
261262
// def currentRound: Int
262263
// def totalRounds: Int
263264
// def byes: (PlayerId, Int) => Boolean // playerId, round => true if player has a bye in that round
@@ -297,12 +298,6 @@ trait Tournament:
297298
.map(opponent => scoreOf(opponent.id).into(TiebreakPoint))
298299
.sorted
299300

300-
lazy val lastRoundId: Option[String] = toPlayerGames.values
301-
.maxBy(_.games.size)
302-
.games
303-
.lastOption
304-
.flatMap(_.roundId)
305-
306301
lazy val foreBuchholzSeq: PlayerId => Seq[TiebreakPoint] = memoize: id =>
307302
lastRoundId.fold(buchholzSeq(id)): lastRound =>
308303
opponentsOf(id)
@@ -340,7 +335,8 @@ trait Tournament:
340335

341336
object Tournament:
342337

343-
private case class Impl(games: Map[PlayerId, Tiebreak.PlayerWithGames]) extends Tournament:
338+
private case class Impl(games: Map[PlayerId, Tiebreak.PlayerWithGames], lastRoundId: Option[String])
339+
extends Tournament:
344340

345341
override def toPlayerGames: Map[PlayerId, PlayerWithGames] = games
346342

@@ -375,8 +371,8 @@ object Tournament:
375371
if expectedScoreFor(mid, oppRatings) >= myScore then binarySearch(oppRatings, myScore)(low, mid)
376372
else binarySearch(oppRatings, myScore)(mid + 1, high)
377373

378-
def apply(games: Map[PlayerId, Tiebreak.PlayerWithGames]): Tournament =
379-
Impl(games)
374+
def apply(games: Map[PlayerId, Tiebreak.PlayerWithGames], lastRoundId: Option[String]): Tournament =
375+
Impl(games, lastRoundId)
380376

381377
enum CutModifier(val code: String, val name: String, val top: Int, val bottom: Int):
382378
case None extends CutModifier("", "", 0, 0)
@@ -442,9 +438,10 @@ object Tiebreak:
442438

443439
def compute(
444440
games: Map[PlayerId, Tiebreak.PlayerWithGames],
445-
tiebreaks: List[Tiebreak]
441+
tiebreaks: List[Tiebreak],
442+
lastRoundId: Option[String]
446443
): List[PlayerWithScore] =
447-
Tournament(games).compute(tiebreaks)
444+
Tournament(games, lastRoundId).compute(tiebreaks)
448445

449446
type PlayerPoints = Map[PlayerId, List[TiebreakPoint]]
450447

0 commit comments

Comments
 (0)