Forum Replies Created
-
AuthorPosts
-
Jeremy
KeymasterHi Yev,
Use the Selector element’s
shuffle
command, as illustrated above and in the tutorial:newSelector("images") , defaultImage.size(100,100).selector("images") , newCanvas("3x3", 300, 300) .add( 0, 0,newImage("one.png")) .add(100, 0,newImage("two.png")) .add(200, 0,newImage("three.png")) .add( 0,100,newImage("four.png")) .add(100,100,newImage("five.png")) .add(200,100,newImage("six.png")) .add( 0,200,newImage("seven.png")) .add(100,200,newImage("eight.png")) .add(200,200,newImage("nine.png")) .print() , getSelector("images").shuffle().disable()
Jeremy
Jeremy
KeymasterHi Laia,
You could inject some plain javascript into your code to conditionally reference the first vs the second sentence:
newTrial("practice", oneFirst = (Math.random()>=0.5) , newAudio("audio1", "1fishSquareTank.mp3"), newAudio("audio2", "2fishRoundTank.mp3"), newText("sentence1", "The fish swims in a tank which is perfectly square."), newText("sentence2", "The fish swim in a tank which is perfectly round.") , newCanvas("frases", 800, 400).print() , getText(oneFirst?"sentence1":"sentence2").print( 0,0,getCanvas("frases")), getAudio(oneFirst?"audio1":"audio2").play().wait() , getText(oneFirst?"sentence2":"sentence1").print(400,0,getCanvas("frases")), getAudio(oneFirst?"audio2":"audio1").play().wait() , newSelector("choice") .add( getText("sentence1") , getText("sentence2") ) .log() .wait() ) .log("startWith", oneFirst?1:2) // log which sentence came first
Jeremy
Jeremy
KeymasterHi,
What you describe is the
placeholder
attribute of the HTMLtextarea
element, and PennController does not provide a direct command to set it, but it actually isn’t that hard to implement:newTextInput('text').print() , // The bit after the dash ('text') needs to match the name of the TextInput element newFunction( ()=>document.querySelector("textarea.PennController-text").placeholder = 'This is the default text.' ).call() ,
Jeremy
Jeremy
KeymasterHi,
The columns are not randomized: the
features
array is randomized, which contains predicates over labels of trials; in effect, it is the order in which the trials are inserted in the sequence that is randomized, not the table or its columns, and not the way the trials are created more generallyIf you want to detect a change in feature upon runtime, you can use a global Var element to remember the value of the
Feature
column from the trial that was run before the current one, and compare the value of that Var element with the current value ofrow.Feature
: if they are different, it means the current trial is starting a new feature block:newTrial( row.Feature + "-" + row.Item , newText("instruct_exerc", "Bitte bewerten Sie, ob beide Tiere gleich gut Verursacher oder Empfänger der Handlung sein können.") .css({'font-family': "helvetica"}) .center() .print() , newVar("feature") .global().test.is( row.Feature ).failure( newText("feature_change", "Attention: New Feature ") .cssContainer({"margin-top":"2em", "margin-bottom":"2em", 'font-family': "helvetica"}) .css("font-size", "1.2em").color("Red").bold().center() .print() ) .set( row.Feature ) ,
Jeremy
Jeremy
KeymasterHi Karen,
When the Question controller’s
as
parameter is not an array of strings, but an array of pairs of strings (whose first member represents a key and the second member is the printed answer) you cannot pass a string ashasCorrect
: you need to either passtrue
, in which case it means the first answer is the correct one, or a integer between0
and the length of the array minus one, so in your case where you have two answers, either0
(first answer in the array, selectable by pressing F) or1
(second answer in the array, selectable by pressing J)Now, there is a subtlety, which is that values fetched from the table in
Template
are interpreted as strings by default, so even if you list0
s and1
s in your “Corr” column, they’ll still be interpreted as strings when you referencerow.Corr
. The solution is to force a coercion into an integer, usingparseInt
:newController("Question", {q: "Is it reasonable?", as: [["F","reasonable"], ["J","unreasonable"]], hasCorrect: parseInt(row.Corr), randomOrder: false})
Jeremy
Jeremy
KeymasterNote that I found another bug with the suggestion above: creating a second DragDrop element messes with detecting dropping events on it, hence never validating its
wait
command. So instead of creating two DragDrop elements, one should create and reuse a single one:newDragDrop("dragdrop") .addDrag(getImage("bear")) .addDrop(getCanvas("flowerCV")) .wait() .removeDrag(getImage("bear")) .removeDrop(getCanvas("flowerCV")) , // ... getDragDrop("dragdrop") .addDrag(getCanvas("flowerCV")) .addDrop(getCanvas("boxCV")) .wait()
Jeremy
Jeremy
KeymasterSimply print the “bear” Image element and the Canvas elements containing the other images on a bigger Canvas element, and then shuffle those:
newCanvas("mainContainer", 900,300).print() , newImage("bear","bear.png").size(100,100).print(0,0,getCanvas("mainContainer")), newImage("bearCopy","bear.png").size(100,100).cssContainer("pointer-events","none").css("pointer-events","none") , newCanvas("flowerCV", 200,200).add(0,0,newImage("flower","flower.png").size(200,200)).print(300,0,getCanvas("mainContainer")) , newCanvas("boxCV", 300,300).add(0,0,newImage("box","box.png").size(300,300)).print(600,0,getCanvas("mainContainer")) , newSelector("shuffle").add(getImage("bear"),getCanvas("flowerCV"),getCanvas("boxCV")).shuffle().disable()
Jeremy
Jeremy
KeymasterHi,
I just realized I never addressed the previous post, so I will do it now. Unfortunately there is no built-in way to log coordinates in a DragDrop element, but it can be achieved using some javascript. The
set
command of Var elements accepts javascript functions, so we can create one Var element for each pair of coordinates we want to log:newTimer(5000).start() .wait() , newVar("manXY").set(v=>{ const bcr = getImage("man")._element.jQueryElement[0].getBoundingClientRect(); return bcr.x+';'+bcr.y; }).log(), newVar("boyXY").set(v=>{ const bcr = getImage("boy")._element.jQueryElement[0].getBoundingClientRect(); return bcr.x+';'+bcr.y; }).log(), newVar("figlistXY").set(v=>{ const bcr = getCanvas("figlist")._element.jQueryElement[0].getBoundingClientRect(); return bcr.x+';'+bcr.y; }).log() )
Now, regarding the linking of two pictures, it should be possible in theory, but I found out there are a few bugs with such chaining in the DragDrop element. We will need a few tricks to work around those bugs, namely we will remove the image of the bear once it’s placed on the flower, and replace it with a copy of it; we will need to retrieve the coordinates of the original image to do that though, which will involve some javascript
We will also need to have the bear and the flower placed on a Canvas element and make them “transparent” so that the Canvas element can be dragged onto the box:ERRATUM: see this post on how to use a single DragDrop element instead
newText("instructions", "Put the bear on the flower").print() , newImage("bear","bear.png").size(100,100).print(), newImage("bearCopy","bear.png").size(100,100).cssContainer("pointer-events","none").css("pointer-events","none") , newCanvas("flowerCV", 200,200).add(0,0,newImage("flower","flower.png").size(200,200)).print() , newCanvas("boxCV", 300,300).add(0,0,newImage("box","box.png").size(300,300)).print() , newDragDrop("bearToFlower") .addDrag(getImage("bear")) .addDrop(getCanvas("flowerCV")) .wait() , newFunction(()=>new Promise(async r=>{ const bearBCR = getImage("bear")._element.jQueryElement[0].getBoundingClientRect(); const flowerBCR = getCanvas("flowerCV")._element.jQueryElement[0].getBoundingClientRect(); await getCanvas("flowerCV").add(bearBCR.x-flowerBCR.x,bearBCR.y-flowerBCR.y,getImage("bearCopy"))._runPromises(); r(); })).call() , getImage("bear").hidden().remove(), getImage("flower").cssContainer("pointer-events","none") , getText("instructions").text("Now put them in the box") , newDragDrop("flowerToBox") .addDrag(getCanvas("flowerCV")) .addDrop(getCanvas("boxCV")) .wait()
Let me know if you have questions
Jeremy
-
This reply was modified 2 years, 8 months ago by
Jeremy. Reason: reference to correction below
Jeremy
KeymasterHi,
If you used the Ibexfarm interface to delete those two files, they were deleted using Perl’s
unlink
function, so the OS no longer maintains a copy of the files. In that case, you might want to consider using some recovery tools to try and retrieve your files (eg. PhotoRect is a free, cross-platform software that I’ve used with success in the past) — do it as soon as you can though, since when the OS reallocates memory used by the deleted files those can no longer be recoveredIf you deleted them manually using a file browser, maybe the OS sent copies in a recycle bin of some sort
Jeremy
Jeremy
KeymasterHi,
You cannot use PennController’s
test
commands to conditionally include an Image element: you are effectively creating an Image element for your filler items too, which don’t have any value forflan_file
, resulting in invalid Image elementsIn the script you currently have in your project, your sentence and flanker filler trials actually have nothing in common (as things stand, they do not define pic-spr pairs: there is no pic-spr sequence of commands, unlike in my code above for example; your code currently either includes
pic
commands orspr
commands in a trial) so if that’s the kind of design you are implementing, I would just split the CSV file in two tables and correspondingly use twoTemplate
commands to generate the filler trials (and also oneTemplate
for your target trials, since they all seem to be SPR’s):Template("flanker-fillers.csv", newTrial("fillers", ...pic(row) ) Template("sentence-fillers.csv", newTrial("fillers", ...spr(row) ) Template("items-target.csv", newTrial("targets", ...spr(row) )
Jeremy
Jeremy
KeymasterHi Karen,
Add
randomOrder: false
to the Question controller:newController("Question", {q: "Is it reasonable?", as: [["F","reasonable"], ["J","unreasonable"]], hasCorrect: row.Corr, randomOrder: false})
Jeremy
Jeremy
KeymasterHi,
One option is to report the features in your table (as you are currently doing in Features_SemVerMixed.csv) and label your items accordingly:
newTrial( row.Feature + "-" + row.Item ,
Then you can reference the labels in your
Sequence
command. This would show items 1-to-5 in a fixed order for each feature, with the feature groups of items randomized:features = [...new Array(10)].map((v,n)=>startsWith("Feature "+Number(n+1))) fisherYates(features) Sequence("WelcomeConsent", "counter", "demographics", "instructions1", "exercise", "startofexp", ...features, SendResults(), "Bye");
If you would like to additionally randomize the order of the items within each feature group, replace the first line with:
features = [...new Array(10)].map((v,n)=>randomize(startsWith("Feature "+Number(n+1))))
Jeremy
Jeremy
KeymasterHi,
The script that’s actually running has
PennController.ResetPrefix(null)
too far down (it should be the first line of the script) and it misses a comma between"demographic"
and"instructions"
in theSequence
commandThis is most likely due to the Save function bug on the farm: try copying the content of your script file, deleting it from your project and recreating it and pasting the content back in, and it should work
Jeremy
Jeremy
KeymasterHi,
Since your code associates
F
with the image placed where “File1IDb1” originates, andJ
with the image placed where “File2IDb1” originates, and sincelog
reports the result ofshuffle
in the Comments column, you can technically retrieve the key that was pressed from the results file. For example, from this line I can determine that I pressedJ
, since I selected the option that is listed second in the last column (File1IDb1):1666024185 REDACTED PennController 0 0 unlabeled NULL Selector selection1 Selection File1IDb1 1666024185448 File2IDb1;File1IDb1
That being said, you can still directly log which key was pressed using a Key element in parallel to the Selector element:
newKey("FJ").log("last") , newSelector("selection1") .disableClicks() .add( getImage("File1IDb1") , getImage("File2IDb1") ) .shuffle() .keys("F","J") .wait() .log() , getKey("FJ").disable()
Jeremy
-
This reply was modified 2 years, 8 months ago by
-
AuthorPosts