feat(jogos): pedra, papel e tesoura, quantos dedos e achou! com a mão

- lib/maos.ts: dedos esticados pelos 21 pontos do MediaPipe (vale em
  qualquer rotação), contagem, jogada e leitura estável (mão parada);
- lib/jogos.svelte.ts: os três jogos conversam com o Carinha por comandos
  (fala com legenda, gestos e símbolo nos olhos) e contam como brincadeira
  para o modo vida; cartão "Jogos com a mão" no Ao vivo liga a câmera e o
  rastreamento com um toque;
- servidor: comandos "dizer" (até 120 caracteres) e "olhos" (símbolos e
  números permitidos, 0,5 a 8 s); rosto mostra o símbolo nos olhos.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
julio
2026-10-11 19:53:48 -03:00
co-authored by Claude Opus 5.5
parent 92701e8a16
commit 3d954efc03
10 changed files with 479 additions and 1 deletions
+12
View File
@@ -81,6 +81,18 @@ class ServidorTest(unittest.TestCase):
self.assertEqual(self.pedir('GET', '/app/health', token=None)[0], 200)
self.assertEqual(self.pedir('GET', '/estado?t=' + TOKEN, token=None)[0], 200)
def test_comandos_dos_jogos_falar_e_olhos(self):
self.assertEqual(kiosk.ordem_de_comando('dizer', ' Pedra... '), 'dizer Pedra...')
self.assertEqual(kiosk.ordem_de_comando('olhos', {'simbolo': '✌️', 'segundos': 3}), 'olhos ✌️ 3.0')
self.assertEqual(kiosk.ordem_de_comando('olhos', {'simbolo': '3', 'segundos': 99}), 'olhos 3 8.0')
self.assertEqual(kiosk.ordem_de_comando('olhos', {}), 'olhos - 2.5')
for tipo, valor in (('olhos', {'simbolo': '<b>'}), ('olhos', {'simbolo': '1', 'segundos': 'x'}), ('dizer', ' ')):
with self.assertRaises(ValueError):
kiosk.ordem_de_comando(tipo, valor)
codigo, _ = self.pedir('POST', '/comando', {'tipo': 'dizer', 'valor': 'Já!'})
self.assertEqual(codigo, 200)
self.assertIn('dizer Já!', kiosk.FILA.ordens())
def test_pagina_do_rosto_sempre_conferida_e_api_sem_cache(self):
# o WebView do celular não pode seguir com uma carinha.html velha depois de um deploy
for rota, esperado in (('/carinha.html', 'no-cache'), ('/gestos', 'no-store')):