How to add page breaks in between randomized items?

PennController for IBEX Forums Support How to add page breaks in between randomized items?

Viewing 11 posts - 1 through 11 (of 11 total)
  • Author
    Posts
  • #8511
    lilymelodyli
    Participant

    Hi Jeremy,

    I’m trying to set up a simple experiment with PCIbex, in which 180 short audio files (targets + fillers) will be played to the participants in randomized order and they will rate their acceptability using a 1-7 scale.

    I’m now trying to add breaks between every 60 randomized audio files (60×3=180) so that participants could take a break in between. However, it keeps stuck with using

    PennController.Sequence( "welcome" , "preloadExperiment", sepWithN( "break", randomize("experiment"), 5) , "demographics", "send" , "final" )

    but it’s okay if I changed it to

    PennController.Sequence( "welcome" , "preloadExperiment", sepWith( "break", randomize("experiment")) , "demographics", "send" , "final" )

    p.s. I’m putting 5 in the code because I’m still working on the script and haven’t uploaded the full set of audio files to PCIbex Farm.

    FYI, below is the script I’m working on…

    PennController.ResetPrefix(null);
    
    PennController.DebugOff();
    
    PennController.Sequence( "welcome" , "preloadExperiment", sepWithN( "break", randomize("experiment"), 5) , "demographics", "send" , "final" )
    
    PennController.CheckPreloaded( startsWith("experiment") )
        .label( "preloadExperiment" )
    
    PennController("welcome",
        defaultText
            .print()
        ,
        newText("<h1> Welcome! <h1>")
        .center()
        ,
        newText("...
        ,
    
        newTextInput("ID")
            .print()
        ,
        newButton("Agree")
            .print()
            .wait()
        ,
        newVar("ID")
            .settings.global()
            .set( getTextInput("ID") )
    )
    .log( "ID" , getVar("ID") )
    
    PennController.Template(
        variable => PennController( "experiment" ,
        newAudio("variable", variable.AudioFile)
      	.play()
      	.log()
    	.wait()
    	,
    	
        newButton("Replay")
      	.callback( getAudio("variable").play() )
     	.print()
    	,
    
        newScale("judgement",  "1", "2", "3", "4", "5", "6", "7")
    	.button()
    	.settings.radio()
    	.settings.labelsPosition("bottom")
    	.settings.center()
    	.print()
          	.settings.log()
    	.wait("")
    	,
    
        getAudio("variable")
    	.wait("first")
    	,
    
        randomize("variable")
    )
    .log( "ID" , getVar("ID") ) 
    .log( "Item" , variable.Item ) 
    )
    
    newTrial("break",
        newText("<h2> Please take a 5 mins break! <h2>")
    	.center()
    	.print()
    	,
        newButton("Continue")
    	.center()
    	.print()
    	.wait()
    )
    
    PennController("demographics",
       defaultText
            .print()
        ,
        newText("Age?")
        ,
        newTextInput("Age?")
            .print()
            .settings.log()
        ...
        ,
           newButton("Done")
            .print()
            .wait() 
    ) 
    .log( "ID" , getVar("ID") ) 
    
    PennController.SendResults( "send" )

    Thank you very much!
    Lily

    • This topic was modified 1 year, 8 months ago by lilymelodyli.
    #8514
    Jeremy
    Keymaster

    Hi Lily,

    The function sepWithN is not a native function to Ibex or PCIbex: what definition do you use? Using this definition, your code (with 5) works perfectly for me:

    function SepWithN(sep, main, n) {
        this.args = [sep,main];
    
        this.run = function(arrays) {
            assert(arrays.length == 2, "Wrong number of arguments (or bad argument) to SepWithN");
            assert(parseInt(n) > 0, "N must be a positive number");
            let sep = arrays[0];
            let main = arrays[1];
    
            if (main.length <= 1)
                return main;
                
            else {
                let newArray = [];
                while (main.length){
                    for (let i = 0; i < n && main.length>0; i++)
                        newArray.push(main.shift());
                    for (let j = 0; j < sep.length; ++j)
                        newArray.push(sep[j]);
                }
                return newArray;
            }
        };
    }
    function sepWithN(sep, main, n) { return new SepWithN(sep, main, n); }

    NB: since you have PennController.ResetPrefix(null) at the top of your script, you don't need to have the PennController. prefix on any of the commands below, ie you can replace PennController.Sequence with Sequence, PennController.CheckPreloaded with CheckPreloaded, and so on

    Jeremy

    #8515
    lilymelodyli
    Participant

    Hi Jeremy,

    Thank you so much for your reply! I thought sepWithN is a built-in function in PCIbex, that’s why I didn’t know I should create a definition for it. I’m also very new to programming/scripting, so my entire script is made by reading the user menu of PCIbex, and by copying and pasting stuff from different sources, based on my understanding on what’s going on in their scripts.

    After adding your script of sepWithN, now I can have a break for every 5 audio files played. However, a follow-up question is it also gives me a break after my final item, which is the 10th audio file in my current situation. I tried to change it from 5 to 3, but it will do the same after the very last item. I wonder if there’s a way to avoid having the break after the last item?

    I also have a question about recording response time. My study measures both the participants’ ratings, as well as their response time. I saw from another discussion thread that there is no reaction time recorded by default in PCIbex, which is perfectly understandable. However, with my script below, I have something that kind of looks like reaction time in my results. The reaction time-like thingy appears in the column of my rating results, that is the “value” column. Do you know what may have happened here? Do I have to change my script?

    Template(
        variable => PennController( "experiment" ,
        newAudio("variable", variable.AudioFile)
      	.play()
      	.log()
    	.wait()
    	,
    	
        newButton("Replay")
      	.callback( getAudio("variable").play() )
     	.print()
    	,
    
        newScale("judgement",  "1", "2", "3", "4", "5", "6", "7")
    	.button()
    	.settings.radio()
    	.settings.labelsPosition("bottom")
    	.settings.center()
    	.print()
          	.settings.log()
    	.wait("")
    	,
    
        getAudio("variable")
    	.wait("first")
    	,
    
        randomize("variable")
    )
    .log( "ID" , getVar("ID") ) 
    .log( "Item" , variable.Item ) 
    )

    The last question is about aesthetic. In my first page of the experiment, participants will enter their participant ID and press “Agree” to start the experiment. However, the “Agree” button is at the very bottom edge of the page, which is a bit difficult to press. I was trying to add space in between by using the code: newCanvas("empty canvas", 1, 40).print(), but it only works between elements (texts, buttons), not the page bottom. I looked at other discussion and people suggested changing the CSS file. Since I’m not familiar with all these, I’m afraid I may accidentally ruin the CSS file. So, is there a way to add some extra space between the “Agree” button and the bottom of the page?

    Thank you once again!
    Lily

    #8516
    lilymelodyli
    Participant

    Hi Jeremy,

    A quick question about preloading audio files: as you know, I have 180 short audio files to play in my experiment. As they are pretty small (in total 3-4MB only), I first tried to upload everything onto PCIbex Farm. However, when I tried to run the experiment, it just takes forever to preload the files and the experiment may stop and get stuck in the middle.

    I saw that you suggested in another post to upload a zip file to avoid this problem. But what I don’t understand is where I could host the zip file. I know that cloud services like Dropbox and Google Drive don’t work, what about GitHub? Or any suggestion on this issue?

    Thanks again!
    Lily

    #8517
    Jeremy
    Keymaster

    Hi Lily,

    it also gives me a break after my final item, which is the 10th audio file in my current situation.

    You can change the definition of sepWithN to handle that situation. Add , dropLast to the functions’ arguments, and prefix newArray.push(sep[j]); with a conditional on whether there remain any items in main. Concretely, replace the respective lines with:

    function SepWithN(sep, main, n, dropLast) {
    // ...
                        if (main.length>0||dropLast==undefined) newArray.push(sep[j]);
    // ...
    function sepWithN(sep, main, n, dropLast) { return new SepWithN(sep, main, n, dropLast); }

    Then you can sepWithN to not add the last break like this: sepWithN( "break", randomize("experiment"), 5, "dropLast")

    However, with my script below, I have something that kind of looks like reaction time in my results. The reaction time-like thingy appears in the column of my rating results, that is the “value” column. Do you know what may have happened here?

    Scale elements will log which button was selected, and when it was selected. You should see a value from 1 to 7 in one column (the selected button) and a 13-digit number in another (the timestamp). You’ll also have a timestamp for when the audio stopped playing in an earlier line: subtract the end-of-playback timestamp from the scale-choice timestamp and you’ll get your response time

    I was trying to add space in between by using the code: newCanvas(“empty canvas”, 1, 40).print(), but it only works between elements (texts, buttons), not the page bottom

    It does work at the bottom of the page, but if you’re printing the Canvas element after the “Agree” button was clicked (ie. after its wait command) then you’ll just never see it. But this would work:

    newButton("Agree").print()
    ,
    newCanvas("empty canvas", 1, 40).print()
    ,
    getButton("Agree").wait()

    I saw that you suggested in another post to upload a zip file to avoid this problem. But what I don’t understand is where I could host the zip file. I know that cloud services like Dropbox and Google Drive don’t work, what about GitHub? Or any suggestion on this issue?

    GitHub does not provide that service: in order for the experiment to run, it needs to download the zip file in the background, but by default background downloads from other domains (ie. from outside the farm) are blocked by browsers, unless the distant server explicitly gives permission for the operation, which you can do with some services, but not with GitHub

    One such service you could look into is Amazon S3, which is included in the 12-month AWS Free Tier offer. See this post for more information

    Jeremy

    #8529
    lilymelodyli
    Participant

    Hi Jeremy,

    Thanks for answering the different questions! I’m now done with the page break, reaction time and aesthetic.

    I followed your advice to create an Amazon S3 bucket to host my zip file, and then changed the CORS settings with the following JSON configuration (taken from the other post you sent me).

    [
        {
            "AllowedHeaders": [
                "*"
            ],
            "AllowedMethods": [
                "GET"
            ],
            "AllowedOrigins": [
                "https://farm.pcibex.net"
            ],
            "ExposeHeaders": []
        }
    ]

    However, when I tried to run the script, I got an error message and the experiment got stuck with the preloading process:

    [17:15:38] Error downloading https://s3.ap-southeast-1.amazonaws.com/nus.qe.cantonese.cl/Stimuli_mp3.zip:;Error: Ajax error for https://s3.ap-southeast-1.amazonaws.com/nus.qe.cantonese.cl/Stimuli_mp3.zip : 403 Forbidden (newTrial: 0-welcome)

    I also tried to open the URL of my Amazon bucket, and it also said “AccessDenied”. Do you know what may have happened here?

    Lily

    #8530
    Jeremy
    Keymaster

    Hi Lily,

    Your bucket should allow public access to your file, see this post for details

    Jeremy

    #8531
    lilymelodyli
    Participant

    Hi Jeremy,

    I just tried to change the ACL, but I only found “list” but not “read” option for the object option…

    Link to the screenshot of my ACL options, as I can’t attach it as a image here.

    Lily

    • This reply was modified 1 year, 7 months ago by lilymelodyli.
    • This reply was modified 1 year, 7 months ago by lilymelodyli.
    #8534
    lilymelodyli
    Participant

    Hi Jeremy,

    Oh please don’t bother with the ACL. I figured out what’s going on following the YouTube clip here. I can now grant access of my zip file and load the files to PCIbex farm.

    Thank you so much for your help over the last few days! Hopefully I won’t run into any problem later 🙂 But in case anything happened, I will let you know!

    Cheers,
    Lily

    #8542
    lilymelodyli
    Participant

    Hi Jeremy,

    Sorry to bother you again. I can now run my experiment smoothly, but then I have a problem with reading the results.

    Because I have two breaks in between the 175 audio files (I’ve modified the number of audio files), I expect to have 3 sets of data. However, I don’t know why set 1 and 3 (of one participant) are recorded twice in the .csv file, while set 2 is also somehow duplicated but is always incomplete. It makes me very hard to read the results, and also makes the file exceptionally huge. Do you have any ideas about this issue?

    FYI – this is the .cvs file for my own trial (result of one person only).

    Thank you,
    Lily

    #8547
    Jeremy
    Keymaster

    Hi Lily,

    Could you share the demonstration link to your experiment, here or at support@pcibex.net, so I can have a better look at the situation? Thank you

    Jeremy

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