Jeremy

Forum Replies Created

Viewing 15 posts - 1,381 through 1,395 (of 1,522 total)
  • Author
    Posts
  • in reply to: How to present two lines on one page? #4997
    Jeremy
    Keymaster

    The code in my second message actually already does what you describe: it presents the sentence “Today is a very nice day!” as a whole chunk, and the second sentence word-by-word

    This is actually how the DashedSentence controller works by default in Ibex: if you take a close look at the s parameter, the first time it is an array of one element (that element being the string) whereas the second time it is a string, directly (no square brackets). When the parameter is an array, every element is presented as a chunk, but when the parameter is directly a string, it is split using the space character and each word (separated by a space) is a chunk.

    Jeremy

    in reply to: How to present two lines on one page? #4994
    Jeremy
    Keymaster

    Sorry, posting a new message because after re-reading your message I think I just realized that you want something slightly different. Would you be OK with having two DashedSentence back-to-back, like this?

    newTrial(
      newController( "DashedSentence" , {s: ["Today is a very nice day!"]} )
        .print()
        .wait()
        ,
      newController( "DashedSentence" , {s: "So I went outside for a walk."} )
        .print()
        .wait()
    )
    in reply to: Using Group for two different blocks #4992
    Jeremy
    Keymaster

    Hi,

    I’m not sure I understand your design, but wouldn’t a table like the one below work the way you want?

    AddTable("myTable", `ItemNumber,ButtonText,Group,Block
    1,Lorem,A,1
    2,ipsum,A,1
    3,dolor,A,1
    4,sit,A,2
    5,consectetur,A,2
    6,adipiscing,A,2
    7,elit,B,1
    8,sed,B,1
    9,do,B,1
    10,eiusmod,B,2
    11,tempor,B,2
    12,incididunt,B,2`)
    
    Sequence( randomize("block-1") , "break" , randomize("block-2") )
    
    newTrial( "break" , newButton("Start second half").print().wait() )
    
    Template( "myTable" , row => 
      newTrial( "block-"+row.Block ,
        newButton(row.ButtonText).print().wait()
      )
      .log( "OrderGroup" , row.Group )
    )

    This is just illustrating two order groups, my understanding is that you’d want to have 18 of them so using letters as group labels you would add rows until you have an R group. I used different items on every single row (different item numbers and different button text).

    Is this the kind of thing you want to do?

    Jeremy

    in reply to: How to present two lines on one page? #4991
    Jeremy
    Keymaster

    Hello Jun,

    Yes, one option would be to inject the native-Ibex DashedSentence controller in a PCIbex trial, like this:

    newTrial(
      newText("context", "Today is a very nice day!")
        .css('font-family', 'monospace')
        .center()
        .print()
      ,
      newText("instructions", "

    Press Space to start reading the next sentence

    ").italic().print() , newKey(" ").wait() , getText("instructions").remove() , getText("context").text("_____ __ _ ____ ____ ____") , newController( "DashedSentence" , {s: "So, I went outside for a walk.", display: "in place"} ) .print() .wait() )

    More info on the DashedSentence controller in the original Ibex documentation

    Jeremy

    • This reply was modified 5 years, 3 months ago by Jeremy. Reason: Tried to make the example closer to what was described
    Jeremy
    Keymaster

    Hi,

    1. If you look at the documentation page for the VoiceRecorder element, you’ll see that there are two relevant commands: a wait command and a test.recorded command. I would favor the first one, using it like this:

    newTrial(
      newVoiceRecorder("sample")
        .print()
        .wait()
      ,
      newButton("Next")
        .print()
        .wait()
    )

    Alternatively, you could use getVoiceRecorder("sample").test.recorded() in your button’s wait command to validate the click only if a recording is present.

    2. You can partially customize the text by passing a string as the second parameter of InitiateRecorder. I should add an option to customize the consent text too, but in the meantime you can add this to your script:

    let replaceConsentMic = ()=>{
            let consentLink = $(".PennController-PennController a.Message-continue-link");
            if (consentLink.length > 0 && consentLink[0].innerHTML.match(/^By clicking this link I understand that I grant this experiment's script access to my recording device/))
                consentLink.html("En cliquant sur ce lien je comprends que j'autorise le script de cette expérience à accéder à mon microphone...");
            else
                window.requestAnimationFrame( replaceConsentMic );
    };
    window.requestAnimationFrame( replaceConsentMic );

    Of course you want to replace the French text with your own text.

    Let me know if you have questions

    Jeremy

    in reply to: conditions in self-paced reading experiment #4987
    Jeremy
    Keymaster

    Hi,

    There are a few things that cause your script to crash:

    • Elements should not be created by nesting them, ie. this is not valid syntax: newText((newScale. Either you create a Text element (if you just want to show a sentence or a paragraph on the screen) or you create a Scale element (if you want to provide participants with one). If you want to show both elements on the same line, one before the other, that’s what the before and after commands are for (you can use new* or get* commands inside the parentheses of non-new/get* commands).
    • All new* commands follow the same syntactic rules, in particular, they all require to be immediately followed by a pair of parentheses in which you (optionally) pass parameters. The first occurrence of newScale in your script comes with no such pair of parentheses, but the second occurrence does.
    • Besides a first optional name parameter, the parameter(s) of newScale can have two possible formats (as described on the documentation): either you use a single number that specifies the number of points on your scale, or you give a series of strings (separated by commas) that correspond to the labels of your scale’s buttons. So either something like newScale("yesno", "Yes", "No") or something like newScale("correctness", 5).
    • The script will execute the lines in newTrial from the top down, and will only halt on wait commands. Since your script has no wait command, it will execute all the lines in an instant and immediately reach the closing parenthesis of newTrial, effectively ending your trial milliseconds after it started. You want to insert a wait command somewhere.

    I am not totally sure what exactly you want your script to do, but below is a working variant of it. Note that I took the liberty to get rid of the .settings prefixes that became deprecated with PennController 1.7, and that the Text element named DashedSentence is just that: a Text element, so the content of row.DS will be printed at once. If you want to use the native-Ibex DashedSentence controller, you can use newController("DashedSentence", {s: row.DS}).print().wait() (you can take a look at the Controller element documentation page and this topic in the FAQ/Tips section).

    Template(row =>
        newTrial(
            newText(row.sentence)
                .print()
            ,
            newText("DashedSentence", row.DS)
                .print()
            ,
            newScale("yesnocorrect",  "Yes","No" )
                .labelsPosition("right")
                .keys()
                .before( newText("Is the sentence correct?") )
                .print()
            ,
            newText("How correct would you say it is?")
                .print()
            ,
            newScale("correct", 5)
                .keys()
                .before(newText("completely incorrect"))
                .after(newText("completely correct"))
                .print()
                .wait()
        )
    )

    If you haven’t done so yet (or if you want a refresher) I strongly recommend that you read the tutorial. You can also watch this video of a webinar on this tutorial that we recorded just yesterday.

    Best,
    Jeremy

    in reply to: Centering textInput without centering text cursor #4982
    Jeremy
    Keymaster

    Hello,

    Ah, right, I noticed this problem before. I doubt anyone would even want to center the cursor, so I should probably change the effect of the center command on TextInput elements. In the meantime, you can do this:

    newTextInput().cssContainer("text-align","center").print()

    Jeremy

    in reply to: Recording audio #4971
    Jeremy
    Keymaster

    HI Alan,

    You can record audio any time you want, just make sure that the trial that you create using InitiateRecorder comes before any trial in which you use the VoiceRecorder element in your sequence of trials. For example:

    PennController.ResetPrefix(null)
    
    Sequence( "intro" , "init-audio" , "first-half" , "record-audio" , "second-half" )
    
    AddTable( "first-table" , "ButtonText\nClick on me\nAlmost there\nNext you'll be halfway through" )
    
    AddTable( "second-table" , "ButtonText\nClick again\nAlmost done\nThis is the last trial" )
    
    newTrial("intro" ,
      newText("Welcome!").print()
      ,
      newButton("Start").print().wait()
    )
    
    InitiateRecorder(
      "https://myserver/uploadVoices/saveRecordings.php"
      ,
      "You will first go over a few trials, then record a sample, and then go over some more trial. Please authorize this experiment to access you microphone."
    )
    .label( "init-audio" )
    
    Template( "first-table" , row => 
      newTrial( "first-half" , newButton( row.ButtonText ).print().wait() )
    )
    
    newTrial( "record-audio" , 
      newVoiceRecorder().print().wait()
      ,
      newButton("Continue").print().wait()  
    )
    
    Template( "second-table" , row => 
      newTrial( "second-half" , newButton( row.ButtonText ).print().wait() )
    )

    Of course this example script won’t succeed in sending the audio sample since I provided a fake URL to InitiateRecorder

    Jeremy

    in reply to: conditions in self-paced reading experiment #4961
    Jeremy
    Keymaster

    Then your best option is probably to create another table in parallel for the fillers specifically, in which you don’t need to have a Group column at all (this way you can have only one row per filler item). When you have multiple tables in your project, just make sure to specify which one you want to use in the respective Template commands.

    in reply to: conditions in self-paced reading experiment #4959
    Jeremy
    Keymaster

    If you have 20 items and 5 conditions, with the latin-square design that you illustrated in your table above, each of your participants would experience 4 repetitions of each condition (20 / 5 = 4 items per condition).

    For the different context and question sentences, simply add columns to your table

    Jeremy

    in reply to: conditions in self-paced reading experiment #4957
    Jeremy
    Keymaster

    Hi,

    Yes, with the table you describe, participants in the A group would see two items: the first one in the definite Singular condition, the second one in the bare plural condition. Participants in the B group would see the same two items, but now the first one would be bare plural, and the second one definite Singular. The same logic extends to groups C, D and E.

    Is that what you want?

    Your table should also include columns for your other variable contents, so you probably want to add a Context column, a Question column and as many columns as there are different answer choices to that question on each trial (something like Answer1, Answer2, …)

    Jeremy

    in reply to: Feedback after selecting an image #4953
    Jeremy
    Keymaster

    Good catch about the mismatch between the keys and the images’ positions

    Moving the counterbalancing to the table is actually simpler than what you currently have: just add a pair of columns that you name leftPicture and rightPicture (for example) and simply alternate between “CoveredPicture” and “VisualPicture.” Then you can get rid of the whole “toggle” Var chunk and replace it with something like getCanvas("left").add( 0 , 0 , getImage(row.leftPicture) ) (same thing for “right”)

    And apply the same logic when adding your images to your selector: .add( getImage(row.leftPicture) , getImage(row.rightPicture) ) (no need to change anything about the keys command then)

    Does that make sense?

    Jeremy

    in reply to: Feedback after selecting an image #4951
    Jeremy
    Keymaster

    Hi Elise,

    Yes, the logic is exactly the same as with the Key element, you just test for the selected item using .test.selected:

    Template( "Filler_orig.csv" ,
        row => ["filler_orig",
            "DashedSentence", {s: row.Sentence},
            "PennController", newTrial(
        defaultImage
            .size(400,400)   
            ,
        newImage("CoveredPicture", "covered.jpg")
            ,  
        newImage("VisualPicture", row.Picture)
           ,
        newCanvas(800,400)
            .add(   -25 , 0 , newCanvas("left" , 400, 400) )  
            .add( 425 , 0 , newCanvas("right", 400, 400) )  
            .print()
            .settings.log()
            ,
        newCanvas(50,50)
            .settings.add(-75,-200, newText("(F)"))
            .settings.add(850,-200, newText("(J)"))
            .print()
            ,
        newVar("toggle", 1)  // Initialize with value 1
            .global().set( v=>1-v ).test.is(1) // This should be 1-v, I think
            .success(
                getImage("CoveredPicture").print(0,0,getCanvas("left")),  
                getImage( "VisualPicture").print(0,0,getCanvas("right"))   
            )
            .failure(
                getImage("CoveredPicture").print(0,0,getCanvas("right")),
                getImage( "VisualPicture").print( 0,0,getCanvas("left") )
            )
            ,
        newSelector()
            .settings.disableClicks()
            .settings.add( getImage("CoveredPicture") , getImage("VisualPicture") )
            .settings.keys(          "F"    ,          "J"   )
            .settings.log()
            .wait()
            .test.selected( getImage(row.Target) )
            .success( newText("Good job!").print() )
            .failure( newText("Nope!").print() )
            ,
        newButton("Next").print().wait()
        )
        .log('Condition', row.Condition)
        .log('Item', row.Item)
    ])

    NOTE: I replaced the v-1 bit with 1-v as it makes more sense to me (you want the toggle Var to alternate between 1 and 0, not to tend towards -inifinity)—sorry if that was my mistake from a previous code

    in reply to: conditions in self-paced reading experiment #4949
    Jeremy
    Keymaster

    Hi,

    PennController provides a Template command that can generate trials from a CSV table, and CSV tables can optionally contain a Group (alternatively called List) column that further distinguishes subsets of rows, so that each time the experiment is run only rows from one subset are used.

    You can find an example and discussion of it on this page of the documentation tutorial, which illustrates 4 items each associated with two conditions (Ending: -s vs Ending: No-s) but presented in only one condition to each participation (latin-square design). Take a look at the Table section of the page more particularly.

    Let me know if you have more questions

    Jeremy

    in reply to: .zip file problems #4946
    Jeremy
    Keymaster

    Yes, what you see is a good sign: it means that the script works as intended and does not crash when your request for the image fails

    My guess is that the moving object is missing because your request to your bucket is processed very quickly but, instead of returning the zip file, it returns an error-like object (hence the non-display of your image upon running the trial)

    In the meantime, if you don’t have too many images and the files are not too big, feel free to upload them to the PCIbex Farm (the Potsdam-experiments account currently only uses about 4.5MB out of the new 64MB limit)

    Jeremy

Viewing 15 posts - 1,381 through 1,395 (of 1,522 total)