Table numbers exclusion: handle saving

This commit is contained in:
Claude Brisson
2024-07-27 15:53:41 +02:00
parent 02e1fb8319
commit 6e97c91b2f
5 changed files with 77 additions and 26 deletions

View File

@@ -67,6 +67,15 @@ object TournamentHandler: PairgothApiHandler {
val payload = getObjectPayload(request)
// disallow changing type
if (payload.getString("type")?.let { it != tournament.type.name } == true) badRequest("tournament type cannot be changed")
// specific handling for 'excludeTables'
if (payload.containsKey("excludeTables")) {
val tablesExclusion = payload.getString("excludeTables") ?: badRequest("missing 'excludeTables'")
validateTablesExclusion(tablesExclusion)
val round = payload.getInt("round") ?: badRequest("missing 'round'")
while (tournament.tablesExclusion.size < round) tournament.tablesExclusion.add("")
tournament.tablesExclusion[round - 1] = tablesExclusion
tournament.dispatchEvent(TournamentUpdated, request, tournament.toJson())
} else {
val updated = Tournament.fromJson(payload, tournament)
// copy players, games, criteria (this copy should be provided by the Tournament class - CB TODO)
updated.players.putAll(tournament.players)
@@ -78,13 +87,20 @@ object TournamentHandler: PairgothApiHandler {
putAll(tournament.games(round))
}
updated.dispatchEvent(TournamentUpdated, request, updated.toJson())
}
return Json.Object("success" to true)
}
private fun validateTablesExclusion(exclusion: String) {
if (!tablesExclusionValidator.matches(exclusion)) badRequest("invalid tables exclusion pattern")
}
override fun delete(request: HttpServletRequest, response: HttpServletResponse): Json {
val tournament = getTournament(request)
getStore(request).deleteTournament(tournament)
tournament.dispatchEvent(TournamentDeleted, request, Json.Object("id" to tournament.id))
return Json.Object("success" to true)
}
private val tablesExclusionValidator = Regex("^(?:(?:\\s+|,)*\\d+(?:-\\d+)?)*$")
}

View File

@@ -6,8 +6,6 @@ import com.republicate.kson.toJsonArray
//import kotlinx.datetime.LocalDate
import java.time.LocalDate
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
import org.jeudego.pairgoth.pairing.solver.MacMahonSolver
import org.jeudego.pairgoth.pairing.solver.SwissSolver
import org.jeudego.pairgoth.store.nextPlayerId
import org.jeudego.pairgoth.store.nextTournamentId
import kotlin.math.max
@@ -30,7 +28,8 @@ sealed class Tournament <P: Pairable>(
val pairing: Pairing,
val rules: Rules = Rules.FRENCH,
val gobanSize: Int = 19,
val komi: Double = 7.5
val komi: Double = 7.5,
val tablesExclusion: MutableList<String> = mutableListOf()
) {
companion object {}
enum class Type(val playersNumber: Int, val individual: Boolean = true) {
@@ -170,8 +169,9 @@ class StandardTournament(
pairing: Pairing,
rules: Rules = Rules.FRENCH,
gobanSize: Int = 19,
komi: Double = 7.5
): Tournament<Player>(id, type, name, shortName, startDate, endDate, director, country, location, online, timeSystem, rounds, pairing, rules, gobanSize, komi) {
komi: Double = 7.5,
tablesExclusion: MutableList<String> = mutableListOf()
): Tournament<Player>(id, type, name, shortName, startDate, endDate, director, country, location, online, timeSystem, rounds, pairing, rules, gobanSize, komi, tablesExclusion) {
override val players get() = _pairables
}
@@ -192,8 +192,9 @@ class TeamTournament(
pairing: Pairing,
rules: Rules = Rules.FRENCH,
gobanSize: Int = 19,
komi: Double = 7.5
): Tournament<TeamTournament.Team>(id, type, name, shortName, startDate, endDate, director, country, location, online, timeSystem, rounds, pairing, rules, gobanSize, komi) {
komi: Double = 7.5,
tablesExclusion: MutableList<String> = mutableListOf()
): Tournament<TeamTournament.Team>(id, type, name, shortName, startDate, endDate, director, country, location, online, timeSystem, rounds, pairing, rules, gobanSize, komi, tablesExclusion) {
companion object {
private val epsilon = 0.0001
}
@@ -267,7 +268,8 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament<*>? = n
gobanSize = json.getInt("gobanSize") ?: default?.gobanSize ?: 19,
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) } ?: default?.pairing ?: badRequest("missing pairing")
pairing = json.getObject("pairing")?.let { Pairing.fromJson(it, default?.pairing) } ?: default?.pairing ?: badRequest("missing pairing"),
tablesExclusion = json.getArray("tablesExclusion")?.map { item -> item as String }?.toMutableList() ?: default?.tablesExclusion ?: mutableListOf()
)
else
TeamTournament(
@@ -286,7 +288,8 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament<*>? = n
gobanSize = json.getInt("gobanSize") ?: default?.gobanSize ?: 19,
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) } ?: default?.pairing ?: badRequest("missing pairing")
pairing = json.getObject("pairing")?.let { Pairing.fromJson(it, default?.pairing) } ?: default?.pairing ?: badRequest("missing pairing"),
tablesExclusion = json.getArray("tablesExclusion")?.map { item -> item as String }?.toMutableList() ?: default?.tablesExclusion ?: mutableListOf()
)
json.getArray("players")?.forEach { obj ->
val pairable = obj as Json.Object
@@ -326,7 +329,8 @@ fun Tournament<*>.toJson() = Json.MutableObject(
"gobanSize" to gobanSize,
"timeSystem" to timeSystem.toJson(),
"rounds" to rounds,
"pairing" to pairing.toJson()
"pairing" to pairing.toJson(),
"tablesExclusion" to tablesExclusion.toJsonArray()
)
fun Tournament<*>.toFullJson(): Json.Object {

View File

@@ -405,6 +405,10 @@
margin-top: 0.2em;
}
.tables-exclusion {
margin-top: 0.2em;
}
/* results section */
#results-filter {

View File

@@ -1,6 +1,8 @@
let focused = undefined;
function pair(parts) {
let doWork = () => {
api.postJson(`tour/${tour_id}/pair/${activeRound}`, parts)
.then(rst => {
if (rst !== 'error') {
@@ -9,6 +11,23 @@ function pair(parts) {
});
}
let tablesExclusionControl = $('#exclude-tables');
let value = tablesExclusionControl[0].value;
let origValue = tablesExclusionControl.data('orig');
if (value === origValue) {
// tables exclusion value did not change
doWork();
} else {
// tables exclusion value has change, we must save it first
api.putJson(`tour/${tour_id}`, { round: activeRound, excludeTables: value })
.then(rst => {
if (rst !== 'error') {
doWork();
}
});
}
}
function unpair(games) {
api.deleteJson(`tour/${tour_id}/pair/${activeRound}`, games)
.then(rst => {

View File

@@ -22,6 +22,14 @@
<button class="ui floating choose-round next-round button">&raquo;</button>
</div>
<div class="pairing-stats nobreak">( $pairables.size() pairable, $games.size() games )</div>
<div class="tables-exclusion">
#if($tour.tablesExclusion && $round <= $tour.tablesExclusion.size())
#set($tablesExclusion = $!tour.tablesExclusion[$round - 1])
#else
#set($tablesExclusion = '')
#end
Exclude table numbers: <input type="text" id="exclude-tables" name="exclude-tables" placeholder="ex: 1-34, 38, 45-77" data-orig="$tablesExclusion" value="$tablesExclusion"/>
</div>
<div id="pairing-lists">
<div id="pairing-left">
<div id="pairables" class="multi-select" title="pairable players">