-
Hi, we plan an experiment, which contains several power tests (e.g., Test1, Test2). Each test should have a time limit (e.g., Test1 =>1 minute, Test2=> 2 minutes) and contain more trials than is possible to solve in the given amount of time. So for every participant will solve different amount of trials. If the time stops for the Test1, the experiment should go on with Test2. We would like to present all trials for Test1 on a single page as a survey-text. Thanks in advance, var test_stimuli = [
{ stimulus: "stimuli1"},
{ stimulus: "stimuli2"},
{ stimulus: "stimuli3"},
{ stimulus: "stimuli4"},
{ stimulus: "stimuli4"}
];
var test = {
type: "html-button-response",
stimulus: jsPsych.timelineVariable('stimulus'),
choices: ['Yes','No']
}
var test_procedure = {
timeline: [test],
timeline_variables: test_stimuli
}
timeline.push(test_procedure); |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 8 replies
-
Hi @gdaroczy , I think you'll need to modify the survey-text plugin to include a timeout. You can see how this is implemented in other plugins that have this feature. For example, here's a relevant chunk of the html-keyboard-response plugin. jsPsych/plugins/jspsych-html-keyboard-response.js Lines 140 to 144 in d621710 |
Beta Was this translation helpful? Give feedback.
-
Hi @gdaroczy, I'm not 100% sure what you're trying to do - do you want to stop the trial sequence from continuing after a certain time limit? If so, then I think this might work (disclaimer: it might not be the best/easiest way!): var time_limit = 2500;
var start_time;
var end_test_timer;
var trial_count = 0;
var timeline = [];
var test_stimuli = [
{ stimulus: "stimuli1" },
{ stimulus: "stimuli2" },
{ stimulus: "stimuli3" },
{ stimulus: "stimuli4" },
{ stimulus: "stimuli5" }
];
var n_trials = test_stimuli.length;
var test = {
type: "html-button-response",
stimulus: jsPsych.timelineVariable('stimulus'),
choices: ['Yes', 'No'],
on_load: function() {
trial_count++;
// we need to set up the timer to end the current timeline after a certain duration, but only on the first trial
if (trial_count == 1) {
start_time = performance.now();
var end_test_timer = setTimeout(function() {
// this stuff is just for testing
var end_time = performance.now();
var elapsed_time = end_time - start_time;
console.log("elapsed time: ", elapsed_time);
// this function is all you need to end the current timeline
jsPsych.endCurrentTimeline();
// this function ends the current trial
jsPsych.finishTrial({status: "ended early"});
}, time_limit);
}
},
on_finish: function(data) {
// we also need to cancel the setTimeout timer if the person gets all the way through the timeline before
// time_limit is reached, otherwise endCurrentTimeline will fire during the next timeline - not good!!
if (trial_count == n_trials) {
clearTimeout(end_test_timer);
}
}
}
var test_procedure = {
timeline: [test],
timeline_variables: test_stimuli
}
timeline.push(test_procedure);
timeline.push({
type: 'html-keyboard-response',
stimulus: "Time's up!",
choices: jsPsych.ALL_KEYS
});
jsPsych.init({
timeline: timeline,
on_finish: function () {
jsPsych.data.displayData();
}
}); Note that this will end the current trial early when the time limit is reached, and this is noted in the trial data with jsPsych.finishTrial({status: "ended early"}); Is that what you're trying to do? |
Beta Was this translation helpful? Give feedback.
-
Hi all, Thank you very much for your answers! I was trying to add a trial duration parameter in the survey-multi-select plugin (v8). Here is the modified plugin, and it works perfectly. I added the modified plugin here if anyone needs to make the same modification to their plugin. Here are the modifications I make:
Hopefully it helps! Thank! var jsPsychSurveyMultiSelect = (function (jspsych) { var version = "2.1.0"; const info = { var trial_form = display_element.querySelector("#" + trial_form_id); if (!trial.autocomplete) { trial_form.setAttribute("autocomplete", "off"); } var preamble_id_name = _join(plugin_id_name, "preamble"); if (trial.preamble !== null) { trial_form.innerHTML += ' ' + trial.preamble + " ";} var question_order = []; for (var i = 0; i < trial.questions.length; i++) { question_order.push(i); } if (trial.randomize_question_order) { question_order = this.jsPsych.randomization.shuffle(question_order); } for (var i = 0; i < trial.questions.length; i++) { var question = trial.questions[question_order[i]]; var question_id = question_order[i]; var question_classes = [_join(plugin_id_name, "question")]; if (question.horizontal) { question_classes.push(_join(plugin_id_name, "horizontal")); } trial_form.innerHTML += '<div id="' + _join(plugin_id_name, question_id) + '" data-name="' + question.name + '" class="' + question_classes.join(" ") + '">'; var question_selector = _join(plugin_id_selector, question_id); display_element.querySelector(question_selector).innerHTML += ' ' + question.prompt + " ";for (var j = 0; j < question.options.length; j++) { var option_id_name = _join(plugin_id_name, "option", question_id, j); display_element.querySelector(question_selector).innerHTML += '<div id="' + option_id_name + '" class="' + _join(plugin_id_name, "option") + '">'; var form = document.getElementById(option_id_name); var input_name = _join(plugin_id_name, "response", question_id); var input_id = _join(plugin_id_name, "response", question_id, j); var label = document.createElement("label"); label.setAttribute("class", plugin_id_name + "-text"); label.innerHTML = question.options[j]; label.setAttribute("for", input_id); var input = document.createElement("input"); input.setAttribute("type", "checkbox"); input.setAttribute("name", input_name); input.setAttribute("id", input_id); input.setAttribute("value", question.options[j]); form.appendChild(label); label.insertBefore(input, label.firstChild); } } trial_form.innerHTML += ''; trial_form.innerHTML += '' + trial.button_label + ""; display_element.querySelector("#jspsych-survey-multi-select-next").addEventListener("click", () => { for (var i2 = 0; i2 < trial.questions.length; i2++) { if (trial.questions[i2].required) { if (display_element.querySelector( "#jspsych-survey-multi-select-" + i2 + " input:checked" ) == null) { display_element.querySelector("#jspsych-survey-multi-select-" + i2 + " input").setCustomValidity(trial.required_message); } else { display_element.querySelector("#jspsych-survey-multi-select-" + i2 + " input").setCustomValidity(""); } } } trial_form.reportValidity(); }); /end trial if trial duration is set/ let timeoutID; if(trial.trial_duration !== null){ jsPsych.pluginAPI.setTimeout(() => { trial_form.dispatchEvent(new Event('submit', {cancelable: true, bubbles: true})); },trial.trial_duration); } trial_form.addEventListener("submit", (event) => { if(timeoutID){ this.jsPsych.pluginAPI.clearAllTimeouts(); } event.preventDefault(); var endTime = performance.now(); var response_time = Math.round(endTime - startTime); var question_data = {}; for (var index = 0; index < trial.questions.length; index++) { var match = display_element.querySelector("#jspsych-survey-multi-select-" + index); var val = []; var inputboxes = match.querySelectorAll("input[type=checkbox]:checked"); for (var j2 = 0; j2 < inputboxes.length; j2++) { var currentChecked = inputboxes[j2]; val.push(currentChecked.value); } var id = "Q" + index; var obje = {}; var name = id; if (match.attributes["data-name"].value !== "") { name = match.attributes["data-name"].value; } obje[name] = val; Object.assign(question_data, obje); if (val.length == 0) ; } var trial_data = { rt: response_time, response: question_data, question_order }; this.jsPsych.finishTrial(trial_data); }); var startTime = performance.now(); } simulate(trial, simulation_mode, simulation_options, load_callback) { if (simulation_mode == "data-only") { load_callback(); this.simulate_data_only(trial, simulation_options); } if (simulation_mode == "visual") { this.simulate_visual(trial, simulation_options, load_callback); } } create_simulation_data(trial, simulation_options) { const question_data = {}; let rt = 1e3; for (const q of trial.questions) { let n_answers; if (q.required) { n_answers = this.jsPsych.randomization.randomInt(1, q.options.length); } else { n_answers = this.jsPsych.randomization.randomInt(0, q.options.length); } const name = q.name ? q.name : Q${trial.questions.indexOf(q)} ;const selections = this.jsPsych.randomization.sampleWithoutReplacement(q.options, n_answers); question_data[name] = selections; rt += this.jsPsych.randomization.sampleExGaussian(1500, 400, 1 / 200, true); } const default_data = { response: question_data, rt, question_order: trial.randomize_question_order ? this.jsPsych.randomization.shuffle([...Array(trial.questions.length).keys()]) : [...Array(trial.questions.length).keys()] }; const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options); this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data); return data; } simulate_data_only(trial, simulation_options) { const data = this.create_simulation_data(trial, simulation_options); this.jsPsych.finishTrial(data); } simulate_visual(trial, simulation_options, load_callback) { const data = this.create_simulation_data(trial, simulation_options); const display_element = this.jsPsych.getDisplayElement(); this.trial(display_element, trial); load_callback(); const answers = Object.entries(data.response); for (let i = 0; i < answers.length; i++) { for (const a of answers[i][1]) { this.jsPsych.pluginAPI.clickTarget( display_element.querySelector( #jspsych-survey-multi-select-response-${i}-${trial.questions[i].options.indexOf(a)} ), (data.rt - 1e3) / answers.length * (i + 1) ); } } this.jsPsych.pluginAPI.clickTarget( display_element.querySelector("#jspsych-survey-multi-select-next"), data.rt ); } } return SurveyMultiSelectPlugin; })(jsPsychModule); |
Beta Was this translation helpful? Give feedback.
Hi @gdaroczy ,
I think you'll need to modify the survey-text plugin to include a timeout. You can see how this is implemented in other plugins that have this feature. For example, here's a relevant chunk of the html-keyboard-response plugin.
jsPsych/plugins/jspsych-html-keyboard-response.js
Lines 140 to 144 in d621710