Reply To: Choosing subet of items to present

PennController for IBEX Forums Support Choosing subet of items to present Reply To: Choosing subet of items to present

#6240
Jeremy
Keymaster

Hi Maria,

I had completely lost sight of the fact that in addition to the test on target, each of your trials also tests phase, and what I said above applies to this test too, because it’s a .test command again: all the new* elements are created upon runtime, no matter whether the trial runs as training vs test or sg_target vs pl_target. So what you did is the right thing to do: create the elements before any test and make sure to only use get* in your const declarations (with the single exceptions of sg_devoicing and pl_devoicing, which are only present in test-sg_target and test-pl_target, respectively).

For the same reason, you need to factor newSelector("target") because otherwise you would be creating it twice. Another thing about the Selector element, I’d advise renaming it choice for example, because you already have a Var element named target and even though multiple elements of different types sharing a single name is not a fatal configuration, it’s still better practice to use different names.

Also correct me if I’m wrong, but taking a closer look at your experiment’s script from the link you shared with me, you are using the exact same code for all three types of trials (alt, non, fil), to the letter. The way I understand it, the only differences between those three types of trials lie in what is specified in the table, ie. the nature of the pictures and audios. But the trial structure is exactly the same across all three trial types. Is that right? If so, you don’t need to triple all your Template and const declarations, you can do it just once, and simply label your trials by looking up the Type column of your table.

See how much shorter your code becomes:

const training_trial = variable => [
    newTimer(500).start().wait()
    ,
    getImage("sg_picture").print()
    ,
    newTimer(200).start().wait()
    ,
    getAudio("sg_voicing").play()
    ,
    newTimer(1500).start().wait()
    ,
    getImage("sg_picture").remove()
    ,
    newTimer(1000).start().wait()
    ,
    getImage("pl_picture").print()
    ,
    newTimer(200).start().wait()
    ,
    getAudio("pl_voicing").play()
    ,
    newTimer(2000).start().wait()
    ,
    getImage("pl_picture").remove()
    ,
    newTimer(200).start().wait()
]

const test_trial = variable => [
    newSelector("choice").log()
    ,
    getVar("target").test.is("sg")
        .success( 
            newTimer(500).start().wait()
            ,
            getImage("pl_picture").print()
            ,
            newTimer(200).start().wait()
            ,
            getAudio("pl_voicing").play()
            ,
            newTimer(2000).start().wait()
            ,
            getImage("pl_picture").remove()
            ,
            getImage("sg_picture").print()
            ,
            newTimer(200).start().wait()
            ,
            newAudio("sg_devoicing", variable.SgDevoicingFile)
            ,
            getSelector("choice")
                .add( getAudio("sg_voicing"),getAudio("sg_devoicing") )
                .shuffle()
                .test.index( getAudio("sg_voicing"), 0 )
                .success(
                    getAudio("sg_voicing").play().wait(),
                    getAudio("sg_devoicing").play().wait(),
                    getSelector("choice").keys("1","2").wait()
                )
                .failure( 
                    getAudio("sg_devoicing").play().wait(),
                    getAudio("sg_voicing").play().wait(),
                    getSelector("choice").keys("2","1").wait()
                )
            ,
            newTimer(500).start().wait()
        )
        .failure( 
            newTimer(500).start().wait()
            ,
            getImage("sg_picture").print()
            ,
            newTimer(200).start().wait()
            ,
            getAudio("sg_voicing").play()
            ,
            newTimer(2000).start().wait()
            ,
            getImage("sg_picture").remove()
            ,
            getImage("pl_picture").print()
            ,
            newTimer(200).start().wait()
            ,
            newAudio("pl_devoicing", variable.PlDevoicingFile)
            ,
            getSelector("choice")
                .add( getAudio("pl_voicing"),getAudio("pl_devoicing") )
                .shuffle()
                .test.index( getAudio("pl_voicing"), 0 )
                .success(
                    getAudio("pl_voicing").play().wait(),
                    getAudio("pl_devoicing").play().wait(),
                    getSelector("choice").keys("1","2").wait()

                )
                .failure( 
                    getAudio("pl_devoicing").play().wait(),
                    getAudio("pl_voicing").play().wait(),
                    getSelector("choice").keys("2","1").wait()

                )
        )
]

Template( row =>
    newTrial( row.Type ,
        newImage("sg_picture", row.SgPictureFile),
        newImage("pl_picture", row.PlPictureFile),
        newAudio("sg_voicing", row.SgVoicingFile),
        newAudio("pl_voicing", row.PlVoicingFile)
        ,
        getVar("phase").test.is("training")
            .success( ...training_trial(row) )
            .failure( ...test_trial(row) )
    )
    .log("phase", getVar("phase") )
    .log("sg_picture", row.SgPictureFile )
    .log("Item", row.Item)
)

Notice how you don’t need to filter your table at all, but the trials are now labeled row.Type, which ensures that you’ll still end up with trials labeled alt, some labeled fil and some labeled non, based on your table’s Type column.

I tested this code myself, and the whole experiment ran smoothly. I think we finally got there, but let me know if you have questions

Jeremy