Add pairing basic test

This commit is contained in:
Claude Brisson
2023-05-17 22:16:34 +02:00
parent 67fc65dada
commit b24948ba30
6 changed files with 24 additions and 11 deletions

View File

@@ -19,7 +19,8 @@ object PairingHandler: ApiHandler {
override fun get(request: HttpServletRequest): Json { override fun get(request: HttpServletRequest): Json {
val tournament = getTournament(request) val tournament = getTournament(request)
val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number")
return tournament.pairables.values.filter { !it.skip.contains(round) }.map { it.toJson() }.toJsonArray() val games = tournament.games.getOrNull(round)?.values ?: emptyList()
return games.map { it.toJson() }.toJsonArray()
} }
override fun post(request: HttpServletRequest): Json { override fun post(request: HttpServletRequest): Json {
@@ -38,7 +39,7 @@ object PairingHandler: ApiHandler {
if (it.skip.contains(round)) badRequest("pairable #$id does not play round $round") if (it.skip.contains(round)) badRequest("pairable #$id does not play round $round")
} ?: badRequest("invalid pairable id: #$id") } ?: badRequest("invalid pairable id: #$id")
} }
// check players are not already implied in games // check players are not already implied in games in this round
val pairablesIDs = pairables.map { it.id }.toSet() val pairablesIDs = pairables.map { it.id }.toSet()
tournament.games.getOrNull(round)?.let { games -> tournament.games.getOrNull(round)?.let { games ->
games.values.mapNotNull { game -> games.values.mapNotNull { game ->

View File

@@ -28,6 +28,7 @@ object TournamentHandler: PairgothApiHandler {
} }
override fun put(request: HttpServletRequest): Json { override fun put(request: HttpServletRequest): Json {
// BC TODO - some checks are needed here (cannot lower rounds number if games have been played in removed rounds, for instance)
val tournament = getTournament(request) ?: badRequest("missing or invalid tournament id") val tournament = getTournament(request) ?: badRequest("missing or invalid tournament id")
val payload = getObjectPayload(request) val payload = getObjectPayload(request)
// disallow changing type // disallow changing type

View File

@@ -24,7 +24,7 @@ class Swiss(
var method: Method, var method: Method,
var firstRoundMethod: Method = method var firstRoundMethod: Method = method
): Pairing(SWISS) { ): Pairing(SWISS) {
enum class Method { FOLD, RANDOM, SLIP } enum class Method { SPLIT_AND_FOLD, SPLIT_AND_RANDOM, SPLIT_AND_SLIP }
override fun pair(tournament: Tournament, round: Int, pairables: List<Pairable>): List<Game> { override fun pair(tournament: Tournament, round: Int, pairables: List<Pairable>): List<Game> {
val actualMethod = if (round == 1) firstRoundMethod else method val actualMethod = if (round == 1) firstRoundMethod else method
val history = val history =
@@ -66,7 +66,9 @@ fun Pairing.Companion.fromJson(json: Json.Object) = when (json.getString("type")
} }
fun Pairing.toJson() = when (this) { fun Pairing.toJson() = when (this) {
is Swiss -> Json.Object("type" to type.name, "method" to method.name, "firstRoundMethod" to firstRoundMethod.name) is Swiss ->
if (method == firstRoundMethod) Json.Object("type" to type.name, "method" to method.name)
else Json.Object("type" to type.name, "method" to method.name, "firstRoundMethod" to firstRoundMethod.name)
is MacMahon -> Json.Object("type" to type.name, "bar" to bar, "minLevel" to minLevel) is MacMahon -> Json.Object("type" to type.name, "bar" to bar, "minLevel" to minLevel)
is RoundRobin -> Json.Object("type" to type.name) is RoundRobin -> Json.Object("type" to type.name)
} }

View File

@@ -16,6 +16,7 @@ data class Tournament(
val location: String, val location: String,
val online: Boolean, val online: Boolean,
val timeSystem: TimeSystem, val timeSystem: TimeSystem,
val rounds: Int,
val pairing: Pairing, val pairing: Pairing,
val rules: Rules = Rules.FRENCH, val rules: Rules = Rules.FRENCH,
val gobanSize: Int = 19, val gobanSize: Int = 19,
@@ -45,6 +46,7 @@ data class Tournament(
// Minimal check on round number. // Minimal check on round number.
// CB TODO - the complete check should verify, for each player, that he was either non pairable or implied in the previous round // CB TODO - the complete check should verify, for each player, that he was either non pairable or implied in the previous round
if (round > games.size + 1) badRequest("previous round not paired") if (round > games.size + 1) badRequest("previous round not paired")
if (round > rounds) badRequest("too many rounds")
val evenPairables = val evenPairables =
if (pairables.size % 2 == 0) pairables if (pairables.size % 2 == 0) pairables
else pairables.toMutableList()?.also { it.add(ByePlayer) } else pairables.toMutableList()?.also { it.add(ByePlayer) }
@@ -78,6 +80,7 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament? = null
rules = json.getString("rules")?.let { Rules.valueOf(it) } ?: default?.rules ?: Rules.FRENCH, rules = json.getString("rules")?.let { Rules.valueOf(it) } ?: default?.rules ?: Rules.FRENCH,
gobanSize = json.getInt("gobanSize") ?: default?.gobanSize ?: 19, gobanSize = json.getInt("gobanSize") ?: default?.gobanSize ?: 19,
timeSystem = json.getObject("timeSystem")?.let { TimeSystem.fromJson(it) } ?: default?.timeSystem ?: badRequest("missing timeSystem"), timeSystem = json.getObject("timeSystem")?.let { TimeSystem.fromJson(it) } ?: default?.timeSystem ?: badRequest("missing timeSystem"),
rounds = json.getInt("rounds") ?: default?.rounds ?: badRequest("missing rounds"),
pairing = json.getObject("pairing")?.let { Pairing.fromJson(it) } ?: default?.pairing ?: badRequest("missing pairing") pairing = json.getObject("pairing")?.let { Pairing.fromJson(it) } ?: default?.pairing ?: badRequest("missing pairing")
) )
@@ -95,5 +98,6 @@ fun Tournament.toJson() = Json.Object(
"rules" to rules.name, "rules" to rules.name,
"gobanSize" to gobanSize, "gobanSize" to gobanSize,
"timeSystem" to timeSystem.toJson(), "timeSystem" to timeSystem.toJson(),
"rounds" to rounds,
"pairing" to pairing.toJson() "pairing" to pairing.toJson()
) )

View File

@@ -32,6 +32,7 @@ sealed class Solver(private val history: List<Game>) {
val solution = matching.matching val solution = matching.matching
val result = solution.map { val result = solution.map {
// CB TODO - choice of colors should be here
Game(Store.nextGameId, graph.getEdgeSource(it).id , graph.getEdgeTarget(it).id) Game(Store.nextGameId, graph.getEdgeSource(it).id , graph.getEdgeTarget(it).id)
} }
return result return result

View File

@@ -27,8 +27,10 @@ class BasicTests: TestBase() {
"mainTime" to 1200, "mainTime" to 1200,
"increment" to 10 "increment" to 10
), ),
"rounds" to 2,
"pairing" to Json.Object( "pairing" to Json.Object(
"type" to "ROUNDROBIN" "type" to "SWISS",
"method" to "SPLIT_AND_SLIP"
) )
) )
@@ -79,19 +81,21 @@ class BasicTests: TestBase() {
@Test @Test
fun `004 modify user`() { fun `004 modify user`() {
val resp = TestAPI.put("/api/tour/1/part/1", Json.Object("skip" to Json.Array(1))) as Json.Object // remove player #1 from round #2
val resp = TestAPI.put("/api/tour/1/part/1", Json.Object("skip" to Json.Array(2))) as Json.Object
assertTrue(resp.getBoolean("success") == true, "expecting success") assertTrue(resp.getBoolean("success") == true, "expecting success")
val player = TestAPI.get("/api/tour/1/part/1") as Json.Object val player = TestAPI.get("/api/tour/1/part/1") as Json.Object
assertEquals("[1]", player.getArray("skip").toString(), "First player should have id #1") assertEquals("[2]", player.getArray("skip").toString(), "First player should have id #1")
} }
@Test @Test
fun `005 pair`() { fun `005 pair`() {
val resp = TestAPI.post("/api/tour/1/part", anotherPlayer) as Json.Object val resp = TestAPI.post("/api/tour/1/part", anotherPlayer) as Json.Object
assertTrue(resp.getBoolean("success") == true, "expecting success") assertTrue(resp.getBoolean("success") == true, "expecting success")
val pairable = TestAPI.get("/api/tour/1/pair/1") val games = TestAPI.post("/api/tour/1/pair/1", Json.Array("all"))
logger.info(pairable.toString()) val possibleResults = setOf(
"[{\"id\":1,\"w\":1,\"b\":2,\"r\":\"?\"}]",
"[{\"id\":1,\"w\":2,\"b\":1,\"r\":\"?\"}]")
assertTrue(possibleResults.contains(games.toString()), "pairing differs")
} }
} }