Files
carinha-control-panel/tests/test_aprendizado.py
T
julioandClaude Opus 5.5 a99aa897c4 feat(vida): horário de dormir acompanha a rotina da casa e lição honesta
- A lição da rotina separa o que cai na madrugada: "das 10h às 23h vou
  estar acordado; das 23h à 1h é a minha hora de dormir, fico quietinho
  a não ser que alguém me chame" (antes prometia ficar acordado de
  madrugada, o que nunca acontecia).
- Com 5+ dias de rotina, na virada do dia ele mexe sozinho no horário
  da madrugada: atrasa o início se a primeira hora costuma ter gente,
  adianta o fim se a casa acorda cedo; 1 h por noite, no máximo 3 h
  depois / 2 h antes do que a pessoa escolheu, nunca menos de 5 h de
  madrugada, e volta quando as horas esvaziam. Mudança à mão vira a
  nova base. Fica no diário e no "Dia a dia"; liga/desliga no cartão.
- Faixas que passam da meia-noite viram uma só ("das 23h à 1h").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:47:26 -03:00

504 lines
24 KiB
Python

"""Aprendizado com o dia a dia: gosto pelos atos, rotina da casa, sono e o fechamento do dia."""
import http.client
import importlib.util
import json
import random
import sys
import tempfile
import threading
import time
import unittest
from datetime import date, timedelta
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from aprendizado import Aprendizado # noqa: E402
from vida import Vida # noqa: E402
spec = importlib.util.spec_from_file_location('kiosk_aprendizado', ROOT / 'kiosk-server.py')
kiosk = importlib.util.module_from_spec(spec)
spec.loader.exec_module(kiosk)
def em(dia, hora, minuto=0, segundo=0):
return time.mktime((2026, 10, dia, hora, minuto, segundo, 0, 0, -1))
class AprendizadoTest(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.caminho = Path(self.tmp.name) / 'aprendizado.json'
self.a = Aprendizado(self.caminho)
self.a.hoje = self.a._dia_vazio('2026-10-06')
self.diario = []
self.a.anotar = lambda tipo, texto, agora=None: self.diario.append((tipo, texto))
def tearDown(self):
self.tmp.cleanup()
def fazer(self, nome, vezes, resposta=None, inicio=None):
t = inicio or em(6, 15)
for i in range(vezes):
self.a.ato(nome, t + i * 120, perto=True)
if resposta:
self.a.resposta(resposta, t + i * 120 + 20)
def test_gosto_sobe_com_carinho_e_desce_quando_ignorado(self):
self.fazer('rir', 5, 'carinho')
self.fazer('bocejar', 5, inicio=em(6, 16))
self.assertGreater(self.a.peso('rir'), 1.0)
self.assertLess(self.a.peso('bocejar'), 1.0)
self.assertLessEqual(self.a.peso('rir'), 2.0)
self.assertGreaterEqual(self.a.peso('bocejar'), 0.5)
def test_sem_opiniao_com_poucas_tentativas_ou_sozinho(self):
self.fazer('rir', 2, 'carinho')
self.assertEqual(self.a.peso('rir'), 1.0)
for i in range(10):
self.a.ato('pensar', em(6, 15) + i, perto=False) # sem plateia ninguém pode gostar
self.assertEqual(self.a.peso('pensar'), 1.0)
self.assertNotIn('pensar', self.a.itens)
def test_resposta_fora_da_janela_nao_conta(self):
for i in range(4):
self.a.ato('acenar', em(6, 15) + i * 300, perto=True)
self.a.resposta('carinho', em(6, 15) + i * 300 + 200) # 200 s depois: já era outra coisa
self.assertEqual(self.a.itens['acenar']['s'], 0)
def test_cada_ato_agrada_uma_vez(self):
self.a.ato('rir', em(6, 15), perto=True)
for _ in range(5):
self.a.resposta('carinho', em(6, 15) + 10)
self.assertEqual(self.a.itens['rir']['s'], 1.0)
def test_fechar_o_dia_gera_licoes_e_esquece_um_pouco(self):
self.fazer('rir', 4, 'carinho')
self.fazer('bocejar', 5, inicio=em(6, 17))
t_antes = self.a.itens['rir']['t']
self.a.observar(em(7, 0, 1), perto=False) # meia-noite: fecha o dia 6
textos = [t for _, t in self.diario]
self.assertTrue(any('gostam de me ver dar risada' in t for t in textos), textos)
self.assertTrue(any('Tentei bocejar 5 vezes e ninguém ligou' in t for t in textos), textos)
self.assertAlmostEqual(self.a.itens['rir']['t'], t_antes * 0.85, places=2)
self.assertEqual(self.a.hoje['dia'], '2026-10-07')
self.assertTrue(self.caminho.exists())
def test_rotina_da_casa_e_acordar_antes_de_chegarem(self):
for dia in (6, 7, 8):
for minuto in range(60):
self.a.observar(em(dia, 17, minuto), perto=False) # 17h: casa vazia
self.a.observar(em(dia, 18, minuto), perto=True) # 18h: chegou gente
self.a.observar(em(9, 0, 1), perto=False)
self.assertGreaterEqual(self.a.rotina[18], 0.5)
self.assertLess(self.a.rotina[17], 0.3)
self.assertTrue(any('costumam estar por perto das 18h às 19h' in t for _, t in self.diario), self.diario)
self.assertTrue(self.a.chega_logo(em(9, 17, 50)))
self.assertFalse(self.a.chega_logo(em(9, 17, 10))) # ainda falta muito
self.assertFalse(self.a.chega_logo(em(9, 12, 50)))
def test_acordar_a_toa_pede_mais_movimento_naquela_hora(self):
for dia in (6, 7, 8, 9):
for vez in range(2):
t = em(dia, 22, vez * 20)
self.a.acordou_pelo_sensor(t)
for s in range(0, 200, 5):
self.a.observar(t + s, perto=s < 10) # mexeu e sumiu: foi à toa
self.a.observar(em(dia + 1, 0, 1), perto=False)
self.assertGreaterEqual(self.a.extra_pir(em(10, 22, 30)), 1)
self.assertEqual(self.a.extra_pir(em(10, 15)), 0)
self.assertTrue(any('Acordei à toa 2 vezes por volta das 22h' in t for _, t in self.diario), self.diario)
def test_acordar_com_carinho_valeu_a_pena(self):
t = em(6, 22)
self.a.acordou_pelo_sensor(t)
self.a.observar(t + 5, perto=True)
self.a.resposta('carinho', t + 30)
for s in range(35, 200, 5):
self.a.observar(t + s, perto=False)
self.assertEqual(self.a.hoje['falsos'][22], 0)
def test_desligado_nao_aprende_nem_muda_nada(self):
self.a.configurar(dict(ligado=False))
self.fazer('rir', 6, 'carinho')
self.assertEqual(self.a.peso('rir'), 1.0)
self.assertEqual(self.a.extra_pir(em(6, 22)), 0)
self.assertFalse(self.a.chega_logo(em(6, 17, 50)))
def test_esquecer_e_persistencia(self):
self.fazer('rir', 5, 'carinho')
self.fazer('bocejar', 5, inicio=em(6, 17)) # o gosto é relativo: precisa de algo menos querido
self.a.salvar()
outro = Aprendizado(self.caminho)
self.assertGreater(outro.peso('rir'), 1.0)
outro.anotar = lambda *a, **k: None
outro.esquecer()
self.assertEqual(outro.peso('rir'), 1.0)
self.assertEqual(Aprendizado(self.caminho).itens, {})
def ligar_noite(self, ini=23, fim=7):
estado = {'noite': (ini, fim)}
self.a.noite = lambda: estado['noite']
self.a.mudar_noite = lambda i, f: estado.update(noite=(i, f))
return estado
def test_rotina_separa_o_que_cai_na_madrugada(self):
self.ligar_noite(23, 7)
self.a.dias = 3
for h in list(range(10, 24)) + [0, 2]:
self.a.rotina[h] = 0.8
self.a.config['ajustar_sono'] = False
licoes = self.a.fechar_dia()
texto = next(t for t in licoes if t.startswith('Percebi'))
self.assertIn('das 10h às 23h. Vou estar acordado nessa hora.', texto)
self.assertIn('Das 23h à 1h e das 2h às 3h é a minha hora de dormir', texto)
# só gente na madrugada: não promete ficar acordado
self.a.rotina = [None] * 24
self.a.rotina[2], self.a.rotina_avisada = 0.9, []
texto = next(t for t in self.a.fechar_dia() if t.startswith('Percebi'))
self.assertEqual(texto, 'Percebi gente por perto das 2h às 3h, mas é a minha hora de dormir: '
'fico quietinho, a não ser que alguém me chame.')
def test_horario_de_dormir_acompanha_a_casa_aos_poucos_e_volta(self):
estado = self.ligar_noite(23, 7)
self.a.dias = 2
self.a.rotina[23], self.a.rotina[0], self.a.rotina[1] = 0.8, 0.7, 0.7
self.assertEqual(self.a.ajustar_noite('2026-10-06'), []) # poucos dias: ainda não mexe
self.a.dias = 6
licoes = self.a.ajustar_noite('2026-10-06')
self.assertEqual(estado['noite'], (0, 7)) # 1 h por noite
self.assertIn('agora eu vou dormir às 0h (antes era 23h)', licoes[0])
self.assertEqual(self.a.decisoes[0]['tipo'], 'sono')
self.a.ajustar_noite('2026-10-07')
self.a.ajustar_noite('2026-10-08')
self.assertEqual(estado['noite'], (2, 7)) # 1h tem gente, 2h já não conta
self.a.rotina[2] = 0.9
self.a.ajustar_noite('2026-10-09')
self.assertEqual(estado['noite'], (2, 7)) # no máximo 3 h depois do escolhido
# a casa voltou a dormir cedo: volta 1 h por noite até o horário escolhido
self.a.rotina[1] = self.a.rotina[0] = self.a.rotina[23] = 0.1
self.assertIn('volto a dormir às 1h', self.a.ajustar_noite('2026-10-10')[0])
self.a.ajustar_noite('2026-10-11')
self.a.ajustar_noite('2026-10-12')
self.assertEqual(estado['noite'], (23, 7))
self.assertEqual(self.a.ajustar_noite('2026-10-13'), [])
def test_acordar_mais_cedo_limites_e_horario_escolhido_a_mao(self):
estado = self.ligar_noite(23, 7)
self.a.dias = 6
self.a.rotina[6], self.a.rotina[5] = 0.8, 0.8
self.a.ajustar_noite('2026-10-06')
self.a.ajustar_noite('2026-10-07')
self.a.ajustar_noite('2026-10-08')
self.assertEqual(estado['noite'], (23, 5)) # no máximo 2 h antes
# a pessoa muda o horário à mão: vira a nova base e ele não desfaz
estado['noite'] = (22, 8)
self.a.rotina = [None] * 24
self.assertEqual(self.a.ajustar_noite('2026-10-09'), [])
self.assertEqual(self.a.sono_base, (22, 8))
# madrugada nunca fica menor que 5 h
estado['noite'] = (2, 7)
self.a.rotina[2], self.a.rotina[6] = 0.9, 0.9
self.a.ajustar_noite('2026-10-10')
self.assertEqual(estado['noite'], (2, 7))
# desligado ou sem madrugada: não mexe
self.a.config['ajustar_sono'] = False
self.assertEqual(self.a.ajustar_noite('2026-10-11'), [])
self.a.config['ajustar_sono'] = True
self.a.noite = lambda: None
self.assertEqual(self.a.ajustar_noite('2026-10-12'), [])
def test_validar(self):
with self.assertRaises(ValueError):
self.a.configurar(dict(ligado='sim'))
with self.assertRaises(ValueError):
self.a.configurar(dict(outro=True))
class VidaComAprendizadoTest(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.a = Aprendizado(Path(self.tmp.name) / 'aprendizado.json')
self.a.hoje = self.a._dia_vazio('2026-10-06')
self.v = Vida(Path(self.tmp.name) / 'vida.json', iniciar=False, rng=random.Random(3))
self.v.aprendizado = self.a
self.ordens = []
self.v.enfileirar = self.ordens.append
self.v.ultimo_tick = em(6, 15)
def tearDown(self):
self.tmp.cleanup()
def test_gesto_que_agrada_sai_mais(self):
for i in range(8):
self.a.ato('rir', em(6, 15) + i * 100, perto=True)
self.a.resposta('carinho', em(6, 15) + i * 100 + 5)
self.a.ato('feliz', em(6, 15) + i * 100 + 50, perto=True)
opcoes = [('rir', 1, ''), ('feliz', 1, '')]
saiu = [self.v.escolher(opcoes)[0] for _ in range(400)]
self.assertGreater(saiu.count('rir'), saiu.count('feliz') * 2)
def test_carinho_e_atos_com_plateia_chegam_ao_aprendizado(self):
self.v.alguem_perto = lambda: True
self.v.celular_online = lambda: True
self.v.proximo_ato = 0
self.v.necessidades.update(energia=90, social=90, diversao=90, alegria=90)
ato = None
for i in range(30):
ato = self.v.tick(em(6, 15) + i * 200)
if ato in self.a.itens:
break
self.assertIn(ato, self.a.itens)
self.v.estimulo('carinho', em(6, 15) + i * 200 + 10)
self.assertGreater(self.a.itens[ato]['s'], 0)
def test_pir_pede_mais_quando_acordou_a_toa_naquela_hora(self):
self.a.falsos[22] = 1.0
self.assertFalse(self.v.pir_acorda(em(6, 22)))
self.assertTrue(self.v.pir_acorda(em(6, 22) + 10))
self.assertEqual(self.a.acordou_em, em(6, 22) + 10)
self.assertTrue(self.v.pir_acorda(em(6, 15)))
def test_acorda_do_cochilo_antes_de_chegarem(self):
self.a.rotina[18], self.a.rotina[17] = 0.8, 0.1
self.v.dormindo_proprio = True
self.v.necessidades['energia'] = 70
self.assertEqual(self.v.agir(em(6, 17, 50)), 'acordar')
self.assertIn('acordar', self.ordens)
def test_sono_profundo_nao_e_interrompido_pela_rotina(self):
self.a.rotina[18], self.a.rotina[17] = 0.8, 0.1
self.v.dormindo_proprio = True
self.v.sono_profundo = True
self.v.necessidades['energia'] = 70
self.assertIsNone(self.v.agir(em(6, 17, 50)))
def semana_tipica(a, semanas=2):
"""Segunda, sexta e fim de semana em casa (7h-23h); terça a quinta fora das 8h às 18h. Começa em 05/10 (segunda)."""
inicio = date(2026, 10, 5)
for i in range(semanas * 7):
d = inicio + timedelta(days=i)
a.hoje = a._dia_vazio(d.isoformat())
for h in range(24):
for m in range(0, 60, 2):
fora = d.weekday() in (1, 2, 3) and 8 <= h < 18
perto = 7 <= h < 23 and not fora and m < 40
a.minuto = None
a.observar(time.mktime((d.year, d.month, d.day, h, m, 0, 0, 0, -1)), perto)
fim = d + timedelta(days=1)
a.observar(time.mktime((fim.year, fim.month, fim.day, 0, 0, 30, 0, 0, -1)), False)
def plano_certo():
dias = []
for dia in range(7):
if dia in (1, 2, 3):
periodos = [dict(ini=0, fim=7, tipo='dormindo'), dict(ini=7, fim=8, tipo='casa'),
dict(ini=8, fim=18, tipo='fora'), dict(ini=18, fim=23, tipo='casa'), dict(ini=23, fim=24, tipo='dormindo')]
else:
periodos = [dict(ini=0, fim=7, tipo='dormindo'), dict(ini=7, fim=23, tipo='casa'), dict(ini=23, fim=24, tipo='dormindo')]
dias.append(dict(dia=dia, periodos=periodos))
return dict(padroes=['Percebi que de terça a quinta a casa fica vazia das 8h às 18h'], dias=dias)
class SemanaTest(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.a = Aprendizado(Path(self.tmp.name) / 'ap.json')
self.diario = []
self.a.anotar = lambda tipo, texto, agora=None: self.diario.append(texto)
self.pedidos = []
self.resposta = plano_certo()
def ia(provedor, prompt, schema):
self.pedidos.append((provedor, prompt))
return self.resposta
self.a.ia, self.a.pode_ia = ia, lambda provedor: True
self.a.config['analise_ia'] = False # nos testes a análise é chamada direto
def tearDown(self):
self.tmp.cleanup()
def test_quadro_da_semana_separa_os_dias(self):
semana_tipica(self.a)
self.assertEqual(len(self.a.historico), 14)
self.assertLess(self.a.semana[2][10], 0.3) # quarta 10h: fora
self.assertGreater(self.a.semana[0][10], 0.5) # segunda 10h: em casa
self.assertGreater(self.a.semana[4][10], 0.5) # sexta 10h: em casa
self.assertEqual(self.a.esperado(em(14, 10)), 'fora') # 14/10 é quarta
self.assertEqual(self.a.esperado(em(12, 10)), 'casa') # 12/10 é segunda
self.assertTrue(self.a.chega_logo(em(14, 17, 50))) # quarta: chegam às 18h
self.assertFalse(self.a.chega_logo(em(12, 17, 50))) # segunda: já tem gente em casa
self.assertTrue(self.a.casa_vazia(em(14, 10)))
def test_plano_da_ia_que_bate_com_os_dados_e_usado(self):
semana_tipica(self.a)
self.a.analisar(em(19, 1))
self.assertIn('quarta', self.pedidos[0][1])
self.assertIn('sexta (2 dias medidos)', self.pedidos[0][1])
self.assertEqual(self.a.plano['origem'], 'ia')
self.assertGreaterEqual(self.a.conferir(self.a.plano), 0.7)
self.assertIsNone(self.a.sugestao)
self.assertEqual(self.a.esperado(em(14, 10)), 'fora')
self.assertEqual(self.a.esperado(em(14, 2)), 'dormindo')
self.assertTrue(any('terça a quinta' in t for t in self.diario))
def test_plano_da_ia_que_nao_bate_vira_so_sugestao(self):
semana_tipica(self.a)
errado = plano_certo()
for d in errado['dias']:
d['periodos'] = [dict(ini=0, fim=24, tipo='fora')] # "a casa vive vazia": falso
self.resposta = errado
self.a.analisar(em(19, 1))
self.assertIsNone(self.a.plano)
self.assertIsNotNone(self.a.sugestao)
self.assertLess(self.a.conferir(self.a.sugestao), 0.7)
self.assertTrue(any(t.startswith('Acho que') for t in self.diario))
self.a.usar_sugestao()
self.assertEqual(self.a.plano['origem'], 'voce')
def test_rotina_contada_vale_na_hora_e_a_ia_nao_atropela(self):
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
self.assertIn('Fico fora de terça a quinta', self.pedidos[0][1])
self.assertEqual(self.a.plano['origem'], 'voce')
self.assertIsNone(self.a.conferir(self.a.plano)) # ainda sem dados para conferir
semana_tipica(self.a)
self.assertGreaterEqual(self.a.conferir(self.a.plano), 0.7)
self.a.analisar(em(19, 1))
self.assertEqual(self.a.plano['origem'], 'voce') # o que a pessoa disse continua valendo
self.assertIsNotNone(self.a.sugestao)
def test_validar_plano_conserta_o_que_a_ia_erra(self):
p = Aprendizado.validar_plano(dict(padroes=['ok'] * 9, dias=[
dict(dia=0, periodos=[dict(ini=8, fim=20, tipo='casa'), dict(ini=18, fim=30, tipo='fora'),
dict(ini=5, fim=5, tipo='casa'), dict(ini=1, fim=3, tipo='festa')]),
dict(dia=9, periodos=[dict(ini=0, fim=24, tipo='casa')]), 'lixo']), 'ia')
self.assertEqual(p['dias'][0], [dict(ini=8, fim=18, tipo='casa'), dict(ini=18, fim=24, tipo='fora')])
self.assertEqual(len(p['padroes']), 5)
with self.assertRaises(ValueError):
Aprendizado.validar_plano(dict(padroes=[], dias=[]), 'ia')
def test_analise_roda_sozinha_a_meia_noite_com_uma_semana(self):
self.a.config['analise_ia'] = True
semana_tipica(self.a, semanas=1)
for _ in range(50):
if not self.a.analise['ocupado'] and (self.a.plano or self.a.sugestao):
break
time.sleep(0.05)
self.assertEqual(len(self.pedidos), 1) # só na 7ª meia-noite
self.assertIsNotNone(self.a.plano or self.a.sugestao)
def test_persistencia_da_semana_e_do_plano(self):
semana_tipica(self.a, semanas=1)
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
self.a.salvar()
outro = Aprendizado(Path(self.tmp.name) / 'ap.json')
self.assertEqual(outro.semana, self.a.semana)
self.assertEqual(outro.plano['dias'], self.a.plano['dias'])
self.assertEqual(len(outro.historico), 7)
def test_casa_vazia_faz_ele_cochilar_para_guardar_pique(self):
v = Vida(Path(self.tmp.name) / 'v.json', iniciar=False, rng=random.Random(5))
v.aprendizado = self.a
v.enfileirar = lambda ordem: None
v.celular_online = lambda: True
v.necessidades.update(energia=70, diversao=80, social=80, alegria=80)
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
v.visto_em = em(14, 9)
atos = [v.agir(em(14, 10) + i * 120) for i in range(10)]
self.assertIn('atividade dormir', atos)
cochilo = next(d for d in self.a.decisoes if d['tipo'] == 'cochilo')
self.assertEqual(cochilo['motivo'], 'às 10h de quarta a casa costuma ficar vazia, pelo plano que você contou')
class DiaADiaTest(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.a = Aprendizado(Path(self.tmp.name) / 'ap.json')
self.a.ia, self.a.pode_ia = (lambda provedor, prompt, schema: plano_certo()), (lambda provedor: True)
self.a.config['analise_ia'] = False
self.v = Vida(Path(self.tmp.name) / 'v.json', iniciar=False, rng=random.Random(2))
self.v.aprendizado = self.a
self.v.enfileirar = lambda ordem: None
def tearDown(self):
self.tmp.cleanup()
def test_cada_decisao_guarda_o_porque(self):
semana_tipica(self.a)
self.a.analisar(em(19, 1))
self.assertEqual(self.a.decisoes[0]['tipo'], 'ia')
self.assertIn('plano adotado: confere', self.a.decisoes[0]['motivo'])
# acordar antes da chegada (quarta, 17h50)
self.v.dormindo_proprio = True
self.v.necessidades['energia'] = 70
self.assertEqual(self.v.agir(em(14, 17, 50)), 'acordar')
self.assertEqual(self.a.decisoes[0]['motivo'], 'às 18h de quarta costuma ter gente, pelo plano da IA')
# sensor segurado numa hora em que acordou à toa
self.a.falsos[22] = 1.0
self.v.pir_acorda(em(14, 22))
self.v.pir_acorda(em(14, 22) + 30) # a 2ª nota em menos de 10 min não repete
notas = [d for d in self.a.decisoes if d['tipo'] == 'sono']
self.assertEqual(len(notas), 1)
self.assertIn('pede 1 movimento a mais', notas[0]['motivo'])
def test_fechar_o_dia_resume_e_confere_com_o_plano(self):
self.a.informar('Fico fora de terça a quinta, das 8h às 18h')
semana_tipica(self.a, semanas=1)
fechou = [d for d in self.a.decisoes if d['tipo'] == 'dia']
self.assertEqual(len(fechou), 7)
quarta = next(d for d in fechou if 'quarta' in d['texto'])
self.assertIn('conferiu 100% com o plano', quarta['motivo'])
def test_dia_a_dia_de_um_dia_passado_e_de_hoje(self):
semana_tipica(self.a)
self.a.analisar(em(19, 1))
d = self.a.dia_a_dia('2026-10-14')
self.assertEqual(d['nome_dia'], 'quarta')
self.assertFalse(d['hoje'])
self.assertLess(d['medido'][10], 0.3)
self.assertEqual(d['plano'][2], dict(ini=8, fim=18, tipo='fora'))
self.assertEqual(d['confere'], 1.0)
self.assertTrue(any(x['tipo'] == 'dia' for x in d['decisoes']))
self.assertIn('2026-10-05', d['dias'])
hoje = self.a.dia_a_dia()
self.assertTrue(hoje['hoje'])
with self.assertRaises(ValueError):
self.a.dia_a_dia('ontem')
class RotasTest(unittest.TestCase):
def test_status_config_e_esquecer(self):
with tempfile.TemporaryDirectory() as tmp:
kiosk.ARQUIVO_APARENCIA = str(Path(tmp) / 'a.json')
s = kiosk.Servidor(('127.0.0.1', 0), kiosk.Handler)
s.aprendizado = Aprendizado(Path(tmp) / 'ap.json')
kiosk.ligar_eventos(s)
threading.Thread(target=s.serve_forever, daemon=True).start()
try:
def pedir(metodo, rota, corpo=None):
c = http.client.HTTPConnection('127.0.0.1', s.server_port, timeout=5)
dados = json.dumps(corpo).encode() if corpo is not None else None
c.request(metodo, rota, body=dados, headers={'Content-Type': 'application/json'} if dados else {})
r = c.getresponse()
return r.status, json.loads(r.read())
cod, st = pedir('GET', '/aprendizado/status')
self.assertEqual(cod, 200)
self.assertEqual(len(st['rotina']), 24)
cod, st = pedir('POST', '/aprendizado/config', dict(ligado=False))
self.assertEqual((cod, st['config']['ligado']), (200, False))
cod, st = pedir('POST', '/aprendizado/config', dict(ligado='x'))
self.assertEqual(cod, 400)
cod, st = pedir('POST', '/aprendizado/esquecer', {})
self.assertEqual((cod, st['dias']), (200, 0))
cod, est = pedir('GET', '/estado')
self.assertIn('aprendizado', est)
finally:
s.shutdown()
kiosk.EVENTOS.fechar()
if __name__ == '__main__':
unittest.main()