Table renumbering ; various bugfixes and enhancements
This commit is contained in:
@@ -16,7 +16,7 @@ interface PairgothApiHandler: ApiHandler {
|
||||
fun Tournament<*>.dispatchEvent(event: Event, data: Json? = null) {
|
||||
Event.dispatch(event, Json.Object("tournament" to id, "data" to data))
|
||||
// when storage is not in memory, the tournament has to be persisted
|
||||
if (event != Event.tournamentAdded && event != Event.tournamentDeleted)
|
||||
if (event != Event.TournamentAdded && event != Event.TournamentDeleted)
|
||||
Store.replaceTournament(this)
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,6 @@ import org.jeudego.pairgoth.model.Game
|
||||
import org.jeudego.pairgoth.model.getID
|
||||
import org.jeudego.pairgoth.model.toID
|
||||
import org.jeudego.pairgoth.model.toJson
|
||||
import org.jeudego.pairgoth.server.Event
|
||||
import org.jeudego.pairgoth.server.Event.*
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
@@ -59,7 +58,7 @@ object PairingHandler: PairgothApiHandler {
|
||||
}
|
||||
val games = tournament.pair(round, pairables)
|
||||
val ret = games.map { it.toJson() }.toJsonArray()
|
||||
tournament.dispatchEvent(gamesAdded, Json.Object("round" to round, "games" to ret))
|
||||
tournament.dispatchEvent(GamesAdded, Json.Object("round" to round, "games" to ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -78,6 +77,7 @@ object PairingHandler: PairgothApiHandler {
|
||||
game.black = payload.getID("b") ?: badRequest("missing black player id")
|
||||
game.white = payload.getID("w") ?: badRequest("missing white player id")
|
||||
tournament.recomputeDUDD(round, game.id)
|
||||
val previousTable = game.table;
|
||||
// temporary
|
||||
payload.getInt("dudd")?.let { game.drawnUpDown = it }
|
||||
val black = tournament.pairables[game.black] ?: badRequest("invalid black player id")
|
||||
@@ -90,10 +90,15 @@ object PairingHandler: PairgothApiHandler {
|
||||
if (playing.contains(white.id)) badRequest("white is already in another game")
|
||||
if (payload.containsKey("h")) game.handicap = payload.getString("h")?.toIntOrNull() ?: badRequest("invalid handicap")
|
||||
if (payload.containsKey("t")) {
|
||||
// TODO CB - update *all* tables numbers accordingly
|
||||
game.table = payload.getString("t")?.toIntOrNull() ?: badRequest("invalid table number")
|
||||
}
|
||||
tournament.dispatchEvent(gameUpdated, Json.Object("round" to round, "game" to game.toJson()))
|
||||
tournament.dispatchEvent(GameUpdated, Json.Object("round" to round, "game" to game.toJson()))
|
||||
if (game.table != previousTable && tournament.renumberTables(round, game)) {
|
||||
val games = tournament.games(round).values.sortedBy {
|
||||
if (it.table == 0) Int.MAX_VALUE else it.table
|
||||
}
|
||||
tournament.dispatchEvent(TablesRenumbered, Json.Object("round" to round, "games" to games.map { it.toJson() }.toCollection(Json.MutableArray())))
|
||||
}
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
|
||||
@@ -111,7 +116,7 @@ object PairingHandler: PairgothApiHandler {
|
||||
payload.forEach {
|
||||
val id = (it as Number).toInt()
|
||||
val game = tournament.games(round)[id] ?: throw Error("invalid game id")
|
||||
if (game.result != Game.Result.UNKNOWN) {
|
||||
if (game.result != Game.Result.UNKNOWN && game.black != 0 && game.white != 0) {
|
||||
ApiHandler.logger.error("cannot unpair game id ${game.id}: it has a result")
|
||||
// we'll only skip it
|
||||
// throw Error("cannot unpair ")
|
||||
@@ -120,7 +125,7 @@ object PairingHandler: PairgothApiHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
tournament.dispatchEvent(gamesDeleted, Json.Object("round" to round, "games" to payload))
|
||||
tournament.dispatchEvent(GamesDeleted, Json.Object("round" to round, "games" to payload))
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import com.republicate.kson.toJsonArray
|
||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
||||
import org.jeudego.pairgoth.model.Player
|
||||
import org.jeudego.pairgoth.model.fromJson
|
||||
import org.jeudego.pairgoth.server.Event
|
||||
import org.jeudego.pairgoth.server.Event.*
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
@@ -25,7 +24,7 @@ object PlayerHandler: PairgothApiHandler {
|
||||
val payload = getObjectPayload(request)
|
||||
val player = Player.fromJson(payload)
|
||||
tournament.players[player.id] = player
|
||||
tournament.dispatchEvent(playerAdded, player.toJson())
|
||||
tournament.dispatchEvent(PlayerAdded, player.toJson())
|
||||
return Json.Object("success" to true, "id" to player.id)
|
||||
}
|
||||
|
||||
@@ -36,7 +35,7 @@ object PlayerHandler: PairgothApiHandler {
|
||||
val payload = getObjectPayload(request)
|
||||
val updated = Player.fromJson(payload, player)
|
||||
tournament.players[updated.id] = updated
|
||||
tournament.dispatchEvent(playerUpdated, player.toJson())
|
||||
tournament.dispatchEvent(PlayerUpdated, player.toJson())
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ object PlayerHandler: PairgothApiHandler {
|
||||
val tournament = getTournament(request)
|
||||
val id = getSubSelector(request)?.toIntOrNull() ?: badRequest("missing or invalid player selector")
|
||||
tournament.players.remove(id) ?: badRequest("invalid player id")
|
||||
tournament.dispatchEvent(playerDeleted, Json.Object("id" to id))
|
||||
tournament.dispatchEvent(PlayerDeleted, Json.Object("id" to id))
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ object ResultsHandler: PairgothApiHandler {
|
||||
val payload = getObjectPayload(request)
|
||||
val game = tournament.games(round)[payload.getInt("id")] ?: badRequest("invalid game id")
|
||||
game.result = Game.Result.fromSymbol(payload.getChar("result") ?: badRequest("missing result"))
|
||||
tournament.dispatchEvent(Event.resultUpdated, Json.Object("round" to round, "data" to game))
|
||||
tournament.dispatchEvent(Event.ResultUpdated, Json.Object("round" to round, "data" to game))
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import com.republicate.kson.Json
|
||||
import com.republicate.kson.toJsonArray
|
||||
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
|
||||
import org.jeudego.pairgoth.model.TeamTournament
|
||||
import org.jeudego.pairgoth.server.Event
|
||||
import org.jeudego.pairgoth.server.Event.*
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletResponse
|
||||
@@ -26,7 +25,7 @@ object TeamHandler: PairgothApiHandler {
|
||||
val payload = getObjectPayload(request)
|
||||
val team = tournament.teamFromJson(payload)
|
||||
tournament.teams[team.id] = team
|
||||
tournament.dispatchEvent(teamAdded, team.toJson())
|
||||
tournament.dispatchEvent(TeamAdded, team.toJson())
|
||||
return Json.Object("success" to true, "id" to team.id)
|
||||
}
|
||||
|
||||
@@ -38,7 +37,7 @@ object TeamHandler: PairgothApiHandler {
|
||||
val payload = getObjectPayload(request)
|
||||
val updated = tournament.teamFromJson(payload, team)
|
||||
tournament.teams[updated.id] = updated
|
||||
tournament.dispatchEvent(teamUpdated, team.toJson())
|
||||
tournament.dispatchEvent(TeamUpdated, team.toJson())
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
|
||||
@@ -47,7 +46,7 @@ object TeamHandler: PairgothApiHandler {
|
||||
if (tournament !is TeamTournament) badRequest("tournament is not a team tournament")
|
||||
val id = getSubSelector(request)?.toIntOrNull() ?: badRequest("missing or invalid team selector")
|
||||
tournament.teams.remove(id) ?: badRequest("invalid team id")
|
||||
tournament.dispatchEvent(teamDeleted, Json.Object("id" to id))
|
||||
tournament.dispatchEvent(TeamDeleted, Json.Object("id" to id))
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ import org.jeudego.pairgoth.model.fromJson
|
||||
import org.jeudego.pairgoth.model.toJson
|
||||
import org.jeudego.pairgoth.store.Store
|
||||
import org.jeudego.pairgoth.server.ApiServlet
|
||||
import org.jeudego.pairgoth.server.Event
|
||||
import org.jeudego.pairgoth.server.Event.*
|
||||
import org.w3c.dom.Element
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
@@ -44,7 +43,7 @@ object TournamentHandler: PairgothApiHandler {
|
||||
else -> badRequest("missing or invalid payload")
|
||||
}
|
||||
Store.addTournament(tournament)
|
||||
tournament.dispatchEvent(tournamentAdded, tournament.toJson())
|
||||
tournament.dispatchEvent(TournamentAdded, tournament.toJson())
|
||||
return Json.Object("success" to true, "id" to tournament.id)
|
||||
}
|
||||
|
||||
@@ -64,14 +63,14 @@ object TournamentHandler: PairgothApiHandler {
|
||||
clear()
|
||||
putAll(tournament.games(round))
|
||||
}
|
||||
updated.dispatchEvent(tournamentUpdated, updated.toJson())
|
||||
updated.dispatchEvent(TournamentUpdated, updated.toJson())
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
|
||||
override fun delete(request: HttpServletRequest): Json {
|
||||
val tournament = getTournament(request)
|
||||
Store.deleteTournament(tournament)
|
||||
tournament.dispatchEvent(tournamentDeleted, Json.Object("id" to tournament.id))
|
||||
tournament.dispatchEvent(TournamentDeleted, Json.Object("id" to tournament.id))
|
||||
return Json.Object("success" to true)
|
||||
}
|
||||
}
|
||||
|
@@ -90,6 +90,23 @@ sealed class Tournament <P: Pairable>(
|
||||
val blackplayer = solver.pairables.find { p-> p.id == game.black }!!
|
||||
game.drawnUpDown = solver.dudd(blackplayer, whiteplayer)
|
||||
}
|
||||
|
||||
fun renumberTables(round: Int, pivot: Game? = null): Boolean {
|
||||
var changed = false
|
||||
var nextTable = 1
|
||||
games(round).values.filter{ game -> pivot?.let { pivot.id != game.id } ?: true }.sortedBy { game ->
|
||||
val whiteRank = pairables[game.white]?.rating ?: Int.MIN_VALUE
|
||||
val blackRank = pairables[game.black]?.rating ?: Int.MIN_VALUE
|
||||
-(2 * whiteRank + 2 * blackRank) / 2
|
||||
}.forEach { game ->
|
||||
if (pivot != null && nextTable == pivot.table) {
|
||||
++nextTable
|
||||
}
|
||||
changed = changed || game.table != nextTable
|
||||
game.table = nextTable++
|
||||
}
|
||||
return changed
|
||||
}
|
||||
}
|
||||
|
||||
// standard tournament of individuals
|
||||
|
@@ -4,19 +4,20 @@ import info.macias.sse.events.MessageEvent
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
enum class Event {
|
||||
tournamentAdded,
|
||||
tournamentUpdated,
|
||||
tournamentDeleted,
|
||||
playerAdded,
|
||||
playerUpdated,
|
||||
playerDeleted,
|
||||
teamAdded,
|
||||
teamUpdated,
|
||||
teamDeleted,
|
||||
gamesAdded,
|
||||
gamesDeleted,
|
||||
gameUpdated,
|
||||
resultUpdated,
|
||||
TournamentAdded,
|
||||
TournamentUpdated,
|
||||
TournamentDeleted,
|
||||
PlayerAdded,
|
||||
PlayerUpdated,
|
||||
PlayerDeleted,
|
||||
TeamAdded,
|
||||
TeamUpdated,
|
||||
TeamDeleted,
|
||||
GamesAdded,
|
||||
GamesDeleted,
|
||||
GameUpdated,
|
||||
ResultUpdated,
|
||||
TablesRenumbered
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
@@ -45,4 +45,17 @@ class PairgothTool {
|
||||
"SDC" to "Simplified direct confrontation", // Simplified direct confrontation
|
||||
"DC" to "Direct confrontation", // Direct confrontation
|
||||
)
|
||||
|
||||
fun getResultsStats(games: Collection<Json.Object>): Json.Object {
|
||||
var total = 0
|
||||
var known = 0
|
||||
games
|
||||
.filter{ it.getInt("b")!! != 0 && it.getInt("w")!! != 0 }
|
||||
.map { it -> it.getString("r") }
|
||||
.forEach {
|
||||
++total
|
||||
if ("?" != it) ++known
|
||||
}
|
||||
return Json.Object("total" to total, "known" to known)
|
||||
}
|
||||
}
|
@@ -425,6 +425,9 @@
|
||||
font-size: 1rem !important;
|
||||
line-height: 1.1rem !important;
|
||||
min-width: 60vw;
|
||||
&::before {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -145,5 +145,6 @@ the configuration guide le guide de configuration
|
||||
to à
|
||||
unpairable players joueurs non disponibles
|
||||
version 0.1 supports the version 0.1 supporte le système d’appariement
|
||||
white blanc
|
||||
white vs. black blanc vs. Noir
|
||||
confirmed. confirmé(s).
|
@@ -1,4 +1,4 @@
|
||||
function setResult(id, result) {
|
||||
function setResult(id, result, previous) {
|
||||
api.putJson(`tour/${tour_id}/res/${activeRound}`, { id: id, result: result })
|
||||
.then(res => {
|
||||
if (res !== 'error') {
|
||||
@@ -19,6 +19,16 @@ function setResult(id, result) {
|
||||
let resultCell = row.find('td.result');
|
||||
resultCell.text(dispResult).data('result', result);
|
||||
standingsUpToDate = false;
|
||||
|
||||
if (previous === '?') {
|
||||
let indicator = $('#known')[0];
|
||||
let known = parseInt(indicator.innerText);
|
||||
indicator.innerText = ++known;
|
||||
} else if (result === '?') {
|
||||
let indicator = $('#known')[0];
|
||||
let known = parseInt(indicator.innerText);
|
||||
indicator.innerText = --known;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -36,9 +46,9 @@ onLoad(()=>{
|
||||
$('#results-table .result').on('click', e => {
|
||||
let cell = e.target.closest('.result');
|
||||
let gameId = e.target.closest('tr').data('id');
|
||||
let result = cell.data('result');
|
||||
let index = results.indexOf(result);
|
||||
result = results[(index + 1)%results.length];
|
||||
setResult(gameId, result);
|
||||
let oldResult = cell.data('result');
|
||||
let index = results.indexOf(oldResult);
|
||||
let newResult = results[(index + 1)%results.length];
|
||||
setResult(gameId, newResult, oldResult);
|
||||
});
|
||||
});
|
||||
|
@@ -4,6 +4,8 @@
|
||||
<button class="ui floating choose-round prev-round button">«</button>
|
||||
<span class="active-round">$round</span>
|
||||
<button class="ui floating choose-round next-round button">»</button>
|
||||
#set($stats = $utils.getResultsStats($games))
|
||||
<span class="norbeak"><span id="known">$stats.known</span> / $stats.total</span>
|
||||
</div>
|
||||
<div id="results-list" class="roundbox">
|
||||
<table id="results-table" class="ui celled striped table">
|
||||
@@ -23,7 +25,7 @@
|
||||
<td>#$game.t</td>
|
||||
<td class="white player #if($game.r == 'w' || $game.r == '#') winner #elseif($game.r == 'b' || $game.r == '0') looser #end" data-id="$white.id" data-sort="$white.name $white.firstname"><span>#if($white)$white.name $white.firstname #rank($white.rank)#{else}BIP#end</span></td>
|
||||
<td class="black player #if($game.r == 'b' || $game.r == '#') winner #elseif($game.r == 'w' || $game.r == '0') looser #end" data-id="$black.id" data-sort="$black.name $black.firstname"><span>#if($black)$black.name $black.firstname #rank($black.rank)#{else}BIP#end</span></td>
|
||||
<td class="result centered" data-result="$game.r">$dispRst[$game.r]</td>
|
||||
<td class="result centered" data-sort="$game.r" data-result="$game.r">$dispRst[$game.r]</td>
|
||||
</tr>
|
||||
#end
|
||||
#end
|
||||
|
Reference in New Issue
Block a user