Table numbers exclusion is functional
This commit is contained in:
@@ -3,6 +3,7 @@ package org.jeudego.pairgoth.api
|
|||||||
import com.republicate.kson.Json
|
import com.republicate.kson.Json
|
||||||
import com.republicate.kson.toJsonArray
|
import com.republicate.kson.toJsonArray
|
||||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
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.Game
|
||||||
import org.jeudego.pairgoth.model.getID
|
import org.jeudego.pairgoth.model.getID
|
||||||
import org.jeudego.pairgoth.model.toID
|
import org.jeudego.pairgoth.model.toID
|
||||||
@@ -38,6 +39,7 @@ object PairingHandler: PairgothApiHandler {
|
|||||||
if (round > tournament.lastRound() + 1) badRequest("invalid round: previous round has not been played")
|
if (round > tournament.lastRound() + 1) badRequest("invalid round: previous round has not been played")
|
||||||
val payload = getArrayPayload(request)
|
val payload = getArrayPayload(request)
|
||||||
if (payload.isEmpty()) badRequest("nobody to pair")
|
if (payload.isEmpty()) badRequest("nobody to pair")
|
||||||
|
// CB TODO - change convention to empty array for all players
|
||||||
val allPlayers = payload.size == 1 && payload[0] == "all"
|
val allPlayers = payload.size == 1 && payload[0] == "all"
|
||||||
//if (!allPlayers && tournament.pairing.type == PairingType.SWISS) badRequest("Swiss pairing requires all pairable players")
|
//if (!allPlayers && tournament.pairing.type == PairingType.SWISS) badRequest("Swiss pairing requires all pairable players")
|
||||||
val playing = (tournament.games(round).values).flatMap {
|
val playing = (tournament.games(round).values).flatMap {
|
||||||
@@ -57,6 +59,10 @@ object PairingHandler: PairgothApiHandler {
|
|||||||
} ?: badRequest("invalid pairable id: #$id")
|
} ?: badRequest("invalid pairable id: #$id")
|
||||||
}
|
}
|
||||||
val games = tournament.pair(round, pairables)
|
val games = tournament.pair(round, pairables)
|
||||||
|
|
||||||
|
// always renumber table to take table exclusion into account
|
||||||
|
tournament.renumberTables(round)
|
||||||
|
|
||||||
val ret = games.map { it.toJson() }.toJsonArray()
|
val ret = games.map { it.toJson() }.toJsonArray()
|
||||||
tournament.dispatchEvent(GamesAdded, request, Json.Object("round" to round, "games" to ret))
|
tournament.dispatchEvent(GamesAdded, request, Json.Object("round" to round, "games" to ret))
|
||||||
return ret
|
return ret
|
||||||
@@ -122,6 +128,14 @@ object PairingHandler: PairgothApiHandler {
|
|||||||
return Json.Object("success" to true)
|
return Json.Object("success" to true)
|
||||||
} else {
|
} else {
|
||||||
// without id, it's a table renumbering
|
// without id, it's a table renumbering
|
||||||
|
if (payload.containsKey("excludeTables")) {
|
||||||
|
val tablesExclusion = payload.getString("excludeTables") ?: badRequest("missing 'excludeTables'")
|
||||||
|
TournamentHandler.validateTablesExclusion(tablesExclusion)
|
||||||
|
while (tournament.tablesExclusion.size < round) tournament.tablesExclusion.add("")
|
||||||
|
tournament.tablesExclusion[round - 1] = tablesExclusion
|
||||||
|
tournament.dispatchEvent(TournamentUpdated, request, tournament.toJson())
|
||||||
|
}
|
||||||
|
|
||||||
val sortedPairables = tournament.getSortedPairables(round)
|
val sortedPairables = tournament.getSortedPairables(round)
|
||||||
val sortedMap = sortedPairables.associateBy {
|
val sortedMap = sortedPairables.associateBy {
|
||||||
it.getID()!!
|
it.getID()!!
|
||||||
|
@@ -91,7 +91,7 @@ object TournamentHandler: PairgothApiHandler {
|
|||||||
return Json.Object("success" to true)
|
return Json.Object("success" to true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validateTablesExclusion(exclusion: String) {
|
internal fun validateTablesExclusion(exclusion: String) {
|
||||||
if (!tablesExclusionValidator.matches(exclusion)) badRequest("invalid tables exclusion pattern")
|
if (!tablesExclusionValidator.matches(exclusion)) badRequest("invalid tables exclusion pattern")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,10 +6,12 @@ import com.republicate.kson.toJsonArray
|
|||||||
//import kotlinx.datetime.LocalDate
|
//import kotlinx.datetime.LocalDate
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
||||||
|
import org.jeudego.pairgoth.api.ApiHandler.Companion.logger
|
||||||
import org.jeudego.pairgoth.store.nextPlayerId
|
import org.jeudego.pairgoth.store.nextPlayerId
|
||||||
import org.jeudego.pairgoth.store.nextTournamentId
|
import org.jeudego.pairgoth.store.nextTournamentId
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
sealed class Tournament <P: Pairable>(
|
sealed class Tournament <P: Pairable>(
|
||||||
@@ -127,9 +129,12 @@ sealed class Tournament <P: Pairable>(
|
|||||||
fun renumberTables(round: Int, pivot: Game? = null, orderBY: (Game) -> Int = ::defaultGameOrderBy): Boolean {
|
fun renumberTables(round: Int, pivot: Game? = null, orderBY: (Game) -> Int = ::defaultGameOrderBy): Boolean {
|
||||||
var changed = false
|
var changed = false
|
||||||
var nextTable = 1
|
var nextTable = 1
|
||||||
|
val excluded = excludedTables(round)
|
||||||
games(round).values.filter{ game -> pivot?.let { pivot.id != game.id } ?: true }.sortedBy(orderBY).forEach { game ->
|
games(round).values.filter{ game -> pivot?.let { pivot.id != game.id } ?: true }.sortedBy(orderBY).forEach { game ->
|
||||||
|
while (excluded.contains(nextTable)) ++nextTable
|
||||||
if (pivot != null && nextTable == pivot.table) {
|
if (pivot != null && nextTable == pivot.table) {
|
||||||
++nextTable
|
++nextTable
|
||||||
|
while (excluded.contains(nextTable)) ++nextTable
|
||||||
}
|
}
|
||||||
if (game.table != 0) {
|
if (game.table != 0) {
|
||||||
changed = changed || game.table != nextTable
|
changed = changed || game.table != nextTable
|
||||||
@@ -150,6 +155,22 @@ sealed class Tournament <P: Pairable>(
|
|||||||
"ready" to (games.getOrNull(index)?.values?.count { it.result != Game.Result.UNKNOWN } ?: 0)
|
"ready" to (games.getOrNull(index)?.values?.count { it.result != Game.Result.UNKNOWN } ?: 0)
|
||||||
)
|
)
|
||||||
}.toJsonArray()
|
}.toJsonArray()
|
||||||
|
|
||||||
|
fun excludedTables(round: Int): Set<Int> {
|
||||||
|
if (round > tablesExclusion.size) return emptySet()
|
||||||
|
val excluded = mutableSetOf<Int>()
|
||||||
|
val parser = Regex("(\\d+)(?:-(\\d+))?")
|
||||||
|
parser.findAll(tablesExclusion[round - 1]).forEach { match ->
|
||||||
|
val left = match.groupValues[1].toInt()
|
||||||
|
val right = match.groupValues[2].let { if (it.isEmpty()) left else it.toInt() }
|
||||||
|
var t = left
|
||||||
|
do {
|
||||||
|
excluded.add(t)
|
||||||
|
++t
|
||||||
|
} while (t <= right)
|
||||||
|
}
|
||||||
|
return excluded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard tournament of individuals
|
// standard tournament of individuals
|
||||||
|
@@ -38,7 +38,14 @@ function unpair(games) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renumberTables() {
|
function renumberTables() {
|
||||||
api.putJson(`tour/${tour_id}/pair/${activeRound}`, {})
|
let payload = {}
|
||||||
|
let tablesExclusionControl = $('#exclude-tables');
|
||||||
|
let value = tablesExclusionControl[0].value;
|
||||||
|
let origValue = tablesExclusionControl.data('orig');
|
||||||
|
if (value !== origValue) {
|
||||||
|
payload['excludeTables'] = value;
|
||||||
|
}
|
||||||
|
api.putJson(`tour/${tour_id}/pair/${activeRound}`, payload)
|
||||||
.then(rst => {
|
.then(rst => {
|
||||||
if (rst !== 'error') {
|
if (rst !== 'error') {
|
||||||
document.location.reload();
|
document.location.reload();
|
||||||
|
Reference in New Issue
Block a user