Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add response_ends_trial for visual search circle plugin #3211

Merged
merged 4 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strong-ligers-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@jspsych/plugin-visual-search-circle": minor
---

Adds response_ends_trial parameter, with a default value of `true`
1 change: 1 addition & 0 deletions docs/plugins/visual-search-circle.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The `target_present` and `fixation_image` parameters must always be specified. O
| target_absent_key | string | 'f' | The key to press if the target is not present in the search array. |
| trial_duration | numeric | null | The maximum amount of time the participant is allowed to search before the trial will continue. A value of null will allow the participant to search indefinitely. |
| fixation_duration | numeric | 1000 | How long to show the fixation image for before the search array (in milliseconds). |
| response_ends_trial| boolean | true | If true, the trial will end when the participant makes a response. |

## Data Generated

Expand Down
30 changes: 30 additions & 0 deletions packages/plugin-visual-search-circle/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,36 @@ describe("visual-search-circle", () => {

expect(getData().values()[0].correct).toBe(true);
});

it("wait when response_ends_trial is false", async () => {
const { displayElement, expectFinished, expectRunning, getData } = await startTimeline([
{
type: visualSearchCircle,
target: "target.png",
foil: "foil.png",
fixation_image: "fixation.png",
set_size: 4,
target_present: true,
target_present_key: "a",
target_absent_key: "b",
response_ends_trial: false,
trial_duration: 1500,
},
]);

expect(displayElement.querySelectorAll("img").length).toBe(1);

jest.advanceTimersByTime(1000); // fixation duration

expect(displayElement.querySelectorAll("img").length).toBe(5);
pressKey("a");
await expectRunning();

jest.runAllTimers();
await expectFinished();

expect(getData().values()[0].correct).toBe(true);
});
});

describe("visual-search-circle simulation", () => {
Expand Down
53 changes: 30 additions & 23 deletions packages/plugin-visual-search-circle/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ const info = <const>{
pretty_name: "Fixation duration",
default: 1000,
},
/** Whether a keyboard response ends the trial early */
response_ends_trial: {
type: ParameterType.BOOL,
pretty_name: "Response ends trial",
default: true,
},
},
};

Expand Down Expand Up @@ -153,12 +159,21 @@ class VisualSearchCirclePlugin implements JsPsychPlugin<Info> {
}, trial.fixation_duration);
};

const end_trial = (rt: number, correct: boolean, key_press: string) => {
const response = {
rt: null,
key: null,
correct: false,
};

const end_trial = () => {
this.jsPsych.pluginAPI.clearAllTimeouts();
this.jsPsych.pluginAPI.cancelAllKeyboardResponses();

// data saving
var trial_data = {
correct: correct,
rt: rt,
response: key_press,
const trial_data = {
correct: response.correct,
rt: response.rt,
response: response.key,
locations: display_locs,
target_present: trial.target_present,
set_size: trial.set_size,
Expand Down Expand Up @@ -186,11 +201,7 @@ class VisualSearchCirclePlugin implements JsPsychPlugin<Info> {
"px;'></img>";
}

var trial_over = false;

const after_response = (info: { key: string; rt: number }) => {
trial_over = true;

var correct = false;

if (
Expand All @@ -202,12 +213,16 @@ class VisualSearchCirclePlugin implements JsPsychPlugin<Info> {
correct = true;
}

clear_display();
response.rt = info.rt;
response.key = info.key;
response.correct = correct;

end_trial(info.rt, correct, info.key);
if (trial.response_ends_trial) {
end_trial();
}
};

var valid_keys = [trial.target_present_key, trial.target_absent_key];
const valid_keys = [trial.target_present_key, trial.target_absent_key];

const key_listener = this.jsPsych.pluginAPI.getKeyboardResponse({
callback_function: after_response,
Expand All @@ -219,19 +234,11 @@ class VisualSearchCirclePlugin implements JsPsychPlugin<Info> {

if (trial.trial_duration !== null) {
this.jsPsych.pluginAPI.setTimeout(() => {
if (!trial_over) {
if (!response.rt) {
this.jsPsych.pluginAPI.cancelKeyboardResponse(key_listener);

trial_over = true;

var rt = null;
var correct = false;
var key_press = null;

clear_display();

end_trial(rt, correct, key_press);
}

end_trial();
}, trial.trial_duration);
}

Expand Down