From 089b7242924e2496644709196845753f956347e5 Mon Sep 17 00:00:00 2001 From: Theo Barollet Date: Tue, 24 Oct 2023 10:06:11 +0200 Subject: [PATCH 1/2] Annulation du commit sur le bye player par ce qu'il sera choisi directement par le matching a travers un poids. --- .../pairgoth/pairing/solver/BaseSolver.kt | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt index a55903c..771f3a0 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt @@ -24,7 +24,6 @@ sealed class BaseSolver( pairables: List, // All pairables for this round, it may include the bye player pairing: PairingParams, 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) { companion object { @@ -44,22 +43,8 @@ sealed class BaseSolver( pairing.handicap.color(p1, p2) fun pair(): List { - // The byeGame is a list of one game with the bye player or an empty list - val byeGame: List = 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 { // 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") val builder = GraphBuilder(SimpleDirectedWeightedGraph(DefaultWeightedEdge::class.java)) @@ -114,12 +99,6 @@ sealed class BaseSolver( } return result - - } - - fun chooseByePlayer(): Pairable { - // TODO https://github.com/lucvannier/opengotha/blob/master/src/info/vannier/gotha/Tournament.java#L1471 - return ByePlayer } // Base criteria From d26ca7e43b6b59507d4a74b471f6adf3827bf65f Mon Sep 17 00:00:00 2001 From: Theo Barollet Date: Tue, 24 Oct 2023 11:37:30 +0200 Subject: [PATCH 2/2] Choix du bye player a travers un poids pour le matching. Attention la formule est surement mauvaise. --- .../kotlin/org/jeudego/pairgoth/model/Pairing.kt | 4 +++- .../jeudego/pairgoth/pairing/BasePairingHelper.kt | 2 ++ .../org/jeudego/pairgoth/pairing/HistoryHelper.kt | 12 ++++++++++++ .../jeudego/pairgoth/pairing/solver/BaseSolver.kt | 12 ++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) 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 e5ee98a..e7b5fcf 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 @@ -14,7 +14,8 @@ data class BaseCritParams( val dupWeight: Double = MAX_AVOIDDUPGAME, val random: Double = 0.0, 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 { if (nx1 < 0.0 || nx1 > 1.0) throw Error("invalid standardNX1Factor") @@ -25,6 +26,7 @@ data class BaseCritParams( companion object { 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_COLOR_BALANCE = 1000000.0 // 1e6 val default = BaseCritParams() diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/BasePairingHelper.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/BasePairingHelper.kt index abdbd57..fdc2ac8 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/BasePairingHelper.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/BasePairingHelper.kt @@ -75,6 +75,8 @@ abstract class BasePairingHelper( protected val Pairable.group: Int get() = _groups[id]!! + protected val Pairable.nbBye: Int get() = historyHelper.nbPlayedWithBye(this) ?: 0 + // score (number of wins) val Pairable.nbW: Double get() = historyHelper.nbW(this) ?: 0.0 diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt index 516e4a0..7918f0b 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt @@ -20,6 +20,7 @@ open class HistoryHelper(protected val history: List>, scoresGetter: // Generic helper functions open fun playedTogether(p1: Pairable, p2: Pairable) = paired.contains(Pair(p1.id, p2.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] fun drawnUpDown(p: Pairable) = drawnUpDown[p.id] @@ -46,6 +47,17 @@ open class HistoryHelper(protected val history: List>, scoresGetter: } } + private val nbPlayedWithBye: Map 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 by lazy { mutableMapOf().apply { history.flatten().forEach { game -> diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt index 771f3a0..afc4187 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/solver/BaseSolver.kt @@ -40,6 +40,7 @@ sealed class BaseSolver( open fun weight(p1: Pairable, p2: Pairable) = openGothaWeight(p1, p2) + + pairing.base.applyByeWeight(p1, p2) + pairing.handicap.color(p1, p2) fun pair(): List { @@ -142,6 +143,17 @@ sealed class BaseSolver( 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 open fun MainCritParams.apply(p1: Pairable, p2: Pairable): Double { var score = 0.0