Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHello,
The reason you see “Canvas” is because you use
log
on your Canvas element, so the results file will report the timestamp for the execution of itsprint
command.
You are also usinglog
on your Key element, which you probably want, because it will report which ofE
/I
was pressed.
Finally, you are callinglog
on the “wait-separacao” Timer element too, but you meant to call it onnewTrial()
because what you want is to add columns to every line of your results file for those trials that report the values from the “imagem” and “versao” columns of your table:// ... , newTimer("wait-separacao",2500) .start() .wait() ) .log("imagens", row.imagem) .log("item", row.versao) );
Jeremy
Jeremy
KeymasterHi Sam,
PennController’s top-down write-and-execute style makes this kind of disjunctive logic a little tricky. In your case, I suggest you just wait for the Timer element, and have the Selector element halt the timer upon selection:
newSelector("images") .add( getImage("on"), getImage("mid"), getImage("off")) .log() .callback( getTimer("waitSelector").stop() ) , newTimer("waitSelector", 30000) .start() .wait()
Also, you cannot use javascript’s
!
operator on PennController commands (see this guide). If you want to negate a test, just replacetest
withtestNot
Jeremy
Jeremy
KeymasterHi,
What version of PennController are you using? If you’re not using it already, I suggest you upgrade to 2.0.beta where I improved the uploading system
In any case, you should probably add a non-async
UploadRecordings
trial just before theSendResults
trial, to make sure all the recordings are uploaded before finishing the experimentAlso, feel free to share your project’s URL to ease the troubleshooting process
Jeremy
Jeremy
KeymasterHi,
To add to Amila’s suggestion, look at the button command
To play with the aesthetics, you can add CSS rules to Aesthetics/PennController.css like:
.Scale > div { margin: 1em; }
Jeremy
Jeremy
KeymasterHi,
This sounds like a native-Ibex specific question. I think editing the Question controller would indeed be the obvious solution if you want to stick to native Ibex. You would move lines 150-151 (
if (! (this.qp === undefined))
/this.element.append(this.qp);
) below line 159 (this.element.append(table.append(tr.append(td.append(this.xl))));
)Or you can use PennController, which was precisely design to give you more control over the design of you Ibex experiments 😉 For example:
newTrial( newController("DashedSentence",{s: "This is a simple test sentence"}) .print() .log() .wait() .remove() , newScale("answer", "Answer1", "Answer2").button().log().print() , newText("This is a question").print() , getScale("answer").wait() )
Jeremy
Jeremy
KeymasterYou cannot use
getVar
that way, as explained in this guide I mentioned earlierYour first attempt was on the right track, but maybe you forgot to include the trial number in addition to the selection index?
const whichOne = (numbers, selectorName, ex) => numbers.map( number => getSelector(selectorName).test.selected(getImage("o" + number)) .success( newAudio("o" + number + "selected", "ex" + ex + "o" + number + ".m4a") .play() .wait() , getVar("selected").set(number) ) )
and then use it like this:
...whichOne([1,2,3,4,5,6], "response", exNum)
Jeremy
Jeremy
KeymasterHello,
There are a couple problematic aspects with your code. First, elements are specific to trials, so you cannot define a Var element outside the scope of a
newTrial
. Second, yourwhichOne
function runs the risk of an infinite recursive loop (although I have to say it’s a pretty smart way of testing many values without having to duplicate your code). I recommend you read this guide to get a better idea of when commands are executedAll
callback
commands will run a series of commands when the corresponding element’s relevant event happens (eg. a click on a Button element). They’re mainly useful to escape the purely top-down execution of the code, in allowing for interactions to unfold while the main thread of the script iswait
ing somewhere. It is true that they can also be used to re-execute a pre-defined block of code, but I think you are overusing thecallback
command in your codeI think what you want is this:
const whichOne = (numbers, selectorName) => numbers.map( number => getSelector(selectorName).test.selected(getImage("o" + number)) .success( newAudio("o" + number + "selected", "o" + number + "Audio.m4a") .play() .wait() , getVar("selected").set(number) ) ) const runPractice = (LP,RP,LO,RO,tag,correctChoice) => [ clear() , newCanvas("images", 1500, 750) .color("white") .add( 0 , 100 , newImage("p1", LP + ".jpeg" ).size(400, 400) ) .add(450 , 100 , newImage("p2", LP + RP + ".jpeg").size(600,400) ) .add(1100 , 100 , newImage("p3", RP + ".jpeg").size(400, 400) ) .add( 0 , 500 , newImage("o1", LO + ".png") ) .add(200 , 500 , newImage("o2", RO + ".png") ) .add(550 , 500 , newImage("o3", LO + ".png") ) .add(750 , 500 , newImage("o4", RO + ".png") ) .add(1100 , 500 , newImage("o5", LO + ".png") ) .add(1300, 500 , newImage("o6", RO + ".png") ) .add( "center at 50%", "bottom at 100%", newButton("Go") ) .print("center at 50vw","top at 2em") , getButton("Go").wait().remove() , newAudio("description", tag + ".m4a") .play() .wait() , newSelector("response") .add( getImage("o1") , getImage("o2") , getImage("o3") , getImage("o4") , getImage("o5") , getImage("o6") ) .wait() , ...whichOne([1,2,3,4,5,6],"response") , getVar("selected").test.is(row.correctChoice) .success( newHtml("readyscreen", "readyscreen.html") .center() .print() , getButton("Continue").print("center at 50%","bottom at 100%",getCanvas("images")) ) .failure( getButton("runPracticeLaunch").click() ) ] Template("examples.csv", row => newTrial("practice", newVar("selected", 0) , defaultImage.size(200,200) , newButton("runPracticeLaunch") .callback(...runPractice(row.LP,row.RP,row.LO,row.RO,row.tag,row.correctChoice)) .click() , newButton("Continue") .center() .wait() ) )
I couldn’t test this code with your project’s material (feel free to share the demonstration link with me so I can do it) but I tried an non-Template non-Audio version of it which worked. Note that I’m printing the button onto the Canvas element because otherwise they appear below it
Jeremy
Jeremy
KeymasterThank you Giorgio — I just replied by email
For everybody else: there is a bug in one version of PennController 2.0.alpha where Video elements are printed as disabled by default, which adds an opaque gray layer on top of the player. Calling
.enable()
before calling.print()
gets rid of that problem. This issue has been fixed for more recent releasesJeremy
Jeremy
KeymasterWould you mind sharing your project’s demonstration link with me, either here or at support@pcibex.net?
Jeremy
Jeremy
KeymasterHi Giogio,
This code works well for me on PennController 1.8, 1.9 and 2.0.alpha. Do you have a
defaultVideo.disable()
anywhere before that by any chance? If not, the problem could come from the format of the video file. All browsers are supposed to support MP4 files, but note that having a.mp4
extension does not guarantee that the content of your file has indeed been encoded in MP4Jeremy
Jeremy
KeymasterHi Vasilisa,
As explained in the documentation (my emphasis + edit):
This script will take care of receiving and storing encoding data lines in subfolders and one file per participant. It will also output back files where the lines have been decoded. You can directly visit it [NB: your script] through your browser and type in the field that you see the “URL” key that was reported in your results file (something like httpsdomainofmyexperiment/pathtomyexperiment/vEry-l0ng-uniQu3-1dentif1er). Alternatively, you can directly append
key
at the end of the PHP script’s url (replacingkey
with the value from your results file) to get the output file — this is the method we will use in our analyses.In other words, your eye-tracking data will not be stored on the PCIbex Farm, and you should upload a PHP script to your webserver, as described in the documentation. If your PHP script is at
https://my.server.xyz/myETScript.php
, then open this URL in your browser and pastehttpsfarmpcibexnetrKFZClH/af8e9d53-10c3-93c6-1799-6412f8639d0f
in the input field and click “Submit” to get a CSV data file. Or usehttps://my.server.xyz/myETScript.php?experiment=httpsfarmpcibexnetrKFZClH/af8e9d53-10c3-93c6-1799-6412f8639d0f
to access it directly, as illustrated in the Analyses sectionJeremy
Jeremy
KeymasterHi,
How about this?
newTrial("WIPtrial", newButton("ContinueYes","[Clicking this should end trial]"), newButton("ContinueNo","[Clicking this will lock user out of participating and provide explanation]") .callback( clear(), newText("Explanation goes here").print() ) , newDropDown("DD2Drop","Please select a response") .add("Option1","Option2","Option3","Option4","Option5","Option6") .callback( getButton("ContinueYes").print() ) , newText("DD1Text","Yes goes to 2nd DropDown, No will lock the user out of participating (not implemented yet)") .print() , newDropDown("DD1Drop","Please select a response") .add("Yes","No") .callback( self.test.selected("Yes") .success( getButton("ContinueNo").remove(), newText("DD2Text","Many choices DropDown").print(), getDropDown("DD2Drop").print() ) .failure( getButton("ContinueYes").remove(), getText("DD2Text").remove(), getDropDown("DD2Drop").remove(), getButton("ContinueNo").print() ) ) .print() .wait() , getButton("ContinueYes").wait() // this can only complete when button is printed )
Jeremy
June 15, 2021 at 12:36 pm in reply to: Preventing interruptions and ensuring uniform presentation #7057Jeremy
KeymasterHello Matthias,
1. You cannot prevent participants from leaving fullscreen
2. You cannot disable the zoom function of the browser
Points 1 and 2 fall under the more general idea that scripts cannot take control away from clients (same for, eg., forcibly placing the cursor at a specific position on the page)
3. You can use
.css("font", "italic small-caps bold 12px/30px Georgia, serif")
on specific elements, or add CSS rules to files in your project’s Aesthetics folder. Note that those are technically preferences: if the font is not found on the client’s system, or if the client explicitly set their browser to overwrite sites’ preferences, the browser will choose a different font (this doesn’t happen very often when you specify a standard font)4. I’m not sure about this one, but it sounds like it would be beyond the scope of standardized browser specifications. Each browser and/or operating system probably has settings to enable that behavior though, I guess you could invite your participants to follow instructions to manually disable notifications while in fullscreen
Jeremy
Jeremy
KeymasterHi Ugurcan,
Your Var elements are not
.global()
so you cannot access them outside the parentheses of the containingnewTrial
command. Make sure to call.global()
on them before calling.set
Jeremy
Jeremy
KeymasterHi Ugurcan,
Using a Key element drastically simplifies the logic: you just print a Text element that says “F: Yes, J: No” and create and wait for a Key element:
newImage("Q1Image", "https:" + row.ImageURL1).size(703,398) , newText("Q1", "<p style=font-size:22px;>Did you see this image in the video?</p>") , newText("Q1instr","<strong>F: Yes</strong> <strong>J: No</strong>") , getCanvas("testcanv") .remove(getVideo("eventTest")) .add("center at 50%","middle at 50%", getImage("Q1Image")) .add("center at 50%",475, getText("Q1")) .add("center at 50%",525, getText("Q1instr")) , newKey("Q1resp", "FJ").wait() , newVar("TQ1") .set(getKey("Q1resp"))
Jeremy
-
AuthorPosts