Copy OpenGotha procedure to choose bye player

This commit is contained in:
Quentin Rendu
2023-10-30 13:29:24 +01:00
parent 3f37bd39eb
commit 595f505a3a
3 changed files with 34 additions and 7 deletions

View File

@@ -28,7 +28,7 @@ abstract class BasePairingHelper(
} }
// pairables sorted for pairing purposes // pairables sorted for pairing purposes
protected val nameSortedPairables by lazy { protected val nameSortedPairables by lazy {
pairables.sortedWith(::nameSort) pairables.sortedWith(::nameSort).toMutableList()
} }
protected val pairablesMap by lazy { protected val pairablesMap by lazy {

View File

@@ -59,9 +59,28 @@ sealed class BaseSolver(
// println("placement criteria" + placement.criteria.toString()) // println("placement criteria" + placement.criteria.toString())
} }
var chosenByePlayer: Pairable = ByePlayer
// Choose bye player and remove from pairables
if (ByePlayer in nameSortedPairables){
nameSortedPairables.remove(ByePlayer)
var minWeight = 1000.0*round + (Pairable.MAX_RANK - Pairable.MIN_RANK) + 1;
var weightForBye : Double
var byePlayerIndex = 0
for (p in nameSortedPairables){
weightForBye = p.rank + 2*p.main
if (weightForBye <= minWeight){
minWeight = weightForBye
chosenByePlayer = p
}
println("choose Bye: " + p.nameSeed() + " " + weightForBye)
}
println("Bye player : " + chosenByePlayer.nameSeed())
nameSortedPairables.remove(chosenByePlayer)
}
for (i in nameSortedPairables.indices) { for (i in nameSortedPairables.indices) {
// println(nameSortedPairables[i].nameSeed() + " id="+nameSortedPairables[i].id.toString()+" clasmt="+nameSortedPairables[i].placeInGroup.toString()) // println(nameSortedPairables[i].nameSeed() + " id="+nameSortedPairables[i].id.toString()+" clasmt="+nameSortedPairables[i].placeInGroup.toString())
for (j in i + 1 until pairables.size) { for (j in i + 1 until nameSortedPairables.size) {
val p = nameSortedPairables[i] val p = nameSortedPairables[i]
val q = nameSortedPairables[j] val q = nameSortedPairables[j]
weight(p, q).let { if (it != Double.NaN) builder.addEdge(p, q, it) } weight(p, q).let { if (it != Double.NaN) builder.addEdge(p, q, it) }
@@ -80,6 +99,7 @@ sealed class BaseSolver(
File(WEIGHTS_FILE).appendText("secHandiCost="+dec.format(pairing.handicap.handicap(p, q))+"\n") File(WEIGHTS_FILE).appendText("secHandiCost="+dec.format(pairing.handicap.handicap(p, q))+"\n")
File(WEIGHTS_FILE).appendText("secGeoCost="+dec.format(pairing.geo.apply(p, q))+"\n") File(WEIGHTS_FILE).appendText("secGeoCost="+dec.format(pairing.geo.apply(p, q))+"\n")
File(WEIGHTS_FILE).appendText("totalCost="+dec.format(openGothaWeight(p,q))+"\n") File(WEIGHTS_FILE).appendText("totalCost="+dec.format(openGothaWeight(p,q))+"\n")
//File(WEIGHTS_FILE).appendText("ByeCost="+dec.format(pairing.base.applyByeWeight(p,q))+"\n")
} }
} }
@@ -92,8 +112,13 @@ sealed class BaseSolver(
listOf(graph.getEdgeSource(it), graph.getEdgeTarget(it)) listOf(graph.getEdgeSource(it), graph.getEdgeTarget(it))
}.sortedWith(compareBy({ min(it[0].place, it[1].place) })) }.sortedWith(compareBy({ min(it[0].place, it[1].place) }))
/* println(sorted.size)
if (chosenByePlayer != ByePlayer) sorted.add(listOf(chosenByePlayer, ByePlayer))
println(sorted.size)*/
val result = sorted.flatMap { games(white = it[0], black = it[1]) } val result = sorted.flatMap { games(white = it[0], black = it[1]) }
if (DEBUG_EXPORT_WEIGHT) { if (DEBUG_EXPORT_WEIGHT) {
var sumOfWeights = 0.0 var sumOfWeights = 0.0
for (it in sorted) { for (it in sorted) {
@@ -165,8 +190,9 @@ sealed class BaseSolver(
val actualPlayer = if (p1.id == ByePlayer.id) p2 else p1 val actualPlayer = if (p1.id == ByePlayer.id) p2 else p1
// TODO maybe use a different formula than opengotha // TODO maybe use a different formula than opengotha
val x = (actualPlayer.rank - Pairable.MIN_RANK + actualPlayer.main) / (Pairable.MAX_RANK - Pairable.MIN_RANK + mainLimits.second) val x = (actualPlayer.rank - Pairable.MIN_RANK + actualPlayer.main) / (Pairable.MAX_RANK - Pairable.MIN_RANK + mainLimits.second)
concavityFunction(x, BaseCritParams.MAX_BYE_WEIGHT) //concavityFunction(x, BaseCritParams.MAX_BYE_WEIGHT)
BaseCritParams.MAX_BYE_WEIGHT - (actualPlayer.rank + 2*actualPlayer.main) //BaseCritParams.MAX_BYE_WEIGHT - (actualPlayer.rank + 2*actualPlayer.main)
BaseCritParams.MAX_BYE_WEIGHT*(1 - x)
} else { } else {
0.0 0.0
} }

View File

@@ -253,10 +253,11 @@ class PairingTests: TestBase() {
val byePlayerList = mutableListOf<Long>(354, 359, 356, 357, 345, 339, 368, 344, 349, 341) val byePlayerList = mutableListOf<Long>(354, 359, 356, 357, 345, 339, 368, 344, 349, 341)
for (round in 1..7) { for (round in 1..7) {
games = TestAPI.post("/api/tour/$id/pair/$round", Json.Array(playersList.filter{it != byePlayerList[round-1]})).asArray() //games = TestAPI.post("/api/tour/$id/pair/$round", Json.Array(playersList.filter{it != byePlayerList[round-1]})).asArray()
games = TestAPI.post("/api/tour/$id/pair/$round", Json.Array("all")).asArray()
logger.info("games for round $round: {}", games.toString()) logger.info("games for round $round: {}", games.toString())
assertTrue(compare_weights("weights.txt", "opengotha/notsosimpleswiss_weights_R$round.txt"), "Not matching opengotha weights for round $round") assertTrue(compare_weights("weights.txt", "opengotha/notsosimpleswiss_weights_nobye_R$round.txt"), "Not matching opengotha weights for round $round")
assertTrue(compare_games(games, Json.parse(pairings[round - 1])!!.asArray()),"pairings for round $round differ") assertTrue(compare_games(games, Json.parse(pairings[round - 1])!!.asArray()),"pairings for round $round differ")
logger.info("Pairings for round $round match OpenGotha") logger.info("Pairings for round $round match OpenGotha")