Using if statements during a trial

PennController for IBEX Forums Support Using if statements during a trial

This topic contains 8 replies, has 3 voices, and was last updated by Jeremy Jeremy 1 week, 5 days ago.

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #5570
    Avatar
    mrhelfrich
    Participant

    Hello,

    I have a kind of convoluted question.

    My overall goal is to have an experiment where participants read a test item taken from a .csv file. The .csv file also has a column with an comprehension question for some test items, and therefore if the test item they just read has a comprehension question for it, I want them to be shown that instead of the next test item in the .csv file being displayed.

    My plan on how to accomplish this was to use an if statement associated with another column in the csv file. The CSV file has a column that holds either a Y or N for whether or not the test item has a question attached. So after the test item is displayed, if no question was going to be asked, a button would appear telling them to proceed to the next trial, but if there was a test item, a different button would appear telling them they would be taken to a comprehension question. My issue is that I am getting syntax problems with the if statement so I cannot test anything.

    I’ve simplified the code as much as possible to just isolate the problem to post to the forum:

    PennController.ResetPrefix(null);
    
    AddTable( "IfTable" , // for the sake of forum posting, actual experiment uses an embedded .csv file
    "TrialNum,FullText,CompYN,CompQ,CompR,CompTF\n"+
    "1,Trial 1 does not have a comprehension question.,N,,,\n"+
    "2,Trial 2 does have a comprehension question.,Y,Placeholder question for Trial 2 click button to continue no response needed correct answer will be 1 or True.,2,F\n"+
    "3,Trial 3 does have a comprehension question.,Y,Placeholder question for Trial 3 click button to continue no response needed correct answer will be 2 or False.,2,F\n"+
    "4,Trial 4 does not have a comprehension question.,N,,,\n"+
    "5,Trial 5 does have a comprehension question.,Y,Placeholder question for Trial 5 click button to continue no response needed correct answer will be 1 or True.,1,T\n"
    );
    Template( "IfTable" , row =>
        newTrial( "experiment" ,
            newText ("FullText", row.FullText),
            newButton("FTButton1","Proceed to next Trial"),
            newButton("FTButton2","Proceed to Comprehension Question"),
            newText("CompQ",row.CompQ),
            newButton("CQButton","Placeholder, just click to answer"),
            
            getText("FullText")
                .print(),
        if (row.CompYN==Y){
            getButton("FTButton2")
                .print()
                .wait()
                .remove("FTButton2","FullText"),
            getText("CompQ")
                .print(),
            getButton("CQButton")
                .print()
                .wait()
                .remove("CompQ","CQButton")
        }
        else if (row.CompYN==N){
            getButton("FTButton1")
                .print()
                .wait()
                .remove("FTButton1","FullText")       
        }
        ) //closes newTrial
    ) //closes Template
    

    I am not a programmer so I could be making any number of mistakes, the only solution I could come up with to have follow-up questions appear after certain items was an if statement.

    Thank you for your time,
    Max

    • This topic was modified 1 month ago by Avatar mrhelfrich.
    #5572
    Jeremy
    Jeremy
    Keymaster

    Hello Max,

    TLDR: this is the (or rather, one) correct syntax

    newTrial( "experiment" ,
        newText ("FullText", row.FullText),
        newButton("FTButton1","Proceed to next Trial"),
        newButton("FTButton2","Proceed to Comprehension Question"),
        newText("CompQ",row.CompQ),
        newButton("CQButton","Placeholder, just click to answer"),
        getText("FullText").print(),
        ( row.CompYN==Y ?
            getButton("FTButton2")
                .print()
                .wait()
                .remove("FTButton2","FullText"),
            getText("CompQ")
                .print(),
            getButton("CQButton")
                .print()
                .wait()
                .remove("CompQ","CQButton")
        :
            getButton("FTButton1")
                .print()
                .wait()
                .remove("FTButton1","FullText")       
        )
    ) //closes newTrial

    You cannot inject if statements this way into a PennController trial, because the sequence of commands that you pass to newTrial really are arguments that you pass to a function, and javascript does not allow you to insert if statements in this kind of environment. What you can do, however, is use the so-called inline ternary conditional operator, which uses this syntax: ( test ? success : failure )

    Note that the condition will be evaluated at the very beginning of your experiment, which is fine in your case because you are testing the value of a column from your table. If you wanted to test a value that is manipulated upon runtime however, say some input from your participant, you would need to use a PennController test command, to ensure that the test is performed only after input.

    Jeremy

    #5579
    Avatar
    mrhelfrich
    Participant

    Thank you for the quick reply, unfortunately the code you posted is throwing syntax errors when I copy it over. I am not great at understanding the error messages but it seems like it by default after the test ? error checker only allows one get command. I added parentheses to envelop all of the commands that I wanted to run before the : and this gets rid of the syntax errors but when I run the code it doesn’t execute properly (I also had to change row.CompYN==Y ? to row.CompYN=="Y" ? since it was treating it as an expression. I am not certain but it appears that putting parentheses around the multiple commands only stops the syntax errors and the conditional operator you showed me will only run the last command listed before the colon. I changed the text displayed on the buttons to make it easier to see but it looks like the test itself functions properly but it doesn’t execute all of the code when row.CompYN=="Y" is true.

    Here’s the code I have been running that at doesn’t give syntax errors but doesn’t run as expected.

    PennController.ResetPrefix(null);
    // for the sake of forum posting
    AddTable( "IfTable" , 
    "TrialNum,FullText,CompYN,CompQ,CompR,CompTF\n"+
    "1,Trial 1 does not have a comprehension question.,N,,,\n"+
    "2,Trial 2 does have a comprehension question.,Y,Placeholder question for Trial 2 click button to continue no response needed correct answer will be 1 or True.,2,F\n"+
    "3,Trial 3 does have a comprehension question.,Y,Placeholder question for Trial 3 click button to continue no response needed correct answer will be 2 or False.,2,F\n"+
    "4,Trial 4 does not have a comprehension question.,N,,,\n"+
    "5,Trial 5 does have a comprehension question.,Y,Placeholder question for Trial 5 click button to continue no response needed correct answer will be 1 or True.,1,T\n"
    );
    Template( "IfTable" , row =>
        newTrial( "experiment" ,
            newText ("FullText", row.FullText),
            newButton("FTButton1","Proceed to next Trial"),
            newButton("FTButton2","SHOULD DISPLAY IMMEDIATELY AFTER TRIAL 1 AND 4"),
            newText("CompQ",row.CompQ),
            newButton("CQButton","SHOULD DISPLAY WITH COMPQ TEXT ABOVE"),
            getText("FullText").print(),
                (row.CompYN=="Y" ?  // functions like an if statement based on the specified test, if row.CompYN==Y, then the following code is executed, if not, run code after the colon
                  ( // parentheses needed to include multiple commands as part of the 'success' branch of the above test  
                    getButton("FTButton2")
                        .print()
                        .wait()
                        .remove("FTButton2","FullText"),
                    getText("CompQ")
                        .print(),
                    getButton("CQButton")
                        .print()
                        .wait()
                        .remove("CompQ","CQButton")
                  ):  // close parentheses and then colon marks the change to the 'failure' branch of the test
            getButton("FTButton1")
                .print()
                .wait()
                .remove("FTButton1","FullText")       
                )  // closes the 'test'
        ) // closes newTrial
    )  // closes Template
    

    Thanks again for all of your help,
    Max

    #5580
    Jeremy
    Jeremy
    Keymaster

    Hi Max,

    I’m sorry, I went too fast when posting my answer, here is a revised version of the code:

    newTrial( "experiment" ,
        newText ("FullText", row.FullText),
        newButton("FTButton1","Proceed to next Trial"),
        newButton("FTButton2","Proceed to Comprehension Question"),
        newText("CompQ",row.CompQ),
        newButton("CQButton","Placeholder, just click to answer"),
        getText("FullText").print(),
        ( row.CompYN=="Y" ? [
            getButton("FTButton2")
                .print()
                .wait()
                .remove("FTButton2","FullText"),
            getText("CompQ")
                .print(),
            getButton("CQButton")
                .print()
                .wait()
                .remove("CompQ","CQButton")
        ] : [
            getButton("FTButton1")
                .print()
                .wait()
                .remove("FTButton1","FullText")       
        ] )
    ) //closes newTrial

    Besides the lack of double-quotes around Y, the problem was that each comma-separated block of commands represents an object, but the ( test ? success : failure ) structure allows only one object in success and failure. There technically were three objects in the success part of the original code, so the first two were ignored. The solution I just proposed is to package the three objects into a single array: because newTrial treats commands packaged in an array the same way as direct series of commands, you still get the intended result.

    Jeremy

    #5584
    Avatar
    mrhelfrich
    Participant

    Okay, that seems to have solved the problem. I have one minor question now that the code is executing properly.
    The way my code is currently set-up, it draws the text I want and immediately after it draws the button to continue, and depending on the what you helped me with that button will be one of two different buttons. When the test fails, button drawn ends the loop and the next trial occurs and all of the old text gets removed, but when the test succeeds, clicking the button to go to the comprehension question draws the comprehension question and then a different button that will end the loop. I was previously hoping that by specifying what items I wanted removed inside the parentheses of the .remove() line would make it remove those items but now that the code is executing properly that doesn’t do anything and the .remove() command just removes whatever it is attached to. When the test succeeds and getButton("FTButton2") appears, upon clicking it I want both the button itself to be removed as well as the previous command getText("FullText") to be removed. Is there a command to remove previously drawn text sort of like what happens when a trial completes and a new loop starts?

    Thanks again for all of the help,
    Max

    #5586
    Avatar
    mrhelfrich
    Participant

    Unable to edit my reply but I figured out how to resolve the problem, I just needed to call getText("FullText") again and then use .remove().

    #5587
    Jeremy
    Jeremy
    Keymaster

    Hi Max,

    As you say, the remove commands applies to the element it attaches to, so just attach it to the elements you want to remove:

    getButton("FTButton2")
        .print()
        .wait()
        .remove(),
    getText("FullText").remove(),
    getText("CompQ")
        .print(),
    getButton("CQButton")
        .print()
        .wait()
        .remove(),
    getText("CompQ").remove()

    Jeremy

    #5716
    Avatar
    mschrumpf
    Participant

    Hello everybody,
    I am currently working on a very similar experiment: a self-paced reading task where some but not all of the items have a comprehension question.
    I tried to apply your code from earlier in this thread, Jeremy, as stated below. My implementation has completely taken out the skript however, as I now only get the “There must be some items in the running order” error message when I try to run it.
    This is my code:

    Template( "MyTable.csv" ,
        row => newTrial( "experiment" ,
            dashed("sentence", row.Satz)
            ,
            newButton("Fertig")
                .print()
                .wait()
            ,
            newTimer(200)
                .start()
                .wait()
            ,
            newText("Frage", row.Frage)
            ,
            newText("Links", row.Links)
            ,
            newText("Rechts", row.Rechts)
            ,
            newCanvas("Canvas", 450,200)
            ,
            newSelector("Selector")            
            ,
            newTimer("200", 200)
                .start()
                .wait()
            ,
            ( row.Antwort=="1" ? [
                getText("Frage")
                    .print(),
                getText("Links")
                    .print(),
                getText("Rechts", row.Rechts)
                    .print(),
                getCanvas("Canvas")
                    .add(   0 , 0 , getText("Links") )
                    .add( 250 , 0 , getText("Rechts") )
                    .print(),
                getSelector("Selector")
                    .add ( getText("Links"), getText("Rechts"))
                    .keys(          "F"     ,           "J")
                    .log()
                    .once()
                    .wait()
                ] : [
                getText("Frage")
                .print() //Placeholder code. The final skript should just "do nothing" here
                    ] )
        )
        .log("Item" , row.Item )
        .log( "Konsistent" , row.Konsistent )
        .log( "Geschlecht" , row.Geschlecht )
        .log( "Krit" , row.Krit )
        .log( "Anzahl" , row.Anzahl )
        .log( "Antwort" , row.Antwort )
        .log( "Satz" , row.Satz )
        .log( "Frage" , row.Frage )
        .log( "Links" , row.Links )
        .log( "Rechts" , row.Rechts )
    )

    Since the error message is giving me nothing to work with, I would be very grateful for any hints as where I have gone wrong.
    Thanks in advance and best regards

    #5719
    Jeremy
    Jeremy
    Keymaster

    Hello,

    Your problem must be coming from another part of your script, because I just tested what you posted and it works as expected, I don’t get any error message

    Did you make sure you properly defined dashed?

    Jeremy

Viewing 9 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic.