2026-08-07 — marvelousdb: comparador tipo cameradecision + cache de imagenes SerpAPI

Contexto: el usuario pidio (1) hacer el VS battle mas claro con un comparativo cara a cara como cameradecision.com, y (2) cachear imagenes de los personajes sin imagen usando su API key gratuita de SerpAPI.

Estado del problema

  • Solo 135 personajes sin imagen (todos PDSH; Marvel 0). Cabe en el plan gratuito de SerpAPI (~100 busquedas/mes) con 2 runs de —limit.

Implementacion

Comparador (/vs rediseñado)

  • Formulario con dos paneles: select de universo (Public Domain, Marvel Universe, Ultimate Universe) + select de personaje (roster completo via nuevo endpoint /api/characters/names?universe=). Cambiar universo recarga (onchange submit). Boton Fight! → GET /vs?a=<id>&b=<id>; boton Random Fight → aleatorios.
  • API battle ahora acepta ?idA=&idB= (especificos) o ?universeA=&universeB= (aleatorios).
  • Resultado: imagen, universo, debut, poderes como chips, barra de poder (score*10 %, cap 100; gradiente rojo, dorado para el ganador), ganador con borde brillante. Helper handlebars eq para selected.
  • Nota: el HTML de /vs pesa ~600KB por los selects con ~10k options — aceptable local; un autocomplete seria el siguiente paso.

Cache de imagenes (SerpAPI)

  • data/cache-images.js: lee el .db, toma personajes sin thumbnail no cacheados (ORDER BY RANDOM), consulta engine=google_images de SerpAPI ("<name>" superhero character), descarga el primer resultado a public/img/cache/<id>.<ext> y registra data/img-cache.json {id: path}. Flags: --limit N, --universe X. Sleep 1.5s entre queries (plan gratis). Requiere SERPAPI_KEY en .env (error claro si falta).
  • API: carga data/img-cache.json al arranque (Map) y charThumb(id, raw): sin thumbnail en BD → path del cache → si no, placeholder local mejorado (no-image.svg rediseñado, “NO IMAGE YET”).
  • El cache es independiente del .db → sobrevive a rebuilds.

Verificacion

  • 17/17 tests (nuevos: battle con ids, roster names).
  • /vs renderiza 200 con pickers, 10,170 options, powerbars.
  • Cache simulado: personaje sin imagen sirve /img/cache/.jpg.

Pendientes

  • El usuario debe poner SERPAPI_KEY en .env y correr cache-images.js.
  • Selects de 10k options: autocomplete real si molesta.