From 3a92492fcce38e216eae7c7c20f23248022fd9e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 03:40:37 +0000 Subject: [PATCH 1/2] Initial plan From 0590ba3b6c7ea30eca21fdc0b928cc60c4b37bf8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 03:45:12 +0000 Subject: [PATCH 2/2] fix: improve Otter Stop speed progression and fix image sizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace linear 50ms/level speed step with geometric decay (rate=0.88), giving ~180ms jumps at low levels tapering down as the game speeds up - Fix .os-stimulus__img to fill container (width/height 100%) matching feedback images, removing the inconsistent 60px margin - Update game.test.js to reflect new interval values (level 1 → 1320ms, floor reached at level 19 instead of 27) Agent-Logs-Url: https://github.com/acrosman/BrainSpeedExercises/sessions/fb773e3e-8af1-4904-8604-366062d9b0ab Co-authored-by: acrosman <2972053+acrosman@users.noreply.github.com> --- app/games/otter-stop/game.js | 14 ++++++++++---- app/games/otter-stop/style.css | 4 ++-- app/games/otter-stop/tests/game.test.js | 8 ++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/games/otter-stop/game.js b/app/games/otter-stop/game.js index 43f7945..1f6aad9 100644 --- a/app/games/otter-stop/game.js +++ b/app/games/otter-stop/game.js @@ -49,8 +49,12 @@ export function setGoKeys(keys) { /** Display interval at level 0 (milliseconds). */ const BASE_INTERVAL_MS = 1500; -/** How much the interval shrinks per level (milliseconds). */ -const INTERVAL_STEP_MS = 50; +/** + * Geometric decay factor applied to the display interval per level. + * Each level multiplies the current interval by this rate, producing large + * speed jumps at low levels that taper off as the game becomes faster. + */ +const INTERVAL_DECAY_RATE = 0.88; /** Minimum allowed display interval (milliseconds). */ const MIN_INTERVAL_MS = 150; @@ -263,12 +267,14 @@ export function recordResponse(isNoGo, spacePressed) { /** * Return the display interval in milliseconds for the current level. - * Starts at 700 ms and decreases by 50 ms per level, with a floor of 150 ms. + * Uses geometric decay: each level multiplies the base interval by + * INTERVAL_DECAY_RATE, producing large speed jumps early and increasingly + * smaller increments as the game gets faster. Floored at MIN_INTERVAL_MS. * * @returns {number} Display interval in milliseconds. */ export function getCurrentIntervalMs() { - return Math.max(BASE_INTERVAL_MS - level * INTERVAL_STEP_MS, MIN_INTERVAL_MS); + return Math.max(Math.round(BASE_INTERVAL_MS * (INTERVAL_DECAY_RATE ** level)), MIN_INTERVAL_MS); } // ── Getters ─────────────────────────────────────────────────────────────────── diff --git a/app/games/otter-stop/style.css b/app/games/otter-stop/style.css index 85d70f5..f84c2d7 100644 --- a/app/games/otter-stop/style.css +++ b/app/games/otter-stop/style.css @@ -69,8 +69,8 @@ } .os-stimulus__img { - max-width: min(440px, calc(50vmin - 60px)); - max-height: min(440px, calc(50vmin - 60px)); + width: 100%; + height: 100%; object-fit: contain; transition: opacity 0.08s ease; pointer-events: none; diff --git a/app/games/otter-stop/tests/game.test.js b/app/games/otter-stop/tests/game.test.js index 4c12d8f..e731c38 100644 --- a/app/games/otter-stop/tests/game.test.js +++ b/app/games/otter-stop/tests/game.test.js @@ -510,16 +510,16 @@ describe('getCurrentIntervalMs()', () => { expect(getCurrentIntervalMs()).toBe(1500); }); - it('returns 1450 at level 1 (after 3 correct no-go inhibitions)', () => { + it('returns 1320 at level 1 (after 3 correct no-go inhibitions)', () => { recordResponse(true, false); recordResponse(true, false); recordResponse(true, false); - expect(getCurrentIntervalMs()).toBe(1450); + expect(getCurrentIntervalMs()).toBe(1320); // Math.round(1500 * 0.88) }); it('returns 150 at a high level (floor clamped)', () => { - // 3 no-go correct per level, need level 27 → (1500 - 27*50 = 150) - for (let i = 0; i < 81; i += 1) recordResponse(true, false); + // 3 no-go correct per level; floor is reached at level 19 (Math.round(1500 * 0.88^19) < 150) + for (let i = 0; i < 57; i += 1) recordResponse(true, false); expect(getCurrentIntervalMs()).toBe(150); });