Refreshing canvas

PennController for IBEX Forums Support Refreshing canvas

This topic contains 10 replies, has 2 voices, and was last updated by Avatar rventura 1 week, 3 days ago.

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #6982
    Avatar
    rventura
    Participant

    Hi Jeremy,

    I’m running into the following issue: (1) I want to print two canvases to a trial, (2) I want a button on the second canvas to continue to the next trial screen, (3) I want a timer to refresh the first canvas with some changes, and (4) I want the changes made to the first canvas to stay in place after users click on the button to continue to the next trial screen. I am able to do items 1 to 3, but not 4: whenever users click on the button to continue to the next trial screen, the changes made to the first canvas disappear. My question is thus how can I ensure that changes remain in place after users click on the button to continue to the next trial screen?

    Here’s my code:

    Template( GetTable("cond_test.csv"), row => 
        newTrial("Phase_3a",
        
            newTimer("wait_1", 10000)
                .start(),
                
            newTimer("wait_2", 2000)
                .start(),
                
            //Initial canvas
            newCanvas("start", 800,50)
                .add( 0, 0,
                newText("player 1", "PLAYER 1 - OTHER") 
                )
                
                .add( 600, 0,
                newText("player 2", "PLAYER 2 - YOU") 
                )
                
                .print()
            ,
            
            //Final canvas 
            newCanvas("time up", 800,50)
                .add( 0, 0, 
                newText("player 1", "PLAYER 1 - OTHER") )
                
                .add( 600, 0, 
                newText("player 2", "PLAYER 2 - YOU") )
                
                .add( 600, 50,
                newText("player 2", "<i>Your time is up. Get ready for next phase!</i>") ),
    
            //Canvas for players
            newCanvas("players", 800,400)
    
                .add( 600, 20,
                newImage("timer 1", "twomin.gif") 
                )
                
                .add( 500, 50,
                newImage("pic_learn", row.File ) 
                )
     
                .add( 645, 350,
                newText( row.Noun ) 
                )
                
                .add( 0, 0,
                getTimer("wait_1")
                    .callback( getCanvas("start").remove() )
                    .callback( getCanvas("players").remove() )
                    .callback( getCanvas("time up").print() ) 
                )
                
                .add( 645, 400,
                newButton("next", "Next")
                    .print()
                )
                
                .print()
            ,
            
            getTimer("wait_2")
                .callback( getCanvas("start").add( 0,20, newText("<i>Player 1 is ready!</i>") ).refresh() ),
    
            getButton("next")
                .wait()
            
            
        ).log("Cond", row.Cond).log("Chain", row.Group).log("Gen", row.Gen).log("Freq", row.Freq ).log("Noun", row.Noun ).log("File", row.File ).log("ID", GetURLParameter( "ID" ) )
    );

    Thank you so much in advance for any advice you might have!

    Best,
    Rafael

    #6985
    Jeremy
    Jeremy
    Keymaster

    Hi Rafael,

    The last command in your trial is wait on the Button element, so whenever the button is clicked, the trial ends, and all elements are removed from the page, so you’ll just no longer be able to see any changes to the Canvas elements after the click. You will either need to keep track of things across trials using a global Var element and testing it at the beginning of the trial to run different add or print commands accordingly, or change your approach of your task and incorporate it within a single trial

    A couple tips: if you’re not getting the Text elements, you don’t need to explicitly give them names (right now you’re creating two distinct elements both named “player 1” and three distinct elements all named “player 2”). Timer elements have no visual content, no it doesn’t make much sense to add them to a Canvas element. You could simply attach your callback commands directly onto the newTimer command (also, you can pass three comma-separated commands to callback, no need to call three callbacks in a row)

    Jeremy

    #6992
    Avatar
    rventura
    Participant

    Hi Jeremy,

    Thank you, that’s very helpful! A further question I have is: how can I time all the trials in the template? If a timer starts in the beginning of a trial, then a new timer starts every time the user clicks on the button and the user is taken to the next trial. Is there a general way to ensure that users are given a limited amount of time to finish all the trials in the template?

    Many thanks!

    Best,
    Rafael

    #6997
    Jeremy
    Jeremy
    Keymaster

    Hi Rafael,

    The reasoning is the same here: elements are parts of trials, so when their trial ends, they cease to exist. The only exception is the Var element, which can be made global so you can access and manipulate its value across trials

    If you need to keep track of how much time has passed since the beginning of the experiment, you can set a javascript variable to Date.now() and check it on every trial, for example inside a Header. Here’s an example that will print a 2min timer in the top-left corner of the page, and clear the screen and print a “Timed out!” message when there’s not time left:

    ALLOTEDTIME = 2*60*1000
    startTime = Date.now()
    toMinSec = v=>Math.floor((ALLOTEDTIME-v)/60000)+":"+Math.floor(((ALLOTEDTIME-v)/1000)%60)
    
    Header(
        newText("timer", "").print("left at 2em", "top at 2em")
        ,
        newVar("time elapsed")
            .set(v=>Date.now()-startTime)
            .test.is(v=>v>ALLOTEDTIME).success( end() )
        ,
        newTimer("timeout", 500)
            .callback(
                getVar("time elapsed")
                    .set(v=>Date.now()-startTime)
                    .test.is(v=>v>ALLOTEDTIME)
                    .success(
                        clear()
                        ,
                        newText("Time out!").print()
                        ,
                        newButton().wait()   
                    )
                    .failure( 
                        getVar("time elapsed").set(toMinSec)
                        ,
                        getText("timer").text(getVar("time elapsed"))
                        ,
                        getTimer("timeout").start() 
                    )
            )
            .start()
    )

    Jeremy

    #7022
    Avatar
    rventura
    Participant

    Hi Jeremy,

    That’s perfect, thank you! I have yet another question. I want to have a score tracker and for that I initialize a global variable with newVar(“value”, 0).global(). But when I try to update a Text element with getText(“value”).text( getVar(“value”) ), I get an error message I cannot decipher. The code and the error message are below:

    newTrial("Begin_2",
       
        newVar("value", 0).global(),
    
        newText("<h4>You are about to start Phase 2!</h4>").print(),
    
        newButton("Begin Phase 2!")
            .center()
            .print()
            .wait()
    
    );
    
    Template( GetTable( "icon.csv" ), row => 
        newTrial("Phase_2",
    
            newCanvas("score", 600,20)
                .add( 275, 0,
                    newText("score", "score: ")
                ).print()
                .add( 325, 0,
                    newText( "value", "0" )
                ).print()
            ,
            
            getText("value").text( getVar("value") ),
    
    ); 

    And the error message:

    [8:33:40] Command ‘0’ unknown on Var element ‘value’. (PennController: 34)
    [8:33:40] Command ‘length’ unknown on Var element ‘value’. (PennController: 34)
    [8:33:40] Command ‘parentNode’ unknown on Var element ‘value’. (PennController: 34)

    Thanks,
    Rafael

    #7027
    Jeremy
    Jeremy
    Keymaster

    Hi Rafael,

    The Template command from your post contains a trailing , after getText("value").text( getVar("value") ) and misses a closing parenthesis (you seem to include a closing parenthesis for Template( but no closing parenthesis for newTrial()

    Once I fix these two points, your scripts runs smoothly for me. I’m using PennController 2.0.alpha. If you are using an older version, it could be that using the same name ("value") both for the Text element and for the Var element creates a conflict, so maybe try using a different name for your Text element (eg. "value display")

    Jeremy

    #7030
    Avatar
    rventura
    Participant

    Hi Jeremy,

    Thanks for the quick reply! The code that I posted here had a few typos, but the code that’s giving the error message didn’t. My bad for obscuring the issue in a failed attempt to make the post easier to read. Besides, missing parentheses and extra comes don’t usually give me the error messages I’m receiving. Is there a way to check/update my PennController version? I gave the elements different names but still get the same error.

    Here’s the full code:

    newTrial("Begin_2",
        
        //
        newVar("value", 0).global(),
    
        newText("<h4>You are about to start Phase 2!</h4>")
            .print(),
            
        newText("<p> </p>").print(),
        newButton("Begin Phase 2!")
            .center()
            .print()
            .wait()
    
    );
    
    //Phase 2: Produce
    Template( GetTable( "icon.csv" ), row => 
        newTrial("Phase_2",
        
            //
            newCanvas("score", 600,20)
                .add( 275, 0,
                    newText("score", "score: ")
                ).print()
                .add( 325, 0,
                    newText( "score_value", "0" )
                ).print()
            ,
            
            getText("score_value").text( getVar("value") ),
    
            //
            newCanvas("next_trial", 600,250)
                .add( "center at 50%", "middle at 50%",
                    newText("<p>Next . . .</p>")
                ).print()
            ,
            
            newTimer("wait", 600).start().wait(),
            getCanvas("next_trial").remove(),
    
            newCanvas(600,250)
                .add("center at 50%", "middle at 50%", newImage("pic", row.File))
                .print()
            ,
            
            newScale("answer", row.A1, row.A2, row.A3, row.A4 )
                .center()
                .vertical()
                .labelsPosition("right")
                .print()
                .wait()
            ,
            
            getScale("answer")
                .test.selected( row.Noun1)
                .or( getScale("answer").test.selected( row.Noun2) )
                .success(
                    getVar("value").set( v => v+1 ),
                    getText("score_value").text( getVar("value") )
                )
                .failure(
                    getText("score_value").text( getVar("value") ) 
                )
            ,
                
            newText("<p> </p>").print(),
            newButton("next", "Next")
                .center()
                .print()
                .wait()
            
        )
    );

    Best,
    Rafael

    #7033
    Jeremy
    Jeremy
    Keymaster

    The Debug popup’s title shows the project’s PennController version. Feel free to share the demonstration link to your project here or at support@pcibex.net, which will make it easier to view the project’s code (and avoid any typo-insertion issues) and also the version of PennController it uses

    Jeremy

    #7034
    Avatar
    rventura
    Participant

    Great, thank you! It looks like I’m using v2.0.alpha. Here’s the demo link:

    https://farm.pcibex.net/r/ZStOSj/experiment.html?test=true

    Best,
    Rafael

    #7036
    Jeremy
    Jeremy
    Keymaster

    I’ve been working and updating 2.0.alpha on the farm, I think your project uses a slightly older version than the one I was testing your code with

    Download this file and replace your project’s Modules/PennController.js file with it: https://raw.githubusercontent.com/PennController/penncontroller/master/dist/PennController.js

    Jeremy

    #7037
    Avatar
    rventura
    Participant

    It’s working now, thank you!

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

You must be logged in to reply to this topic.