Code cleaning: move history helper creation in tournament class, factorize main score function
This commit is contained in:
@@ -13,12 +13,8 @@ import org.jeudego.pairgoth.model.getID
|
|||||||
import org.jeudego.pairgoth.model.historyBefore
|
import org.jeudego.pairgoth.model.historyBefore
|
||||||
import org.jeudego.pairgoth.pairing.HistoryHelper
|
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||||
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
|
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
|
||||||
import kotlin.math.floor
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.round
|
|
||||||
|
|
||||||
// TODO CB avoid code redundancy with solvers
|
|
||||||
|
|
||||||
fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = false): List<Json.Object> {
|
fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = false): List<Json.Object> {
|
||||||
|
|
||||||
@@ -27,42 +23,12 @@ fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = f
|
|||||||
return min(max(rank, pairing.mmFloor), pairing.mmBar) + MacMahonSolver.mmsZero + mmsCorrection
|
return min(max(rank, pairing.mmFloor), pairing.mmBar) + MacMahonSolver.mmsZero + mmsCorrection
|
||||||
}
|
}
|
||||||
|
|
||||||
fun roundScore(score: Double): Double {
|
|
||||||
val epsilon = 0.00001
|
|
||||||
// Note: this works for now because we only have .0 and .5 fractional parts
|
|
||||||
return if (pairing.pairingParams.main.roundDownScore) floor(score + epsilon)
|
|
||||||
else round(2 * score) / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frozen != null) {
|
if (frozen != null) {
|
||||||
return ArrayList(frozen!!.map { it -> it as Json.Object })
|
return ArrayList(frozen!!.map { it -> it as Json.Object })
|
||||||
}
|
}
|
||||||
|
|
||||||
// CB TODO - factorize history helper creation between here and solver classes
|
val history = historyHelper(round)
|
||||||
val historyHelper = HistoryHelper(historyBefore(round + 1)) {
|
|
||||||
if (pairing.type == PairingType.SWISS) {
|
|
||||||
pairables.mapValues {
|
|
||||||
Pair(0.0, wins[it.key] ?: 0.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pairables.mapValues {
|
|
||||||
it.value.let { pairable ->
|
|
||||||
val mmBase = pairable.mmBase()
|
|
||||||
val score = roundScore(mmBase +
|
|
||||||
(nbW(pairable) ?: 0.0) +
|
|
||||||
(1..round).sumOf { round ->
|
|
||||||
if (playersPerRound.getOrNull(round - 1)?.contains(pairable.id) == true) 0.0 else 1.0
|
|
||||||
} * pairing.pairingParams.main.mmsValueAbsent)
|
|
||||||
Pair(
|
|
||||||
if (pairing.pairingParams.main.sosValueAbsentUseBase) mmBase
|
|
||||||
else roundScore(mmBase + round/2),
|
|
||||||
score
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val neededCriteria = ArrayList(pairing.placementParams.criteria)
|
val neededCriteria = ArrayList(pairing.placementParams.criteria)
|
||||||
if (!neededCriteria.contains(Criterion.NBW)) neededCriteria.add(Criterion.NBW)
|
if (!neededCriteria.contains(Criterion.NBW)) neededCriteria.add(Criterion.NBW)
|
||||||
if (!neededCriteria.contains(Criterion.RATING)) neededCriteria.add(Criterion.RATING)
|
if (!neededCriteria.contains(Criterion.RATING)) neededCriteria.add(Criterion.RATING)
|
||||||
@@ -73,24 +39,24 @@ fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = f
|
|||||||
Criterion.CATEGORY -> StandingsHandler.nullMap
|
Criterion.CATEGORY -> StandingsHandler.nullMap
|
||||||
Criterion.RANK -> pairables.mapValues { it.value.rank }
|
Criterion.RANK -> pairables.mapValues { it.value.rank }
|
||||||
Criterion.RATING -> pairables.mapValues { it.value.rating }
|
Criterion.RATING -> pairables.mapValues { it.value.rating }
|
||||||
Criterion.NBW -> historyHelper.wins
|
Criterion.NBW -> history.wins
|
||||||
Criterion.MMS -> historyHelper.mms
|
Criterion.MMS -> history.mms
|
||||||
Criterion.SCOREX -> historyHelper.scoresX
|
Criterion.SCOREX -> history.scoresX
|
||||||
Criterion.STS -> StandingsHandler.nullMap
|
Criterion.STS -> StandingsHandler.nullMap
|
||||||
Criterion.CPS -> StandingsHandler.nullMap
|
Criterion.CPS -> StandingsHandler.nullMap
|
||||||
|
|
||||||
Criterion.SOSW -> historyHelper.sos
|
Criterion.SOSW -> history.sos
|
||||||
Criterion.SOSWM1 -> historyHelper.sosm1
|
Criterion.SOSWM1 -> history.sosm1
|
||||||
Criterion.SOSWM2 -> historyHelper.sosm2
|
Criterion.SOSWM2 -> history.sosm2
|
||||||
Criterion.SODOSW -> historyHelper.sodos
|
Criterion.SODOSW -> history.sodos
|
||||||
Criterion.SOSOSW -> historyHelper.sosos
|
Criterion.SOSOSW -> history.sosos
|
||||||
Criterion.CUSSW -> if (round == 0) StandingsHandler.nullMap else historyHelper.cumScore
|
Criterion.CUSSW -> if (round == 0) StandingsHandler.nullMap else history.cumScore
|
||||||
Criterion.SOSM -> historyHelper.sos
|
Criterion.SOSM -> history.sos
|
||||||
Criterion.SOSMM1 -> historyHelper.sosm1
|
Criterion.SOSMM1 -> history.sosm1
|
||||||
Criterion.SOSMM2 -> historyHelper.sosm2
|
Criterion.SOSMM2 -> history.sosm2
|
||||||
Criterion.SODOSM -> historyHelper.sodos
|
Criterion.SODOSM -> history.sodos
|
||||||
Criterion.SOSOSM -> historyHelper.sosos
|
Criterion.SOSOSM -> history.sosos
|
||||||
Criterion.CUSSM -> historyHelper.cumScore
|
Criterion.CUSSM -> history.cumScore
|
||||||
|
|
||||||
Criterion.SOSTS -> StandingsHandler.nullMap
|
Criterion.SOSTS -> StandingsHandler.nullMap
|
||||||
|
|
||||||
|
@@ -175,7 +175,7 @@ class Swiss(
|
|||||||
): Pairing(SWISS, pairingParams, placementParams) {
|
): Pairing(SWISS, pairingParams, placementParams) {
|
||||||
companion object {}
|
companion object {}
|
||||||
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>) =
|
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>) =
|
||||||
SwissSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, tournament.pairables, pairingParams, placementParams, tournament.usedTables(round))
|
SwissSolver(round, tournament.rounds, tournament.historyHelper(round), pairables, tournament.pairables, pairingParams, placementParams, tournament.usedTables(round))
|
||||||
}
|
}
|
||||||
|
|
||||||
class MacMahon(
|
class MacMahon(
|
||||||
@@ -203,7 +203,7 @@ class MacMahon(
|
|||||||
): Pairing(MAC_MAHON, pairingParams, placementParams) {
|
): Pairing(MAC_MAHON, pairingParams, placementParams) {
|
||||||
companion object {}
|
companion object {}
|
||||||
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>) =
|
override fun solver(tournament: Tournament<*>, round: Int, pairables: List<Pairable>) =
|
||||||
MacMahonSolver(round, tournament.rounds, tournament.historyBefore(round), pairables, tournament.pairables, pairingParams, placementParams, tournament.usedTables(round), mmFloor, mmBar)
|
MacMahonSolver(round, tournament.rounds, tournament.historyHelper(round), pairables, tournament.pairables, pairingParams, placementParams, tournament.usedTables(round), mmFloor, mmBar)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoundRobin(
|
class RoundRobin(
|
||||||
|
@@ -7,7 +7,8 @@ import com.republicate.kson.toJsonObject
|
|||||||
//import kotlinx.datetime.LocalDate
|
//import kotlinx.datetime.LocalDate
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
||||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.logger
|
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||||
|
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
|
||||||
import org.jeudego.pairgoth.store.nextGameId
|
import org.jeudego.pairgoth.store.nextGameId
|
||||||
import org.jeudego.pairgoth.store.nextPlayerId
|
import org.jeudego.pairgoth.store.nextPlayerId
|
||||||
import org.jeudego.pairgoth.store.nextTournamentId
|
import org.jeudego.pairgoth.store.nextTournamentId
|
||||||
@@ -15,8 +16,10 @@ import org.jeudego.pairgoth.util.MutableBiMultiMap
|
|||||||
import org.jeudego.pairgoth.util.mutableBiMultiMapOf
|
import org.jeudego.pairgoth.util.mutableBiMultiMapOf
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
|
||||||
import kotlin.collections.get
|
import kotlin.collections.get
|
||||||
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.math.round
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
sealed class Tournament <P: Pairable>(
|
sealed class Tournament <P: Pairable>(
|
||||||
@@ -208,6 +211,47 @@ sealed class Tournament <P: Pairable>(
|
|||||||
}
|
}
|
||||||
return excluded
|
return excluded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun roundScore(score: Double): Double {
|
||||||
|
val epsilon = 0.00001
|
||||||
|
// Note: this works for now because we only have .0 and .5 fractional parts
|
||||||
|
return if (pairing.pairingParams.main.roundDownScore) floor(score + epsilon)
|
||||||
|
else round(2 * score) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Pairable.mmBase(): Double {
|
||||||
|
if (pairing !is MacMahon) throw Error("invalid call: tournament is not Mac Mahon")
|
||||||
|
return min(max(rank, pairing.mmFloor), pairing.mmBar) + MacMahonSolver.mmsZero + mmsCorrection
|
||||||
|
}
|
||||||
|
|
||||||
|
fun historyHelper(round: Int): HistoryHelper {
|
||||||
|
return HistoryHelper(historyBefore(round + 1)) {
|
||||||
|
if (pairing.type == PairingType.SWISS) {
|
||||||
|
pairables.mapValues {
|
||||||
|
// In a Swiss tournament the main criterion is the number of wins
|
||||||
|
Pair(0.0, wins[it.key] ?: 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pairables.mapValues {
|
||||||
|
// In a MacMahon tournament the main criterion is the mms
|
||||||
|
it.value.let { pairable ->
|
||||||
|
val mmBase = pairable.mmBase()
|
||||||
|
val score = roundScore(mmBase +
|
||||||
|
(nbW(pairable) ?: 0.0) +
|
||||||
|
(1..round).sumOf { round ->
|
||||||
|
if (playersPerRound.getOrNull(round - 1)?.contains(pairable.id) == true) 0.0 else 1.0
|
||||||
|
} * pairing.pairingParams.main.mmsValueAbsent)
|
||||||
|
Pair(
|
||||||
|
if (pairing.pairingParams.main.sosValueAbsentUseBase) mmBase
|
||||||
|
else roundScore(mmBase + round/2),
|
||||||
|
score
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard tournament of individuals
|
// standard tournament of individuals
|
||||||
|
@@ -5,20 +5,14 @@ import org.jeudego.pairgoth.model.*
|
|||||||
abstract class BasePairingHelper(
|
abstract class BasePairingHelper(
|
||||||
val round: Int,
|
val round: Int,
|
||||||
val totalRounds: Int,
|
val totalRounds: Int,
|
||||||
history: List<List<Game>>, // History of all games played for each round
|
val history: HistoryHelper, // Digested history of all games played for each round
|
||||||
var pairables: List<Pairable>, // All pairables for this round, it may include the bye player
|
var pairables: List<Pairable>, // All pairables for this round, it may include the bye player
|
||||||
val pairablesMap: Map<ID, Pairable>, // Map of all known pairables for this tournament
|
|
||||||
val pairing: PairingParams,
|
val pairing: PairingParams,
|
||||||
val placement: PlacementParams,
|
val placement: PlacementParams,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
abstract val scores: Map<ID, Pair<Double, Double>>
|
val scores get() = history.scores
|
||||||
abstract val scoresX: Map<ID, Double>
|
abstract val scoresX: Map<ID, Double>
|
||||||
val historyHelper =
|
|
||||||
if (pairables.first().let { it is TeamTournament.Team && it.teamOfIndividuals }) TeamOfIndividualsHistoryHelper(
|
|
||||||
history
|
|
||||||
) { scores }
|
|
||||||
else HistoryHelper(history) { scores }
|
|
||||||
|
|
||||||
// Extend pairables with members from all rounds
|
// Extend pairables with members from all rounds
|
||||||
|
|
||||||
@@ -84,28 +78,28 @@ abstract class BasePairingHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// already paired players map
|
// already paired players map
|
||||||
protected fun Pairable.played(other: Pairable) = historyHelper.playedTogether(this, other)
|
protected fun Pairable.played(other: Pairable) = history.playedTogether(this, other)
|
||||||
|
|
||||||
// color balance (nw - nb)
|
// color balance (nw - nb)
|
||||||
protected val Pairable.colorBalance: Int get() = historyHelper.colorBalance(this) ?: 0
|
protected val Pairable.colorBalance: Int get() = history.colorBalance(this) ?: 0
|
||||||
|
|
||||||
protected val Pairable.group: Int get() = _groups[id]!!
|
protected val Pairable.group: Int get() = _groups[id]!!
|
||||||
|
|
||||||
protected val Pairable.drawnUpDown: Pair<Int, Int> get() = historyHelper.drawnUpDown(this) ?: Pair(0, 0)
|
protected val Pairable.drawnUpDown: Pair<Int, Int> get() = history.drawnUpDown(this) ?: Pair(0, 0)
|
||||||
|
|
||||||
protected val Pairable.nbBye: Int get() = historyHelper.nbPlayedWithBye(this) ?: 0
|
protected val Pairable.nbBye: Int get() = history.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() = history.nbW(this) ?: 0.0
|
||||||
|
|
||||||
val Pairable.sos: Double get() = historyHelper.sos[id] ?: 0.0
|
val Pairable.sos: Double get() = history.sos[id] ?: 0.0
|
||||||
val Pairable.sosm1: Double get() = historyHelper.sosm1[id] ?: 0.0
|
val Pairable.sosm1: Double get() = history.sosm1[id] ?: 0.0
|
||||||
val Pairable.sosm2: Double get() = historyHelper.sosm2[id] ?: 0.0
|
val Pairable.sosm2: Double get() = history.sosm2[id] ?: 0.0
|
||||||
val Pairable.sosos: Double get() = historyHelper.sosos[id] ?: 0.0
|
val Pairable.sosos: Double get() = history.sosos[id] ?: 0.0
|
||||||
val Pairable.sodos: Double get() = historyHelper.sodos[id] ?: 0.0
|
val Pairable.sodos: Double get() = history.sodos[id] ?: 0.0
|
||||||
val Pairable.cums: Double get() = historyHelper.cumScore[id] ?: 0.0
|
val Pairable.cums: Double get() = history.cumScore[id] ?: 0.0
|
||||||
fun Pairable.missedRounds(): Int = (1 until round).map { round ->
|
fun Pairable.missedRounds(): Int = (1 until round).map { round ->
|
||||||
if (historyHelper.playersPerRound.getOrNull(round - 1)
|
if (history.playersPerRound.getOrNull(round - 1)
|
||||||
?.contains(id) == true
|
?.contains(id) == true
|
||||||
) 0 else 1
|
) 0 else 1
|
||||||
}.sum()
|
}.sum()
|
||||||
|
@@ -3,11 +3,21 @@ package org.jeudego.pairgoth.pairing
|
|||||||
import org.jeudego.pairgoth.model.*
|
import org.jeudego.pairgoth.model.*
|
||||||
import org.jeudego.pairgoth.model.Game.Result.*
|
import org.jeudego.pairgoth.model.Game.Result.*
|
||||||
import org.jeudego.pairgoth.model.TeamTournament.Team
|
import org.jeudego.pairgoth.model.TeamTournament.Team
|
||||||
|
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map from a pairable ID to a pair of (missed rounds increment, main score).
|
||||||
|
* The missed rounds increment is 0 for Swiss, and a function of the MMS base of the pairable for MacMahon.
|
||||||
|
* The main score is the NBW for the Swiss, the MMS for MacMahon.
|
||||||
|
*/
|
||||||
|
typealias ScoreMapBuilder = HistoryHelper.()-> Map<ID, Pair<Double, Double>>
|
||||||
|
|
||||||
open class HistoryHelper(
|
open class HistoryHelper(
|
||||||
protected val history: List<List<Game>>,
|
protected val history: List<List<Game>>,
|
||||||
// scoresGetter() returns Pair(sos value for missed rounds, 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: ScoreMapBuilder) {
|
||||||
|
|
||||||
private val Game.blackScore get() = when (result) {
|
private val Game.blackScore get() = when (result) {
|
||||||
BLACK, BOTHWIN -> 1.0
|
BLACK, BOTHWIN -> 1.0
|
||||||
@@ -19,7 +29,7 @@ open class HistoryHelper(
|
|||||||
else -> 0.0
|
else -> 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scores by lazy {
|
val scores by lazy {
|
||||||
scoresGetter()
|
scoresGetter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,11 +251,4 @@ open class HistoryHelper(
|
|||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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>>, scoresGetter: () -> Map<ID, Pair<Double, Double>>):
|
|
||||||
HistoryHelper(history, { scoresGetter() }) {
|
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import org.jeudego.pairgoth.model.*
|
|||||||
import org.jeudego.pairgoth.model.MainCritParams.DrawUpDown
|
import org.jeudego.pairgoth.model.MainCritParams.DrawUpDown
|
||||||
import org.jeudego.pairgoth.model.MainCritParams.SeedMethod.*
|
import org.jeudego.pairgoth.model.MainCritParams.SeedMethod.*
|
||||||
import org.jeudego.pairgoth.pairing.BasePairingHelper
|
import org.jeudego.pairgoth.pairing.BasePairingHelper
|
||||||
|
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||||
import org.jeudego.pairgoth.pairing.detRandom
|
import org.jeudego.pairgoth.pairing.detRandom
|
||||||
import org.jeudego.pairgoth.pairing.nonDetRandom
|
import org.jeudego.pairgoth.pairing.nonDetRandom
|
||||||
import org.jeudego.pairgoth.store.nextGameId
|
import org.jeudego.pairgoth.store.nextGameId
|
||||||
@@ -21,13 +22,12 @@ import kotlin.math.*
|
|||||||
sealed class BaseSolver(
|
sealed class BaseSolver(
|
||||||
round: Int,
|
round: Int,
|
||||||
totalRounds: Int,
|
totalRounds: Int,
|
||||||
history: List<List<Game>>, // History of all games played for each round
|
history: HistoryHelper, // History of all games played for each round
|
||||||
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
|
||||||
pairablesMap: Map<ID, Pairable>, // Map of all known pairables in this tournament
|
|
||||||
pairing: PairingParams,
|
pairing: PairingParams,
|
||||||
placement: PlacementParams,
|
placement: PlacementParams,
|
||||||
val usedTables: BitSet
|
val usedTables: BitSet
|
||||||
) : BasePairingHelper(round, totalRounds, history, pairables, pairablesMap, pairing, placement) {
|
) : BasePairingHelper(round, totalRounds, history, pairables, pairing, placement) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val rand = Random(/* seed from properties - TODO */)
|
val rand = Random(/* seed from properties - TODO */)
|
||||||
@@ -79,12 +79,12 @@ sealed class BaseSolver(
|
|||||||
// Choose bye player and remove from pairables
|
// Choose bye player and remove from pairables
|
||||||
if (ByePlayer in nameSortedPairables){
|
if (ByePlayer in nameSortedPairables){
|
||||||
nameSortedPairables.remove(ByePlayer)
|
nameSortedPairables.remove(ByePlayer)
|
||||||
var minWeight = 1000.0*round + (Pairable.MAX_RANK - Pairable.MIN_RANK) + 1;
|
var minWeight = 1000.0 * round + (Pairable.MAX_RANK - Pairable.MIN_RANK) + 1;
|
||||||
var weightForBye : Double
|
var weightForBye : Double
|
||||||
var byePlayerIndex = 0
|
var byePlayerIndex = 0
|
||||||
for (p in nameSortedPairables){
|
for (p in nameSortedPairables){
|
||||||
weightForBye = computeWeightForBye(p)
|
weightForBye = computeWeightForBye(p)
|
||||||
if (p.id in historyHelper.byePlayers) weightForBye += 1000
|
if (p.id in history.byePlayers) weightForBye += 1000
|
||||||
if (weightForBye <= minWeight){
|
if (weightForBye <= minWeight){
|
||||||
minWeight = weightForBye
|
minWeight = weightForBye
|
||||||
chosenByePlayer = p
|
chosenByePlayer = p
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package org.jeudego.pairgoth.pairing.solver
|
package org.jeudego.pairgoth.pairing.solver
|
||||||
|
|
||||||
import org.jeudego.pairgoth.model.*
|
import org.jeudego.pairgoth.model.*
|
||||||
|
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -8,34 +9,18 @@ import kotlin.math.roundToInt
|
|||||||
|
|
||||||
class MacMahonSolver(round: Int,
|
class MacMahonSolver(round: Int,
|
||||||
totalRounds: Int,
|
totalRounds: Int,
|
||||||
history: List<List<Game>>,
|
history: HistoryHelper,
|
||||||
pairables: List<Pairable>,
|
pairables: List<Pairable>,
|
||||||
pairablesMap: Map<ID, Pairable>,
|
allPairablesMap: Map<ID, Pairable>,
|
||||||
pairingParams: PairingParams,
|
pairingParams: PairingParams,
|
||||||
placementParams: PlacementParams,
|
placementParams: PlacementParams,
|
||||||
usedTables: BitSet,
|
usedTables: BitSet,
|
||||||
private val mmFloor: Int, private val mmBar: Int) :
|
private val mmFloor: Int, private val mmBar: Int) :
|
||||||
BaseSolver(round, totalRounds, history, pairables, pairablesMap, pairingParams, placementParams, usedTables) {
|
BaseSolver(round, totalRounds, history, pairables, pairingParams, placementParams, usedTables) {
|
||||||
|
|
||||||
override val scores: Map<ID, Pair<Double, Double>> by lazy {
|
|
||||||
require (mmBar > mmFloor) { "MMFloor is higher than MMBar" }
|
|
||||||
pairablesMap.mapValues {
|
|
||||||
it.value.let { pairable ->
|
|
||||||
val score = roundScore(pairable.mmBase +
|
|
||||||
pairable.nbW +
|
|
||||||
pairable.missedRounds() * pairingParams.main.mmsValueAbsent)
|
|
||||||
Pair(
|
|
||||||
if (pairingParams.main.sosValueAbsentUseBase) pairable.mmBase
|
|
||||||
else roundScore(pairable.mmBase + round/2),
|
|
||||||
score
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val scoresX: Map<ID, Double> by lazy {
|
override val scoresX: Map<ID, Double> by lazy {
|
||||||
require (mmBar > mmFloor) { "MMFloor is higher than MMBar" }
|
require (mmBar > mmFloor) { "MMFloor is higher than MMBar" }
|
||||||
pairablesMap.mapValues {
|
allPairablesMap.mapValues {
|
||||||
it.value.let { pairable ->
|
it.value.let { pairable ->
|
||||||
roundScore(pairable.mmBase + pairable.nbW)
|
roundScore(pairable.mmBase + pairable.nbW)
|
||||||
}
|
}
|
||||||
|
@@ -1,26 +1,20 @@
|
|||||||
package org.jeudego.pairgoth.pairing.solver
|
package org.jeudego.pairgoth.pairing.solver
|
||||||
|
|
||||||
import org.jeudego.pairgoth.model.*
|
import org.jeudego.pairgoth.model.*
|
||||||
|
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SwissSolver(round: Int,
|
class SwissSolver(round: Int,
|
||||||
totalRounds: Int,
|
totalRounds: Int,
|
||||||
history: List<List<Game>>,
|
history: HistoryHelper,
|
||||||
pairables: List<Pairable>,
|
pairables: List<Pairable>,
|
||||||
pairablesMap: Map<ID, Pairable>,
|
pairablesMap: Map<ID, Pairable>,
|
||||||
pairingParams: PairingParams,
|
pairingParams: PairingParams,
|
||||||
placementParams: PlacementParams,
|
placementParams: PlacementParams,
|
||||||
usedTables: BitSet
|
usedTables: BitSet
|
||||||
):
|
):
|
||||||
BaseSolver(round, totalRounds, history, pairables, pairablesMap, pairingParams, placementParams, usedTables) {
|
BaseSolver(round, totalRounds, history, pairables, pairingParams, placementParams, usedTables) {
|
||||||
|
|
||||||
// In a Swiss tournament the main criterion is the number of wins and already computed
|
|
||||||
|
|
||||||
override val scores by lazy {
|
|
||||||
pairablesMap.mapValues {
|
|
||||||
Pair(0.0, historyHelper.wins[it.value.id] ?: 0.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override val scoresX: Map<ID, Double> get() = scores.mapValues { it.value.second }
|
override val scoresX: Map<ID, Double> get() = scores.mapValues { it.value.second }
|
||||||
|
|
||||||
override val mainLimits = Pair(0.0, round - 1.0)
|
override val mainLimits = Pair(0.0, round - 1.0)
|
||||||
|
0
view-webapp/src/main/webapp/explain-pairing.html
Normal file
0
view-webapp/src/main/webapp/explain-pairing.html
Normal file
Reference in New Issue
Block a user