From 1b664822c5bdb4a6cfd7b6c65ff7d0a966d6ce56 Mon Sep 17 00:00:00 2001 From: Mandyx22 <1915537307@qq.com> Date: Tue, 26 May 2026 16:15:19 -0400 Subject: [PATCH 1/2] make sure the new emoji is different from the last one placed on the canvas --- .changeset/slimy-horses-yawn.md | 5 +++++ .../plugin-emoji-screen/src/index.spec.ts | 22 +++++++++++++++++++ packages/plugin-emoji-screen/src/index.ts | 18 ++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 .changeset/slimy-horses-yawn.md diff --git a/.changeset/slimy-horses-yawn.md b/.changeset/slimy-horses-yawn.md new file mode 100644 index 0000000..d59dcc4 --- /dev/null +++ b/.changeset/slimy-horses-yawn.md @@ -0,0 +1,5 @@ +--- +"@jspsych/plugin-emoji-screen": patch +--- + +make sure the new emoji added to the canvas is not the same as the previous one diff --git a/packages/plugin-emoji-screen/src/index.spec.ts b/packages/plugin-emoji-screen/src/index.spec.ts index 58eb3c2..d2b016b 100644 --- a/packages/plugin-emoji-screen/src/index.spec.ts +++ b/packages/plugin-emoji-screen/src/index.spec.ts @@ -68,6 +68,28 @@ describe("emoji-screen", () => { expect(emojiElements.length).toBe(3); }); + it("does not place the same emoji", async () => { + const { displayElement } = await startTimeline([ + { + type: emojiScreen, + emojis: ["😀", "🎉"], + }, + ]); + + const canvas = displayElement.querySelector("#jspsych-emoji-screen-canvas"); + + for (let i = 0; i < 3; i++) { + canvas.dispatchEvent( + new MouseEvent("click", { clientX: 10 + i * 50, clientY: 10, bubbles: true }) + ); + } + + const emojiElements = canvas.querySelectorAll("span[data-emoji]"); + for (let i = 1; i < emojiElements.length; i++) { + expect(emojiElements[i].textContent).not.toBe(emojiElements[i - 1].textContent); + } + }); + it("ends the trial when the key_to_finish key is pressed", async () => { const { expectFinished, getData } = await startTimeline([ { diff --git a/packages/plugin-emoji-screen/src/index.ts b/packages/plugin-emoji-screen/src/index.ts index 87d2050..c496384 100644 --- a/packages/plugin-emoji-screen/src/index.ts +++ b/packages/plugin-emoji-screen/src/index.ts @@ -97,8 +97,14 @@ class EmojiScreenPlugin implements JsPsychPlugin { const x = Math.round(event.clientX - rect.left); const y = Math.round(event.clientY - rect.top); - // Pick a random emoji from the pool - const emoji = trial.emojis[Math.floor(Math.random() * trial.emojis.length)]; + // Pick a random emoji from the pool (different from the previous one) + + const lastEmoji = emoji_locations.at(-1)?.emoji; + let emoji = trial.emojis[Math.floor(Math.random() * trial.emojis.length)]; + if (emoji_locations.length > 0 && emoji === lastEmoji) { + const availableEmojis = trial.emojis.filter(e => e !== lastEmoji); + emoji = availableEmojis[Math.floor(Math.random() * availableEmojis.length)]; + } // Place the emoji at the click location const emojiEl = document.createElement("span"); @@ -162,10 +168,16 @@ class EmojiScreenPlugin implements JsPsychPlugin { const num_clicks = this.jsPsych.randomization.randomInt(1, 5); const simulated_locations: EmojiLocation[] = []; for (let i = 0; i < num_clicks; i++) { + const lastEmoji = simulated_locations.at(-1)?.emoji; + let emoji = trial.emojis[this.jsPsych.randomization.randomInt(0, trial.emojis.length - 1)]; + if (simulated_locations.length > 0 && emoji === lastEmoji) { + const availableEmojis = trial.emojis.filter(e => e !== lastEmoji); + emoji = availableEmojis[this.jsPsych.randomization.randomInt(0, availableEmojis.length - 1)]; + } simulated_locations.push({ x: this.jsPsych.randomization.randomInt(0, 800), y: this.jsPsych.randomization.randomInt(0, 400), - emoji: trial.emojis[this.jsPsych.randomization.randomInt(0, trial.emojis.length - 1)], + emoji: emoji, }); } From 4874f60f888f4969edbe621e6078d17e2549bf16 Mon Sep 17 00:00:00 2001 From: Mandyx22 <1915537307@qq.com> Date: Tue, 26 May 2026 16:28:41 -0400 Subject: [PATCH 2/2] fix the single emoji pool edge case --- packages/plugin-emoji-screen/src/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/plugin-emoji-screen/src/index.ts b/packages/plugin-emoji-screen/src/index.ts index c496384..9b62dcd 100644 --- a/packages/plugin-emoji-screen/src/index.ts +++ b/packages/plugin-emoji-screen/src/index.ts @@ -103,7 +103,9 @@ class EmojiScreenPlugin implements JsPsychPlugin { let emoji = trial.emojis[Math.floor(Math.random() * trial.emojis.length)]; if (emoji_locations.length > 0 && emoji === lastEmoji) { const availableEmojis = trial.emojis.filter(e => e !== lastEmoji); - emoji = availableEmojis[Math.floor(Math.random() * availableEmojis.length)]; + emoji = availableEmojis.length > 0 + ? availableEmojis[Math.floor(Math.random() * availableEmojis.length)] + : lastEmoji; } // Place the emoji at the click location @@ -172,7 +174,9 @@ class EmojiScreenPlugin implements JsPsychPlugin { let emoji = trial.emojis[this.jsPsych.randomization.randomInt(0, trial.emojis.length - 1)]; if (simulated_locations.length > 0 && emoji === lastEmoji) { const availableEmojis = trial.emojis.filter(e => e !== lastEmoji); - emoji = availableEmojis[this.jsPsych.randomization.randomInt(0, availableEmojis.length - 1)]; + emoji = availableEmojis.length > 0 + ? availableEmojis[this.jsPsych.randomization.randomInt(0, availableEmojis.length - 1)] + : lastEmoji; } simulated_locations.push({ x: this.jsPsych.randomization.randomInt(0, 800),