Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHello,
In the demo that you shared, there is a single
newTrial
which includes both task types. It is my understanding from what you said (that two tasks of the same type can follow each other) that you want to decouple the two, ie. not have them inside a singlenewTrial
command. That would also mean no longer associating specific sentences with specific sets of flanker images the way your table is currently set up. The most convenient way to start on that would be to use two different CSV tables for each task typeThen you can create different
newTrial
s inside differentTemplate
commands, giving different labels to trials of each task type. Once you have such labeled trials, you can define a custom predicate function to shuffle your trials as you’d like, for example:const popAelseB = (a,b) => a.pop()||b.pop() function LatinMix(a, b) { this.args = [a,b]; this.run = function(arrays) { assert(arrays.length == 2, "Wrong number of arguments (or bad argument) to LatinMix"); let as = arrays[0]; let bs = arrays[1]; let newArray = []; let i = 0; while (as.length || bs.length){ newArray.push( [ i%2 ? popAelseB(as,bs) : popAelseB(bs,as), (i+1)%4<2 ? popAelseB(as,bs) : popAelseB(bs,as) ] ); i++; } fisherYates(newArray); return newArray.flat(); } } function latinMix(a, b) { return new LatinMix(a, b); }
You can use the function in
Sequence
like this:Sequence( latinMix(randomize("sentence"),randomize("flanker")) ) Template("flanker.csv", row => newTrial("flanker", /* ... */ ) ) Template("sentence.csv", row => newTrial("sentence", /* ... */ ) )
Jeremy
Jeremy
KeymasterHi,
The experiment runs the fillers as a separate list because your table has three different values in the LIST column:
A
,B
and.
What I would do is store the function you pass to
Template
in a variable, create two different CSV tables for the experimental items (with a LIST column) and for the filler items (without a LIST column) and then useTemplate
twice, once on each CSV tableexperimental.csv:
ITEM,SENTENCE,COMPATIBILITY,SUBJECT,LIST,TYPE 101,Sentence 1,1,subject1,A,item 201,Sentence 2,1,subject1,B,item 102,Sentence 3,2,subject2,B,item 202,Sentence 4,2,subject2,A,item
fillers.csv:
ITEM,SENTENCE,COMPATIBILITY,SUBJECT,TYPE 501,Filler 1,.,.,filler 502,Filler 2,.,.,filler 503,Filler 3,.,.,filler
Example of a script:
function_for_template = row => newTrial( row.TYPE , newText( row.SENTENCE ).print() , newScale("answer", "True", "False").button().print().log().wait() ) .log("item", row.ITEM) .log("compatibility", row.COMPATIBILITY) .log("subject", row.SUBJECT) .log("list", (row.LIST===undefined?"filler":row.LIST)) Template("experimental.csv", function_for_template) Template("fillers.csv", function_for_template)
Jeremy
Jeremy
KeymasterHi,
If what you want is provide the user with 7 points visually, you could do that (replace the two occurrences of
10em
with whatever width you prefer):newText("<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span>") .css({display:"flex", "justify-content": "space-between"}) .size("10em","auto") .center() .print() , newScale(100).size("10em","auto").slider().center().log().print()
Then in your analyses, you can simply multiply the score by 0.07 and round it if you like
Jeremy
Jeremy
KeymasterHi Daria,
You can remove
.css("white-space","nowrap")
and add this to Aesthetics/global_main.css instead:.PennController-nowrap .FlashSentence-flashed-sentence, .PennController-nowrap .DashedSentence-sentence { white-space: nowrap; }
This will apply the CSS rule to the sentence in your controller as long as you name the element
"nowrap"
:newController("nowrap", "AcceptabilityJudgment", { s: row.sentence, as: ["1", "2", "3", "4", "5", "6", "7"], presentAsScale: true, leftComment: "Плохо", rightComment: "Хорошо", timeout: 10000 }) .center() .print() .wait() .log() .remove()
Jeremy
April 29, 2022 at 4:36 pm in reply to: Is it possible to shuffle trials according to a % of times? #8132Jeremy
KeymasterDear Larissa,
Both solutions use the same set of four labels, namely
"A"
,"B"
,"C"
and"D"
The first piece of code creates a total of 100 trials: 70 A trials, 10 B trials, 10 C trials and 10 D trials. The text of the button in the first A trial is “A0”, in the second A trial it is “A1”, etc. and similarly for the “B” trials (“B0”, “B1”, etc.), the “C” trials and the “D” trials
The second piece of code creates a total of 4 trials: 1 A trial (button text: “A”), 1 B trial (button text: “B”), 1 C trial (button text: “C”) and 1 D trial (button text: “D”). However, the
Sequence
repeats the A trial 70 times, the B trial 10 times, the C trial 10 times and the D trial 10 timesBoth pieces of code use
shuffle
inSequence
, resulting in a balanced distribution in both casesJeremy
April 28, 2022 at 6:52 pm in reply to: Is it possible to shuffle trials according to a % of times? #8128Jeremy
KeymasterHi,
Using
shuffle
in the sequence will “specif[y] that items matching the given predicates should be shuffled together in such a way that items matching each predicate are evenly spaced. The original relative ordering between items of the same type is preserved.”For example, the following will get as close as possible to separate two B, two C and two D trials with 9 other trials in between, but A trials won’t be separated by more than ~2 trials overall, because of the proportions of trials
Sequence(shuffle("A","B","C","D")) for (let i = 0; i<70; i++) newTrial("A", newButton("A"+i).print().wait()) for (let i = 0; i<10; i++) newTrial("B", newButton("B"+i).print().wait()) for (let i = 0; i<10; i++) newTrial("C", newButton("C"+i).print().wait()) for (let i = 0; i<10; i++) newTrial("D", newButton("D"+i).print().wait())
That's if you have 4 different labels, and actually create 70/10/10/10 trials. But if you only create a total 4 trials, but want to repeat them following a 70/10/10/10 distribution, you could do that:
Sequence(shuffle( ...[...new Array(70)].map(v=>"A"), ...[...new Array(10)].map(v=>"B"), ...[...new Array(10)].map(v=>"C"), ...[...new Array(10)].map(v=>"D"), )) newTrial("A", newButton("A").print().wait()) newTrial("B", newButton("B").print().wait()) newTrial("C", newButton("C").print().wait()) newTrial("D", newButton("D").print().wait())
Does that answer your question?
Jeremy
Jeremy
KeymasterHi,
You could use
.css("white-space", "nowrap")
Also, I see in your code that you have
defaultText.css("font-size", "80")
but then you don’t create any Text element, instead you use Controller elements to display content: thecss
command won’t affect those elements. You can try calling.css("font-size", "80")
on each Controller elementBesides, you might want to edit Aesthetics/PennController.css to change
width: 40em !important;
towidth: 60em !important;
for example (you would then need to changemargin-left: calc(50vw - 20em);
tomargin-left: calc(50vw - 30em);
to keep the content centered)Jeremy
Jeremy
KeymasterHi Jack,
I would recommend reserving the data-collection link for actual participants, otherwise you might end up with noise submissions from test runs mixed in with valuable submissions from actual participants. The recommended link to share is the demonstration link, which comes with the debugger and a link to edit a copy of the project, which I need to troubleshoot issues. I did look up the database and fetched the demonstration for your project, but you might want to edit your message to not circulate the data collection link
Regarding the formatting issues, it’s coming from the fact that your HTML document is written as a standalone document, whereas it is actually injected as a part of another document when you include it in your experiment. More specifically, your HTML document contains a
body
node and applies CSS rules to allh1
,header
,p
,div
, etc. nodes in the document, which will necessarily also target those outside your HTML document, ie. including the nodes introduced by IBEX and PCIbexWhat you can do is delete the first 5 lines of your HTML document (from
<!DOCTYPE html>
through<title>Passage One</title>
) as well</html>
at the very end. Then replace<body>
with<div class="thisDocument">
and</body>
at the end with</div>
. Finally, prepend every selector in the CSS rules with.thisDocument
, eg replaceh1 { font-size: 2em; }
with.thisDocument h1 { font-size: 2em; }
andh2, h3, h4 { font-size: 1.5em; }
with.thisDocument h2, .thisDocument h3, .thisDocument h4 { font-size: 1.5em; }
, etc. Also make sure to replacebody {
with.thisDocument {
in those rulesYou should be good once you proceed to those edits
Jeremy
Jeremy
KeymasterHi Erin,
There are two issues with the code above: 1) the Timer element is not
start
ed, so it will bewait
ed for forever, and 2) there seems to be a bug in thecallback
command of the Controller element!So you’ll need to work around the Controller element’s
callback
command. Here’s a suggestion, which consists in placing await
command inside anothercallback
command (this time, a bug-free one, called on a Timer element) so thatwait
does not block the main thread of execution:newTrial("trial-1", defaultText .center() .print() , newAudio("llego-profesora", "La_profesora_llegó_a_la_clase_en_la.mp3") .play() , newText("llego-profesora-t", "La profesora llegó a la clase en la momento preciso.") .center() .unfold(3650) , getAudio("llego-profesora") .wait("first") , newTimer("hurry", 3000).start() , newTimer("dummy", 1) .callback( newController("AcceptabilityJudgment", { q: "¿Es esta oración aceptable?", s: "", as : ["SÍ", "NO"], instructions : "Haz clic, SÍ o NO", presentAsScale : true, leftComment : "es aceptable", rightComment : "no es aceptable" }) .center() .print() .log() .wait() , getTimer("hurry").stop() ) .start() , getTimer("hurry").wait() )
Jeremy
Jeremy
KeymasterHi Jack,
It’s a little hard to tell out of context. Do you have a link to your experiment that you could share, here or at support@pcibex.net?
Jeremy
Jeremy
KeymasterHi Rhosean,
When I open your certificate, I get these validity dates:
Validity Not Before Sun, 23 Jan 2022 05:41:45 GMT Not After Sat, 23 Apr 2022 05:41:44 GMT
I’m not sure where the discrepancy lies, but maybe you could try to manually force a certificate refresh on DreamHost?
Jeremy
Jeremy
KeymasterHi Rhosean,
There is a problem with your domain: when I try to open https://www.rhosean.xyz/nsfSESresults/resources/APIMaudio.zip directly in my browser, I get a “Warning: Potential Security Risk Ahead” message. Most likely your SSL certificate has expired. Renew your certificate and the problem should go away
Jeremy
Jeremy
KeymasterHi Larissa,
True continuity doesn’t really exist in the digital world (does it even exist in the non-digital world?) 😉
Use a high value for the number of points, eg. 1000:
newScale(1000).slider().print()
Jeremy
April 26, 2022 at 1:02 pm in reply to: Issue with changing font size in FlashSentence and AcceptabilityJudgment #8109Jeremy
KeymasterHi Radim,
FlashSentence and AcceptabilityJudgmentSentence do not introduce a node with a class name of the form
CONTROLLERNAME-sentence
the way DashedSentence does, but of the formCONTROLLERNAME-flashed-sentence
. So do this instead:.FlashSentence-flashed-sentence { font-size: 30; } .DashedSentence-sentence { font-size: 30; } .AcceptabilityJudgment-flashed-sentence { font-size: 30; }
Jeremy
Jeremy
KeymasterHi Dod,
Yes, whichever method you use, one MediaRecorder element means one audio file, containing the most recent recording — you should try it out yourself though to double-check. Zip files containing recordings have non-related, unique filenames and may contain one or more recordings (because trials can contain several MediaRecorder elements, and uploads can take place after several trials too) but the audio files in the zip files are indeed named after the name of the MediaRecorder
Jeremy
-
AuthorPosts