Implement standings freezing
This commit is contained in:
@@ -25,7 +25,7 @@ interface ApiHandler {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ package org.jeudego.pairgoth.api
|
||||
import com.republicate.kson.Json
|
||||
import org.jeudego.pairgoth.model.Criterion
|
||||
import org.jeudego.pairgoth.model.DatabaseId
|
||||
import org.jeudego.pairgoth.model.Game
|
||||
import org.jeudego.pairgoth.model.MacMahon
|
||||
import org.jeudego.pairgoth.model.Pairable
|
||||
import org.jeudego.pairgoth.model.Pairable.Companion.MIN_RANK
|
||||
@@ -34,6 +35,10 @@ fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = f
|
||||
else ceil(score - epsilon)
|
||||
}
|
||||
|
||||
if (frozen != null) {
|
||||
return ArrayList(frozen!!.map { it -> it as Json.Object })
|
||||
}
|
||||
|
||||
// CB TODO - factorize history helper creation between here and solver classes
|
||||
val historyHelper = HistoryHelper(historyBefore(round + 1)) {
|
||||
if (pairing.type == PairingType.SWISS) wins.mapValues { Pair(0.0, it.value) }
|
||||
@@ -116,5 +121,50 @@ fun Tournament<*>.getSortedPairables(round: Int, includePreliminary: Boolean = f
|
||||
it.value.forEach { p -> p["place"] = place }
|
||||
place += it.value.size
|
||||
}
|
||||
|
||||
return sortedPairables
|
||||
}
|
||||
|
||||
fun Tournament<*>.populateResultsArray(sortedPairables: List<Json.Object>, round: Int = rounds) {
|
||||
// fill result
|
||||
val sortedMap = sortedPairables.associateBy {
|
||||
it.getID()!!
|
||||
}
|
||||
|
||||
for (r in 1..round) {
|
||||
games(r).values.forEach { game ->
|
||||
val white = if (game.white != 0) sortedMap[game.white] else null
|
||||
val black = if (game.black != 0) sortedMap[game.black] else null
|
||||
val whiteNum = white?.getInt("num") ?: 0
|
||||
val blackNum = black?.getInt("num") ?: 0
|
||||
val whiteColor = if (black == null) "" else "w"
|
||||
val blackColor = if (white == null) "" else "b"
|
||||
val handicap = if (game.handicap == 0) "" else "${game.handicap}"
|
||||
assert(white != null || black != null)
|
||||
if (white != null) {
|
||||
val mark = when (game.result) {
|
||||
Game.Result.UNKNOWN -> "?"
|
||||
Game.Result.BLACK, Game.Result.BOTHLOOSE -> "-"
|
||||
Game.Result.WHITE, Game.Result.BOTHWIN -> "+"
|
||||
Game.Result.JIGO, Game.Result.CANCELLED -> "="
|
||||
}
|
||||
val results = white.getArray("results") as Json.MutableArray
|
||||
results[r - 1] =
|
||||
if (blackNum == 0) "0$mark"
|
||||
else "$blackNum$mark/$whiteColor$handicap"
|
||||
}
|
||||
if (black != null) {
|
||||
val mark = when (game.result) {
|
||||
Game.Result.UNKNOWN -> "?"
|
||||
Game.Result.BLACK, Game.Result.BOTHWIN -> "+"
|
||||
Game.Result.WHITE, Game.Result.BOTHLOOSE -> "-"
|
||||
Game.Result.JIGO, Game.Result.CANCELLED -> "="
|
||||
}
|
||||
val results = black.getArray("results") as Json.MutableArray
|
||||
results[r - 1] =
|
||||
if (whiteNum == 0) "0$mark"
|
||||
else "$whiteNum$mark/$blackColor$handicap"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package org.jeudego.pairgoth.api
|
||||
import com.republicate.kson.Json
|
||||
import com.republicate.kson.toJsonArray
|
||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
||||
import org.jeudego.pairgoth.api.TournamentHandler.dispatchEvent
|
||||
import org.jeudego.pairgoth.model.Game
|
||||
import org.jeudego.pairgoth.model.Tournament
|
||||
import org.jeudego.pairgoth.model.getID
|
||||
@@ -66,7 +65,7 @@ object PairingHandler: PairgothApiHandler {
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
val tournament = getTournament(request)
|
||||
val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number")
|
||||
// only allow last round (if players have not been paired in the last round, it *may* be possible to be more laxist...)
|
||||
|
@@ -31,7 +31,7 @@ object PlayerHandler: PairgothApiHandler {
|
||||
return Json.Object("success" to true, "id" to player.id)
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
val tournament = getTournament(request)
|
||||
val id = getSubSelector(request)?.toIntOrNull() ?: badRequest("missing or invalid player selector")
|
||||
val player = tournament.players[id] ?: badRequest("invalid player id")
|
||||
|
@@ -18,7 +18,7 @@ object ResultsHandler: PairgothApiHandler {
|
||||
return games.map { it.toJson() }.toJsonArray()
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
val tournament = getTournament(request)
|
||||
val round = getSubSelector(request)?.toIntOrNull() ?: badRequest("invalid round number")
|
||||
val payload = getObjectPayload(request)
|
||||
|
@@ -2,27 +2,23 @@ package org.jeudego.pairgoth.api
|
||||
|
||||
import com.republicate.kson.Json
|
||||
import com.republicate.kson.toJsonArray
|
||||
import org.jeudego.pairgoth.api.PairingHandler.dispatchEvent
|
||||
import org.jeudego.pairgoth.model.Criterion
|
||||
import org.jeudego.pairgoth.model.Criterion.*
|
||||
import org.jeudego.pairgoth.model.Game.Result.*
|
||||
import org.jeudego.pairgoth.model.ID
|
||||
import org.jeudego.pairgoth.model.MacMahon
|
||||
import org.jeudego.pairgoth.model.Pairable
|
||||
import org.jeudego.pairgoth.model.PairingType
|
||||
import org.jeudego.pairgoth.model.Tournament
|
||||
import org.jeudego.pairgoth.model.adjustedTime
|
||||
import org.jeudego.pairgoth.model.displayRank
|
||||
import org.jeudego.pairgoth.model.getID
|
||||
import org.jeudego.pairgoth.model.historyBefore
|
||||
import org.jeudego.pairgoth.pairing.HistoryHelper
|
||||
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
|
||||
import java.io.PrintWriter
|
||||
import java.time.format.DateTimeFormatter
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import org.jeudego.pairgoth.model.TimeSystem.TimeSystemType.*
|
||||
import org.jeudego.pairgoth.model.toJson
|
||||
import org.jeudego.pairgoth.server.Event
|
||||
import org.jeudego.pairgoth.server.WebappManager
|
||||
import java.io.OutputStreamWriter
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -35,46 +31,8 @@ object StandingsHandler: PairgothApiHandler {
|
||||
val includePreliminary = request.getParameter("include_preliminary")?.let { it.toBoolean() } ?: false
|
||||
|
||||
val sortedPairables = tournament.getSortedPairables(round, includePreliminary)
|
||||
val sortedMap = sortedPairables.associateBy {
|
||||
it.getID()!!
|
||||
}
|
||||
tournament.populateResultsArray(sortedPairables, round)
|
||||
|
||||
for (r in 1..round) {
|
||||
tournament.games(r).values.forEach { game ->
|
||||
val white = if (game.white != 0) sortedMap[game.white] else null
|
||||
val black = if (game.black != 0) sortedMap[game.black] else null
|
||||
val whiteNum = white?.getInt("num") ?: 0
|
||||
val blackNum = black?.getInt("num") ?: 0
|
||||
val whiteColor = if (black == null) "" else "w"
|
||||
val blackColor = if (white == null) "" else "b"
|
||||
val handicap = if (game.handicap == 0) "" else "${game.handicap}"
|
||||
assert(white != null || black != null)
|
||||
if (white != null) {
|
||||
val mark = when (game.result) {
|
||||
UNKNOWN -> "?"
|
||||
BLACK, BOTHLOOSE -> "-"
|
||||
WHITE, BOTHWIN -> "+"
|
||||
JIGO, CANCELLED -> "="
|
||||
}
|
||||
val results = white.getArray("results") as Json.MutableArray
|
||||
results[r - 1] =
|
||||
if (blackNum == 0) "0$mark"
|
||||
else "$blackNum$mark/$whiteColor$handicap"
|
||||
}
|
||||
if (black != null) {
|
||||
val mark = when (game.result) {
|
||||
UNKNOWN -> "?"
|
||||
BLACK, BOTHWIN -> "+"
|
||||
WHITE, BOTHLOOSE -> "-"
|
||||
JIGO, CANCELLED -> "="
|
||||
}
|
||||
val results = black.getArray("results") as Json.MutableArray
|
||||
results[r - 1] =
|
||||
if (whiteNum == 0) "0$mark"
|
||||
else "$whiteNum$mark/$blackColor$handicap"
|
||||
}
|
||||
}
|
||||
}
|
||||
val acceptHeader = request.getHeader("Accept") as String?
|
||||
val accept = acceptHeader?.substringBefore(";")
|
||||
val acceptEncoding = acceptHeader?.substringAfter(";charset=", "utf-8") ?: "utf-8"
|
||||
@@ -268,6 +226,14 @@ ${
|
||||
}
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
val tournament = getTournament(request)
|
||||
val sortedPairables = tournament.getSortedPairables(tournament.rounds)
|
||||
tournament.frozen = sortedPairables.toJsonArray()
|
||||
tournament.dispatchEvent(Event.TournamentUpdated, request, tournament.toJson())
|
||||
return Json.Object("status" to "ok")
|
||||
}
|
||||
|
||||
private val numFormat = DecimalFormat("###0.#")
|
||||
private val frDate: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ object TeamHandler: PairgothApiHandler {
|
||||
return Json.Object("success" to true, "id" to team.id)
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
val tournament = getTournament(request)
|
||||
if (tournament !is TeamTournament) badRequest("tournament is not a team tournament")
|
||||
val id = getSubSelector(request)?.toIntOrNull() ?: badRequest("missing or invalid player selector")
|
||||
|
@@ -34,6 +34,7 @@ object TournamentHandler: PairgothApiHandler {
|
||||
// additional attributes for the webapp
|
||||
json["stats"] = tour.stats()
|
||||
json["teamSize"] = tour.type.playersNumber
|
||||
json["frozen"] = tour.frozen != null
|
||||
}
|
||||
}
|
||||
} ?: badRequest("no tournament with id #${id}")
|
||||
@@ -61,7 +62,7 @@ object TournamentHandler: PairgothApiHandler {
|
||||
return Json.Object("success" to true, "id" to tournament.id)
|
||||
}
|
||||
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json {
|
||||
override fun put(request: HttpServletRequest, response: HttpServletResponse): Json? {
|
||||
// CB TODO - some checks are needed here (cannot lower rounds number if games have been played in removed rounds, for instance)
|
||||
val tournament = getTournament(request)
|
||||
val payload = getObjectPayload(request)
|
||||
|
@@ -52,6 +52,9 @@ sealed class Tournament <P: Pairable>(
|
||||
protected val _pairables = mutableMapOf<ID, P>()
|
||||
val pairables: Map<ID, Pairable> get() = _pairables
|
||||
|
||||
// frozen standings
|
||||
var frozen: Json.Array? = null
|
||||
|
||||
// pairing
|
||||
fun pair(round: Int, pairables: List<Pairable>): List<Game> {
|
||||
// Minimal check on round number.
|
||||
@@ -335,7 +338,7 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament<*>? = n
|
||||
tournament.teams[team.getID("id")!!] = tournament.teamFromJson(team)
|
||||
}
|
||||
}
|
||||
(json["games"] as Json.Array?)?.forEachIndexed { i, arr ->
|
||||
json.getArray("games")?.forEachIndexed { i, arr ->
|
||||
val round = i + 1
|
||||
val tournamentGames = tournament.games(round)
|
||||
val games = arr as Json.Array
|
||||
@@ -344,6 +347,9 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament<*>? = n
|
||||
tournamentGames[game.getID("id")!!] = Game.fromJson(game)
|
||||
}
|
||||
}
|
||||
json.getArray("frozen")?.also {
|
||||
tournament.frozen = it
|
||||
}
|
||||
return tournament
|
||||
}
|
||||
|
||||
@@ -374,5 +380,8 @@ fun Tournament<*>.toFullJson(): Json.Object {
|
||||
json["teams"] = Json.Array(teams.values.map { it.toJson() })
|
||||
}
|
||||
json["games"] = Json.Array((1..lastRound()).mapTo(Json.MutableArray()) { round -> games(round).values.mapTo(Json.MutableArray()) { it.toJson() } });
|
||||
if (frozen != null) {
|
||||
json["frozen"] = frozen
|
||||
}
|
||||
return json
|
||||
}
|
||||
|
Reference in New Issue
Block a user