PennController for IBEX › Forums › Support › Conditional training phase
Tagged: ue
- This topic has 8 replies, 3 voices, and was last updated 3 years, 2 months ago by Jeremy.
-
AuthorPosts
-
November 25, 2020 at 9:43 am #6382suzParticipant
Dear all,
I was wondering, following up on this topic, whether (or how) I can make the training phase in a maze task such that training trial only ends when the participant has completed N sentences successfully. Background: the maze task is quite unnatural, so if the training phase only has two or three items, but the participant fails on all of them, that’s hardly a successful training phase; in turn, if a participant is quick on the uptake, having to go through five or six items might be unnecessary.
So in other words, I was wondering if there was a way to add a conditional loop that counts the numbers of “successes”, and aborts the trial when it equals two, but as long as that condition is not met, it continues to loop through the file “training.csv”, allowing to present, say, four training items continually until success = 2 (I guess once I know how this can be done in principle, I’d be fine to add a condition that aborts the trial after 10 unsuccessful attempts to avoid infinite looping):
Template("training.csv", row => newTrial("training", newController("Maze", {s: row.Sentence, a: row.Distractor}) .css("font-size", "1.5em") .css("font-family", "Verdana") .print() .log() .wait() .remove() .test.passed() .failure(newText("<br/>oops!").css("font-size", "1.5em").css("color", "red").print()) .success(newText("<br/>great!").css("font-size", "1.5em").css("color", "green").print()) , newTimer(500).start().wait() ) )
From what I understand, I need to know where “success” is stored. Is this task possible in this code or would I need a separate function elsewhere? Is there a topic that addresses this? Afaik, it’s a rather commonly desired property, but I couldn’t find anything in the forum or the doc files (given my inexperience with JS).
Any help much appreciated, as always.
Best,
SusanneNovember 25, 2020 at 1:24 pm #6385JeremyKeymasterHi Susanne,
You can increment a Var element upon success, check the value of that Var element at the beginning of your trials and only run them if it’s below 2. No need to resort to plain javascript:
Template("training.csv", row => newTrial("training", newVar("training_successes", 0) .global() .test.is( v => v > 2 ) .success( end() ) , newController("Maze", {s: row.Sentence, a: row.Distractor}) .css("font-size", "1.5em") .css("font-family", "Verdana") .print() .log() .wait() .remove() .test.passed() .failure( newText("<br/>oops!").css("font-size", "1.5em").css("color", "red").print() ) .success( getVar("training_successes").set( v => v+1 ), newText("<br/>great!").css("font-size", "1.5em").css("color", "green").print() ) , newTimer(500).start().wait() ) )
Let me know if you have questions
Jeremy
November 25, 2020 at 2:52 pm #6386suzParticipantHi Jeremy,
This is brilliant, thanks! So I gather that at failure it cannot re-use or re-loop through trainings.csv (judging from this topic I just found here)? That’s fine, I’ll just have 10 or so training items then, that should do the trick. (The progress bar is relative to the full number of possible items, so for early-finishers this will ‘jump’ a little, but that’s not a problem.)
Again, thanks a lot for your swift response, I’m getting the hang of things!
Best,
SusanneNovember 25, 2020 at 3:04 pm #6387JeremyKeymasterHi Susanne,
Sorry, I hadn’t understood your question. You are correct, it’s not possible to re-loop through training.csv using PCIbex at the moment.
Let me know if you have more questions
Jeremy
November 25, 2020 at 3:07 pm #6388suzParticipantHi Jeremy,
Nah, that’s all for now, and exactly what I needed for the intended primary purpose. Thanks!
—Susanne
July 27, 2021 at 11:30 am #7129ginopino09ParticipantHello Jeremy,
I’m sorry I don’t if I can continue this thread with a similar issue.I’m trying to ascreening test for my experiment where participants will have to score at 70% in an easy English test. If they do not reach this threshold they are not allowed to continue the experiment. I’m having problems even with calculating the test score.
AddTable("LEX",`WORDS,RES PLATERY,F DENIAL,J GENERIC,J MENSIBLE,F SCORNFUL,J STOUTLY,J ABLAZE,J JERMSHAW,F') Template("LEX", row=> newTrial("Engl_prof", newVar("score", 0).global(), newText(row.WORDS).print("center at 50vw","middle at 50vh"), , newText("<span style='color:red'><b>F = it doesn't exist</span></b>, <span style='color:green'><b>J = it exists</span></b>").print("center at 50vw","middle at 75vh"), newKey("lext","FJ") .wait() .log() .callback( getKey("lext") .test.pressed(row.RES) .success(getVar("score").set(v=>v+1)) )) ), newTrial("resul", newVar("score").global(), newText("yscore") .before(newText("Your score is: ")) .text(getVar("score")) .after(newText("/60")) .print(), newButton("Ok").print().wait(), newVar("score").global(), getVar("score").test.is( v => v > 41 ) .success(end) .failure(newText("I'm sorry but your score is too low. You cannot continue the experiment.").print().wait()) )
I saw that you explained this method somewhere else, but I cannot figure out the problem.
Best,
Giorgio
July 27, 2021 at 2:07 pm #7130JeremyKeymasterHi,
The code you posted has several syntax errors that make it crash. If it comes from an existing project, please consider sharing the demonstration link. Or, if you directly report some code here, try to copy-paste it from the existing project so no new errors are introduced in the process
This is the code I tested myself, after fixing the syntax errors:
AddTable("LEX",`WORDS,RES PLATERY,F DENIAL,J GENERIC,J MENSIBLE,F SCORNFUL,J STOUTLY,J ABLAZE,J JERMSHAW,F`) Template("LEX", row=> newTrial("Engl_prof", newVar("score", 0).global() , newText(row.WORDS).print("center at 50vw","middle at 50vh") , newText("<span style='color:red'><b>F = it doesn't exist</span>>/b>, <span style='color:green'><b>J = it exists</span></b>") .print("center at 50vw","middle at 75vh") , newKey("lext","FJ") .wait() .log() .callback( getKey("lext") .test.pressed(row.RES) .success(getVar("score").set(v=>v+1)) ) ) ) newTrial("result", newVar("score").global(), newText("yscore") .before(newText("Your score is: ")) .text(getVar("score")) .after(newText("/60")) .print() , newButton("Ok").print().wait(), newVar("score").global(), getVar("score").test.is( v => v > 41 ) .success(end) .failure( newText("I'm sorry but your score is too low. You cannot continue the experiment.").print().wait() ) )
When I ran the experiment, the debugger immediately reported an error:
Ambiguous use of getVar(“score”): more than one elements were created with that name-- getVar(“score”) will refer to the first one
Indeed, in the second
newTrial
you create the “score” Var element twice, so I took the second one out, and then I was able to run the experiment with no warnings or errorsYour main problem here is that you associate a
callback
to the Key element after a keypress happened. In fact you don’t need to usecallback
at all: all you want to do is wait for a keypress, and do something after that (namely, a test) andwait
already gives you that:newKey("lext","FJ") .wait() .log() .test.pressed(row.RES) .success(getVar("score").set(v=>v+1))
Now, your “result” (“resul” in your original code) trial checks whether the value of the “score” Var element is greater than 41, but since your table only defines 8 trials, of course you’ll never pass that threshold, even with a perfect score. 70% of 8 is 5.6, so you could replace
41
with5
. You could also print the “OK” button only if the test is a success, thus only letting the accurate participants continue:newTrial("result", newVar("score").global(), newText("yscore") .before(newText("Your score is: ")) .text(getVar("score")) .after(newText("/8")) .print() , newButton("Ok"), getVar("score").test.is( v => v > 5 ) .success(getButton("OK").print()) .failure( newText("I'm sorry but your score is too low. You cannot continue the experiment.").print() ) , getButton("OK").wait() )
One caveat: it is against some recruitment platforms’ policies (and maybe some IRB policies?) to prevent a participant who started your experiment from completing it, so this is something you might want to double-check
Jeremy
July 28, 2021 at 7:49 am #7133ginopino09ParticipantGreat thank you, it works!
My actual table has 60 trials, this is why of the number is used.
Also, thank you for the warning about recruitment policies, we already did that and it’s fine as long as we pay for their time and they are informed from the beginning about the screening test.I have another silly question.
I need block order randomization (no need to counterbalance).
I see that you suggested in another post to do something like this:( Math.random()>=0.5 ? [ Sequence("intro","block1","block2","results") ] : [ Sequence("intro","block2","block1","results") ])
But what if I have more blocks and I need to randomized them between 4 orders?
Or even more, like 24 orders?
Do I use the same math.random function?If this questions doens’t belong here, I can delete it and move it below a post with similar requests.
Thank you again for your help.
Giorgio
July 28, 2021 at 11:13 am #7136JeremyKeymasterHi Giorgio,
If you have many blocks, I recommend the following approach:
var blocks = ["block1","block2","block3","block4"]; fisherYates(blocks); Sequence("intro",...blocks,"results")
Jeremy
-
AuthorPosts
- You must be logged in to reply to this topic.