Recompute DUDD at import (plus some code cleaning)

This commit is contained in:
Claude Brisson
2024-05-28 12:29:49 +02:00
parent 8636f939e4
commit 6dc634df7e
4 changed files with 44 additions and 21 deletions

View File

@@ -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 }

View File

@@ -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)

View File

@@ -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<Pairable>): List<Game>
abstract fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>): BaseSolver
fun pair(tournament: Tournament<*>, round: Int, pairables: List<Pairable>): List<Game> {
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<Pairable>): List<Game> {
return SwissSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, pairingParams, placementParams, tournament.usedTables(round)).pair()
}
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>) =
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<Pairable>): List<Game> {
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<Pairable>) =
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<Pairable>): List<Game> {
TODO()
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>): BaseSolver {
TODO("not implemented")
}
}

View File

@@ -74,15 +74,10 @@ sealed class Tournament <P: Pairable>(
else mutableMapOf<ID, Game>().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 <P: Pairable>(
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)