Show sourcecode
The following files exists in this folder. Click to view.
common.js
maze.js
reaction.js
simon.js
reaction.js
116 lines UTF-8 Unix (LF)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
'use strict';
(function() {
const pid = getParticipantId();
const screen = document.getElementById('screen');
const msgEl = document.getElementById('message');
const subEl = document.getElementById('sub-message');
const overlay = document.getElementById('reaction-instructions-overlay');
let state = 'WAITING'; // WAITING | COUNTDOWN | READY | RESULT
let currentRound = 1;
let delayTimer = null;
let currentDelay = 0;
let tStart = 0;
function setScreen(cls, msg, sub) {
screen.className = 'reaction-screen ' + cls;
msgEl.textContent = msg;
subEl.textContent = sub || '';
}
function randomDelay() {
return MIN_DELAY + Math.floor(Math.random() * (MAX_DELAY - MIN_DELAY));
}
async function saveRound(roundNum, reactionMs, premature, delay) {
try {
await apiPost('../api/save_reaction.php', {
participant_id: pid,
round_number: roundNum,
reaction_ms: reactionMs,
was_premature: premature ? 1 : 0,
delay_ms: delay
});
} catch (e) {
console.error('Failed to save reaction round:', e);
}
}
function startCountdown() {
state = 'COUNTDOWN';
currentDelay = randomDelay();
setScreen('countdown', 'Vänta på grönt...', 'Runda ' + currentRound + ' av ' + TOTAL_ROUNDS);
delayTimer = setTimeout(function() {
state = 'READY';
tStart = performance.now();
setScreen('ready', 'KLICKA NU!', 'Runda ' + currentRound + ' av ' + TOTAL_ROUNDS);
}, currentDelay);
}
async function handleInput() {
if (state === 'WAITING') {
startCountdown();
return;
}
if (state === 'COUNTDOWN') {
clearTimeout(delayTimer);
setScreen('countdown', 'För tidigt!', 'Vänta på den gröna skärmen...');
await saveRound(currentRound, 0, true, currentDelay);
setTimeout(function() {
state = 'WAITING';
setScreen('waiting', 'Klicka eller tryck mellanslag för att försöka igen Runda ' + currentRound, 'Runda ' + currentRound + ' av ' + TOTAL_ROUNDS);
}, 1500);
return;
}
if (state === 'READY') {
const reactionMs = Math.round(performance.now() - tStart);
state = 'RESULT';
setScreen('result', reactionMs + ' ms', 'Runda ' + currentRound + ' av ' + TOTAL_ROUNDS);
const times = JSON.parse(sessionStorage.getItem('reaction_times') || '[]');
times.push(reactionMs);
sessionStorage.setItem('reaction_times', JSON.stringify(times));
await saveRound(currentRound, reactionMs, false, currentDelay);
setTimeout(function() {
currentRound++;
if (currentRound > TOTAL_ROUNDS) {
window.location.href = 'maze.php';
} else {
state = 'WAITING';
setScreen('waiting', 'Klicka eller tryck mellanslag för att börja Runda ' + currentRound, 'Runda ' + currentRound + ' av ' + TOTAL_ROUNDS);
}
}, 1500);
return;
}
}
// Click handler
screen.addEventListener('click', handleInput);
// Spacebar handler
document.addEventListener('keydown', function(e) {
if (e.code === 'Space' && screen.style.display !== 'none') {
e.preventDefault();
handleInput();
}
});
// Instruction overlay dismiss
if (overlay) {
function dismissOverlay() {
overlay.style.display = 'none';
screen.style.display = '';
}
document.getElementById('reaction-start-btn').addEventListener('click', dismissOverlay);
} else {
screen.style.display = '';
}
})();