diff --git a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairgothApiHandler.kt b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairgothApiHandler.kt index fc5297c..ac7cd69 100644 --- a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairgothApiHandler.kt +++ b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairgothApiHandler.kt @@ -6,6 +6,10 @@ import javax.servlet.http.HttpServletRequest interface PairgothApiHandler: ApiHandler { - fun getTournament(request: HttpServletRequest): Tournament? = getSelector(request)?.toIntOrNull()?.let { Store.getTournament(it) } + fun getTournament(request: HttpServletRequest): Tournament { + val tournamentId = getSelector(request)?.toIntOrNull() ?: ApiHandler.badRequest("invalid tournament id") + return Store.getTournament(tournamentId) ?: ApiHandler.badRequest("unknown tournament id") + } + } \ No newline at end of file diff --git a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt index b6ff0c9..e12351e 100644 --- a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt +++ b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/PairingHandler.kt @@ -9,18 +9,15 @@ import org.jeudego.pairgoth.model.toJson import org.jeudego.pairgoth.store.Store import javax.servlet.http.HttpServletRequest -object PairingHandler: ApiHandler { - - private fun getTournament(request: HttpServletRequest): Tournament { - val tournamentId = getSelector(request)?.toIntOrNull() ?: badRequest("invalid tournament id") - return Store.getTournament(tournamentId) ?: badRequest("unknown tournament id") - } +object PairingHandler: PairgothApiHandler { override fun get(request: HttpServletRequest): Json { val tournament = getTournament(request) val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") - val games = tournament.games.getOrNull(round)?.values ?: emptyList() - return games.map { it.toJson() }.toJsonArray() + val playing = (tournament.games.getOrNull(round)?.values ?: emptyList()).flatMap { + listOf(it.black, it.white) + }.toSet() + return tournament.pairables.values.filter { !it.skip.contains(round) && !playing.contains(it.id) }.toJsonArray() } override fun post(request: HttpServletRequest): Json { @@ -29,25 +26,21 @@ object PairingHandler: ApiHandler { val payload = getArrayPayload(request) val allPlayers = payload.size == 1 && payload[0] == "all" if (!allPlayers && tournament.pairing.type == Pairing.PairingType.SWISS) badRequest("Swiss pairing requires all pairable players") + val playing = (tournament.games.getOrNull(round)?.values ?: emptyList()).flatMap { + listOf(it.black, it.white) + }.toSet() val pairables = if (allPlayers) - tournament.pairables.values.filter { !it.skip.contains(round) } + tournament.pairables.values.filter { !it.skip.contains(round) && !playing.contains(it.id) } else payload.map { + // CB - because of the '["all"]' map, conversion to int lands here... Better API syntax for 'all players'? if (it is Number) it.toInt() else badRequest("invalid pairable id: #$it") }.map { id -> tournament.pairables[id]?.also { if (it.skip.contains(round)) badRequest("pairable #$id does not play round $round") + if (playing.contains(it.id)) badRequest("pairable #$id already plays round $round") } ?: badRequest("invalid pairable id: #$id") } - // check players are not already implied in games in this round - val pairablesIDs = pairables.map { it.id }.toSet() - tournament.games.getOrNull(round)?.let { games -> - games.values.mapNotNull { game -> - if (pairablesIDs.contains(game.black)) game.black else if (pairablesIDs.contains(game.white)) game.white else null - }.let { - if (it.isNotEmpty()) badRequest("The following players are already playing this round: ${it.joinToString { id -> "#${id}" }}") - } - } val games = tournament.pair(round, pairables) return games.map { it.toJson() }.toJsonArray() } diff --git a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/ResultsHandler.kt b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/ResultsHandler.kt index b87a022..1dbe1a6 100644 --- a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/ResultsHandler.kt +++ b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/ResultsHandler.kt @@ -1,4 +1,47 @@ package org.jeudego.pairgoth.api -class ResultsHandler: ApiHandler { -} \ No newline at end of file +import com.republicate.kson.Json +import com.republicate.kson.toJsonArray +import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest +import org.jeudego.pairgoth.model.Game +import org.jeudego.pairgoth.model.Tournament +import org.jeudego.pairgoth.model.toJson +import org.jeudego.pairgoth.store.Store +import javax.servlet.http.HttpServletRequest + +object ResultsHandler: PairgothApiHandler { + + override fun get(request: HttpServletRequest): Json { + val tournament = getTournament(request) + val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") + val games = tournament.games.getOrNull(round)?.values ?: emptyList() + return games.map { it.toJson() }.toJsonArray() + } + + override fun post(request: HttpServletRequest): Json { + val tournament = getTournament(request) + val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") + val payload = getObjectPayload(request) + val game = tournament.games[round][payload.getInt("id")] ?: badRequest("invalid game id") + game.result = Game.Result.valueOf(payload.getString("result") ?: badRequest("missing result")) + return Json.Object("success" to true) + } + + override fun put(request: HttpServletRequest): Json { + val tournament = getTournament(request) + val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") + val payload = getObjectPayload(request) + val game = tournament.games[round][payload.getInt("id")] ?: badRequest("invalid game id") + game.result = Game.Result.valueOf(payload.getString("result") ?: badRequest("missing result")) + return Json.Object("success" to true) + } + + override fun delete(request: HttpServletRequest): Json { + val tournament = getTournament(request) + val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number") + val payload = getObjectPayload(request) + val game = tournament.games[round][payload.getInt("id")] ?: badRequest("invalid game id") + tournament.games[round].remove(payload.getInt("id") ?: badRequest("invalid game id")) ?: badRequest("invalid game id") + return Json.Object("success" to true) + } +} diff --git a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/StandingsHandler.kt b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/StandingsHandler.kt index 9dbc249..d83dc20 100644 --- a/webapp/src/main/kotlin/org/jeudego/pairgoth/api/StandingsHandler.kt +++ b/webapp/src/main/kotlin/org/jeudego/pairgoth/api/StandingsHandler.kt @@ -1,4 +1,4 @@ package org.jeudego.pairgoth.api -class StandingsHandler: ApiHandler { +object StandingsHandler: PairgothApiHandler { } \ No newline at end of file diff --git a/webapp/src/main/kotlin/org/jeudego/pairgoth/web/ApiServlet.kt b/webapp/src/main/kotlin/org/jeudego/pairgoth/web/ApiServlet.kt index e4ba9cc..229e972 100644 --- a/webapp/src/main/kotlin/org/jeudego/pairgoth/web/ApiServlet.kt +++ b/webapp/src/main/kotlin/org/jeudego/pairgoth/web/ApiServlet.kt @@ -4,6 +4,7 @@ import com.republicate.kson.Json import org.jeudego.pairgoth.api.ApiHandler import org.jeudego.pairgoth.api.PairingHandler import org.jeudego.pairgoth.api.PlayerHandler +import org.jeudego.pairgoth.api.ResultsHandler import org.jeudego.pairgoth.api.TournamentHandler import org.jeudego.pairgoth.util.Colorizer.blue import org.jeudego.pairgoth.util.Colorizer.green @@ -84,6 +85,7 @@ class ApiServlet : HttpServlet() { null -> TournamentHandler "part" -> PlayerHandler "pair" -> PairingHandler + "res" -> ResultsHandler else -> ApiHandler.badRequest("unknown sub-entity: $subEntity") } "player" -> PlayerHandler diff --git a/webapp/src/test/kotlin/ImportTests.kt b/webapp/src/test/kotlin/ImportTests.kt index 324c37f..ceaab92 100644 --- a/webapp/src/test/kotlin/ImportTests.kt +++ b/webapp/src/test/kotlin/ImportTests.kt @@ -13,8 +13,14 @@ class ImportTests: TestBase() { val resource = file.readText(StandardCharsets.UTF_8) val resp = TestAPI.post("/api/tour", resource) val id = resp.asObject().getInt("id") - val tournament = TestAPI.get("/api/tour/$id") + val tournament = TestAPI.get("/api/tour/$id").asObject() logger.info(tournament.toString()) + val players = TestAPI.get("/api/tour/$id/part").asArray() + logger.info(players.toString()) + for (round in 1..tournament.getInt("rounds")!!) { + val games = TestAPI.get("/api/tour/$id/res/1").asArray() + logger.info("games for round $round: {}", games.toString()) + } } } -} \ No newline at end of file +}