import { initJsPsych } from 'jspsych'; import 'jspsych/css/jspsych.css'; import jsPsychHtmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response'; import jsPsychFullscreen from '@jspsych/plugin-fullscreen'; import jsPsychHtmlButtonResponse from '@jspsych/plugin-html-button-response'; import jsPsychSurvey from '@jspsych/plugin-survey'; import '@jspsych/plugin-survey/css/survey.css'; import './styles.css'; import { getStimulusMap } from './scripts/text-stimuli.js'; import { textStimuli } from './scripts/text-stimuli.js'; import JsPsychDieRoll from './plugins/jspsych-die-roll.js'; import JsPsychCaptcha from './plugins/jspsych-captcha.js'; import html from './utils/html.js'; const experiment_name = import.meta.env.VITE_EXPERIMENT_NAME; let prolific_id; let probe_condition; // will be set to ai or human based on the condition. let debug; let probe_order; // will be set to ai_first or human_first based on the condition const CAPTCHA_TRIAL_COUNT = debug ? 2 : 12; // set to 10 for main experiment function delayed_redirect(url) { setTimeout(() => { window.location = url; }, 5000); } const jsPsych = initJsPsych({ on_finish: function() { jsPsych.getDisplayElement().innerHTML = textStimuli.complete; }, on_close: function() { delayed_redirect(import.meta.env.VITE_CLOSED_URL); }, on_data_update: function() { if (debug) { console.log(jsPsych.data.get().json()); } }, show_progress_bar: true, }); debug = jsPsych.data.getURLVariable('debug') === 'true' || import.meta.env.VITE_DEBUG === 'true'; console.log('debug:', debug); prolific_id = jsPsych.data.getURLVariable('PROLIFIC_PID'); const COND = Number(jsPsych.data.getURLVariable('C')); const probe_preamble = `In this experiment, we told you that you would roll a die to determine the difficulty of the captcha task.\nHowever, `; const probe_closing_text = `\n\nPlease share your thoughts and suspicions about this by indicating your agreement with the following statements.`; const probe_text_die = probe_preamble + 'the die roll was rigged, so that the number you received (and therefore the difficulty of the captcha task) was pre-determined. ' + probe_closing_text; const probe_text_difficulty = probe_preamble + 'while the die roll was random, the difficulty of the captcha task was pre-determined and unrelated to the die roll. ' + probe_closing_text; let die_result = 3; switch (COND) { case 0: probe_condition = 'die'; probe_order = 'die_first'; die_result = 4; break; case 1: probe_condition = 'die'; probe_order = 'die_first'; die_result = 4; break; case 2: probe_condition = 'difficulty'; probe_order = 'die_first'; die_result = 4; break; case 3: probe_condition = 'difficulty'; probe_order = 'die_first'; die_result = 4; break; case 4: probe_condition = 'die'; probe_order = 'difficulty_first'; break; case 5: probe_condition = 'die'; probe_order = 'difficulty_first'; break; case 6: probe_condition = 'difficulty'; probe_order = 'difficulty_first'; break; case 7: probe_condition = 'difficulty'; probe_order = 'difficulty_first'; break; } const stimulusMap = getStimulusMap(); const props = { condition: probe_condition, prolific_id: prolific_id, experiment_name: experiment_name, probe_order: probe_order, cond: COND, }; if (debug) { console.log(props); } jsPsych.data.addProperties(props); const timeline = []; const pre_consent_info = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('pre_consent_info'), }; const enter_fullscreen = { type: jsPsychFullscreen, fullscreen_mode: true, }; const consent_form = { type: jsPsychHtmlButtonResponse, stimulus: stimulusMap.get('consent'), choices: ['Exit', 'Continue'], on_finish: function(data) { if (data.response === 0) { jsPsych.abortExperiment(stimulusMap.get('no_consent')); } }, }; const instructions_1 = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('instructions_1'), }; const instructions_2 = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('instructions_2'), }; const instructions_3 = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('instructions_3'), }; const debrief = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('debrief'), }; const pre_survey_info = { type: jsPsychHtmlKeyboardResponse, choices: [' '], stimulus: stimulusMap.get('pre_survey_info'), }; const die_roll_trial = { type: JsPsychDieRoll, prompt: html`

Click the die once to start it rolling, then click it again to stop.

`, rigged_value: die_result, roll_duration: 2200, result_template: `You rolled a {{value}} (moderate difficulty). Click 'continue' to proceed.`, }; const create_captcha_trial = trial_index => { return { type: JsPsychCaptcha, prompt: '

Enter the characters you see into the textbox below.

', difficulty: die_result, button_label: 'Continue', error_text: '', allow_refresh: false, require_correct: false, data: { trial_id: 'captcha_entry', captcha_index: trial_index + 1, captcha_total: CAPTCHA_TRIAL_COUNT, }, }; }; const captcha_trials = Array.from({ length: CAPTCHA_TRIAL_COUNT }, (_, index) => create_captcha_trial(index) ); const die_probe_row = { text: 'I suspected that the die roll was not random, or the number I received was pre-determined.', value: 'SuspicionDie', }; const difficulty_probe_row = { text: 'I suspected that, contrary to what I was told, the captcha task difficulty was not determined by the die roll.', value: 'SuspicionDifficulty', }; const survey_function = survey => { survey.onAfterRenderPage.add(function(sender, options) { console.log('Survey page rendered:', sender.currentPage); if (survey.activePage.name === 'page2') { const nextButton = document.querySelector('#sv-nav-next > div > input'); if (nextButton) { let seconds = 20; const originalText = nextButton.value.replace(/\s*\(\d+\)$/, '') || 'Continue'; nextButton.disabled = true; nextButton.value = `${originalText} (${seconds})`; const interval = setInterval(() => { seconds--; nextButton.value = `${originalText} (${seconds})`; if (seconds <= 0) { clearInterval(interval); nextButton.disabled = false; nextButton.value = originalText; } }, 1000); } } }); }; const survey = { type: jsPsychSurvey, survey_function: survey_function, survey_json: { showQuestionNumbers: false, completeText: 'Done!', pageNextText: 'Continue', pagePrevText: 'Previous', showPrevButton: false, pages: [ { name: 'page1', elements: [ { type: 'matrix', name: 'Please answer the following questions about your experience in the captcha task.', alternateRows: true, isAllRowRequired: debug ? false : true, rowOrder: 'random', rows: [ { text: `I found the captcha task difficult.`, value: 'Difficulty', }, { text: `I felt lucky during the die roll.`, value: 'Luck', }, { text: `I felt unlucky during the die roll.`, value: 'Bad_luck', }, { text: `I think I solved all the captchas correctly.`, value: 'Accuracy', }, { text: `I think I solved captchas faster than most other participants would have.`, value: 'Relative_performance', }, { text: `I think I solved captchas slower than most other participants would have.`, value: 'Relative_performance_slow', }, ], columns: [ { value: 5, text: 'Strongly agree', }, { value: 4, text: 'Agree', }, { value: 3, text: 'Neutral', }, { value: 2, text: 'Disagree', }, { value: 1, text: 'Strongly disagree', }, ], }, ], }, { name: 'page2', elements: [ { type: 'matrix', name: probe_condition === 'die' ? probe_text_die : probe_text_difficulty, alternateRows: true, isAllRowRequired: debug ? false : true, rowOrder: 'random', rows: [ probe_order === 'die_first' ? die_probe_row : difficulty_probe_row, { text: `There's no question here. Select 'Disagree' to show that you're paying attention.`, value: 'AttentionCheck', }, probe_order === 'die_first' ? difficulty_probe_row : die_probe_row, ], columns: [ { value: 5, text: 'Strongly agree', }, { value: 4, text: 'Agree', }, { value: 3, text: 'Neutral', }, { value: 2, text: 'Disagree', }, { value: 1, text: 'Strongly disagree', }, ], }, ], }, { name: 'page3', elements: [ { type: 'radiogroup', title: 'Please indicate your gender', choices: ['Male', 'Female', 'Other'], isRequired: debug ? false : true, colCount: 0, name: 'gender', }, { type: 'radiogroup', title: 'Please indicate your handedness', choices: ['Right', 'Left', 'Ambidextrous/Other'], isRequired: debug ? false : true, colCount: 0, name: 'handedness', }, { type: 'text', title: 'How old are you?', name: 'age', isRequired: debug ? false : false, inputType: 'number', min: 18, max: 100, defaultValue: 18, }, ], }, ], }, }; const main_experiment_timeline = [ instructions_1, instructions_2, die_roll_trial, instructions_3, ...captcha_trials, pre_survey_info, survey, debrief, ]; if (debug) { timeline.push(...main_experiment_timeline); } if (!debug) { timeline.push(pre_consent_info); timeline.push(consent_form); timeline.push(enter_fullscreen); timeline.push(...main_experiment_timeline); } jsPsych.run(timeline);