From 5b98d1b2bfb5de2d0092e7f5d1bf0a6ad737212f Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 14 Sep 2026 18:57:00 +0000 Subject: [PATCH] =?UTF-8?q?atuq:=20no=20era=20el=20perfil=20=E2=80=94=20so?= =?UTF-8?q?n=20DOS=20SALIDAS,=20y=20el=20=C2=AB3=20de=2013=C2=BB=20med?= =?UTF-8?q?=C3=ADa=20la=20c=C3=A1mara?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dos cosas antes de la medición: el MOZ_LOG de las que pintan y las que no termina IDÉNTICO (las dos commitean WaylandBufferSHM de 1280x696), y el cruce de las 15 corridas está confundido — las 13 de «perfil del usuario» salieron todas con VGA=1. `screendump` de QMP fotografía UN dispositivo. Con VGA=1 hay dos, y hasta ahora se miraba uno. Con `id=` en cada uno y capturando los dos en cada toma, en la misma corrida y el mismo instante: +312s ██ PRIMERA PINTURA — 704456 px EN vga0 gpu0 = 962675 px de fondo + panel y dock (el escritorio, SIN navegador) vga0 = 703766 px magenta (la ventana, con la página) ⇒ cosmic-comp maneja las DOS salidas y la ventana cae en una u otra. «Pinta 3 de 13» era cuántas veces cayó en la pantalla que yo fotografiaba: una tasa de mi cámara, no del producto. El §6.10.ter tiene la misma explicación (aquel arranque también traía `drm: card0 card1`). Queda en pie, ya sin confundido: el navegador arranca, mapea y commitea SIEMPRE; cuando la ventana está en la pantalla que se mira, se ve entre +184 y +312 s; el perfil no era la causa y cosmic-comp nesteado tampoco. ⚠ Tercera vez en el día con la misma forma: un ✗ de una captura de UNA pantalla no dice «la ventana no está», dice «no está en ESA» — igual que `mapped 1` no probaba que se viera. El estado anota ahora en qué pantalla apareció y cuántas se fotografiaron, y el vigía NO cuenta las ciegas: las nombra. --- docs/26-atuq-envoltorio-gecko.md | 54 ++++++++++++++++++++++++- docs/state/primera-pintura.json | 67 +++++++++++++++++++++++++------- scripts/cosmic/atuq-en-imagen.py | 49 ++++++++++++++++------- scripts/vigia-imagen.py | 26 ++++++++++--- 4 files changed, 162 insertions(+), 34 deletions(-) diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md index 9044e229..9eab1405 100644 --- a/docs/26-atuq-envoltorio-gecko.md +++ b/docs/26-atuq-envoltorio-gecko.md @@ -1773,7 +1773,7 @@ buffer no llega a la pantalla. Lo próximo es mirarlo del lado del compositor recibe su `configure`, en qué workspace y en qué salida quedó la ventana— y correr N veces para tener una tasa, no una anécdota. -#### 6.10.septies La TASA: pinta **3 de 13** con el perfil del usuario — y cuando pinta, siempre a ~200 s (2026-09-14) +#### 6.10.septies La TASA: «3 de 13» — ⚠ **el número medía LA CÁMARA, no el producto (ver §6.10.octies)** (2026-09-14) Diez corridas seguidas, idénticas, con `scripts/cosmic/tasa-primera-pintura.sh`: `--as-user`, `VGA=1`, ventana de 480 s, captura cada 30 s. Más las cinco de las secciones anteriores, todas sobre la misma @@ -1784,6 +1784,12 @@ imagen y anotadas en `docs/state/primera-pintura.json`: | perfil del usuario (lo que hace un usuario) | **3 de 13** | 184, 199, 204 s | | perfil nuevo en tmpfs | 2 de 2 | 197, 197 s | +⚠ **ESTA TABLA NO SIGNIFICA LO QUE PARECE.** Las 13 del perfil del usuario salieron todas con `VGA=1` +y la de perfil nuevo casi ninguna ⇒ «perfil» y «vídeo» están confundidos; y las capturas miraban UNA +de las DOS salidas. El §6.10.octies lo mide: la ventana cae en cualquiera de las dos pantallas, así +que los ✗ son «no estaba en la que fotografié». Lo que sí sobrevive es el tiempo: cuando se la ve, +se la ve entre +184 y +312 s. + **Dos cosas que el número dice y una anécdota no podía:** 1. **cuando pinta, pinta siempre en la misma ventana** —184…204 s— y nunca a los 300, 400 ni 900. O @@ -1805,6 +1811,52 @@ ventana de observación›»—. **No las invalida** (se verificó una por una q dejó su `MOZ_LOG` de 1200–5000 líneas), pero una corrida abortada de verdad se vería casi igual: por eso el guion de la tasa cuenta las **abortadas aparte** en vez de sumarlas a los fallos. +#### 6.10.octies La causa: **son DOS SALIDAS y la ventana cae en cualquiera** — y el «3 de 13» medía la cámara (2026-09-14) + +El §6.10.septies cerró con «con el perfil del usuario pinta 3 de 13, con perfil nuevo 2 de 2» y la +pregunta «qué hace el primer arranque del perfil». La respuesta es: **nada**. Dos cosas antes de la +medición que la contestó: + +1. **el `MOZ_LOG` de las que pintan y las que no termina IDÉNTICO** — las dos commitean + `WaylandBufferSHM` de 1280×696. O sea que el navegador dibuja igual en los dos casos; +2. **el cruce de las 15 corridas está CONFUNDIDO**: las 13 «perfil del usuario» salieron TODAS con + `VGA=1`, y de «perfil nuevo» hay una sola con dos tarjetas. Con esa tabla no se puede separar + «perfil» de «vídeo»: comparar una columna que no varía es comparar con nada. + +**La medición que lo contesta:** `screendump` de QMP fotografía **un** dispositivo. Con `VGA=1` hay +dos (`vga0` estándar + `gpu0` virtio-gpu) y hasta ahora se fotografiaba uno. Se le puso `id=` a cada +uno y se capturan LOS DOS en cada toma. Resultado, en la misma corrida y el mismo instante: + + +312s ██ PRIMERA PINTURA — 704456 px de la página EN vga0 + gpu0 = 962 675 px de fondo azul + panel y dock (el escritorio, SIN navegador) + vga0 = 703 766 px magenta (la ventana, con la página) + +⇒ **`cosmic-comp` maneja las DOS salidas y la ventana cae en una u otra.** Lo que se publicó como +«pinta 3 de 13» era **cuántas veces la ventana cayó en la pantalla que yo fotografiaba**. No es una +tasa del producto: es una tasa de mi cámara. Y el §6.10.ter —«arranca y no pinta la ventana»— tiene +la misma explicación: aquel arranque también tenía dos tarjetas (`drm: card0 card1`), y la captura +miraba una. + +**Lo que queda en pie de todo lo anterior**, ahora sí sin confundido: +· el navegador arranca, mapea su superficie y commitea cuadros **siempre** (eso nunca falló); +· cuando la ventana está en la pantalla que se mira, se ve entre **+184 y +312 s**; +· el perfil del usuario **no** era la causa, y `cosmic-comp` nesteado tampoco (§6.10.quater). + +⚠ **La lección de método, que es la tercera vez en el mismo día:** con dos salidas, un ✗ de una +captura de una sola pantalla **no dice «la ventana no está»**, dice «no está en ESA». Igual que +`mapped 1` no probaba que se viera, una foto no prueba que no exista: prueba dónde no está. Por eso +`docs/state/primera-pintura.json` anota ahora **en qué pantalla** apareció y **cuántas fotografió** +cada corrida, y `scripts/vigia-imagen.py` **no cuenta las ciegas** — las nombra aparte: + + ⚠ pintaron 6 de 6 corridas CONCLUYENTES · primera pintura +184…+312s + ✓ +312s vga0 perfil del usuario vga+virtio-gpu (dos DRM) + ⚠ 10 corridas NO se cuentan: con dos salidas fotografiaron UNA sola, y su ✗ sólo dice que + la ventana no estaba en esa pantalla + +**Lo que sigue**, y ahora es otra pregunta: no «por qué no pinta» sino **por qué el escritorio abre la +ventana en la salida que no tiene el foco** —y si con una sola salida (`-vga none`, que es como se va +a usar la imagen de verdad) eso desaparece—. Es barato: la misma serie con una tarjeta. + ### 6.11 Y ahora la pregunta que faltaba: ¿REPRODUCE? (2026-09-07) El §6.10 preguntó «¿qué NO puede hacer?» y contestó leyendo cadenas. Media pregunta. La otra mitad diff --git a/docs/state/primera-pintura.json b/docs/state/primera-pintura.json index f0babc4c..c761244c 100644 --- a/docs/state/primera-pintura.json +++ b/docs/state/primera-pintura.json @@ -14,7 +14,9 @@ "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", "capturas": "work/atuq-imagen-1tarjeta", - "nota": "reconstruida de las capturas guardadas" + "nota": "reconstruida de las capturas guardadas", + "pantallas_fotografiadas": 1, + "pantalla": "desconocida (una sola captura)" }, { "medido": "2026-09-14T14:36:00Z", @@ -30,7 +32,9 @@ "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", "capturas": "work/atuq-imagen-2tarjetas", - "nota": "reconstruida de las capturas guardadas" + "nota": "reconstruida de las capturas guardadas", + "pantallas_fotografiadas": 1, + "pantalla": "desconocida (una sola captura)" }, { "medido": "2026-09-14T14:47:00Z", @@ -46,7 +50,8 @@ "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", "capturas": "work/atuq-imagen-comousuario", - "nota": "reconstruida; el MOZ_LOG commiteaba buffers a +330 s, DESPUÉS de la última captura" + "nota": "reconstruida; el MOZ_LOG commiteaba buffers a +330 s, DESPUÉS de la última captura", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T15:10:00Z", @@ -62,7 +67,9 @@ "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", "capturas": "work/atuq-imagen-usuario-largo", - "nota": "reconstruida de las capturas guardadas" + "nota": "reconstruida de las capturas guardadas", + "pantallas_fotografiadas": 1, + "pantalla": "desconocida (una sola captura)" }, { "medido": "2026-09-14T15:58:44Z", @@ -78,7 +85,8 @@ "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", "capturas": "work/atuq-imagen-medicion", - "nota": "NO pintó en 900 s y el MOZ_LOG commiteaba WaylandBufferSHM desde ≤ +377 s: «mapped 1» NO prueba que se vea" + "nota": "NO pintó en 900 s y el MOZ_LOG commiteaba WaylandBufferSHM desde ≤ +377 s: «mapped 1» NO prueba que se vea", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T16:17:13Z", @@ -92,7 +100,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T16:26:43Z", @@ -106,7 +115,9 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1, + "pantalla": "desconocida (una sola captura)" }, { "medido": "2026-09-14T16:39:48Z", @@ -120,7 +131,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T16:48:45Z", @@ -134,7 +146,9 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1, + "pantalla": "desconocida (una sola captura)" }, { "medido": "2026-09-14T17:03:19Z", @@ -148,7 +162,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T17:18:52Z", @@ -162,7 +177,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T17:34:16Z", @@ -176,7 +192,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T17:51:50Z", @@ -190,7 +207,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T18:10:43Z", @@ -204,7 +222,8 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 }, { "medido": "2026-09-14T18:25:53Z", @@ -218,7 +237,25 @@ "mem_mb": 2560, "vcpus": 2, "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 1 + }, + { + "medido": "2026-09-14T18:54:22Z", + "imagen": "/mnt/cosecha/takana-cosmic-qemu.img", + "segundos_primera_pintura": 312, + "presupuesto_s": 420, + "ventana_s": 480, + "cadencia_s": 40, + "lanzamiento": "perfil del usuario", + "video": "vga+virtio-gpu (dos DRM)", + "mem_mb": 2560, + "vcpus": 2, + "acel": "tcg", + "guion": "scripts/cosmic/atuq-en-imagen.py", + "pantallas_fotografiadas": 2, + "pantalla": "vga0", + "nota": "la ventana apareció en vga0 mientras gpu0 seguía mostrando el escritorio sin navegador" } ] } diff --git a/scripts/cosmic/atuq-en-imagen.py b/scripts/cosmic/atuq-en-imagen.py index b47ead4f..d715f248 100755 --- a/scripts/cosmic/atuq-en-imagen.py +++ b/scripts/cosmic/atuq-en-imagen.py @@ -46,7 +46,13 @@ SMP = os.environ.get("SMP", "2") # Un compositor con dos tarjetas puede componer en la que el `screendump` NO muestra. Por eso el # default acá es UNA sola (-vga none) y la reproducción del caso original es una opción explícita: # son dos mediciones distintas y hay que poder pedir cada una por su nombre. -VGA_ARGS = [] if os.environ.get("VGA") == "1" else ["-vga", "none"] +# Las dos pantallas van con ID EXPLÍCITO (`vga0`, `gpu0`) y no por el `-vga std` implícito, porque +# `screendump` de QMP fotografía UN dispositivo y hay que poder pedir cada uno por su nombre: con dos +# salidas, el compositor puede poner la ventana en la que la captura por defecto NO muestra, y eso se +# ve exactamente igual que «la ventana no aparece». +DOS_PANTALLAS = os.environ.get("VGA") == "1" +VGA_ARGS = (["-vga", "none", "-device", "VGA,id=vga0"] if DOS_PANTALLAS else ["-vga", "none"]) +PANTALLAS = ["gpu0", "vga0"] if DOS_PANTALLAS else ["gpu0"] class Serial: @@ -115,6 +121,18 @@ class Serial: return self.esperar(marca, segundos, nombre=f"de «{orden[:40]}»") +def capturar(ruta_qmp, out, nombre): + """Fotografía CADA pantalla del guest y devuelve {pantalla: fichero}. + + Con dos salidas hay que mirar las dos: la ventana puede estar viva y dibujando en la que no se + fotografía, y eso es indistinguible de «no pinta» si sólo se mira una. + """ + ficheros = {p: os.path.join(out, f"{nombre}-{p}.ppm") for p in PANTALLAS} + qmp(ruta_qmp, [{"execute": "screendump", "arguments": {"filename": f, "device": p}} + for p, f in ficheros.items()]) + return ficheros + + def pintado(ppm): """¿Cuántos píxeles de la pantalla son la página de prueba? @@ -132,7 +150,7 @@ def pintado(ppm): return sum(n for n, (r, g, b) in im.getcolors(1 << 24) if r > 90 and b > 90 and g < 40) -def anotar_medicion(segundos, a): +def anotar_medicion(segundos, a, pantalla=None): """Deja el tiempo de primera pintura en `docs/state/primera-pintura.json`. Va al estado del repo y no a un log porque quien pregunta «¿esta imagen se puede usar?» es @@ -145,11 +163,14 @@ def anotar_medicion(segundos, a): "medido": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "imagen": IMG, "segundos_primera_pintura": segundos, # None = no pintó dentro de la ventana + "pantalla": pantalla, # EN CUÁL de las salidas apareció (medido 2026-09-14: + # con dos, la ventana cae en cualquiera de las dos) + "pantallas_fotografiadas": len(PANTALLAS), # con 1 y dos salidas, un ✗ NO es concluyente "presupuesto_s": a.budget, "ventana_s": a.wait, "cadencia_s": a.cadence, # la RESOLUCIÓN del número: ±cadencia "lanzamiento": "perfil del usuario" if a.as_user else "perfil nuevo en tmpfs", - "video": "vga+virtio-gpu (dos DRM)" if VGA_ARGS == [] else "virtio-gpu solo (-vga none)", + "video": "vga+virtio-gpu (dos DRM)" if DOS_PANTALLAS else "virtio-gpu solo (-vga none)", "mem_mb": int(MEM), "vcpus": int(SMP), "acel": "tcg", "guion": "scripts/cosmic/atuq-en-imagen.py", } @@ -214,7 +235,7 @@ def main(): qemu = [ "nice", "-n", "10", "qemu-system-x86_64", "-machine", "q35", "-accel", "tcg", "-cpu", "max", "-m", MEM, "-smp", SMP, - *VGA_ARGS, "-device", "virtio-gpu-pci", "-display", "none", "-nic", "none", + *VGA_ARGS, "-device", "virtio-gpu-pci,id=gpu0", "-display", "none", "-nic", "none", "-drive", f"if=pflash,format=raw,unit=0,file={OVMF_CODE},readonly=on", "-drive", f"if=pflash,format=raw,unit=1,file={vars_fd}", "-drive", f"file={IMG},format=raw,if=virtio", @@ -244,8 +265,8 @@ def main(): print(ser.cmd("echo ENTORNO: WD=$WAYLAND_DISPLAY XDG=$XDG_RUNTIME_DIR DBUS=$DBUS_SESSION_BUS_ADDRESS").strip()) print(ser.cmd("ls -l $XDG_RUNTIME_DIR; ls /usr/lib/dri").strip()) - qmp(qmp_sock, [{"execute": "screendump", "arguments": {"filename": os.path.join(out, "antes.ppm")}}]) - print("== captura ANTES", flush=True) + capturar(qmp_sock, out, "antes") + print("== captura ANTES (%s)" % ", ".join(PANTALLAS), flush=True) if a.only_cosmic: print("== CONTROL: no se lanza el navegador") @@ -278,21 +299,23 @@ def main(): primera = None # segundos hasta la PRIMERA captura con la página en pantalla while time.time() - t0 < a.wait: time.sleep(a.cadence); n += 1 - shot = os.path.join(out, f"durante-{n}.ppm") - qmp(qmp_sock, [{"execute": "screendump", "arguments": {"filename": shot}}]) + tomas = capturar(qmp_sock, out, f"durante-{n}") t = int(time.time() - t0) - px = pintado(shot) + medidas = {p: pintado(f) for p, f in tomas.items()} + px = max((v for v in medidas.values() if v is not None), default=None) + donde = next((p for p, v in medidas.items() if v and v > 100_000), None) if primera is None and px and px > 100_000: primera = t - print(f" +{t}s ██ PRIMERA PINTURA — {px} px de la página", flush=True) + print(f" +{t}s ██ PRIMERA PINTURA — {px} px de la página EN {donde}", flush=True) if a.until_paint: break else: vivos = ser.cmd("for c in /proc/[0-9]*/comm; do cat $c 2>/dev/null; done | grep -c atuq") v = vivos.splitlines()[1].strip() if len(vivos.splitlines()) > 1 else "?" - print(f" +{t}s px de la página: {px if px is not None else '?'} procesos atuq: {v}", flush=True) + detalle = " ".join(f"{p}={medidas[p]}" for p in PANTALLAS) + print(f" +{t}s px de la página: {detalle} procesos atuq: {v}", flush=True) - qmp(qmp_sock, [{"execute": "screendump", "arguments": {"filename": os.path.join(out, "despues.ppm")}}]) + capturar(qmp_sock, out, "despues") print("== captura DESPUES", flush=True) # EL NÚMERO. No «pinta / no pinta»: CUÁNTO TARDA. Medido el 2026-09-14 sobre esta misma @@ -314,7 +337,7 @@ def main(): # El número se PUBLICA donde lo pueda leer el vigía de la imagen, que es estático y no # arranca nada: sin esto el dato vive en el scrollback del que corrió la VM y se pierde, # que es exactamente lo que pasó con la corrida a mano del §6.10.ter. - anotar_medicion(primera, a) + anotar_medicion(primera, a, donde if primera is not None else None) # La evidencia que no se puede leer de una captura: qué hizo el widget de Wayland. print("---- atuq.log (cola) ----") diff --git a/scripts/vigia-imagen.py b/scripts/vigia-imagen.py index c8fc00e3..cef8c4f4 100644 --- a/scripts/vigia-imagen.py +++ b/scripts/vigia-imagen.py @@ -43,6 +43,10 @@ # Ninguno contesta «¿y cuándo se ve?» — y esa pregunta ya cobró: el §6.10.ter del SDD 26 dio por # hecho que `atuq` «no pinta nunca» en la imagen arrancada CON ESTE VIGÍA EN ✓, y la medición # repetida mostró que pintaba a los +137…+204 s. Lo medido había sido la paciencia. +# Y el 2026-09-14, peor: con DOS tarjetas DRM la ventana cae en cualquiera de las dos salidas, y las +# capturas miraban UNA ⇒ el «3 de 13» que se publicó medía dónde apuntaba la cámara. Por eso el dato +# que se lee acá trae en qué PANTALLA apareció, y las corridas ciegas (dos salidas, una captura) no +# se cuentan. # Arrancar la imagen son ~15 min de QEMU sin KVM, así que no se hace acá: `scripts/cosmic/atuq-en- # imagen.py` lo mide y deja el número en `docs/state/primera-pintura.json`, y este vigía lo LEE y lo # dice con sus condiciones (lanzamiento, vídeo, RAM, vcpus) — el tiempo depende de la carga de la @@ -273,26 +277,38 @@ def informe_primera_pintura(): print(" ⊘ el fichero no tiene corridas") return False - # Se informan TODAS las corridas y no la última, porque el fenómeno es INTERMITENTE: el - # 2026-09-14 dos corridas idénticas dieron «+204 s» y «no pintó en 900 s». Un solo número acá - # sería el de la corrida que tocó, y el lector lo leería como el del producto. + # Se informan TODAS las corridas y no la última, porque el fenómeno es INTERMITENTE. Y se separan + # por CUÁNTAS SALIDAS fotografió cada una: medido el 2026-09-14, con dos tarjetas DRM la ventana + # cae en cualquiera de las dos salidas, así que un ✗ de una corrida que sólo miró una pantalla NO + # dice que la ventana no esté: dice que no estaba EN ESA. Contarlos juntos fue lo que produjo un + # «3 de 13» que medía la cámara y no el producto. + ciegas = [c for c in corridas if c.get("pantallas_fotografiadas", 1) < 2 + and "dos DRM" in (c.get("video") or "") + and c.get("segundos_primera_pintura") is None] + corridas = [c for c in corridas if c not in ciegas] pintaron = [c["segundos_primera_pintura"] for c in corridas if c.get("segundos_primera_pintura") is not None] n, m = len(pintaron), len(corridas) marca = "✓" if n == m else ("✗" if n == 0 else "⚠") + if ciegas: + marca = "⚠" # con corridas ciegas de por medio, un 6/6 no es un ✓: es un «lo que se pudo medir» if pintaron: - print(" %s pintaron %d de %d corridas · primera pintura %s" + print(" %s pintaron %d de %d corridas CONCLUYENTES · primera pintura %s" % (marca, n, m, ("+%ds" % pintaron[0]) if n == 1 else "+%d…+%ds" % (min(pintaron), max(pintaron)))) else: print(" %s NINGUNA de %d corridas pintó" % (marca, m)) for c in corridas[-6:]: seg = c.get("segundos_primera_pintura") - print(" %s %-9s %-22s %-26s %s" + print(" %s %-9s %-10s %-22s %-26s %s" % ("✓" if seg is not None else "✗", ("+%ds" % seg) if seg is not None else "—", + (c.get("pantalla") or "")[:10], c.get("lanzamiento", "?"), c.get("video", "?"), (c.get("medido") or "")[:16])) + if ciegas: + print(" ⚠ %d corridas NO se cuentan: con dos salidas fotografiaron UNA sola, y su ✗ sólo" + " dice que la ventana no estaba en esa pantalla" % len(ciegas)) fallidas = [c for c in corridas if c.get("segundos_primera_pintura") is None] if fallidas: print(" ⚠ en las que NO pintó, el MOZ_LOG igual decía `mapped 1` + «has buffer» +"