I'm trying to create an experiment in Gorilla experiment builder that uses specific js Gorilla hooks.
There are 3 types of screens a participant could be redirected to: A "correct & fast" screen ( if they answer under 2 seconds), a "correct but slow" screen (if they answer over two seconds), and an "incorrect" screen (if they give the wrong response).
Here is the code I have. The first while loop works, but it fails as soon as it tries to redirect participants to something other than the "correct fast" screen.
I'm not an expert with javascript at all, so this might just be the way I've written it but I can't seem to figure it out.
//If the RT is FAST (less than 2 seconds AND correct, move to a correct fast screen)
var reactionTime = gorilla.readStopwatch();
while (reactionTime <= 2000) {
if (response == "g") {
//If the RT is slow but still correct, move to a correct slow screen.
return { new_screenName: 'Correct_fast'};
}
while (reactionTime > 2000) {
if (response == "g") {
//If the response is incorrect, move to an incorrect screen.
return { new_screenName: 'Correct_slow'};
} else if (response == "h") {
return { new_screenName: 'Incorrect'};
}
}
}
I don't know anything about Gorilla but here's a vanilla js timer.
let start, slow = false;
function step(timestamp) {
start ??= timestamp;
const elapsed = timestamp - start;
if (elapsed > 2000) slow = true; // slow = true after 2 seconds
if (elapsed < 2000) { // Recursion loop ends after 2 seconds
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step); // requestAnimationFrame passes step() one argument, a DOMHighResTimeStamp similar to the one returned by performance.now()
Dealing with time between async events can require advanced JS skills/experience and is good way to be forced to quickly learn a lot. Here's how I would solve this problem.
async function TestExperiment(){
var answer, wasSlow, newScreenName;
[answer, wasSlow] = await Promise.all([getAnswer(), checkIfSlow()])
if (answer == 'wrong') newScreenName = 'incorrect'
else if (!wasSlow) newScreenName = 'correct_fast'
else if (wasSlow) newScreenName = 'correct_slow'
console.log('New Page =>', newScreenName)
function checkIfSlow(){
return new Promise( resolve => {
let start, slow = false;
function step(timestamp) {
start ??= timestamp;
const elapsed = timestamp - start;
if (answer) resolve(slow) // resolve early if answer set before 2 seconds
if (elapsed > 2000) { // resolve after 2 seconds
slow = true;
resolve(slow)
}
if (elapsed < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
})
}
function getAnswer() {
return new Promise( resolve => {
let correctBtn = document.getElementById('correct')
let wrongBtn = document.getElementById('wrong')
correctBtn.onclick = () => {
answer = 'correct'
resolve(answer)
}
wrongBtn.onclick = () => {
answer = 'wrong'
resolve(answer)
}
});
}
}
TestExperiment()
<button id="correct">correct</button>
<button id="wrong">wrong</button>
I think your Problem could be, that your second while loop is nested into your first while loop so right now your code checks if reactionTime is more than 2000 only when reactionTime is smaller than 2000. You could either make 2 loops or just verify when response is given
if(response == 'g' && reactionTime <= 2000){
return { new_screenName: 'Correct_fast'};
else if(response == 'g'){
return { new_screenName: 'Correct_slow'};
}else{
return {new_screenName: 'Incorrect'};
}