Add a tournament overview dialog

This commit is contained in:
Claude Brisson
2024-04-13 23:15:42 +02:00
parent 9e09a0edef
commit 7837daf973
6 changed files with 85 additions and 3 deletions

View File

@@ -30,7 +30,9 @@ object TournamentHandler: PairgothApiHandler {
if (accept == "application/pairgoth") { if (accept == "application/pairgoth") {
it.toFullJson() it.toFullJson()
} else { } else {
it.toJson() it.toJson().also { json ->
(json as Json.MutableObject)["stats"] = it.stats()
}
} }
} ?: badRequest("no tournament with id #${id}") } ?: badRequest("no tournament with id #${id}")
} }

View File

@@ -120,6 +120,15 @@ sealed class Tournament <P: Pairable>(
fun pairedPlayers() = games.flatMap { it.values }.flatMap { listOf(it.black, it.white) }.toSet() fun pairedPlayers() = games.flatMap { it.values }.flatMap { listOf(it.black, it.white) }.toSet()
fun hasPlayer(dbId: DatabaseId, pId: String) = pId.isNotBlank() && players.values.filter { player -> pId == player.externalIds[dbId] }.isNotEmpty() fun hasPlayer(dbId: DatabaseId, pId: String) = pId.isNotBlank() && players.values.filter { player -> pId == player.externalIds[dbId] }.isNotEmpty()
fun stats() = (0..rounds - 1).map { index ->
Json.Object(
"participants" to pairables.values.count { !it.skip.contains(index + 1) },
"paired" to (games.getOrNull(index)?.values?.flatMap { listOf(it.black, it.white) }?.count { it != 0 } ?: 0),
"games" to (games.getOrNull(index)?.values?.count() ?: 0),
"ready" to (games.getOrNull(index)?.values?.count { it.result != Game.Result.UNKNOWN } ?: 0)
)
}.toJsonArray()
} }
// standard tournament of individuals // standard tournament of individuals
@@ -257,7 +266,7 @@ fun Tournament.Companion.fromJson(json: Json.Object, default: Tournament<*>? = n
return tournament return tournament
} }
fun Tournament<*>.toJson() = Json.Object( fun Tournament<*>.toJson() = Json.MutableObject(
"id" to id, "id" to id,
"type" to type.name, "type" to type.name,
"name" to name, "name" to name,

View File

@@ -532,11 +532,12 @@
} }
#title { #title {
position: relative;
font-size: 1rem !important; font-size: 1rem !important;
margin-top: 0.1em !important; margin-top: 0.1em !important;
} }
#logo, #lang, .steps, #filter-box, #reglist-mode, #footer, #unpairables, #pairing-buttons, button, #standings-params, #logout, .pairing-stats, .result-sheets, .toggle { #logo, #lang, .steps, #filter-box, #reglist-mode, #footer, #unpairables, #pairing-buttons, button, #standings-params, #logout, .pairing-stats, .result-sheets, .toggle, #overview {
display: none !important; display: none !important;
} }

View File

@@ -16,6 +16,29 @@
font-weight: bold; font-weight: bold;
} }
#overview {
position: absolute;
top: 0.2em;
right: 0.5em;
z-index: 2;
button {
line-height: 0.6em;
}
transform: scale(0.65);
}
#tournament-overview table {
table-layout: fixed;
text-align: center;
border-collapse: collapse;
th, td {
border: solid 1px gray;
}
th {
padding: 0 0.5em;
}
}
/* information section */ /* information section */
form { form {

View File

@@ -24,10 +24,18 @@ function setResult(id, result, previous) {
let indicator = $('#known')[0]; let indicator = $('#known')[0];
let known = parseInt(indicator.innerText); let known = parseInt(indicator.innerText);
indicator.innerText = ++known; indicator.innerText = ++known;
// and again for overview
indicator = $('#known2')[0];
known = parseInt(indicator.innerText);
indicator.innerText = ++known;
} else if (result === '?') { } else if (result === '?') {
let indicator = $('#known')[0]; let indicator = $('#known')[0];
let known = parseInt(indicator.innerText); let known = parseInt(indicator.innerText);
indicator.innerText = --known; indicator.innerText = --known;
// and again for overview
indicator = $('#known2')[0];
known = parseInt(indicator.innerText);
indicator.innerText = --known;
} }
} }
}) })

View File

@@ -32,6 +32,7 @@
#if($tour) #if($tour)
<h1 id="title"> <h1 id="title">
$esc.html($tour.name) $esc.html($tour.name)
<div id="overview"><button class="ui mini green circular icon floating button"><i class="ui small info icon"></i></button></div>
</h1> </h1>
#end #end
#translate('tour-information.inc.html') #translate('tour-information.inc.html')
@@ -153,6 +154,9 @@
} }
}); });
} }
$('#overview').on('click', () => {
modal('tournament-overview')
});
}); });
// ]]# // ]]#
#include('/js/tour-information.inc.js') #include('/js/tour-information.inc.js')
@@ -174,3 +178,38 @@
vertical-align: initial; vertical-align: initial;
} }
</style> </style>
#if($tour)
<div id="tournament-overview" class="popup">
<div class="popup-body">
<div class="popup-content">
<table>
<thead>
<tr>
<th>Round</th>
<th>Participants</th>
<th>Paired</th>
<th>Results</th>
</tr>
</thead>
<tbody>
#foreach($r in [1..$tour.rounds])
#set($stats = $tour.stats[$r - 1])
<tr>
<td>$r</td>
<td>$stats.participants</td>
<td>$stats.paired</td>
<td>#if($round == $r)<span id="known2">#end$stats.ready#if($round == $r)</span>#end/$stats.games</td>
</tr>
#end
</tbody>
</table>
</div>
<div class="popup-footer">
<button type="button" class="ui gray right labeled icon floating close button">
<i class="times icon"></i>
Close
</button>
</div>
</div>
</div>
#end