From 3408c25e9ee43e66d43e0af346479e50d5c2831a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 01:10:34 +0000 Subject: [PATCH 1/3] Initial plan From ce060553f01456e31a513a62e8d25fa43ad4e9f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 01:14:40 +0000 Subject: [PATCH 2/3] Add 15ms lead-in before Fast Piggie image flash --- app/games/fast-piggie/index.js | 28 +++++++++++++---------- app/games/fast-piggie/tests/index.test.js | 8 +++++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/games/fast-piggie/index.js b/app/games/fast-piggie/index.js index cbe4db0..8c05b8f 100644 --- a/app/games/fast-piggie/index.js +++ b/app/games/fast-piggie/index.js @@ -240,6 +240,7 @@ let _clickEnabled = false; let _selectedWedge = -1; // for keyboard navigation let _hoveredWedge = -1; // for mouse hover highlighting let _roundTimer = null; // setTimeout handle +const ROUND_IMAGE_FLASH_DELAY_MS = 15; /** * Updates the score, round count, and display time in the UI. @@ -319,19 +320,22 @@ function _runRound() { _currentRound = { ...round, slotAssignment }; const { width, height } = _canvas; - drawBoard( - _ctx, width, height, wedgeCount, imageCount, _images, - outlierWedgeIndex, true, slotAssignment, - ); - + clearImages(_ctx, width, height, wedgeCount); _roundTimer = setTimeout(() => { - clearImages(_ctx, width, height, wedgeCount); - _currentRound._imagesHiddenAt = Date.now(); - _clickEnabled = true; - _hoveredWedge = -1; - _selectedWedge = -1; - _canvas.focus(); - }, displayDurationMs); + drawBoard( + _ctx, width, height, wedgeCount, imageCount, _images, + outlierWedgeIndex, true, slotAssignment, + ); + + _roundTimer = setTimeout(() => { + clearImages(_ctx, width, height, wedgeCount); + _currentRound._imagesHiddenAt = Date.now(); + _clickEnabled = true; + _hoveredWedge = -1; + _selectedWedge = -1; + _canvas.focus(); + }, displayDurationMs); + }, ROUND_IMAGE_FLASH_DELAY_MS); } /** diff --git a/app/games/fast-piggie/tests/index.test.js b/app/games/fast-piggie/tests/index.test.js index 93e70d9..9f97b7d 100644 --- a/app/games/fast-piggie/tests/index.test.js +++ b/app/games/fast-piggie/tests/index.test.js @@ -1185,6 +1185,14 @@ describe('_triggerFlash and next-round timers', () => { }); }); +describe('_runRound image flash timing', () => { + it('schedules the image flash 15ms after wedges are hidden', () => { + const setTimeoutSpy = jest.spyOn(globalThis, 'setTimeout'); + plugin.start(); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 15); + }); +}); + // =========================================================================== // loadImages onerror path and init() .catch() fallback // (f[4] and f[33] in index.js) From 75776b29875fe5286c2e5141c86c5fe277b43117 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 01:18:08 +0000 Subject: [PATCH 3/3] Adjust Fast Piggie flash timing with 15ms lead-in --- app/games/fast-piggie/index.js | 22 +++++++++++++++++++++- app/games/fast-piggie/tests/index.test.js | 12 ++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/games/fast-piggie/index.js b/app/games/fast-piggie/index.js index 8c05b8f..e11b213 100644 --- a/app/games/fast-piggie/index.js +++ b/app/games/fast-piggie/index.js @@ -240,6 +240,8 @@ let _clickEnabled = false; let _selectedWedge = -1; // for keyboard navigation let _hoveredWedge = -1; // for mouse hover highlighting let _roundTimer = null; // setTimeout handle +let _imageFlashTimer = null; // setTimeout handle before image flash +// Give the board a small lead-in so previous wedge highlights clear before image flash starts. const ROUND_IMAGE_FLASH_DELAY_MS = 15; /** @@ -303,6 +305,15 @@ function _highlightKeyboardSelection() { function _runRound() { if (!game.isRunning()) return; + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } + if (_roundTimer) { + clearTimeout(_roundTimer); + _roundTimer = null; + } + _clickEnabled = false; _selectedWedge = -1; const round = game.generateRound(game.getLevel(), game.getSpeedLevel()); @@ -321,7 +332,8 @@ function _runRound() { const { width, height } = _canvas; clearImages(_ctx, width, height, wedgeCount); - _roundTimer = setTimeout(() => { + _imageFlashTimer = setTimeout(() => { + _imageFlashTimer = null; drawBoard( _ctx, width, height, wedgeCount, imageCount, _images, outlierWedgeIndex, true, slotAssignment, @@ -618,6 +630,10 @@ export default { * @returns {Promise} Game result */ async stop() { + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } if (_roundTimer) { clearTimeout(_roundTimer); _roundTimer = null; @@ -656,6 +672,10 @@ export default { * Reset the game to its initial state. */ reset() { + if (_imageFlashTimer) { + clearTimeout(_imageFlashTimer); + _imageFlashTimer = null; + } if (_roundTimer) { clearTimeout(_roundTimer); _roundTimer = null; diff --git a/app/games/fast-piggie/tests/index.test.js b/app/games/fast-piggie/tests/index.test.js index 9f97b7d..8cef8eb 100644 --- a/app/games/fast-piggie/tests/index.test.js +++ b/app/games/fast-piggie/tests/index.test.js @@ -1186,10 +1186,18 @@ describe('_triggerFlash and next-round timers', () => { }); describe('_runRound image flash timing', () => { + const mockedDisplayDurationMs = 2000; + it('schedules the image flash 15ms after wedges are hidden', () => { const setTimeoutSpy = jest.spyOn(globalThis, 'setTimeout'); - plugin.start(); - expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 15); + try { + plugin.start(); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 15); + jest.advanceTimersByTime(15); + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), mockedDisplayDurationMs); + } finally { + setTimeoutSpy.mockRestore(); + } }); });