Files
gitea-actionsandClaude Opus 5 d7c63cf98b stats: síň slávy a kariérní statistiky
- rekordy: nejvyšší tah, nejvyšší konečné skóre, nejrychlejší výhra
- kariéra: počet her, výher, úspěšnost, průměrné pořadí, průměr na tah
  a kolikrát koho postihlo vynulování
- do statistik jdou jen dohrané hry, nedohrané a opuštěné se ignorují
- celkové skóre počítá SQL stejným pravidlem jako core.Game.totals(),
  tedy součet tahů po posledním vynulování; testem ověřeno, že se obě
  cesty shodují
- vědomě chybí celkový součet bodů napříč hrami — cílové skóre je u každé
  hry jiné, metrika by odměňovala jen toho, kdo hrál nejvíc
- README se spuštěním a přehledem modulů

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 19:04:50 +02:00

113 lines
3.3 KiB
HTML

{% extends "base.html" %}
{% block title %}Nová hra{% endblock %}
{% block body %}
<div class="phone">
<header class="masthead">
<div>
<p class="eyebrow">Počitadlo</p>
<h1>Kostky</h1>
</div>
</header>
{% if request.args.get('chyba') %}
<p class="error">{{ request.args.get('chyba') }}</p>
{% endif %}
{% if running %}
<div class="notice">
<span>Rozehraná hra {{ running }} čeká.</span>
<a href="{{ url_for('game_view', game_id=running) }}">Pokračovat</a>
</div>
{% endif %}
<form method="post" action="{{ url_for('new_game') }}">
<p class="eyebrow">Kdo hraje</p>
<p class="hint">Ťukej jména v pořadí, jak sedíte kolem stolu.</p>
<div class="chips" id="chips">
{% for player in players %}
<button type="button" class="chip" aria-pressed="false" data-name="{{ player.name }}">
{{ player.name }}<span class="seat"></span>
</button>
{% endfor %}
</div>
<div class="add-player">
<input type="text" id="new-name" placeholder="Nový hráč" autocomplete="off">
<button type="button" id="add">Přidat</button>
</div>
<div class="field" style="margin-top: 1.5rem">
<label for="final">Cílové skóre</label>
<input type="number" name="final_score" id="final" value="{{ final_score }}" inputmode="numeric">
</div>
<div id="chosen"></div>
<button class="btn" type="submit">Začít hru</button>
</form>
<p class="footer">
<a href="{{ url_for('board_redirect') }}">Zápisník</a>
<a href="{{ url_for('hall') }}">Síň slávy</a>
</p>
</div>
<script>
const chips = document.getElementById("chips");
const chosen = [];
function render() {
for (const chip of chips.querySelectorAll(".chip")) {
const seat = chosen.indexOf(chip.dataset.name);
chip.setAttribute("aria-pressed", seat > -1);
chip.querySelector(".seat").textContent = seat > -1 ? seat + 1 : "";
}
// Pořadí odeslaných polí je pořadí u stolu.
document.getElementById("chosen").replaceChildren(...chosen.map(name => {
const field = document.createElement("input");
field.type = "hidden";
field.name = "player";
field.value = name;
return field;
}));
}
chips.addEventListener("click", event => {
const chip = event.target.closest(".chip");
if (!chip) return;
const seat = chosen.indexOf(chip.dataset.name);
if (seat > -1) chosen.splice(seat, 1);
else chosen.push(chip.dataset.name);
render();
});
const field = document.getElementById("new-name");
function addPlayer() {
const name = field.value.trim();
if (!name) return;
if (!chips.querySelector(`[data-name="${CSS.escape(name)}"]`)) {
const chip = document.createElement("button");
chip.type = "button";
chip.className = "chip";
chip.dataset.name = name;
chip.append(name, Object.assign(document.createElement("span"), { className: "seat" }));
chips.append(chip);
}
if (!chosen.includes(name)) chosen.push(name);
field.value = "";
render();
}
document.getElementById("add").addEventListener("click", addPlayer);
field.addEventListener("keydown", event => {
if (event.key === "Enter") { event.preventDefault(); addPlayer(); }
});
</script>
{% endblock %}