Handicap wrongly chosen in MM
This commit is contained in:
@@ -97,11 +97,17 @@ data class HandicapParams(
|
|||||||
val ceiling: Int = 9, // Possible values are between 0 and 9
|
val ceiling: Int = 9, // Possible values are between 0 and 9
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val default = HandicapParams(
|
val swissDefault = HandicapParams(
|
||||||
weight = 0.0, // default disables handicap
|
weight = 0.0, // TODO 'default disables handicap' => seems wrong, not used
|
||||||
useMMS = false,
|
useMMS = false,
|
||||||
rankThreshold = -30, // 30k
|
rankThreshold = -30, // 30k
|
||||||
ceiling = 0)
|
ceiling = 0)
|
||||||
|
val mmDefault = HandicapParams(
|
||||||
|
weight = 0.0,
|
||||||
|
useMMS = true,
|
||||||
|
rankThreshold = 0, // 1D
|
||||||
|
ceiling = 9)
|
||||||
|
fun default(type: PairingType) = if (type == MAC_MAHON) mmDefault else swissDefault
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +160,7 @@ class Swiss(
|
|||||||
defSecCrit = MainCritParams.MAX_CATEGORIES_WEIGHT
|
defSecCrit = MainCritParams.MAX_CATEGORIES_WEIGHT
|
||||||
),
|
),
|
||||||
geo = GeographicalParams.disabled,
|
geo = GeographicalParams.disabled,
|
||||||
handicap = HandicapParams.default
|
handicap = HandicapParams.default(SWISS)
|
||||||
),
|
),
|
||||||
placementParams: PlacementParams = PlacementParams(
|
placementParams: PlacementParams = PlacementParams(
|
||||||
Criterion.NBW, Criterion.SOSW, Criterion.SOSOSW
|
Criterion.NBW, Criterion.SOSW, Criterion.SOSOSW
|
||||||
@@ -176,7 +182,12 @@ class MacMahon(
|
|||||||
geo = GeographicalParams(
|
geo = GeographicalParams(
|
||||||
avoidSameGeo = MainCritParams.MAX_SCORE_WEIGHT
|
avoidSameGeo = MainCritParams.MAX_SCORE_WEIGHT
|
||||||
),
|
),
|
||||||
handicap = HandicapParams()
|
handicap = HandicapParams(
|
||||||
|
weight = MainCritParams.MAX_SCORE_WEIGHT, // TODO - contradictory with the comment above (not used anyway ?!)
|
||||||
|
useMMS = true,
|
||||||
|
rankThreshold = 0,
|
||||||
|
ceiling = 9
|
||||||
|
)
|
||||||
),
|
),
|
||||||
placementParams: PlacementParams = PlacementParams(
|
placementParams: PlacementParams = PlacementParams(
|
||||||
Criterion.NBW, Criterion.SOSW, Criterion.SOSOSW
|
Criterion.NBW, Criterion.SOSW, Criterion.SOSOSW
|
||||||
@@ -247,16 +258,16 @@ fun MainCritParams.toJson() = Json.Object(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun SecondaryCritParams.Companion.fromJson(json: Json.Object) = SecondaryCritParams(
|
fun SecondaryCritParams.Companion.fromJson(json: Json.Object) = SecondaryCritParams(
|
||||||
barThresholdActive = json.getBoolean("barTreshold") ?: default.barThresholdActive,
|
barThresholdActive = json.getBoolean("barThreshold") ?: default.barThresholdActive,
|
||||||
rankThreshold = json.getInt("rankTreshold") ?: default.rankThreshold,
|
rankThreshold = json.getInt("rankThreshold") ?: default.rankThreshold,
|
||||||
nbWinsThresholdActive = json.getBoolean("winsTreshold") ?: default.nbWinsThresholdActive,
|
nbWinsThresholdActive = json.getBoolean("winsThreshold") ?: default.nbWinsThresholdActive,
|
||||||
defSecCrit = json.getDouble("secWeight") ?: default.defSecCrit
|
defSecCrit = json.getDouble("secWeight") ?: default.defSecCrit
|
||||||
)
|
)
|
||||||
|
|
||||||
fun SecondaryCritParams.toJson() = Json.Object(
|
fun SecondaryCritParams.toJson() = Json.Object(
|
||||||
"barTreshold" to barThresholdActive,
|
"barThreshold" to barThresholdActive,
|
||||||
"rankTreshold" to rankThreshold,
|
"rankThreshold" to rankThreshold,
|
||||||
"winsTreshold" to nbWinsThresholdActive,
|
"winsThreshold" to nbWinsThresholdActive,
|
||||||
"secWeight" to defSecCrit
|
"secWeight" to defSecCrit
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -274,18 +285,18 @@ fun GeographicalParams.toJson() = Json.Object(
|
|||||||
"mmsDiffClub" to preferMMSDiffRatherThanSameClub
|
"mmsDiffClub" to preferMMSDiffRatherThanSameClub
|
||||||
)
|
)
|
||||||
|
|
||||||
fun HandicapParams.Companion.fromJson(json: Json.Object) = HandicapParams(
|
fun HandicapParams.Companion.fromJson(json: Json.Object, type: PairingType) = HandicapParams(
|
||||||
weight = json.getDouble("weight") ?: default.weight,
|
weight = json.getDouble("weight") ?: default(type).weight,
|
||||||
useMMS = json.getBoolean("useMMS") ?: default.useMMS,
|
useMMS = json.getBoolean("useMMS") ?: default(type).useMMS,
|
||||||
rankThreshold = json.getInt("treshold") ?: default.rankThreshold,
|
rankThreshold = json.getInt("threshold") ?: default(type).rankThreshold,
|
||||||
correction = json.getInt("correction") ?: default.correction,
|
correction = json.getInt("correction") ?: default(type).correction,
|
||||||
ceiling = json.getInt("ceiling") ?: default.ceiling
|
ceiling = json.getInt("ceiling") ?: default(type).ceiling
|
||||||
)
|
)
|
||||||
|
|
||||||
fun HandicapParams.toJson() = Json.Object(
|
fun HandicapParams.toJson() = Json.Object(
|
||||||
"weight" to weight,
|
"weight" to weight,
|
||||||
"useMMS" to useMMS,
|
"useMMS" to useMMS,
|
||||||
"treshold" to rankThreshold,
|
"threshold" to rankThreshold,
|
||||||
"correction" to correction,
|
"correction" to correction,
|
||||||
"ceiling" to ceiling
|
"ceiling" to ceiling
|
||||||
)
|
)
|
||||||
@@ -302,7 +313,7 @@ fun Pairing.Companion.fromJson(json: Json.Object): Pairing {
|
|||||||
val main = json.getObject("main")?.let { MainCritParams.fromJson(it) } ?: defaultParams.pairingParams.main
|
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 secondary = json.getObject("secondary")?.let { SecondaryCritParams.fromJson(it) } ?: defaultParams.pairingParams.secondary
|
||||||
val geo = json.getObject("geo")?.let { GeographicalParams.fromJson(it) } ?: defaultParams.pairingParams.geo
|
val geo = json.getObject("geo")?.let { GeographicalParams.fromJson(it) } ?: defaultParams.pairingParams.geo
|
||||||
val hd = json.getObject("handicap")?.let { HandicapParams.fromJson(it) } ?: defaultParams.pairingParams.handicap
|
val hd = json.getObject("handicap")?.let { HandicapParams.fromJson(it, type) } ?: defaultParams.pairingParams.handicap
|
||||||
val pairingParams = PairingParams(base, main, secondary, geo, hd)
|
val pairingParams = PairingParams(base, main, secondary, geo, hd)
|
||||||
val placementParams = json.getArray("placement")?.let { PlacementParams.fromJson(it) } ?: defaultParams.placementParams
|
val placementParams = json.getArray("placement")?.let { PlacementParams.fromJson(it) } ?: defaultParams.placementParams
|
||||||
return when (type) {
|
return when (type) {
|
||||||
@@ -319,7 +330,7 @@ fun Pairing.toJson(): Json.Object = Json.MutableObject(
|
|||||||
"type" to type.name,
|
"type" to type.name,
|
||||||
"base" to pairingParams.base.toJson(),
|
"base" to pairingParams.base.toJson(),
|
||||||
"main" to pairingParams.main.toJson(),
|
"main" to pairingParams.main.toJson(),
|
||||||
"secondary" to pairingParams.main.toJson(),
|
"secondary" to pairingParams.secondary.toJson(),
|
||||||
"geo" to pairingParams.geo.toJson(),
|
"geo" to pairingParams.geo.toJson(),
|
||||||
"handicap" to pairingParams.handicap.toJson(),
|
"handicap" to pairingParams.handicap.toJson(),
|
||||||
"placement" to placementParams.toJson()
|
"placement" to placementParams.toJson()
|
||||||
|
@@ -486,14 +486,14 @@ sealed class BaseSolver(
|
|||||||
|
|
||||||
// Handicap functions
|
// Handicap functions
|
||||||
// Has to be overridden if handicap is not based on rank
|
// Has to be overridden if handicap is not based on rank
|
||||||
open fun HandicapParams.handicap(p1: Pairable, p2: Pairable): Int {
|
open fun HandicapParams.handicap(white: Pairable, black: Pairable): Int {
|
||||||
var hd = 0
|
var hd = 0
|
||||||
var pseudoRank1: Int = p1.rank
|
var pseudoRankWhite: Int = white.rank
|
||||||
var pseudoRank2: Int = p2.rank
|
var pseudoRankBlack: Int = black.rank
|
||||||
|
|
||||||
pseudoRank1 = min(pseudoRank1, rankThreshold)
|
pseudoRankWhite = min(pseudoRankWhite, rankThreshold)
|
||||||
pseudoRank2 = min(pseudoRank2, rankThreshold)
|
pseudoRankBlack = min(pseudoRankBlack, rankThreshold)
|
||||||
hd = pseudoRank1 - pseudoRank2
|
hd = pseudoRankWhite - pseudoRankBlack
|
||||||
|
|
||||||
return clamp(hd)
|
return clamp(hd)
|
||||||
}
|
}
|
||||||
|
@@ -81,7 +81,7 @@ class BasicTests: TestBase() {
|
|||||||
val aPlayer = Json.Object(
|
val aPlayer = Json.Object(
|
||||||
"name" to "Burma",
|
"name" to "Burma",
|
||||||
"firstname" to "Nestor",
|
"firstname" to "Nestor",
|
||||||
"rating" to 1600,
|
"rating" to -500,
|
||||||
"rank" to -5,
|
"rank" to -5,
|
||||||
"country" to "FR",
|
"country" to "FR",
|
||||||
"club" to "13Ma"
|
"club" to "13Ma"
|
||||||
@@ -90,12 +90,36 @@ class BasicTests: TestBase() {
|
|||||||
val anotherPlayer = Json.Object(
|
val anotherPlayer = Json.Object(
|
||||||
"name" to "Poirot",
|
"name" to "Poirot",
|
||||||
"firstname" to "Hercule",
|
"firstname" to "Hercule",
|
||||||
"rating" to 1700,
|
"rating" to -100,
|
||||||
"rank" to -1,
|
"rank" to -1,
|
||||||
"country" to "FR",
|
"country" to "FR",
|
||||||
"club" to "75Op"
|
"club" to "75Op"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val aMMTournament = Json.Object(
|
||||||
|
"type" to "INDIVIDUAL",
|
||||||
|
"name" to "Mon Tournoi",
|
||||||
|
"shortName" to "mon-tournoi",
|
||||||
|
"startDate" to "2023-05-10",
|
||||||
|
"endDate" to "2023-05-12",
|
||||||
|
"country" to "FR",
|
||||||
|
"location" to "Marseille",
|
||||||
|
"online" to false,
|
||||||
|
"timeSystem" to Json.Object(
|
||||||
|
"type" to "FISCHER",
|
||||||
|
"mainTime" to 1200,
|
||||||
|
"increment" to 10
|
||||||
|
),
|
||||||
|
"rounds" to 2,
|
||||||
|
"pairing" to Json.Object(
|
||||||
|
"type" to "MAC_MAHON",
|
||||||
|
"handicap" to Json.Object(
|
||||||
|
"correction" to 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
var aTournamentID: ID? = null
|
var aTournamentID: ID? = null
|
||||||
var aTeamTournamentID: ID? = null
|
var aTeamTournamentID: ID? = null
|
||||||
var aPlayerID: ID? = null
|
var aPlayerID: ID? = null
|
||||||
@@ -174,7 +198,21 @@ class BasicTests: TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `007 team tournament, MacMahon`() {
|
fun `007 Mac Mahon handicap`() {
|
||||||
|
var resp = TestAPI.post("/api/tour", aMMTournament).asObject()
|
||||||
|
val tourId = resp.getInt("id") ?: throw Error("tournament creation failed")
|
||||||
|
resp = TestAPI.post("/api/tour/$tourId/part", aPlayer).asObject().also { assertTrue(it.getBoolean("success")!!) }
|
||||||
|
val p1 = resp.getInt("id")!!
|
||||||
|
resp = TestAPI.post("/api/tour/$tourId/part", anotherPlayer).asObject().also { assertTrue(it.getBoolean("success")!!) }
|
||||||
|
val p2 = resp.getInt("id")!!
|
||||||
|
val game = TestAPI.post("/api/tour/$tourId/pair/1", Json.Array("all")).asArray().getObject(0) ?: throw Error("pairing failed")
|
||||||
|
assertEquals(p2, game.getInt("w"))
|
||||||
|
assertEquals(p1, game.getInt("b"))
|
||||||
|
assertEquals(3, game.getInt("h"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `008 team tournament, MacMahon`() {
|
||||||
var resp = TestAPI.post("/api/tour", aTeamTournament).asObject()
|
var resp = TestAPI.post("/api/tour", aTeamTournament).asObject()
|
||||||
assertTrue(resp.getBoolean("success") == true, "expecting success")
|
assertTrue(resp.getBoolean("success") == true, "expecting success")
|
||||||
aTeamTournamentID = resp.getInt("id")
|
aTeamTournamentID = resp.getInt("id")
|
||||||
@@ -204,5 +242,4 @@ class BasicTests: TestBase() {
|
|||||||
// TODO check pairing
|
// TODO check pairing
|
||||||
// val expected = """"["id":1,"w":5,"b":6,"h":3,"r":"?"]"""
|
// val expected = """"["id":1,"w":5,"b":6,"h":3,"r":"?"]"""
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user