Reeng of solver classes for main crit, start MM

This commit is contained in:
Claude Brisson
2023-06-20 18:00:48 +02:00
parent f7fd2013b3
commit bf0739286a
4 changed files with 42 additions and 41 deletions

View File

@@ -3,7 +3,7 @@ package org.jeudego.pairgoth.pairing
import org.jeudego.pairgoth.model.*
import org.jeudego.pairgoth.model.Game.Result.*
open class HistoryHelper(protected val history: List<List<Game>>, computeScore: () -> Map<ID, Double>) {
open class HistoryHelper(protected val history: List<List<Game>>, private val scores: Map<ID, Double>) {
private val Game.blackScore get() = when (result) {
BLACK, BOTHWIN -> 1.0
@@ -58,17 +58,12 @@ open class HistoryHelper(protected val history: List<List<Game>>, computeScore:
}
}
// Has to be set after construction
private val score by lazy {
computeScore()
}
// SOS related functions given a score function
val sos by lazy {
(history.flatten().map { game ->
Pair(game.black, score[game.white] ?: 0.0)
Pair(game.black, scores[game.white] ?: 0.0)
} + history.flatten().map { game ->
Pair(game.white, score[game.black] ?: 0.0)
Pair(game.white, scores[game.black] ?: 0.0)
}).groupingBy { it.first }.fold(0.0) { acc, next ->
acc + next.second
}
@@ -77,9 +72,9 @@ open class HistoryHelper(protected val history: List<List<Game>>, computeScore:
// sos-1
val sosm1 by lazy {
(history.flatten().map { game ->
Pair(game.black, score[game.white] ?: 0.0)
Pair(game.black, scores[game.white] ?: 0.0)
} + history.flatten().map { game ->
Pair(game.white, score[game.black] ?: 0.0)
Pair(game.white, scores[game.black] ?: 0.0)
}).groupBy {
it.first
}.mapValues {
@@ -91,9 +86,9 @@ open class HistoryHelper(protected val history: List<List<Game>>, computeScore:
// sos-2
val sosm2 by lazy {
(history.flatten().map { game ->
Pair(game.black, score[game.white] ?: 0.0)
Pair(game.black, scores[game.white] ?: 0.0)
} + history.flatten().map { game ->
Pair(game.white, score[game.black] ?: 0.0)
Pair(game.white, scores[game.black] ?: 0.0)
}).groupBy {
it.first
}.mapValues {
@@ -105,9 +100,9 @@ open class HistoryHelper(protected val history: List<List<Game>>, computeScore:
// sodos
val sodos by lazy {
(history.flatten().map { game ->
Pair(game.black, if (game.result == Game.Result.BLACK) score[game.white] ?: 0.0 else 0.0)
Pair(game.black, if (game.result == Game.Result.BLACK) scores[game.white] ?: 0.0 else 0.0)
} + history.flatten().map { game ->
Pair(game.white, if (game.result == Game.Result.WHITE) score[game.black] ?: 0.0 else 0.0)
Pair(game.white, if (game.result == Game.Result.WHITE) scores[game.black] ?: 0.0 else 0.0)
}).groupingBy { it.first }.fold(0.0) { acc, next ->
acc + next.second
}
@@ -134,17 +129,16 @@ open class HistoryHelper(protected val history: List<List<Game>>, computeScore:
acc + next.whiteScore
})
}.reduce { acc, map ->
(acc.keys + map.keys).associate<ID, ID, Double> { id ->
Pair(id, acc.getOrDefault(id, 0.0) + acc.getOrDefault(id, 0.0) + map.getOrDefault(id, 0.0))
}.toMap()
(acc.keys + map.keys).associateWith { id -> acc.getOrDefault(id, 0.0) + acc.getOrDefault(id, 0.0) + map.getOrDefault(id, 0.0) }
.toMap()
}
}
}
// CB TODO - a big problem with the current naive implementation is that the team score is -for now- the sum of team members individual scores
class TeamOfIndividualsHistoryHelper(history: List<List<Game>>, computeScore: () -> Map<ID, Double>):
HistoryHelper(history, computeScore) {
class TeamOfIndividualsHistoryHelper(history: List<List<Game>>, scores: Map<ID, Double>):
HistoryHelper(history, scores) {
private fun Pairable.asTeam() = this as TeamTournament.Team
@@ -156,4 +150,7 @@ class TeamOfIndividualsHistoryHelper(history: List<List<Game>>, computeScore: ()
//override fun sos(p:Pairable) = p.asTeam().teamPlayers.map { super.sos(it) ?: throw Error("unknown player id: #${it.id}") }.sum()
//override fun sosos(p:Pairable) = p.asTeam().teamPlayers.map { super.sosos(it) ?: throw Error("unknown player id: #${it.id}") }.sum()
//override fun sodos(p:Pairable) = p.asTeam().teamPlayers.map { super.sodos(it) ?: throw Error("unknown player id: #${it.id}") }.sum()
// TODO CB - now that we've got the rounds in history helper, calculate virtual scores
// also - try to factorize a bit calculations
}

View File

@@ -9,16 +9,18 @@ class MacMahonSolver(round: Int,
placementParams: PlacementParams):
Solver(round, history, pairables, pairingParams, placementParams) {
val Pairable.mmBase: Double get() = rank + 30.0 // TODO use params
val Pairable.mms: Double get() = mmBase + nbW // TODO real calculation
override val scores: Map<ID, Double> by lazy {
historyHelper.wins.mapValues {
pairablesMap[it.key]!!.let { pairable ->
pairable.mmBase + pairable.nbW
}
}
}
val Pairable.mmBase: Double get() = rank + 30.0 // TODO use params
val Pairable.mms: Double get() = scores[id] ?: 0.0
// CB TODO - configurable criteria
override val Pairable.main get() = mms
override val mainLimits get() = TODO()
override fun computeStandingScore(): Map<ID, Double> {
TODO("Not yet implemented")
}
override fun evalCriterion(pairable: Pairable, criterion: Criterion) = when (criterion) {
Criterion.MMS -> pairable.mms
else -> super.evalCriterion(pairable, criterion)

View File

@@ -47,8 +47,18 @@ sealed class Solver(
val rand = Random(/* seed from properties - TODO */)
}
val historyHelper = if (pairables.first().let { it is TeamTournament.Team && it.teamOfIndividuals }) TeamOfIndividualsHistoryHelper(history, ::computeStandingScore)
else HistoryHelper(history, ::computeStandingScore)
abstract val scores: Map<ID, Double>
val historyHelper = if (pairables.first().let { it is TeamTournament.Team && it.teamOfIndividuals }) TeamOfIndividualsHistoryHelper(history, scores)
else HistoryHelper(history, scores)
// pairables sorted using overloadable sort function
private val sortedPairables by lazy {
pairables.sortedWith(::sort)
}
protected val pairablesMap by lazy {
pairables.associateBy { it.id }
}
open fun sort(p: Pairable, q: Pairable): Int {
for (criterion in placement.criteria) {
@@ -68,11 +78,9 @@ sealed class Solver(
pairing.geo.apply(p1, p2)
// The main criterion that will be used to define the groups should be defined by subclasses
abstract val Pairable.main: Double
val Pairable.main: Double get() = scores[id] ?: 0.0
abstract val mainLimits: Pair<Double, Double>
// SOS and variants will be computed based on this score
abstract fun computeStandingScore(): Map<ID, Double>
fun pair(): List<Game> {
// check that at this stage, we have an even number of pairables
if (pairables.size % 2 != 0) throw Error("expecting an even number of pairables")
@@ -314,11 +322,6 @@ sealed class Solver(
pairables.associate { pairable -> Pair(pairable.id, pairable.main.toInt()) }
}
// pairables sorted using overloadable sort function
private val sortedPairables by lazy {
pairables.sortedWith(::sort)
}
// place (among sorted pairables)
val Pairable.place: Int get() = _place[id]!!
private val _place by lazy {

View File

@@ -10,10 +10,9 @@ class SwissSolver(round: Int,
Solver(round, history, pairables, pairingParams, placementParams) {
// In a Swiss tournament the main criterion is the number of wins and already computed
override val Pairable.main: Double get() = nbW // Rounded Down TODO make it a parameter ?
override val mainLimits = Pair(0.0, round - 1.0)
override fun computeStandingScore(): Map<ID, Double> {
return historyHelper.wins
}
override val scores: Map<ID, Double>
get() = historyHelper.wins
override val mainLimits = Pair(0.0, round - 1.0)
}