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..9b62dcd 100644 --- a/packages/plugin-emoji-screen/src/index.ts +++ b/packages/plugin-emoji-screen/src/index.ts @@ -97,8 +97,16 @@ 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.length > 0 + ? availableEmojis[Math.floor(Math.random() * availableEmojis.length)] + : lastEmoji; + } // Place the emoji at the click location const emojiEl = document.createElement("span"); @@ -162,10 +170,18 @@ 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.length > 0 + ? availableEmojis[this.jsPsych.randomization.randomInt(0, availableEmojis.length - 1)] + : lastEmoji; + } 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, }); }