From 6dc634df7ea349e0af2a71ceb7af5a42b420b825 Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Tue, 28 May 2024 12:29:49 +0200 Subject: [PATCH] Recompute DUDD at import (plus some code cleaning) --- .../jeudego/pairgoth/api/PairingHandler.kt | 10 +++--- .../jeudego/pairgoth/api/TournamentHandler.kt | 1 + .../org/jeudego/pairgoth/model/Pairing.kt | 20 ++++++----- .../org/jeudego/pairgoth/model/Tournament.kt | 34 +++++++++++++++---- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt index dc51ca0..ee534a9 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt @@ -75,14 +75,14 @@ object PairingHandler: PairgothApiHandler { listOf(it.black, it.white) }.toSet() if (game.result != Game.Result.UNKNOWN && ( - game.black != payload.getInt("b") || - game.white != payload.getInt("w") || - game.handicap != payload.getInt("h") - )) badRequest("Game already has a result") + game.black != payload.getInt("b") || + game.white != payload.getInt("w") || + game.handicap != payload.getInt("h") + )) badRequest("Game already has a result") game.black = payload.getID("b") ?: badRequest("missing black player id") game.white = payload.getID("w") ?: badRequest("missing white player id") - tournament.recomputeHdAndDUDD(round, game.id) + tournament.recomputeDUDD(round, game.id) val previousTable = game.table; // temporary //payload.getInt("dudd")?.let { game.drawnUpDown = it } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/TournamentHandler.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/TournamentHandler.kt index bf39fd3..c11065f 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/TournamentHandler.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/api/TournamentHandler.kt @@ -55,6 +55,7 @@ object TournamentHandler: PairgothApiHandler { is Element -> OpenGotha.import(payload) else -> badRequest("missing or invalid payload") } + tournament.recomputeDUDD() getStore(request).addTournament(tournament) tournament.dispatchEvent(TournamentAdded, request, tournament.toJson()) return Json.Object("success" to true, "id" to tournament.id) diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Pairing.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Pairing.kt index fa12ee1..01cb937 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Pairing.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Pairing.kt @@ -4,6 +4,7 @@ import com.republicate.kson.Json import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest import org.jeudego.pairgoth.model.MainCritParams.SeedMethod.SPLIT_AND_SLIP import org.jeudego.pairgoth.model.PairingType.* +import org.jeudego.pairgoth.pairing.solver.BaseSolver import org.jeudego.pairgoth.pairing.solver.MacMahonSolver import org.jeudego.pairgoth.pairing.solver.SwissSolver import kotlin.math.min @@ -129,7 +130,10 @@ sealed class Pairing( val pairingParams: PairingParams, val placementParams: PlacementParams) { companion object {} - abstract fun pair(tournament: Tournament<*>, round: Int, pairables: List): List + abstract fun solver(tournament: Tournament<*>, round: Int, pairables: List): BaseSolver + fun pair(tournament: Tournament<*>, round: Int, pairables: List): List { + return solver(tournament, round, pairables).pair() + } } internal fun Tournament<*>.historyBefore(round: Int) = @@ -169,9 +173,8 @@ class Swiss( ) ): Pairing(SWISS, pairingParams, placementParams) { companion object {} - override fun pair(tournament: Tournament<*>, round: Int, pairables: List): List { - return SwissSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, pairingParams, placementParams, tournament.usedTables(round)).pair() - } + override fun solver(tournament: Tournament<*>, round: Int, pairables: List) = + SwissSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, pairingParams, placementParams, tournament.usedTables(round)) } class MacMahon( @@ -198,17 +201,16 @@ class MacMahon( var mmBar: Int = 0 // 1D ): Pairing(MAC_MAHON, pairingParams, placementParams) { companion object {} - override fun pair(tournament: Tournament<*>, round: Int, pairables: List): List { - return MacMahonSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, pairingParams, placementParams, tournament.usedTables(round), mmFloor, mmBar).pair() - } + override fun solver(tournament: Tournament<*>, round: Int, pairables: List) = + MacMahonSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, pairingParams, placementParams, tournament.usedTables(round), mmFloor, mmBar) } class RoundRobin( pairingParams: PairingParams = PairingParams(), placementParams: PlacementParams = PlacementParams(Criterion.NBW, Criterion.RATING) ): Pairing(ROUND_ROBIN, pairingParams, placementParams) { - override fun pair(tournament: Tournament<*>, round: Int, pairables: List): List { - TODO() + override fun solver(tournament: Tournament<*>, round: Int, pairables: List): BaseSolver { + TODO("not implemented") } } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Tournament.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Tournament.kt index 35a9ee3..bcf13b5 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Tournament.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/model/Tournament.kt @@ -74,15 +74,10 @@ sealed class Tournament ( else mutableMapOf().also { games.add(it) } fun lastRound() = max(1, games.size) - fun recomputeHdAndDUDD(round: Int, gameID: ID) { + fun recomputeDUDD(round: Int, gameID: ID) { // Instantiate solver with game history - // TODO cleaner solver instantiation val history = historyBefore(round) - val solver = if (pairing is Swiss) { - SwissSolver(round, rounds, history, pairables.values.toList(), pairing.pairingParams, pairing.placementParams, usedTables(round)) - } else if (pairing is MacMahon) { - MacMahonSolver(round, rounds, history, pairables.values.toList(), pairing.pairingParams, pairing.placementParams, usedTables(round), pairing.mmFloor, pairing.mmBar) - } else throw Exception("Invalid tournament type") + val solver = pairing.solver(this, round, pairables.values.toList()) // Recomputes DUDD and hd val game = games(round)[gameID]!! @@ -92,6 +87,31 @@ sealed class Tournament ( game.handicap = solver.hd(white = white, black = black) } + + /** + * Recompute DUDD for the specified round + */ + fun recomputeDUDD(round: Int) { + // Instantiate solver with game history + val history = historyBefore(round) + val solver = pairing.solver(this, round, pairables.values.toList()) + for (game in games(round).values) { + val white = solver.pairables.find { p-> p.id == game.white }!! + val black = solver.pairables.find { p-> p.id == game.black }!! + game.drawnUpDown = solver.dudd(black, white) + } + } + + + /** + * Recompute DUDD for all rounds + */ + fun recomputeDUDD() { + for (round in 1..rounds) { + recomputeDUDD(round) + } + } + fun usedTables(round: Int): BitSet = games(round).values.map { it.table }.fold(BitSet()) { acc, table -> acc.set(table)