feat(vida): modo autônomo, o Carinha como bichinho virtual
Novo módulo vida.py: energia, alegria, companhia e diversão caem com o tempo e sobem com presença (PIR), movimento, conversa e carinho. Delas sai o humor e, do humor, os atos: gestos, cochilo quando cansado, dormir à noite sem ninguém por perto, acenar pedindo atenção quando carente com gente perto, tocar reações da biblioteca e inventar figurinhas novas com o Gemini (no máximo 3 por dia, 90 min entre elas). - O celular recebe "humor x" e escolhe os gestos soltos por ele. - Toque na tela do celular conta como carinho/cutucada (/vida/cuidar). - Respeita E-Stop e o modo presença (ninguém em casa = quieto). - Painel: cartão Vida no Ao vivo com humor, barras, cuidados, ritmo e diário; liga por padrão. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -359,6 +359,20 @@ const r = {
|
||||
const SEQS = sequencias();
|
||||
const LIVRES = ["feliz", "olhar_esq", "olhar_dir", "olhar_baixo",
|
||||
"surpreso", "coracao", "piscadinha", "bravo", "triste", "alegre"];
|
||||
/* Modo vida (servidor): o humor do bichinho escolhe os gestos soltos entre um ato e outro. */
|
||||
const LIVRES_HUMOR = {
|
||||
feliz: ["feliz", "alegre", "piscadinha", "coracao", "olhar_esq", "olhar_dir"],
|
||||
tranquilo: ["olhar_esq", "olhar_dir", "feliz", "piscadinha", "olhar_baixo"],
|
||||
entediado: ["olhar_esq", "olhar_dir", "olhar_baixo", "pensar"],
|
||||
carente: ["olhar_baixo", "triste", "olhar_esq", "olhar_dir"],
|
||||
triste: ["triste", "olhar_baixo", "olhar_baixo"],
|
||||
cansado: ["olhar_baixo", "piscar2"],
|
||||
};
|
||||
let HUMOR = "normal";
|
||||
function gestoSolto() {
|
||||
const lista = LIVRES_HUMOR[HUMOR] || LIVRES;
|
||||
return lista[Math.floor(Math.random() * lista.length)];
|
||||
}
|
||||
|
||||
function proximo() {
|
||||
if (!r.fila.length) { r.kf = null; return; }
|
||||
@@ -527,6 +541,8 @@ function trata(ordem) {
|
||||
if (v.length === 3 && v.every((n) => !isNaN(n))) {
|
||||
CIANO.splice(0, 3, ...v); r.cor = v;
|
||||
}
|
||||
} else if (ordem.indexOf("humor ") === 0) {
|
||||
HUMOR = ordem.slice(6).trim();
|
||||
} else if (ordem === "dormir" || ordem === "sono") {
|
||||
r.dormindo = true;
|
||||
} else if (ordem === "acordar") {
|
||||
@@ -627,9 +643,10 @@ if (MODO_PAINEL) {
|
||||
if (!inicio) return;
|
||||
const dx = e.clientX - inicio.x, dy = e.clientY - inicio.y, dur = performance.now() - inicio.t;
|
||||
inicio = null;
|
||||
if (r.dormindo) { trata('acordar'); return; }
|
||||
if (Math.abs(dx) > 60 && Math.abs(dx) > Math.abs(dy) && dur < 900) { animar('coracao'); return; }
|
||||
if (r.dormindo) { trata('acordar'); cuidar('cutucar'); return; }
|
||||
if (Math.abs(dx) > 60 && Math.abs(dx) > Math.abs(dy) && dur < 900) { animar('coracao'); cuidar('carinho'); return; }
|
||||
if (dur < 350 && Math.hypot(dx, dy) < 15) {
|
||||
cuidar('cutucar');
|
||||
animar('surpreso');
|
||||
setTimeout(() => animar('feliz'), 700);
|
||||
}
|
||||
@@ -736,6 +753,15 @@ function relatarSom(evento, n) {
|
||||
if (evento !== "adormeceu") registrarEvento("som", evento, n);
|
||||
}
|
||||
|
||||
/* Toque na tela vira cuidado no modo vida (carinho/cutucada). Só o celular conta. */
|
||||
function cuidar(acao) {
|
||||
if (new URLSearchParams(location.search).get("aparelho") !== "1") return;
|
||||
try {
|
||||
fetch("/vida/cuidar", { method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ acao }) }).catch(() => {});
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
/* Histórico de detecções no servidor (o app tira a foto do evento). Só o celular registra. */
|
||||
function registrarEvento(tipo, evento, nivel) {
|
||||
if (new URLSearchParams(location.search).get("aparelho") !== "1") return;
|
||||
@@ -1105,8 +1131,10 @@ function laco(t) {
|
||||
animar("piscar");
|
||||
proxPiscar = t + 1600 + Math.random() * 3500;
|
||||
} else if (AUTO && t >= proxGesto) {
|
||||
animar(LIVRES[Math.floor(Math.random() * LIVRES.length)]);
|
||||
proxGesto = t + 7000 + Math.random() * 8000;
|
||||
animar(gestoSolto());
|
||||
// cansado e triste mexem menos; feliz, mais
|
||||
const ritmo = { cansado: 1.8, triste: 1.5, feliz: 0.8 }[HUMOR] || 1;
|
||||
proxGesto = t + (7000 + Math.random() * 8000) * ritmo;
|
||||
}
|
||||
} else if (t >= proxGesto) {
|
||||
proxGesto = t + 7000 + Math.random() * 8000;
|
||||
|
||||
Reference in New Issue
Block a user