Webové počitadlo na LAN s historií her #2
No files matched your search
+10
-4
@@ -144,14 +144,20 @@ a { color: var(--ink); }
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheet tfoot td {
|
.sheet .totals td {
|
||||||
border-top: 2px solid var(--ink);
|
border-bottom: 2px solid var(--ink);
|
||||||
font-size: 2.1rem;
|
font-size: 2.1rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding-top: 0.7rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sheet tfoot .label { font-weight: 400; }
|
.sheet .totals .label { font-weight: 400; font-size: 0.85rem; }
|
||||||
|
|
||||||
|
.sheet .more td {
|
||||||
|
text-align: left;
|
||||||
|
color: var(--ink-soft);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-family: var(--font-ui);
|
||||||
|
}
|
||||||
|
|
||||||
/* --- nuly za sebou ------------------------------------------------------- */
|
/* --- nuly za sebou ------------------------------------------------------- */
|
||||||
|
|
||||||
|
|||||||
+20
-11
@@ -16,6 +16,20 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
{# Součty patří nahoru: po padesáti kolech by je jinak nikdo neviděl. #}
|
||||||
|
<tbody class="totals">
|
||||||
|
<tr>
|
||||||
|
<td class="label">Celkem</td>
|
||||||
|
{% for name in game.names %}
|
||||||
|
<td class="{{ 'marked' if name == current }}">
|
||||||
|
{{ totals[name]|cislo }}
|
||||||
|
{%- if streaks[name] %} <span class="ticks">{{ '✕' * streaks[name] }}</span>{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for row in rows %}
|
{% for row in rows %}
|
||||||
<tr>
|
<tr>
|
||||||
@@ -41,17 +55,12 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
{% if hidden %}
|
||||||
<tr>
|
<tr class="more">
|
||||||
<td class="label">Celkem</td>
|
<td class="label" colspan="{{ game.names|length + 1 }}">… a dalších {{ hidden|kola }}</td>
|
||||||
{% for name in game.names %}
|
|
||||||
<td class="{{ 'marked' if name == current }}">
|
|
||||||
{{ totals[name]|cislo }}
|
|
||||||
{%- if streaks[name] %} <span class="ticks">{{ '✕' * streaks[name] }}</span>{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
{% endif %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -191,3 +191,48 @@ def test_sin_slavy(client):
|
|||||||
|
|
||||||
def test_sin_slavy_bez_her(client):
|
def test_sin_slavy_bez_her(client):
|
||||||
assert "Rekordy přibudou po první hře" in text(client.get("/stats"))
|
assert "Rekordy přibudou po první hře" in text(client.get("/stats"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_zapisnik_zacina_nejnovejsim_kolem(client):
|
||||||
|
game_id = start_game(client, "Adam", final_score=99999)
|
||||||
|
for value in (111, 222, 333):
|
||||||
|
score(client, game_id, value)
|
||||||
|
|
||||||
|
panel = text(client.get(f"/board/{game_id}/panel"))
|
||||||
|
|
||||||
|
assert panel.index("333") < panel.index("222") < panel.index("111")
|
||||||
|
|
||||||
|
|
||||||
|
def test_soucty_jsou_nad_koly(client):
|
||||||
|
game_id = start_game(client, "Adam", final_score=99999)
|
||||||
|
score(client, game_id, 450)
|
||||||
|
|
||||||
|
panel = text(client.get(f"/board/{game_id}/panel"))
|
||||||
|
|
||||||
|
assert panel.index("Celkem") < panel.index(">450<")
|
||||||
|
|
||||||
|
|
||||||
|
def test_tabule_useka_starou_historii(client):
|
||||||
|
game_id = start_game(client, "Adam", final_score=999999)
|
||||||
|
for value in range(1, 31):
|
||||||
|
score(client, game_id, value * 10)
|
||||||
|
|
||||||
|
panel = text(client.get(f"/board/{game_id}/panel"))
|
||||||
|
|
||||||
|
assert "a dalších 15 kol" in panel
|
||||||
|
assert "300" in panel # nejnovější kolo tam je
|
||||||
|
assert ">150<" not in panel # patnácté odspodu už ne
|
||||||
|
|
||||||
|
|
||||||
|
def test_kratka_hra_nic_neuseka(client):
|
||||||
|
game_id = start_game(client, "Adam", final_score=99999)
|
||||||
|
score(client, game_id, 100)
|
||||||
|
|
||||||
|
assert "a dalších" not in text(client.get(f"/board/{game_id}/panel"))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("count, expected", [
|
||||||
|
(1, "1 kolo"), (2, "2 kola"), (4, "4 kola"), (5, "5 kol"), (22, "22 kol"),
|
||||||
|
])
|
||||||
|
def test_sklonovani_kol(count, expected):
|
||||||
|
assert web.kola(count) == expected
|
||||||
@@ -20,6 +20,10 @@ app = Flask(__name__)
|
|||||||
|
|
||||||
PORT = int(os.environ.get("DICE_PORT", 8000))
|
PORT = int(os.environ.get("DICE_PORT", 8000))
|
||||||
|
|
||||||
|
# Kolik kol tabule ukáže. Zbytek historie je na hráčích, ne na tabuli —
|
||||||
|
# ta má ukazovat stav, ne archiv.
|
||||||
|
BOARD_ROUNDS = 15
|
||||||
|
|
||||||
|
|
||||||
# --- připojení k databázi ---------------------------------------------------
|
# --- připojení k databázi ---------------------------------------------------
|
||||||
|
|
||||||
@@ -87,6 +91,15 @@ def datum(value: str) -> str:
|
|||||||
return f"{int(den[2])}. {int(den[1])}. {den[0]}"
|
return f"{int(den[2])}. {int(den[1])}. {den[0]}"
|
||||||
|
|
||||||
|
|
||||||
|
@app.template_filter("kola")
|
||||||
|
def kola(count: int) -> str:
|
||||||
|
if count == 1:
|
||||||
|
return "1 kolo"
|
||||||
|
if 2 <= count <= 4:
|
||||||
|
return f"{count} kola"
|
||||||
|
return f"{count} kol"
|
||||||
|
|
||||||
|
|
||||||
@app.template_filter("cislo")
|
@app.template_filter("cislo")
|
||||||
def cislo(value: int) -> str:
|
def cislo(value: int) -> str:
|
||||||
"""Tisíce se v češtině oddělují mezerou."""
|
"""Tisíce se v češtině oddělují mezerou."""
|
||||||
@@ -95,8 +108,11 @@ def cislo(value: int) -> str:
|
|||||||
|
|
||||||
# --- zápisník ---------------------------------------------------------------
|
# --- zápisník ---------------------------------------------------------------
|
||||||
|
|
||||||
def scoresheet(game: Game) -> list[dict]:
|
def scoresheet(game: Game) -> tuple[list[dict], int]:
|
||||||
"""Řádky zápisníku po kolech.
|
"""Řádky zápisníku po kolech, od nejnovějšího.
|
||||||
|
|
||||||
|
Naposledy odehrané kolo patří nahoru — po padesáti kolech by jinak bylo
|
||||||
|
to podstatné mimo obrazovku. Vrací i počet kol, která se nevešla.
|
||||||
|
|
||||||
Tahy zapsané před posledním vynulováním se přeškrtnou — přesně tak, jak
|
Tahy zapsané před posledním vynulováním se přeškrtnou — přesně tak, jak
|
||||||
by se škrtaly na papíře.
|
by se škrtaly na papíře.
|
||||||
@@ -118,19 +134,24 @@ def scoresheet(game: Game) -> list[dict]:
|
|||||||
})
|
})
|
||||||
rows.append({"round": number, "cells": cells})
|
rows.append({"round": number, "cells": cells})
|
||||||
|
|
||||||
return rows
|
rows.reverse()
|
||||||
|
hidden = max(0, len(rows) - BOARD_ROUNDS)
|
||||||
|
|
||||||
|
return rows[:BOARD_ROUNDS], hidden
|
||||||
|
|
||||||
|
|
||||||
def view(game: Game, game_id: int, row) -> dict:
|
def view(game: Game, game_id: int, row) -> dict:
|
||||||
"""Společný podklad pro zápisník i pro zadávací pohled."""
|
"""Společný podklad pro zápisník i pro zadávací pohled."""
|
||||||
totals = game.totals()
|
totals = game.totals()
|
||||||
winner = row["winner_name"] if row["status"] == storage.STATUS_FINISHED else ""
|
winner = row["winner_name"] if row["status"] == storage.STATUS_FINISHED else ""
|
||||||
|
rows, hidden = scoresheet(game)
|
||||||
return {
|
return {
|
||||||
"game": game,
|
"game": game,
|
||||||
"game_id": game_id,
|
"game_id": game_id,
|
||||||
"row": row,
|
"row": row,
|
||||||
"totals": totals,
|
"totals": totals,
|
||||||
"rows": scoresheet(game),
|
"rows": rows,
|
||||||
|
"hidden": hidden,
|
||||||
"streaks": {name: game.zero_streak(name) for name in game.names},
|
"streaks": {name: game.zero_streak(name) for name in game.names},
|
||||||
"standings": game.standings(),
|
"standings": game.standings(),
|
||||||
"winner": winner,
|
"winner": winner,
|
||||||
|
|||||||
Reference in new issue
Block a user