feat: clock + place games

This commit is contained in:
2026-09-17 01:33:54 +02:00
parent d104480188
commit 6866b45f66
46 changed files with 2043 additions and 10 deletions
+33
View File
@@ -0,0 +1,33 @@
"""Compact wire format for the clock websocket.
JSON's braces/quotes/keys are pure overhead for messages this small and this
frequent (a heartbeat every second, to every connection). Each message is
instead a short string: a one-letter type tag followed by '|'-separated
fields, in a fixed order the client already knows from this table (missing/
null fields are written as an empty segment):
s|<end>|<now>|<duration>|<bonus>|<next> initial state, once per connection
t|<end>|<now>|<pressed> shared timer update ("pressed" is "1" or "")
k|<next>|<now> your press was accepted
r|c|<next>|<now> your press was rejected: on cooldown
r|a your press was rejected: not logged in
Client -> server has exactly one message, sent as the bare literal "press"
(no fields, so no delimiter needed).
Whether the game is enabled at all for this event (EventGame.enabled) is
checked once, at connect time - a connection is refused outright rather than
accepted-but-disabled, so there's no "disabled" case in this wire format.
"""
DELIMITER = "|"
def encode(*parts) -> str:
return DELIMITER.join("" if p is None else str(p) for p in parts)
def to_epoch_ms(dt) -> int:
"""Epoch-ms integer: far cheaper than an ISO-8601 string and needs no
client-side parsing (the frontend already does its clock math in epoch ms)."""
return int(dt.timestamp() * 1000)