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 f37f023..335edab 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 @@ -8,7 +8,7 @@ import org.jeudego.pairgoth.pairing.MacMahonSolver import org.jeudego.pairgoth.pairing.SwissSolver // base pairing parameters -data class BasePairingParams( +data class BaseCritParams( // standard NX1 factor for concavity curves val nx1: Double = 0.5, val dupWeight: Double = MAX_AVOIDDUPGAME, @@ -27,7 +27,7 @@ data class BasePairingParams( const val MAX_AVOIDDUPGAME = 500000000000000.0 // 5e14 const val MAX_RANDOM = 1000000000.0 // 1e9 const val MAX_COLOR_BALANCE = 1000000.0 // 1e6 - val default = BasePairingParams() + val default = BaseCritParams() } } @@ -106,7 +106,7 @@ data class HandicapParams( enum class PairingType { SWISS, MAC_MAHON, ROUND_ROBIN } data class PairingParams( - val base: BasePairingParams = BasePairingParams(), + val base: BaseCritParams = BaseCritParams(), val main: MainCritParams = MainCritParams(), val secondary: SecondaryCritParams = SecondaryCritParams(), val geo: GeographicalParams = GeographicalParams(), @@ -123,11 +123,11 @@ sealed class Pairing( private fun Tournament<*>.historyBefore(round: Int) = if (lastRound() == 0) emptyList() - else (0 until round).flatMap { games(round).values } + else (0 until round).map { games(round).values.toList() } class Swiss( pairingParams: PairingParams = PairingParams( - base = BasePairingParams(), + base = BaseCritParams(), main = MainCritParams( seedSystem1 = SPLIT_AND_SLIP, seedSystem2 = SPLIT_AND_SLIP @@ -153,7 +153,7 @@ class Swiss( class MacMahon( pairingParams: PairingParams = PairingParams( - base = BasePairingParams(), + base = BaseCritParams(), main = MainCritParams(), secondary = SecondaryCritParams( defSecCrit = MainCritParams.MAX_SCORE_WEIGHT @@ -184,7 +184,7 @@ class RoundRobin( // Serialization -fun BasePairingParams.Companion.fromJson(json: Json.Object) = BasePairingParams( +fun BaseCritParams.Companion.fromJson(json: Json.Object) = BaseCritParams( nx1 = json.getDouble("nx1") ?: default.nx1, dupWeight = json.getDouble("dupWeight") ?: default.dupWeight, random = json.getDouble("random") ?: default.random, @@ -192,7 +192,7 @@ fun BasePairingParams.Companion.fromJson(json: Json.Object) = BasePairingParams( colorBalance = json.getDouble("colorBalanceWeight") ?: default.colorBalance ) -fun BasePairingParams.toJson() = Json.Object( +fun BaseCritParams.toJson() = Json.Object( "nx1" to nx1, "dupWeight" to dupWeight, "random" to random, @@ -281,7 +281,7 @@ fun Pairing.Companion.fromJson(json: Json.Object): Pairing { MAC_MAHON -> MacMahon() ROUND_ROBIN -> RoundRobin() } - val base = json.getObject("base")?.let { BasePairingParams.fromJson(it) } ?: defaultParams.pairingParams.base + val base = json.getObject("base")?.let { BaseCritParams.fromJson(it) } ?: defaultParams.pairingParams.base val main = json.getObject("main")?.let { MainCritParams.fromJson(it) } ?: defaultParams.pairingParams.main val secondary = json.getObject("secondary")?.let { SecondaryCritParams.fromJson(it) } ?: defaultParams.pairingParams.secondary val geo = json.getObject("geo")?.let { GeographicalParams.fromJson(it) } ?: defaultParams.pairingParams.geo 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 2b90725..ebb47b4 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 @@ -1,8 +1,19 @@ package org.jeudego.pairgoth.pairing import org.jeudego.pairgoth.model.* +import org.jeudego.pairgoth.model.Game.Result.* -open class HistoryHelper(protected val history: List, computeScore: () -> Map) { +open class HistoryHelper(protected val history: List>, computeScore: () -> Map) { + + private val Game.blackScore get() = when (result) { + BLACK, BOTHWIN -> 1.0 + else -> 0.0 + } + + private val Game.whiteScore get() = when (result) { + WHITE, BOTHWIN -> 1.0 + else -> 0.0 + } fun getCriterionValue(p: Pairable, crit: Criterion): Double { // Returns generic criterion @@ -23,13 +34,12 @@ open class HistoryHelper(protected val history: List, computeScore: () -> // 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 nbW(p: Pairable) = numberWins[p.id] - + open fun nbW(p: Pairable) = wins[p.id] protected val paired: Set> by lazy { - (history.map { game -> + (history.flatten().map { game -> Pair(game.black, game.white) - } + history.map { game -> + } + history.flatten().map { game -> Pair(game.white, game.black) }).toSet() } @@ -37,25 +47,26 @@ open class HistoryHelper(protected val history: List, computeScore: () -> // Returns the number of games played as white // Only count games without handicap private val colorBalance: Map by lazy { - history.flatMap { game -> if (game.handicap == 0) { + history.flatten().filter { game -> + game.handicap == 0 + }.flatMap { game -> listOf(Pair(game.white, +1), Pair(game.black, -1)) - } else { - listOf(Pair(game.white, 0), Pair(game.black, 0)) - } - }.groupingBy { it.first }.fold(0) { acc, next -> + }.groupingBy { + it.first + }.fold(0) { acc, next -> acc + next.second } } - val numberWins: Map by lazy { + val wins: Map by lazy { mutableMapOf().apply { - history.forEach { game -> + history.flatten().forEach { game -> when (game.result) { Game.Result.BLACK -> put(game.black, getOrDefault(game.black, 0.0) + 1.0) Game.Result.WHITE -> put(game.white, getOrDefault(game.white, 0.0) + 1.0) Game.Result.BOTHWIN -> { - put(game.black, getOrDefault(game.black, 0.0) + 0.5) - put(game.white, getOrDefault(game.white, 0.0) + 0.5) + put(game.black, getOrDefault(game.black, 0.0) + 1.0) + put(game.white, getOrDefault(game.white, 0.0) + 1.0) } else -> {} } @@ -70,9 +81,9 @@ open class HistoryHelper(protected val history: List, computeScore: () -> // SOS related functions given a score function val sos by lazy { - (history.map { game -> + (history.flatten().map { game -> Pair(game.black, score[game.white] ?: 0.0) - } + history.map { game -> + } + history.flatten().map { game -> Pair(game.white, score[game.black] ?: 0.0) }).groupingBy { it.first }.fold(0.0) { acc, next -> acc + next.second @@ -80,20 +91,38 @@ open class HistoryHelper(protected val history: List, computeScore: () -> } // sos-1 - val sosm1: Map by lazy { - TODO() + val sosm1 by lazy { + (history.flatten().map { game -> + Pair(game.black, score[game.white] ?: 0.0) + } + history.flatten().map { game -> + Pair(game.white, score[game.black] ?: 0.0) + }).groupBy { + it.first + }.mapValues { + val scores = it.value.map { it.second }.sorted() + scores.sum() - (scores.firstOrNull() ?: 0.0) + } } // sos-2 - val sosm2: Map by lazy { - TODO() + val sosm2 by lazy { + (history.flatten().map { game -> + Pair(game.black, score[game.white] ?: 0.0) + } + history.flatten().map { game -> + Pair(game.white, score[game.black] ?: 0.0) + }).groupBy { + it.first + }.mapValues { + val scores = it.value.map { it.second }.sorted() + scores.sum() - scores.getOrElse(0) { 0.0 } - scores.getOrElse(1) { 0.0 } + } } // sodos val sodos by lazy { - (history.map { game -> + (history.flatten().map { game -> Pair(game.black, if (game.result == Game.Result.BLACK) score[game.white] ?: 0.0 else 0.0) - } + history.map { game -> + } + history.flatten().map { game -> Pair(game.white, if (game.result == Game.Result.WHITE) score[game.black] ?: 0.0 else 0.0) }).groupingBy { it.first }.fold(0.0) { acc, next -> acc + next.second @@ -102,9 +131,9 @@ open class HistoryHelper(protected val history: List, computeScore: () -> // sosos val sosos by lazy { - (history.map { game -> + (history.flatten().map { game -> Pair(game.black, sos[game.white] ?: 0.0) - } + history.map { game -> + } + history.flatten().map { game -> Pair(game.white, sos[game.black] ?: 0.0) }).groupingBy { it.first }.fold(0.0) { acc, next -> acc + next.second @@ -112,14 +141,25 @@ open class HistoryHelper(protected val history: List, computeScore: () -> } // cumulative score - val cumscore: Map by lazy { - TODO() + val cumScore by lazy { + history.map { games -> + (games.groupingBy { it.black }.fold(0.0) { acc, next -> + acc + next.blackScore + }) + + (games.groupingBy { it.white }.fold(0.0) { acc, next -> + acc + next.whiteScore + }) + }.reduce { acc, map -> + (acc.keys + map.keys).associate { id -> + Pair(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, computeScore: () -> Map): +class TeamOfIndividualsHistoryHelper(history: List>, computeScore: () -> Map): HistoryHelper(history, computeScore) { private fun Pairable.asTeam() = this as TeamTournament.Team diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt index cbfaeea..afeb908 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt @@ -2,7 +2,12 @@ package org.jeudego.pairgoth.pairing import org.jeudego.pairgoth.model.* -class MacMahonSolver(round: Int, history: List, pairables: List, pairingParams: PairingParams, placementParams: PlacementParams): Solver(round, history, pairables, pairingParams, placementParams) { +class MacMahonSolver(round: Int, + history: List>, + pairables: List, + pairingParams: PairingParams, + placementParams: PlacementParams): + Solver(round, history, pairables, pairingParams, placementParams) { // val Pairable.mms get() = mmBase + nbW // TODO real calculation @@ -32,5 +37,4 @@ class MacMahonSolver(round: Int, history: List, pairables: List, else -> -1.0 } } - } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt index 4d6525a..7db564f 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt @@ -17,23 +17,15 @@ val DEBUG_EXPORT_WEIGHT = true private fun detRandom(max: Double, p1: Pairable, p2: Pairable): Double { var inverse = false - - val seed1 = p1.nameSeed() - val seed2 = p2.nameSeed() - - var name1 = seed1 - var name2 = seed2 + var name1 = p1.nameSeed() + var name2 = p2.nameSeed() if (name1 > name2) { name1 = name2.also { name2 = name1 } inverse = true } - val s = name1 + name2 - var nR = 0.0 - for (i in s.indices) { - val c = s[i] - nR += (c.code * (i + 1)).toDouble() - } - nR = nR * 1234567 % (max + 1) + var nR = "$name1$name2".mapIndexed { i, c -> + c.code.toDouble() * (i + 1) + }.sum() * 1234567 % (max + 1) if (inverse) nR = max - nR return nR } @@ -43,18 +35,22 @@ private fun nonDetRandom(max: Double) = else Math.random() * (max + 1.0) sealed class Solver( - val round: Int, - history: List, - val pairables: List, - val pairingParams: PairingParams, - val placementParams: PlacementParams) { + val round: Int, + history: List>, + val pairables: List, + val pairing: PairingParams, + val placement: PlacementParams + ) { companion object { 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) + open fun sort(p: Pairable, q: Pairable): Int { - for (criterion in placementParams.criteria) { + for (criterion in placement.criteria) { val criterionP = getCriterionValue(p, criterion) val criterionQ = getCriterionValue(q, criterion) if (criterionP != criterionQ) { @@ -65,9 +61,10 @@ sealed class Solver( } open fun weight(p1: Pairable, p2: Pairable) = 1.0 + // 1 is minimum value because 0 means "no matching allowed" - applyBaseCriteria(p1, p2) + - applyMainCriteria(p1, p2) + - applySecondaryCriteria(p1, p2) + pairing.base.apply(p1, p2) + + pairing.main.apply(p1, p2) + + pairing.secondary.apply(p1, p2) + + pairing.geo.apply(p1, p2) // The main criterion that will be used to define the groups should be defined by subclasses abstract fun mainCriterion(p1: Pairable): Int @@ -114,22 +111,48 @@ sealed class Solver( return result } - open fun applyBaseCriteria(p1: Pairable, p2: Pairable): Double { - var score = 0.0 + // base criteria + open fun BaseCritParams.apply(p1: Pairable, p2: Pairable): Double { + var score = 0.0 // Base Criterion 1 : Avoid Duplicating Game // Did p1 and p2 already play ? score += avoidDuplicatingGames(p1, p2) // Base Criterion 2 : Random score += applyRandom(p1, p2) // Base Criterion 3 : Balance W and B - score += applyBalanceBW(p1, p2) + score += applyColorBalance(p1, p2) return score } + // Weight score computation details + open fun BaseCritParams.avoidDuplicatingGames(p1: Pairable, p2: Pairable): Double { + return if (p1.played(p2)) 0.0 // We get no score if pairables already played together + else dupWeight + } + + open fun BaseCritParams.applyRandom(p1: Pairable, p2: Pairable): Double { + return if (deterministic) detRandom(random, p1, p2) + else nonDetRandom(random) + } + + open fun BaseCritParams.applyColorBalance(p1: Pairable, p2: Pairable): Double { + // This cost is never applied if potential Handicap != 0 + // It is fully applied if wbBalance(sP1) and wbBalance(sP2) are strictly of different signs + // It is half applied if one of wbBalance is 0 and the other is >=2 + val potentialHd: Int = pairing.handicap.handicap(p1, p2) + if (potentialHd == 0) { + val wb1: Int = p1.colorBalance + val wb2: Int = p2.colorBalance + if (wb1 * wb2 < 0) return colorBalance + else if (wb1 == 0 && abs(wb2) >= 2 || wb2 == 0 && abs(wb1) >= 2) return colorBalance / 2 + } + return 0.0 + } + // Main criteria - open fun applyMainCriteria(p1: Pairable, p2: Pairable): Double { + open fun MainCritParams.apply(p1: Pairable, p2: Pairable): Double { var score = 0.0 // Main criterion 1 avoid mixing category is moved to Swiss with category @@ -147,76 +170,26 @@ sealed class Solver( return score } - open fun applySecondaryCriteria(p1: Pairable, p2: Pairable): Double { - var score = 0.0 - // See Swiss with category for minimizing handicap criterion - - // TODO understand where opengotha test if need to be applied - - // Geographical criterion - score += avoidSameGeo(p1, p2) - - return score - } - - // Weight score computation details - // Base criteria - open fun avoidDuplicatingGames(p1: Pairable, p2: Pairable): Double { - if (p1.played(p2)) { - return 0.0 // We get no score if pairables already played together - } else { - return pairingParams.base.dupWeight - } - } - - open fun applyRandom(p1: Pairable, p2: Pairable): Double { - if (pairingParams.base.deterministic) { - return detRandom(pairingParams.base.random, p1, p2) - } else { - return nonDetRandom(pairingParams.base.random) - } - } - - open fun applyBalanceBW(p1: Pairable, p2: Pairable): Double { - // This cost is never applied if potential Handicap != 0 - // It is fully applied if wbBalance(sP1) and wbBalance(sP2) are strictly of different signs - // It is half applied if one of wbBalance is 0 and the other is >=2 - val potentialHd: Int = handicap(p1, p2) - if (potentialHd == 0) { - val wb1: Int = p1.colorBalance - val wb2: Int = p2.colorBalance - if (wb1 * wb2 < 0) { - return pairingParams.base.colorBalance - } else if (wb1 == 0 && abs(wb2) >= 2) { - return pairingParams.base.colorBalance / 2 - } else if (wb2 == 0 && abs(wb1) >= 2) { - return pairingParams.base.colorBalance / 2 - } - } - return 0.0 - } - - open fun minimizeScoreDifference(p1: Pairable, p2: Pairable): Double { + open fun MainCritParams.minimizeScoreDifference(p1: Pairable, p2: Pairable): Double { var score = 0.0 val scoreRange: Int = numberGroups // TODO check category equality if category are used in SwissCat - val x = abs(p1.group - p2.group) as Double / scoreRange.toDouble() - val k: Double = pairingParams.base.nx1 - score = pairingParams.main.scoreWeight * (1.0 - x) * (1.0 + k * x) + val x = abs(p1.group - p2.group).toDouble() / scoreRange.toDouble() + val k: Double = pairing.base.nx1 + score = scoreWeight * (1.0 - x) * (1.0 + k * x) return score } - fun applySeeding(p1: Pairable, p2: Pairable): Double { + fun MainCritParams.applySeeding(p1: Pairable, p2: Pairable): Double { var score = 0.0 // Apply seeding for players in the same group if (p1.group == p2.group) { val (cla1, groupSize) = p1.placeInGroup val cla2 = p2.placeInGroup.first - val maxSeedingWeight = pairingParams.main.seedingWeight + val maxSeedingWeight = seedingWeight - val currentSeedSystem: MainCritParams.SeedMethod = if (round <= pairingParams.main.lastRoundForSeedSystem1) - pairingParams.main.seedSystem1 else pairingParams.main.seedSystem2 + val currentSeedSystem= if (round <= lastRoundForSeedSystem1) seedSystem1 else seedSystem2 score += when(currentSeedSystem) { // The best is to get 2 * |Cla1 - Cla2| - groupSize close to 0 @@ -245,21 +218,30 @@ sealed class Solver( return score } - open fun doNeedToApplySecondaryCriteria(p1: Pairable, p2: Pairable) { + open fun SecondaryCritParams.apply(p1: Pairable, p2: Pairable): Double { + var score = 0.0 + // See Swiss with category for minimizing handicap criterion + + // TODO understand where opengotha test if need to be applied + + return score + } + + open fun SecondaryCritParams.notNeeded(p1: Pairable, p2: Pairable) { // secCase = 0 : No player is above thresholds // secCase = 1 : One player is above thresholds // secCase = 2 : Both players are above thresholds // TODO understand where it is used } - fun avoidSameGeo(p1: Pairable, p2: Pairable): Double { + fun GeographicalParams.apply(p1: Pairable, p2: Pairable): Double { val placementScoreRange = numberGroups - val geoMaxCost = pairingParams.geo.avoidSameGeo + val geoMaxCost = avoidSameGeo - val countryFactor = pairingParams.geo.preferMMSDiffRatherThanSameCountry - val clubFactor: Int = pairingParams.geo.preferMMSDiffRatherThanSameClub - //val groupFactor: Int = pairingParams.geo.preferMMSDiffRatherThanSameClubsGroup + val countryFactor = preferMMSDiffRatherThanSameCountry + val clubFactor: Int = preferMMSDiffRatherThanSameClub + //val groupFactor: Int = preferMMSDiffRatherThanSameClubsGroup // Same country val countryRatio = if (p1.country != p2.country && countryFactor != 0) { @@ -298,12 +280,12 @@ sealed class Solver( var geoRatio = mainPart + secPart / 2.0 if (geoRatio > 0.0) { - geoRatio += 0.5 / placementScoreRange as Double + geoRatio += 0.5 / placementScoreRange.toDouble() } // The concavity function is applied to geoRatio to get geoCost - val dbGeoCost: Double = geoMaxCost.toDouble() * (1.0 - geoRatio) * (1.0 + pairingParams.base.nx1 * geoRatio) - var score = pairingParams.main.scoreWeight - dbGeoCost + val dbGeoCost: Double = geoMaxCost.toDouble() * (1.0 - geoRatio) * (1.0 + pairing.base.nx1 * geoRatio) + var score = pairing.main.scoreWeight - dbGeoCost score = min(score, geoMaxCost) return score @@ -311,48 +293,37 @@ sealed class Solver( // Handicap functions // Has to be overridden if handicap is not based on rank - open fun handicap(p1: Pairable, p2: Pairable): Int { + open fun HandicapParams.handicap(p1: Pairable, p2: Pairable): Int { var hd = 0 var pseudoRank1: Int = p1.rank var pseudoRank2: Int = p2.rank - pseudoRank1 = min(pseudoRank1, pairingParams.handicap.rankThreshold) - pseudoRank2 = min(pseudoRank2, pairingParams.handicap.rankThreshold) + pseudoRank1 = min(pseudoRank1, rankThreshold) + pseudoRank2 = min(pseudoRank2, rankThreshold) hd = pseudoRank1 - pseudoRank2 - return clampHandicap(hd) + return clamp(hd) } - open fun clampHandicap(inputHd: Int): Int { - var hd = inputHd - if (hd > 0) { - hd -= pairingParams.handicap.correction - hd = min(hd, 0) - } - if (hd < 0) { - hd += pairingParams.handicap.correction - hd = max(hd, 0) - } + open fun HandicapParams.clamp(input: Int): Int { + var hd = input + if (hd >= correction) hd -= correction + if (hd < 0) hd = max(hd + correction, 0) // Clamp handicap with ceiling - hd = min(hd, pairingParams.handicap.ceiling) - hd = max(hd, -pairingParams.handicap.ceiling) + hd = min(hd, ceiling) + hd = max(hd, -ceiling) return hd } open fun games(black: Pairable, white: Pairable): List { // CB TODO team of individuals pairing - return listOf(Game(id = Store.nextGameId, black = black.id, white = white.id, handicap = handicap(black, white))) + return listOf(Game(id = Store.nextGameId, black = black.id, white = white.id, handicap = pairing.handicap.handicap(black, white))) } // Generic parameters calculation //private val standingScore by lazy { computeStandingScore() } - val historyHelper = if (pairables.first().let { it is TeamTournament.Team && it.teamOfIndividuals }) TeamOfIndividualsHistoryHelper(history, ::computeStandingScore) - else HistoryHelper(history, ::computeStandingScore) - - - // Decide each pairable group based on the main criterion private val numberGroups by lazy { val (mainScoreMin, mainScoreMax) = mainCriterionMinMax() @@ -401,9 +372,5 @@ sealed class Solver( val Pairable.sosm2: Double get() = historyHelper.sosm2[id]!! val Pairable.sosos: Double get() = historyHelper.sosos[id]!! val Pairable.sodos: Double get() = historyHelper.sodos[id]!! - val Pairable.cums: Double get() = historyHelper.cumscore[id]!! - - - - + val Pairable.cums: Double get() = historyHelper.cumScore[id]!! } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt index 29dbe4c..a456d44 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt @@ -3,7 +3,7 @@ package org.jeudego.pairgoth.pairing import org.jeudego.pairgoth.model.* class SwissSolver(round: Int, - history: List, + history: List>, pairables: List, pairingParams: PairingParams, placementParams: PlacementParams): @@ -19,7 +19,7 @@ class SwissSolver(round: Int, } override fun computeStandingScore(): Map { - return historyHelper.numberWins + return historyHelper.wins } override fun getSpecificCriterionValue(p: Pairable, criterion: Criterion): Double {