From 8d76ce471b22bec850a4b7c1d31a4766f014d0ef Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Mon, 2 Sep 2024 20:13:00 +0200 Subject: [PATCH] Align on opengotha for SOS and SOSOS missed rounds calculations --- .../jeudego/pairgoth/pairing/HistoryHelper.kt | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) 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 14572e5..ad2e538 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 @@ -5,14 +5,9 @@ import org.jeudego.pairgoth.model.Game.Result.* open class HistoryHelper( protected val history: List>, - // scoresGetter() returns Pair(absentSosValueForOthers, score) where score is nbw for Swiss, mms for MM, ... + // scoresGetter() returns Pair(sos value for missed rounds, score) where score is nbw for Swiss, mms for MM, ... scoresGetter: HistoryHelper.()-> Map>) { - // List of all the pairables ID present in the history - val allPairables = history.flatten() - .map { game -> listOf(game.white, game.black) } - .flatten().distinct() - private val Game.blackScore get() = when (result) { BLACK, BOTHWIN -> 1.0 else -> 0.0 @@ -76,12 +71,12 @@ open class HistoryHelper( } } - // Set of all implied players for each round + // Set of all implied players for each round (warning: does comprise games with BIP) val playersPerRound: List> by lazy { history.map { it.fold(mutableSetOf()) { acc, next -> - acc.add(next.white) - acc.add(next.black) + if(next.white != 0) acc.add(next.white) + if (next.black != 0) acc.add(next.black) acc } } @@ -106,20 +101,30 @@ open class HistoryHelper( // define mms to be a synonym of scores val mms by lazy { scores.mapValues { it -> it.value.second } } - // SOS related functions given a score function val sos by lazy { - (history.flatten().map { game -> - Pair(game.black, scores[game.white]?.second?.let { it - game.handicap } ?: 0.0) + val historySos = (history.flatten().map { game -> + Pair( + game.black, + if (game.white == 0) scores[game.black]?.first ?: 0.0 + else scores[game.white]?.second?.let { it - game.handicap } ?: 0.0 + ) } + history.flatten().map { game -> - Pair(game.white, scores[game.black]?.second?.let { it + game.handicap } ?: 0.0) - }).groupingBy { it.first }.fold(0.0) { acc, next -> + Pair( + game.white, + if (game.black == 0) scores[game.white]?.first ?: 0.0 + else scores[game.black]?.second?.let { it + game.handicap } ?: 0.0 + ) + }).groupingBy { + it.first + }.fold(0.0) { acc, next -> acc + next.second - }.mapValues { (id, score) -> - // "If the player does not participate in a round, the opponent's score is replaced by the starting score of the player himself." - score + playersPerRound.sumOf { players -> - if (players.contains(id)) 0.0 - else scores[id]?.first ?: 0.0 + } + + scores.mapValues { (id, pair) -> + (historySos[id] ?: 0.0) + playersPerRound.sumOf { + if (it.contains(id)) 0.0 else pair.first } + } } @@ -177,24 +182,25 @@ open class HistoryHelper( // sosos val sosos by lazy { val currentRound = history.size - (history.flatten().filter { game -> - game.white != 0 // Remove games against byePlayer - }.map { game -> + val historySosos = (history.flatten().map { game -> Pair(game.black, sos[game.white] ?: 0.0) - } + history.flatten().filter { game -> - game.white != 0 // Remove games against byePlayer - }.map { game -> + } + history.flatten().map { game -> Pair(game.white, sos[game.black] ?: 0.0) - }).groupingBy { it.first }.fold(0.0) { acc, next -> + }).groupingBy { + it.first + }.fold(0.0) { acc, next -> acc + next.second - }.mapValues { (id, sosos) -> - sosos + playersPerRound.sumOf { players -> - if (players.contains(id)) 0.0 - else (scores[id]?.first ?: 0.0) * currentRound + } + + scores.mapValues { (id, pair) -> + (historySosos[id] ?: 0.0) + playersPerRound.sumOf { + if (it.contains(id)) 0.0 else pair.first * currentRound } + } } + // cumulative score val cumScore by lazy { history.map { games ->