Merge branch 'pairing2' of gitlab.jeudego.org:tournois/pairgoth into pairing2

This commit is contained in:
Quentin Rendu
2023-10-24 11:55:09 +02:00
4 changed files with 30 additions and 23 deletions

View File

@@ -14,7 +14,8 @@ data class BaseCritParams(
val dupWeight: Double = MAX_AVOIDDUPGAME, val dupWeight: Double = MAX_AVOIDDUPGAME,
val random: Double = 0.0, val random: Double = 0.0,
val deterministic: Boolean = true, val deterministic: Boolean = true,
val colorBalanceWeight: Double = MAX_COLOR_BALANCE val colorBalanceWeight: Double = MAX_COLOR_BALANCE,
val byeWeight: Double = MAX_BYE_WEIGHT // This weight is not in opengotha
) { ) {
init { init {
if (nx1 < 0.0 || nx1 > 1.0) throw Error("invalid standardNX1Factor") if (nx1 < 0.0 || nx1 > 1.0) throw Error("invalid standardNX1Factor")
@@ -25,6 +26,7 @@ data class BaseCritParams(
companion object { companion object {
const val MAX_AVOIDDUPGAME = 500000000000000.0 // 5e14 const val MAX_AVOIDDUPGAME = 500000000000000.0 // 5e14
const val MAX_BYE_WEIGHT = 100000000000.0 // 1e11
const val MAX_RANDOM = 1000000000.0 // 1e9 const val MAX_RANDOM = 1000000000.0 // 1e9
const val MAX_COLOR_BALANCE = 1000000.0 // 1e6 const val MAX_COLOR_BALANCE = 1000000.0 // 1e6
val default = BaseCritParams() val default = BaseCritParams()

View File

@@ -75,6 +75,8 @@ abstract class BasePairingHelper(
protected val Pairable.group: Int get() = _groups[id]!! protected val Pairable.group: Int get() = _groups[id]!!
protected val Pairable.nbBye: Int get() = historyHelper.nbPlayedWithBye(this) ?: 0
// score (number of wins) // score (number of wins)
val Pairable.nbW: Double get() = historyHelper.nbW(this) ?: 0.0 val Pairable.nbW: Double get() = historyHelper.nbW(this) ?: 0.0

View File

@@ -20,6 +20,7 @@ open class HistoryHelper(protected val history: List<List<Game>>, scoresGetter:
// Generic helper functions // Generic helper functions
open fun playedTogether(p1: Pairable, p2: Pairable) = paired.contains(Pair(p1.id, p2.id)) open fun playedTogether(p1: Pairable, p2: Pairable) = paired.contains(Pair(p1.id, p2.id))
open fun colorBalance(p: Pairable) = colorBalance[p.id] open fun colorBalance(p: Pairable) = colorBalance[p.id]
open fun nbPlayedWithBye(p: Pairable) = nbPlayedWithBye[p.id]
open fun nbW(p: Pairable) = wins[p.id] open fun nbW(p: Pairable) = wins[p.id]
fun drawnUpDown(p: Pairable) = drawnUpDown[p.id] fun drawnUpDown(p: Pairable) = drawnUpDown[p.id]
@@ -46,6 +47,17 @@ open class HistoryHelper(protected val history: List<List<Game>>, scoresGetter:
} }
} }
private val nbPlayedWithBye: Map<ID, Int> by lazy {
history.flatten().flatMap { game ->
// Duplicates (white, black) into (white, black) and (black, white)
listOf(Pair(game.white, game.black), Pair(game.black, game.white))
}.groupingBy {
it.first
}.fold(0) { acc, next ->
acc + if (next.second == ByePlayer.id) 1 else 0
}
}
val wins: Map<ID, Double> by lazy { val wins: Map<ID, Double> by lazy {
mutableMapOf<ID, Double>().apply { mutableMapOf<ID, Double>().apply {
history.flatten().forEach { game -> history.flatten().forEach { game ->

View File

@@ -24,7 +24,6 @@ sealed class BaseSolver(
pairables: List<Pairable>, // All pairables for this round, it may include the bye player pairables: List<Pairable>, // All pairables for this round, it may include the bye player
pairing: PairingParams, pairing: PairingParams,
placement: PlacementParams, placement: PlacementParams,
val forcedBye: Pairable? = null, // This parameter is non-null to force the given pairable to be chosen as a bye player.
) : BasePairingHelper(history, pairables, pairing, placement) { ) : BasePairingHelper(history, pairables, pairing, placement) {
companion object { companion object {
@@ -41,25 +40,12 @@ sealed class BaseSolver(
open fun weight(p1: Pairable, p2: Pairable) = open fun weight(p1: Pairable, p2: Pairable) =
openGothaWeight(p1, p2) + openGothaWeight(p1, p2) +
pairing.base.applyByeWeight(p1, p2) +
pairing.handicap.color(p1, p2) pairing.handicap.color(p1, p2)
fun pair(): List<Game> { fun pair(): List<Game> {
// The byeGame is a list of one game with the bye player or an empty list
val byeGame: List<Game> = if (pairables.size % 2 != 0) {
// We must choose a bye player
val physicalByePlayer = forcedBye ?: chooseByePlayer()
// Remove the bye from the pairables
pairables = pairables.filterNot { it == physicalByePlayer }
// Assign a special game to the bye player
listOf( Game(Store.nextGameId, physicalByePlayer.id, ByePlayer.id) )
} else {
listOf()
}
return listOf(pairEvenNumberOfPlayers(), byeGame).flatten() // Add the bye game to the actual paired games
}
fun pairEvenNumberOfPlayers(): List<Game> {
// check that at this stage, we have an even number of pairables // check that at this stage, we have an even number of pairables
// The BYE player should have been added beforehand to make a number of pairables even.
if (pairables.size % 2 != 0) throw Error("expecting an even number of pairables") if (pairables.size % 2 != 0) throw Error("expecting an even number of pairables")
val builder = GraphBuilder(SimpleDirectedWeightedGraph<Pairable, DefaultWeightedEdge>(DefaultWeightedEdge::class.java)) val builder = GraphBuilder(SimpleDirectedWeightedGraph<Pairable, DefaultWeightedEdge>(DefaultWeightedEdge::class.java))
@@ -115,12 +101,6 @@ sealed class BaseSolver(
} }
return result return result
}
fun chooseByePlayer(): Pairable {
// TODO https://github.com/lucvannier/opengotha/blob/master/src/info/vannier/gotha/Tournament.java#L1471
return ByePlayer
} }
// Base criteria // Base criteria
@@ -164,6 +144,17 @@ sealed class BaseSolver(
return score return score
} }
open fun BaseCritParams.applyByeWeight(p1: Pairable, p2: Pairable): Double {
// The weight is applied if one of p1 or p2 is the BYE player
return if (p1.id == ByePlayer.id || p2.id == ByePlayer.id) {
val actualPlayer = if (p1.id == ByePlayer.id) p2 else p1
// TODO maybe use a different formula than opengotha
BaseCritParams.MAX_BYE_WEIGHT - (1000 * actualPlayer.nbBye + actualPlayer.rank + 2*actualPlayer.main)
} else {
0.0
}
}
// Main criteria // Main criteria
open fun MainCritParams.apply(p1: Pairable, p2: Pairable): Double { open fun MainCritParams.apply(p1: Pairable, p2: Pairable): Double {
var score = 0.0 var score = 0.0