From e0666135834e941c4fc9372d00792a4f45551e99 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Fri, 2 Oct 2026 20:33:21 +0200 Subject: [PATCH] Watch a held body for a time, not for a count of frames The suite to 46c620a (#294) was red by one check: e2e 41, "a body dragged while playing hangs where the pointer holds it and is let go at rest". The body hung where it should, on -3490 in every frame, and fell from rest. The check failed on its own bound of 30 frames while held: that run drew 21 in the second of holding, the green runs of the day drew 37 to 54. - The bound is now the time the hold was watched: 800 ms between the first and the last sample before the release, and five samples at least. - The detail of the check names that time next to the frames. - Nothing in src/ changes. This is not the wobble of 9cff528 and 543b052 (#282) once more. Those were about when the samples are taken, this one about how many a runner manages. Why that run was so slow is not known. Tests: - e2e 41 on melektaus-atx: 21 checks, all pass, 66 frames in 1114 ms while held. - No counter-probe: a run as slow as the red one was not reproduced. Co-Authored-By: Claude Opus 5.5 --- tools/e2e/41-physics.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/e2e/41-physics.mjs b/tools/e2e/41-physics.mjs index b7c2e829..9b84d74c 100644 --- a/tools/e2e/41-physics.mjs +++ b/tools/e2e/41-physics.mjs @@ -328,7 +328,11 @@ export async function physics(t) { const letGo = await evaluate('window.__dragLetGo'); const log = (await json('__gm.world()'))?.log ?? []; await stop(); - const held = dragSamples.filter((s) => s.t < letGo).map((s) => s.y); + const heldSamples = dragSamples.filter((s) => s.t < letGo); + const held = heldSamples.map((s) => s.y); + // How long the hold was watched, not how many frames that took: a busy runner drew 21 frames + // in the second a quiet one draws 50 in, and a count of 30 called that a failure. + const heldFor = held.length > 1 ? heldSamples.at(-1).t - heldSamples[0].t : 0; const released = dragSamples.filter((s) => s.t >= letGo); // 200 ms of free fall from rest is about 25 below the hold, a body let go at speed is not. const falling = released.filter((s) => s.t - letGo <= 200).map((s) => s.y); @@ -336,7 +340,8 @@ export async function physics(t) { check( 'a body dragged while playing hangs where the pointer holds it and is let go at rest', arrived && - held.length >= 30 && + held.length >= 5 && + heldFor >= 800 && held.every((y) => Math.abs(y - target) < 1.5) && // Let go it only falls: no jump above the hold, no kick up. How far the first frame after // the release has already fallen follows the frame time, so that is not a bound here. @@ -347,7 +352,7 @@ export async function physics(t) { JSON.stringify({ target, arrived, - held: { frames: held.length, first: held[0], last: held.at(-1) }, + held: { frames: held.length, ms: Math.round(heldFor), first: held[0], last: held.at(-1) }, stamped: typeof letGo === 'number', released: released.slice(0, 3).map((s) => [Math.round(s.t - letGo), s.y]), fell,