Forum Replies Created
-
AuthorPosts
-
March 17, 2020 at 3:52 pm in reply to: HTML links/input not working on post-experiment HTML page #4884
Jeremy
KeymasterThey shouldn’t, this is a bug—which version of PennController are you using? I’ll need to fix that
March 17, 2020 at 3:26 pm in reply to: HTML links/input not working on post-experiment HTML page #4882Jeremy
KeymasterHi,
I’m not familiar with this bug, but it sounds like there’s an invisible element covering part of the document: do you have a Canvas in another trial (maybe in Header?) that could cause problems if not removed from the screen? Feel free to share the link to the experiment with me if you need further assistance
Jeremy
Jeremy
KeymasterIf you log your audio elements using the command log("play"), your results file will report a line whenever the audio file is played, indicating its name and when it started playing, this way you can tell which was played first by comparing the timestamps. Another option is to store
randomAudios[0]
andrandomAudios[1]
in a couple of global Var elements that you log at the end of yournewTrial
, following the same method as described on this tutorial page.Jeremy
KeymasterHi,
There are two undocumented commandsand
andor
that let you do just what you want, e.g:newTrial( newScale("score", 10).print() , newSelector("text") , newText("hello").print().selector("text") , newText("world").print().selector("text") , newButton("validate") .print() .wait( getScale("score").test.selected(5).and( getSelector("text").test.selected( getText("hello") ) ) ) )
Be careful with
selector.test.selected
though, as it will crash if run when no element is selected. I’ll fix this bug in the next release, for the moment you should probably use await
command on the selector before testing it.Jeremy
KeymasterHi!
Unfortunately there’s no pure-PennController way of doing this yet, but here is a simple enough workaround injecting some javascript in a trial script (fisherYates
is an Ibex-native function):AddHost("https://upload.wikimedia.org/wikipedia/commons/") // This is where the files are newTrial( newButton("start").print().wait().remove() , randomAudios = ["8/8f/Nl-winputje.ogg","2/2a/Nl-zonderegisters.ogg"],fisherYates(randomAudios) , newAudio(randomAudios[0]) .play() .wait() , newAudio(randomAudios[1]) .play() .wait() , newButton("ok").print().wait() )
Jeremy
KeymasterHi Elise,
1. It really depends on how you want to counterbalance the position of your pictures. One option is to take care of counterbalancing directly in your table. Another option is to toggle a global Var element on every trial to alternatively display each picture on the left/right. Here’s an example where I alternate showing the text/picture to the left/right on every other trial (note that I’m using PennController 1.7, which shortens command names):
Sequence( randomize("test") ) // This is just a dummy table for this example AddTable("myTable", `DummyColumn dummyRow1 dummyRow2 dummyRow3 dummyRow4`) Template( "myTable" , row => newTrial( "test" , defaultImage.size(200,200) // I want to make sure my images fit in my canvases , newCanvas(400,200) .add( 0 , 0 , newCanvas("left" , 200, 200) ) // The 'left' and 'right' canvases .add( 200 , 0 , newCanvas("right", 200, 200) ) // are simple containers .print() , newVar("toggle", 1) // Initialize with value 1 .global().set( v=>1-v ).test.is(1) // Set to 1 - itself = 1 or 0 on every other trial .success( newImage("pcibex-logo.png").print(0,0,getCanvas("left")), // Fill the containers newText( row.DummyColumn ).print(0,0,getCanvas("right")) // accordingly ) .failure( newImage("pcibex-logo.png").print(0,0,getCanvas("right")), newText( row.DummyColumn ).print( 0,0,getCanvas("left") ) ) , newButton("Next").print().wait() ) )
If you’d rather counterbalance upon generation rather than upon execution, ie. have a half-half overall distribution but randomly distributed, add
var i = 0
just above yourTemplate
line, and replacev=>v-1
in theset
command with(i++)%2
2.
Re. preloading: unfortunately there’s no built-in function in PennController yet to control that. What you can do is detect when the preloading message pops up usingrequestAnimationFrame
and replace it manually using javascript. It’s not very clean but it does the job. Here’s an example (this code goes at the top of your script, and replace<p>This is a test</p>
with whatever HTML content you want to display):let replacePreloadingText = ()=>{ let mainPs = $(".PennController-PennController div p"); if (mainPs.length == 2 && mainPs[0].innerHTML == "Please wait while the resources are preloading"){ mainPs.remove(); $(".PennController-PennController div").append("
This is a test
"); } else window.requestAnimationFrame( replacePreloadingText ); } window.requestAnimationFrame( replacePreloadingText );Re. sending the results: there is a native-Ibex option to overwrite the message documented in the manual which consists in defining the variable
sendingResultsMessage
to whatever message you want to display instead. Not sure whether you can use HTML there.Let me know if you have any questions
Jeremy
-
This reply was modified 5 years, 4 months ago by
Jeremy.
Jeremy
KeymasterTo follow-up on this, I just released PennController 1.7 which lets you use SendResults() as a command to… send the results. So one can replace the whole
newFunction...
bit in the code above (includingcall()
) withSendResults()
Jeremy
KeymasterYes, you also need to do it when you call
getVar
Just a question, when you say that you included a
getVar
at the top of your Template function, do you mean inside or outside the nestedPennController
command (the one starting after=>
)?Feel free to share your code if the problem persists
Jeremy
Jeremy
KeymasterHi,
There is a known bug with global Var elements which will be fixed with the release of PennController 1.7—I am not quite ready to make that release yet, but if you’re in a hurry I just published a version 1.7 alpha, you can sync it to your project following the steps described here and typing
1.7alpha
in the branch fieldAlso, did you make sure to also call
.settings.global()
on thegetVar
just before you useset
?Jeremy
Jeremy
KeymasterHi Diane,
Yes, it’s possible, but clicking that button would be a point of no return for the participant. Here is one way of doing it (some of this code is hard to make sense of if you’re not already familiar with the arcane of Ibex)
PennController.ResetPrefix(null); PennController.AddTable("myTable", `Label,Text target,Hello filler,hello target,World filler,world`) PennController.Sequence("welcome", rshuffle("target","filler")) PennController.Header( newCanvas("confirmation", '75vw', '80vh') .settings.css("background-color", "floralwhite") .settings.add( "center at 50%", "middle at 25%" , newText("Are you sure you want to send your incomplete results now?") ) .settings.add( "center at 50%", "middle at 75%" , newScale("quit", "Yes", "No").settings.button() ) , newButton("stop", "Stop").settings.callback( getCanvas("confirmation") .print("center at 50vw", "middle at 50vh") , getScale("quit").wait() , getCanvas("confirmation").remove() , getScale("quit").test.selected("Yes") .success( getButton("stop").remove() , newFunction( () => { let mainNode = $("p.PennController-PennController"); mainNode.empty(); let options = { _finishedCallback: r=>console.log("sent",r) , _cssPrefix: '', _utils: { setTimeout: ()=>null } }; addSafeBindMethodPair('__SendResults__'); mainNode['__SendResults__'](options); }).call() ) ) .print("bottom at 98vh","right at 98vw") ) PennController( "welcome" , newButton("Start").print().wait() ) .noHeader() PennController.Template( "myTable", row => PennController( newButton(row.Text).print().wait() ) )
I’ll try to implement a user-friendly option in the next release
I’m also working on a new PCIbex Farm which will use a new engine, and I’m trying to see if it could try to regular send partial results after each trial
Let me know if you have any questions
Jeremy
Jeremy
KeymasterHi,
I think the problem still has to do with quotas—unfortunately for now you still need to let me know when you’ve freed up some space after exceeding the quota (I’m working on a new farm that should handle those things much more smoothly). I double-checked and the lab’s account indeed appeared on the quota-exceeding list, even though it now occupies less than 32MB. I’ve took it off the list, you should be good to go now. Sorry for the inconvenience.
Jeremy
Jeremy
KeymasterHi Elise,
There must be something else going on in your script, because when I try the script above, neither “wrong” nor “correct” appears on the screen until I press the corresponding key. Do you have any
print
command elsewhere, maybe called on defaultText? Do you use theprint
command on the wrong-feedback element somewhere ahead of the key test?Jeremy
Jeremy
KeymasterThe problem is coming from the Canvas elements: PennController doesn’t understand that you specified the dimension of an anonymous element, instead it takes the first number to be the element’s id (in your case, 700 for the first Canvas, 500 for the second one). As a result the second number is interpreted as the Canvas’ width instead of its height, and so its height is null, making the feedback and button appear behind the Canvas (= under a 0px tall element). Give a name to each of you Canvas and the problem should go away (I would also suggest resizing your Canvas, they are very big right now)
Jeremy
Jeremy
KeymasterHi Elise,
The problem is coming from the
PennController
command that you call from inside anotherPennController
command, just before yourgetKey("answer")
. It simply shouldn’t be there. Try again with the fixed script below:PennController.Template("Materials_Practice.csv", row => ["dashed_practice", "DashedSentence", {s: row.Sentence}, "PennController", PennController( newImage("CoveredPicture", "covered.png") .settings.size(500,500) , newImage("1", row.Picture) .settings.size(500,500) , newText("leftLabel","(F)") , newText("rightLabel","(J)") , newCanvas(700,500) .settings.add( 350 , 0 , getImage("CoveredPicture")) .settings.add( -250, 0 , getImage("1") ) .print() , newCanvas(500,500) .settings.add(0,500, getText("leftLabel")) .settings.add(600,500, getText("rightLabel")) .print() , newKey("answer","FJ") .wait() , newText("positive feedback", "Correct!") , newText("negative feedback", "Wrong...") , getKey("answer") .test.pressed("F") .success( getText("positive feedback") .print() ) .failure( getText("negative feedback") .print() ) , newButton("continue", "Next") .print() .wait() // You need to wait before going to the next trial )] )
Jeremy
February 11, 2020 at 10:44 am in reply to: Trouble loading a batch of images into the experiment #4690Jeremy
KeymasterHi!
If all the pictures fail to show up (and you only have their contour) the problem is probably bad URLs. Do you get the filenames from a table? Sometimes there’s a problem with that and you end up with the wrong link (e.g. missing a
/
somewhere) Did you check the Debug window’s logs?
Feel free to share the link to your experiment so we can get a better idea of what’s going onWhen you need to load many files the best solution from the participant’s perspective is to use a ZIP file: this way, there’s only one request and you’re certain that when they get the file, no resource is missing (as long as you included them all in the file). But it’s true that the setup can be challenging depending on your hosting platform.
Best
Jeremy -
This reply was modified 5 years, 4 months ago by
-
AuthorPosts