scripts/experiment-properties/instructions/instructions_controller.js
export {get_instructions}
/**
* Generates the instructions html for the given experiment.
*
* @param {object} experiment
*
* @return {string} html for the instructions jsPsych block
*/
function get_instructions(experiment) {
// EXPERIMENTS from experiments-config.js
let experiment_name = experiment.constructor.name.toLowerCase();
let instructions_info = EXPERIMENTS[experiment_name].instructions;
if (!instructions_info.default_html || instructions_info.default_html.length === 0) {
throw new Error("No default html specified for experiment " + experiment_name);
}
if (!instructions_info.default_images || instructions_info.default_images.length === 0) {
throw new Error("No default images are defined for experiment " + experiment_name);
}
let default_html = instructions_info.default_html;
let default_images = instructions_info.default_images;
let condition_instructions_object = CONDITIONS[experiment.condition_name].instructions;
// If there is custom html/images defined for this experiment
if (condition_instructions_object) {
return get_custom_instructions(experiment, condition_instructions_object, default_html, default_images);
}
// Else use default html and images
else {
return get_html_with_images(default_html, default_images);
}
}
/**
* Generates custom instructions depending on whether custom_html is defined, or
* custom_images is defined.
*
* @param {object} experiment
* @param {object} condition_instructions_object
* @param {string} default_html
* @param {array} default_images
*
* @return {string} html for custom instructions
*/
function get_custom_instructions(experiment, condition_instructions_object, default_html, default_images) {
// Validation check that experiment in instructions object is a supported experiment for the condition
Object.keys(condition_instructions_object).forEach(function(exp) {
if (!CONDITIONS[experiment.condition_name]["experiment"].includes(exp)) {
throw new Error("Experiment " + exp + " is listed within instructions key but is not among the supported experiments " +
"listed for the condition. Listed experiments are: " + CONDITIONS[experiment.condition_name]["experiment"] + ".");
}
});
let condition_instructions = condition_instructions_object[experiment.constructor.name.toLowerCase()];
// If no instructions for this experiment, use default
if (!condition_instructions) {
return get_html_with_images(default_html, default_images);
}
else {
// Validation check that must only have one key (custom_html or custom_images) defined
if (Object.keys(condition_instructions).length > 1) {
throw new Error("Only one key permitted inside instructions object for experiment " + experiment.constructor.name.toLowerCase() + ". Must be " +
"either custom_html or custom_images.");
}
// If there is custom html
if (condition_instructions.custom_html) {
return condition_instructions.custom_html;
}
// If there is custom images
else if (condition_instructions.custom_images) {
let images = condition_instructions.custom_images;
// Validation check that specified num of custom_images == num of default_images
if (images.length !== default_images.length) {
throw new Error("The default instruction for this experiment requires " + default_images.length + " image(s). " + images.length + " image(s) were specified for the condition instead.");
}
return get_html_with_images(default_html, images);
} else {
throw new Error("No custom_html or custom_images defined in instructions object for this condition for experiment " + experiment.constructor.name);
}
}
}
/**
* Replaces any 'image1.png', 'image2.png' ... etc with each string
* entry in images.
*
* NOTE: When defining default_html in experiments-config.js, need to name
* images as 'image1.png', 'image2.png' so this code knows what to replace
*
* @param {string} html
* @param {array} images
*
* @return {string} html with any 'image1.png' etc replaced with entries in images
*/
function get_html_with_images(html, images) {
let counter = 1;
for (let image_url of images) {
let url_to_replace = "image" + counter + ".png";
html = html.replace(url_to_replace, image_url);
counter++;
}
return html;
}