Progress bar for each sentence?

PennController for IBEX Forums Support Progress bar for each sentence?

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #10501
    E.Inshakova
    Participant

    Hello Jeremy!

    I’ve been test-running an acceptability judgement experiment, and some participants have requested a progress bar in the questionnaire to see how much time is left to evaluate each sentence. Is it possible to include such an element in the trial template?

    Thanks in advance,
    Evgeniya Inshakova

    #10506
    Jeremy
    Keymaster

    Hello Evgeniya,

    At the top of your script, define the size you want for that progress bar, for example 100*20px: const PROGRESS_SIZE = {w: 100, h: 20}

    Then in your trial, print the Canvas elements that stand for your progress bar and run a function to update it when you launch the timeout. In this example, I’m setting a duration of 5000m:

    newCanvas("progressContainer", PROGRESS_SIZE.w, PROGRESS_SIZE.h)
        .add(0,0,newCanvas("progress", PROGRESS_SIZE.w, PROGRESS_SIZE.h).color("green"))
        .css("border","solid 1px black")
        .center()
        .print()
    ,
    newVar("timerInfo").set(()=>[Date.now(),5000]) // set the duration here
    ,
    newFunction( "updateProgress", ()=>{
        const [s,d] = getVar("timerInfo")._element.value;
        const p = (Date.now()-s) / d;
        if (p>1) return;
        getCanvas("progress").size((1-p)*PROGRESS_SIZE.w,PROGRESS_SIZE.h)._runPromises();
        window.requestAnimationFrame( getFunction("updateProgress")._element.function );
    } ).call()

    Here’s a full example:

    const PROGRESS_SIZE = {w: 100, h: 20}
    
    newTrial(
        newCanvas("progressContainer", PROGRESS_SIZE.w, PROGRESS_SIZE.h)
            .add(0,0,newCanvas("progress", PROGRESS_SIZE.w, PROGRESS_SIZE.h).color("green"))
            .css("border","solid 1px black")
            .center()
            .print()
        ,
        newVar("timerInfo").set(()=>[Date.now(),5000]) // set the duration here
        ,
        newFunction( "updateProgress", ()=>{
            const [s,d] = getVar("timerInfo")._element.value;
            const p = (Date.now()-s) / d;
            if (p>1) return;
            getCanvas("progress").size((1-p)*PROGRESS_SIZE.w,PROGRESS_SIZE.h)._runPromises();
            window.requestAnimationFrame( getFunction("updateProgress")._element.function );
        } ).call()
        ,
        newController("AcceptabilityJudgment",{
            s:"What did the cat chase that was running to hide?",
            q:"How good does this sentence sound?",
            as:['1','2','3','4','5'],
            presentAsScale: true,
            timeout:5000 // the durations have to match
        })
            .center().print().wait().remove()
        ,
        getCanvas("progressContainer").remove(),
        newButton("Next").center().print().wait()
    )

    Jeremy

    #10508
    E.Inshakova
    Participant

    Thanks a lot, Jeremy, that was really very helpful!

    Evgeniya Inshakova

    #10509
    E.Inshakova
    Participant

    Hello Jeremy,

    I added your piece of code into my script, but no progress bar appeared in the preview. Did I do something wrong?

    PennController.ResetPrefix(null);
    const PROGRESS_SIZE = {w: 100, h: 20};
    newTrial(
        newCanvas("progressContainer", PROGRESS_SIZE.w, PROGRESS_SIZE.h)
            .add(0,0,newCanvas("progress", PROGRESS_SIZE.w, PROGRESS_SIZE.h).color("green"))
            .css("border","solid 1px black")
            .center()
            .print()
        ,
        newVar("timerInfo").set(()=>[Date.now(),15000]) // set the duration here
        ,
        newFunction( "updateProgress", ()=>{
            const [s,d] = getVar("timerInfo")._element.value;
            const p = (Date.now()-s) / d;
            if (p>1) return;
            getCanvas("progress").size((1-p)*PROGRESS_SIZE.w,PROGRESS_SIZE.h)._runPromises();
            window.requestAnimationFrame( getFunction("updateProgress")._element.function );
        } ).call()
        ,
    // Experimental trial
    Template("items_pilot.csv", row => 
        newTrial("pilot_experiment",
            defaultText
                .cssContainer({"margin-bottom":"1em"})
                .css({"font-size": "large"})
                    .center()
                    .print()
            ,        
            newTimer("break", 1000)  //пауза между предложениями = 1 с
                .start()
                .wait()
            ,
            newText("context", row.context)
                .css({"background-color": "LightCyan"})
            ,    
            newText("sentence", row.sentence)
            ,
            newScale("natural", "1", "2", "3", "4", "5", "6", "7")
            .before( newText("left", "Полностью неприемлемо  ") )
            .after(  newText("right", "  Полностью приемлемо")  )
            .log("last")
            .print()
            .callback(getTimer("timeout").stop())
            ,
            newVar("rating")
            .global()
            .set(getScale("natural"))
            ,
            newTimer("timeout", 15000)
                .start()
                .wait()
    //        ,
    //        getTimer("timeout")
    //            .wait()
        )
        .log("group", row.group)
        .log( "rating" , getVar("rating") )
        .log("condition", row.condition)
        .log("item", row.item)
        .log("exp_number",row.exp_number)
        .log("construction", row.construction)
        .log("governor", row.governor)
        .log("noun", row.noun)
        .log("pr_n", row.pr_n)
    ,
        getCanvas("progressContainer").remove()
    ));

    Link to my demo:

    Evgeniya Inshakova

    #10511
    Jeremy
    Keymaster

    Hello Evgeniya,

    What this chunk of code does is embed a Template command inside a newTrial command, which won’t produce the desired result. If you’d like to brush up on PCIbex experiment structure, I recommend taking a look at this section of the documentation

    What you want to do is insert the commands in the newTrial you already have:

    PennController.ResetPrefix(null);
    const PROGRESS_SIZE = {w: 100, h: 20};
    
    // Experimental trial
    Template("items_pilot.csv", row => 
        newTrial("pilot_experiment",
            defaultText
                .cssContainer({"margin-bottom":"1em"})
                .css({"font-size": "large"})
                .center()
                .print()
            ,        
            newTimer("break", 1000)  //пауза между предложениями = 1 с
                .start()
                .wait()
            ,
            // Printing the Canvas element above the context (feel free to move it somewhere else)
            newCanvas("progressContainer", PROGRESS_SIZE.w, PROGRESS_SIZE.h)
                .add(0,0,newCanvas("progress", PROGRESS_SIZE.w, PROGRESS_SIZE.h).color("green"))
                .css("border","solid 1px black")
                .center()
                .print()
            ,
            newText("context", row.context)
                .css({"background-color": "LightCyan"})
            ,    
            newText("sentence", row.sentence)
            ,
            newScale("natural", "1", "2", "3", "4", "5", "6", "7")
                .before( newText("left", "Полностью неприемлемо  ") )
                .after(  newText("right", "  Полностью приемлемо")  )
                .log("last")
                .print()
                .callback(getTimer("timeout").stop())
            ,
            // Initiating the countdown just before starting the "timeout" Timer element
            newVar("timerInfo").set(()=>[Date.now(),15000]) // set the duration here
            ,
            newFunction( "updateProgress", ()=>{
                const [s,d] = getVar("timerInfo")._element.value;
                const p = (Date.now()-s) / d;
                if (p>1) return;
                getCanvas("progress").size((1-p)*PROGRESS_SIZE.w,PROGRESS_SIZE.h)._runPromises();
                window.requestAnimationFrame( getFunction("updateProgress")._element.function );
            } ).call()
            ,
            newTimer("timeout", 15000)
                .start()
                .wait()
            ,
            // Remove the progress bar once the timer ends (either naturally or by a selection)
            getCanvas("progressContainer").remove()
            ,
            // I moved this here because I presume you want to wait for a selection to happen before setting the Var element
            newVar("rating")
                .global()
                .set(getScale("natural"))
        )
        .log("group", row.group)
        .log( "rating" , getVar("rating") )
        .log("condition", row.condition)
        .log("item", row.item)
        .log("exp_number",row.exp_number)
        .log("construction", row.construction)
        .log("governor", row.governor)
        .log("noun", row.noun)
        .log("pr_n", row.pr_n)
    )

    Jeremy

    #10513
    E.Inshakova
    Participant

    Thank you again, Jeremy!

    Everything works now.

    Evgeniya Inshakova

Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.