Rename jsPsych.end... functions to jsPsych.abort... and implement abortCurrentTimeline

This commit is contained in:
bjoluc 2022-11-08 22:27:32 +01:00
parent b6e096a1cc
commit 2092d12a60
8 changed files with 28 additions and 52 deletions

View File

@ -5,7 +5,7 @@
<script src="../packages/plugin-html-keyboard-response/dist/index.browser.js"></script>
<script src="../packages/plugin-image-keyboard-response/dist/index.browser.js"></script>
<script src="../packages/plugin-preload/dist/index.browser.js"></script>
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css">
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css" />
</head>
<body></body>
<script>
@ -37,7 +37,7 @@
prompt: '<p>Press "y" to continue. Press "n" to end this node of the experiment.</p>',
on_finish: function(data) {
if (jsPsych.pluginAPI.compareKeys(data.response, "n")) {
jsPsych.endCurrentTimeline();
jsPsych.abortCurrentTimeline();
}
},
timeline: trials
@ -49,6 +49,5 @@
};
jsPsych.run([preload, block, after_block]);
</script>
</html>

View File

@ -4,7 +4,7 @@
<script src="../packages/jspsych/dist/index.browser.js"></script>
<script src="../packages/plugin-image-keyboard-response/dist/index.browser.js"></script>
<script src="../packages/plugin-preload/dist/index.browser.js"></script>
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css">
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css" />
</head>
<body></body>
<script>
@ -32,13 +32,12 @@
stimulus_width: 300,
on_finish: function(data) {
if (jsPsych.pluginAPI.compareKeys(data.response, 'n')) {
jsPsych.endExperiment('The experiment was ended. This is the end message.');
jsPsych.abortExperiment('The experiment was ended. This is the end message.');
}
},
timeline: trials
};
jsPsych.run([preload, block]);
</script>
</html>

View File

@ -10,3 +10,4 @@ A growing list of implemented 8.0 changes so we don't loose track
- Drop `jsPsych.data.getDataByTimelineNode()` since nodes have no IDs anymore
- Trial results do no longer have the `internal_node_id` property
- `save_trial_parameters` can only be used to remove parameters that are specified in the plugin info
- `endExperiment()` and `endCurrentTimeline()` => `abortExperiment()` and `abortCurrentTimeline()`

View File

@ -176,7 +176,7 @@ export class JsPsych {
getProgress() {
return {
total_trials: this.timeline?.getNaiveTrialCount(),
current_trial_global: 0, // TODO This used to be `this.global_trial_index` is a global trial index still needed / does it make sense and, if so, how should it be maintained?
current_trial_global: this.timeline?.getLatestNode().index ?? 0,
percent_complete: this.timeline?.getNaiveProgress() * 100,
};
}
@ -200,8 +200,7 @@ export class JsPsych {
return this.domContainer;
}
// TODO Should this be called `abortExperiment()`?
endExperiment(endMessage?: string, data = {}) {
abortExperiment(endMessage?: string, data = {}) {
this.endMessage = endMessage;
this.timeline.abort();
this.pluginAPI.cancelAllKeyboardResponses();
@ -209,9 +208,14 @@ export class JsPsych {
this.finishTrial(data);
}
// TODO Is there a legit use case for this "global" function that cannot be achieved with callback functions in trial/timeline descriptions?
endCurrentTimeline() {
// this.timeline.endActiveNode();
abortCurrentTimeline() {
let currentTimeline = this.timeline?.getLatestNode();
if (currentTimeline instanceof Trial) {
currentTimeline = currentTimeline.parent;
}
if (currentTimeline instanceof Timeline) {
currentTimeline.abort();
}
}
getCurrentTrial() {
@ -254,7 +258,7 @@ export class JsPsych {
}
getTimeline() {
return this.timeline?.description;
return this.timeline?.description.timeline;
}
get extensions() {

View File

@ -11,7 +11,7 @@ test("works on basic timeline", async () => {
type: htmlKeyboardResponse,
stimulus: "trial 1",
on_finish: () => {
jsPsych.endExperiment("the end");
jsPsych.abortExperiment("the end");
},
},
{
@ -35,7 +35,7 @@ test("works with looping timeline (#541)", async () => {
{
timeline: [{ type: htmlKeyboardResponse, stimulus: "trial 1" }],
loop_function: () => {
jsPsych.endExperiment("the end");
jsPsych.abortExperiment("the end");
},
},
],
@ -64,7 +64,7 @@ test("if on_finish returns a Promise, wait for resolve before showing end messag
type: htmlKeyboardResponse,
stimulus: "foo",
on_finish: () => {
jsPsych.endExperiment("done");
jsPsych.abortExperiment("done");
},
},
{

View File

@ -1,7 +1,7 @@
import htmlKeyboardResponse from "@jspsych/plugin-html-keyboard-response";
import { clickTarget, pressKey, simulateTimeline } from "@jspsych/test-utils";
import { JsPsych, JsPsychPlugin, ParameterType, TrialType, initJsPsych } from "../../src";
import { JsPsych, ParameterType, initJsPsych } from "../../src";
jest.useFakeTimers();
@ -306,7 +306,7 @@ describe("data simulation mode", () => {
expect(getData().values()[2].rt).toBe(200);
});
test("endExperiment() works in simulation mode", async () => {
test("abortExperiment() works in simulation mode", async () => {
const jsPsych = initJsPsych();
const timeline = [
@ -314,7 +314,7 @@ describe("data simulation mode", () => {
type: htmlKeyboardResponse,
stimulus: "foo",
on_finish: () => {
jsPsych.endExperiment("done");
jsPsych.abortExperiment("done");
},
},
{

View File

@ -378,8 +378,7 @@ describe("conditional function", () => {
});
});
// TODO Do we need `endCurrentTimeline`?
describe.skip("endCurrentTimeline", () => {
describe("endCurrentTimeline", () => {
test("stops the current timeline, skipping to the end after the trial completes", async () => {
const jsPsych = initJsPsych();
const { getHTML } = await startTimeline(
@ -390,7 +389,7 @@ describe.skip("endCurrentTimeline", () => {
type: htmlKeyboardResponse,
stimulus: "foo",
on_finish: () => {
jsPsych.endCurrentTimeline();
jsPsych.abortCurrentTimeline();
},
},
{
@ -425,7 +424,7 @@ describe.skip("endCurrentTimeline", () => {
type: htmlKeyboardResponse,
stimulus: "foo",
on_finish: () => {
jsPsych.endCurrentTimeline();
jsPsych.abortCurrentTimeline();
},
},
{
@ -485,29 +484,3 @@ describe("nested timelines", () => {
await pressKey("a");
});
});
// TODO Should we have such a function?
// describe("add node to end of timeline", () => {
// test("adds node to end of timeline", async () => {
// const jsPsych = initJsPsych();
// const { getHTML } = await startTimeline(
// [
// {
// type: htmlKeyboardResponse,
// stimulus: "foo",
// on_start: () => {
// jsPsych.addNodeToEndOfTimeline({
// timeline: [{ type: htmlKeyboardResponse, stimulus: "bar" }],
// });
// },
// },
// ],
// jsPsych
// );
// expect(getHTML()).toMatch("foo");
// await pressKey("a");
// expect(getHTML()).toMatch("bar");
// await pressKey("a");
// });
// });

View File

@ -373,7 +373,7 @@ class BrowserCheckPlugin implements JsPsychPlugin<Info> {
const trial_data = { ...Object.fromEntries(feature_data) };
this.jsPsych.endExperiment(this.t.exclusion_message(trial_data), trial_data);
this.jsPsych.abortExperiment(this.t.exclusion_message(trial_data), trial_data);
}
simulate(
@ -429,7 +429,7 @@ class BrowserCheckPlugin implements JsPsychPlugin<Info> {
if (trial.inclusion_function(data)) {
this.jsPsych.finishTrial(data);
} else {
this.jsPsych.endExperiment(trial.exclusion_message(data), data);
this.jsPsych.abortExperiment(trial.exclusion_message(data), data);
}
});
}