feat(jogos): telão com contagem regressiva, jogadas lado a lado e resultado

- comando "telao" (validado: texto curto, tom, símbolos permitidos, até
  2 lados) e letreiro por cima do rosto: título enorme que estoura e
  pisca, as duas jogadas (VOCÊ ✊ × ✋ CARINHA), cor por resultado;
- pedra, papel e tesoura: 3, 2, 1 piscando, "JÁ!", o que ele leu da sua
  mão, "VENCI!!!" / "VOCÊ GANHOU!" / "EMPATE!" com placar e o campeão;
  quantos dedos e achou! também usam o telão;
- o cartão do painel mostra o mesmo destaque.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
julio
2026-10-11 22:33:09 -03:00
co-authored by Claude Opus 5.5
parent 3d954efc03
commit 82f9673692
6 changed files with 218 additions and 6 deletions
+29
View File
@@ -240,9 +240,38 @@ def ordem_de_comando(tipo, valor):
except (TypeError, ValueError):
raise ValueError("Segundos inválidos") from None
return "olhos %s %.1f" % (simbolo or "-", segundos)
if tipo == "telao": # letreiro grande por cima do rosto (jogos)
return "telao " + json.dumps(validar_telao(valor), ensure_ascii=False, separators=(",", ":"))
raise ValueError("Tipo de comando inválido")
TONS_TELAO = ("neutro", "eu", "voce", "empate", "conta")
def validar_telao(v):
"""{titulo, sub, tom, piscar, segundos, lados:[{rotulo, simbolo, nome}]} só com texto curto e símbolos permitidos."""
if not isinstance(v, dict):
raise ValueError("Telão inválido")
texto = lambda x, n: " ".join(str(x or "").split())[:n]
t = dict(titulo=texto(v.get("titulo"), 24), sub=texto(v.get("sub"), 80),
tom=v.get("tom") if v.get("tom") in TONS_TELAO else "neutro", piscar=v.get("piscar") is True)
try:
t["segundos"] = max(0.3, min(10.0, float(v.get("segundos", 2.5))))
except (TypeError, ValueError):
raise ValueError("Segundos inválidos") from None
lados = v.get("lados") or []
if not isinstance(lados, list) or len(lados) > 2:
raise ValueError("Lados inválidos")
t["lados"] = []
for l in lados:
if not isinstance(l, dict) or (l.get("simbolo") and l.get("simbolo") not in OLHOS_JOGO):
raise ValueError("Símbolo inválido no telão")
t["lados"].append(dict(rotulo=texto(l.get("rotulo"), 12), simbolo=l.get("simbolo") or "", nome=texto(l.get("nome"), 14)))
if not t["titulo"] and not t["lados"]:
raise ValueError("Telão vazio")
return t
class Handler(SimpleHTTPRequestHandler):
extensoes_map = {".html": "text/html; charset=utf-8",
".js": "text/javascript; charset=utf-8",