Skip to content

Fase 1, examen y zoom: el lote completo desde el PR #4 (decisiones 52-60) - #5

Merged
jmoredev merged 6 commits into
mainfrom
develop
Oct 16, 2026
Merged

jmoredev merged 6 commits into
mainfrom
develop

Conversation

@jmoredev

Copy link
Copy Markdown
Owner

Qué trae

Todo lo entregado en develop desde que main quedó en c68198e (PR #4):

  • Arrastre táctil: pointercancel en las dos superficies de arrastre y touch-action efectivo (el inline de OrbitControls ganaba a la clase) — decisión 52.
  • Resumen del examen: cada fallo se anota con la pieza, el hueco señalado y qué iba ahí, y lo que quedó sin colocar con su fase — decisión 53.
  • Aviso de carga no bloqueante con porcentaje mientras llega el modelo de la placa (hasta 18,8 MB) — decisión 54.
  • Fase 1 en rejilla 6×3 para que dos piezas de la misma columna visual no se dibujen una detrás de otra — decisión 55.
  • En examen no hay pistas: la barra de estado deja de nombrar la pieza y el hueco compatible, sin paneles laterales y sin imán — decisiones 51 y 56.
  • Cartel de fase al empezar cada fase en práctica, con lastAdvance para no mentir — decisión 57.
  • Ventanita con la pieza seleccionada ampliada (PNG del conector o vista 3D de cerca, sin el nombre en examen) montada una sola vez por fase: antes se desmontaba en cada colocación y creaba un contexto WebGL cada vez — decisiones 58 y 59.
  • Carteles de la fase 1 separados (6×3, filas a 1,75 u): soltar cerca del borde contaba el cartel de al lado y restaba puntos — decisión 60.

Verificación

  • npx tsc -b y npm run lint en 0.
  • Arnés e2e completo en verde (node tests/run.mjs, todas las secciones, ~14 min) con las secciones 13-19 y la falsación de cada regla nueva.
  • Medición de la decisión 60 con la proyección real de la cámara: el peor hueco en pantalla entre dos tarjetas pasa de 23 px a 31 px, y la banda que contaba el cartel de al lado (separación mínima 0,95 u frente a los 1,20 u que exige snapRadius + wrongRadius) desaparece.
  • Revisión nativa RDD: aprobada y quemada sobre 014da1f (sus cuatro avisos están arreglados en 014da1f y 8736687).

Nota

La fusión es decisión de la persona usuaria; el despliegue lo hace el workflow al entrar en main.

…de la fase 1

Un solo commit porque los cambios están entrelazados en los mismos ficheros
(hoja de estilos, App, store, arnés y documentación).

- Arrastre: `pointercancel` en las dos superficies desde las que se empieza a
  arrastrar y `touch-action` efectivo en el lienzo (el inline que escribe
  OrbitControls al desmontarse ganaba a la clase, así que la regla era inerte).
- Examen: resumen final con la pieza, el hueco y qué iba ahí, más lo que quedó sin
  colocar con su fase; y la barra de estado deja de dar el nombre de la pieza y
  del hueco compatible.
- Aviso de carga con porcentaje, no bloqueante, mientras llega un modelo pesado.
- Fase 1: mesa de 6 columnas x 3 filas (filas a 2,1 u) para que dos piezas de la
  misma columna visual no se dibujen una detrás de otra, y ventanita con la pieza
  seleccionada ampliada (PNG nitido del conector o vista 3D de cerca, sin el
  nombre en examen).
- Practica: cartel al empezar cada fase con lo que hay que hacer en ella.
- Arnes: secciones 13-17, check de "misma columna visual" en la 11, preflight de
  servidor y de instancia del store, y ONLY=<secciones> para acotar pasadas.
  210 comprobaciones en verde y falsacion de cada regla nueva.
…tera

La ventanita de la fase 1 miraba siempre de frente, así que la CPU y el SSD
salían de canto, el disipador por su parte de abajo y los altavoces de espaldas
(las que son PNG, como los cables, salían bien).

Ahora mide la caja envolvente real de la pieza y coloca la cámara mirando a su
centro desde tres cuartos y desde arriba, a la distancia que la deja entera. El
margen de esa distancia cubre que con perspectiva el extremo cercano de una pieza
larga se agranda: con menos margen la RAM se salía por los dos lados.
… como progreso

Dos hallazgos de la revision nativa del rango comprometido (dfd2838..HEAD):

- R4-001 (resilience): el mini lienzo de la pieza usaba el frameloop por defecto
  (always), asi que mantenia un bucle de render WebGL propio mientras hubiera una
  pieza seleccionada, aunque la escena sea estatica tras el encuadre. En los
  portatiles modestos que busca el proyecto eso es carga de GPU sostenida; pasa a
  demand (el encuadre sigue teniendo su fotograma al montar y al llegar el modelo).
- R4-002 (resilience): la barra de carga anunciaba cada cambio de porcentaje por
  aria-live, decenas de anuncios mientras baja un modelo de 18,8 MB. Pasa a
  role=progressbar con aria-valuenow/aria-valuemin/aria-valuemax y aria-label, y
  la seccion 15 del arnes lo fija con una comprobacion nueva.

El CRITICAL R3-001 de esa revision (selectedId anulable en ExamMiss) se disputa:
quitando la guarda if (!selectedId) return de endDrag, tsc falla exactamente con
ese error, y con la guarda sale en 0.
…he y fase completada

Cuatro hallazgos advisory de la revision nativa del candidato c1c4243:

- R4-001 (resilience): alternar entre un conector con PNG y una pieza 3D
  desmontaba y montaba el Canvas, y cada montaje crea un contexto WebGL nuevo:
  alternando en la fase 1 se puede agotar el limite del navegador y la ventanita
  deja de pintar. Ahora el lienzo se queda montado y la imagen se superpone.
- R4-002 (resilience): la imagen del conector gana onError y cae a la vista 3D
  si el PNG falla, en vez de dejar el icono roto.
- R3-001 (reliability): la seccion 15 desactiva la cache del navegador; con la
  cache, secciones anteriores ya habian cargado el mismo modelo y la barra podia
  no llegar a verse.
- R3-002 (reliability): la seccion 16 completa la fase 2 colocando sus piezas y
  comprueba el kicker "Fase completada", que antes solo se probaba al saltar.
… el ciclo

El panel del zoom se montaba condicionado a la pieza seleccionada, asi que se
desmontaba en cada colocacion de la fase 1 (18 por partida) y cada montaje
creaba un contexto WebGL nuevo; el que el navegador se lleva por agotamiento es
el mas antiguo, o sea el de la escena principal. Ahora el panel (y su lienzo)
viven toda la fase 1 y, sin seleccion, se ocultan con `zoom--oculto` (asi el
lienzo conserva su tamano y su contexto); fuera de la fase 1 se desmontan,
porque alli el lienzo no hace falta. Hallazgo R4-001 de la revision nativa.

Arnes:
- `componentZoom` (seccion 17) da una vuelta entera al ciclo de la fase 1
  -seleccionar, colocar (que deselecciona) y volver a seleccionar- y marca el
  nodo del lienzo: falsado, con el montaje condicional fallan las cinco
  comprobaciones de ese ciclo. La primera version del check (marcador entre dos
  selecciones seguidas) no cazaba el defecto; se corrigio al falsarlo.
- Seccion nueva 18 (`examIdentifyHint`): en la fase 1 de examen se coge una
  pieza de la mesa y se lleva sobre su cartel, con el control de que el puntero
  llego a estar encima; falsado, sin la guardia de la barra de estado el aviso
  vuelve a decir «Suelta aqui: <pieza>».
- El calculo de pantalla de la fase 1 sale de la seccion 17 a un ayudante
  (`pantallaFase1`) que ahora comparten las dos.

AGENTS.md: decision 59 (el panel se monta una vez por fase, no por pieza) y la
56 apunta tambien a la 18.

Verificado: `tsc -b` en 0, `npm run lint` sin avisos y las dos secciones en
verde tras restaurar el arreglo y la guardia.
Cada cartel acepta un solo tipo de pieza, asi que la pieza nunca se colocaba en el
cartel equivocado: el defecto que reporto el alumnado era de conteo. `endDrag`
cuenta fallo cuando NO hay cartel correcto a `snapRadius` (0,6) y SI uno ajeno a
`wrongRadius` (0,6), de modo que esa banda existia mientras dos carteles estuvieran
a menos de 0,6 + 0,6 = 1,2 u. Con las filas a 0,95 u empezaba a 0,35 u del centro,
o sea 0,15 u mas alla del borde visible de la tarjeta (1,0 x 0,4): soltar cerca del
borde contaba el cartel de al lado y restaba puntos (medido en examen: 0 -> 1
fallos y 100 -> 97 puntos).

El reparto pasa a 6 columnas x 3 filas (18 celdas exactas) con las filas a 1,75 u,
asi que las dos regiones ya no se solapan: fallar de largo solo deja la pieza sin
colocar. Medido con la proyeccion de la camara: el peor hueco en pantalla entre dos
tarjetas pasa de 23 px a 31 px y la fila de atras queda a 0,25 u del borde de la
mesa. Cuatro filas de cinco columnas no caben mas separadas (a 1,25 u el margen al
borde es 0,1 u y a 1,3 se sale de la mesa).

Arnes:
- Seccion nueva 19 (`identifyCards`): la regla geometrica (separacion minima >=
  snapRadius + wrongRadius, leida de los datos), el hueco en pantalla entre tarjetas
  y el efecto reportado en examen -soltar 0,7 u hacia el cartel vecino mas proximo-,
  con el control de que sobre su propio cartel si coloca. Falsado: con las filas a
  0,95 u fallan los cuatro (separacion 0,95 < 1,20; hueco 23 < 28 px; fallos 0 -> 1
  y puntos 100 -> 97).
- Los desplazamientos para coger una pieza de la mesa estaban repetidos en tres
  secciones y solo una tenia los de abajo: ahora son la constante `COGER_PIEZA`. Sin
  ellos el monitor no se dejaba coger (su centro dibujado queda 0,15 u por debajo
  del punto que calcula el arnes: lo encoge `trayScaleFor`) y las comprobaciones
  dependientes caian como si fuera un defecto del producto.

AGENTS.md: decision 60 con las mediciones antes y despues.

Verificado: `tsc -b` en 0, `npm run lint` sin avisos y la pasada integra del arnes
en verde (todas las secciones).
@jmoredev
jmoredev merged commit 8a44a13 into main Oct 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant