Align on opengotha for SOS and SOSOS missed rounds calculations

This commit is contained in:
Claude Brisson
2024-09-02 20:13:00 +02:00
parent c171d839c3
commit 8d76ce471b

View File

@@ -5,14 +5,9 @@ import org.jeudego.pairgoth.model.Game.Result.*
open class HistoryHelper( open class HistoryHelper(
protected val history: List<List<Game>>, protected val history: List<List<Game>>,
// 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<ID, Pair<Double, Double>>) { scoresGetter: HistoryHelper.()-> Map<ID, Pair<Double, Double>>) {
// 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) { private val Game.blackScore get() = when (result) {
BLACK, BOTHWIN -> 1.0 BLACK, BOTHWIN -> 1.0
else -> 0.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<Set<ID>> by lazy { val playersPerRound: List<Set<ID>> by lazy {
history.map { history.map {
it.fold(mutableSetOf<ID>()) { acc, next -> it.fold(mutableSetOf<ID>()) { acc, next ->
acc.add(next.white) if(next.white != 0) acc.add(next.white)
acc.add(next.black) if (next.black != 0) acc.add(next.black)
acc acc
} }
} }
@@ -106,20 +101,30 @@ open class HistoryHelper(
// define mms to be a synonym of scores // define mms to be a synonym of scores
val mms by lazy { scores.mapValues { it -> it.value.second } } val mms by lazy { scores.mapValues { it -> it.value.second } }
// SOS related functions given a score function
val sos by lazy { val sos by lazy {
(history.flatten().map { game -> val historySos = (history.flatten().map { game ->
Pair(game.black, scores[game.white]?.second?.let { it - game.handicap } ?: 0.0) 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 -> } + history.flatten().map { game ->
Pair(game.white, scores[game.black]?.second?.let { it + game.handicap } ?: 0.0) Pair(
}).groupingBy { it.first }.fold(0.0) { acc, next -> 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 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 -> scores.mapValues { (id, pair) ->
if (players.contains(id)) 0.0 (historySos[id] ?: 0.0) + playersPerRound.sumOf {
else scores[id]?.first ?: 0.0 if (it.contains(id)) 0.0 else pair.first
} }
} }
} }
@@ -177,24 +182,25 @@ open class HistoryHelper(
// sosos // sosos
val sosos by lazy { val sosos by lazy {
val currentRound = history.size val currentRound = history.size
(history.flatten().filter { game -> val historySosos = (history.flatten().map { game ->
game.white != 0 // Remove games against byePlayer
}.map { game ->
Pair(game.black, sos[game.white] ?: 0.0) Pair(game.black, sos[game.white] ?: 0.0)
} + history.flatten().filter { game -> } + history.flatten().map { game ->
game.white != 0 // Remove games against byePlayer
}.map { game ->
Pair(game.white, sos[game.black] ?: 0.0) 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 acc + next.second
}.mapValues { (id, sosos) -> }
sosos + playersPerRound.sumOf { players ->
if (players.contains(id)) 0.0 scores.mapValues { (id, pair) ->
else (scores[id]?.first ?: 0.0) * currentRound (historySosos[id] ?: 0.0) + playersPerRound.sumOf {
if (it.contains(id)) 0.0 else pair.first * currentRound
} }
} }
} }
// cumulative score // cumulative score
val cumScore by lazy { val cumScore by lazy {
history.map { games -> history.map { games ->