Jeremy

Forum Replies Created

Viewing 15 posts - 796 through 810 (of 1,522 total)
  • Author
    Posts
  • in reply to: Trouble logging participant information #7098
    Jeremy
    Keymaster

    Hello,

    The reason you see “Canvas” is because you use log on your Canvas element, so the results file will report the timestamp for the execution of its print command.
    You are also using log on your Key element, which you probably want, because it will report which of E/I was pressed.
    Finally, you are calling log on the “wait-separacao” Timer element too, but you meant to call it on newTrial() because what you want is to add columns to every line of your results file for those trials that report the values from the “imagem” and “versao” columns of your table:

        // ...
        ,
        newTimer("wait-separacao",2500)
          .start()
          .wait()
      )
      .log("imagens", row.imagem)
      .log("item", row.versao)
    );
    

    Jeremy

    in reply to: wait on a condition #7097
    Jeremy
    Keymaster

    Hi Sam,

    PennController’s top-down write-and-execute style makes this kind of disjunctive logic a little tricky. In your case, I suggest you just wait for the Timer element, and have the Selector element halt the timer upon selection:

    newSelector("images")
      .add( getImage("on"), getImage("mid"), getImage("off"))
      .log()
      .callback( getTimer("waitSelector").stop() )
    ,
    newTimer("waitSelector", 30000) 
      .start()
      .wait()
    

    Also, you cannot use javascript’s ! operator on PennController commands (see this guide). If you want to negate a test, just replace test with testNot

    Jeremy

    in reply to: Last recording not saved #7092
    Jeremy
    Keymaster

    Hi,

    What version of PennController are you using? If you’re not using it already, I suggest you upgrade to 2.0.beta where I improved the uploading system

    In any case, you should probably add a non-async UploadRecordings trial just before the SendResults trial, to make sure all the recordings are uploaded before finishing the experiment

    Also, feel free to share your project’s URL to ease the troubleshooting process

    Jeremy

    in reply to: Horizontal clickable scale #7091
    Jeremy
    Keymaster

    Hi,

    To add to Amila’s suggestion, look at the button command

    To play with the aesthetics, you can add CSS rules to Aesthetics/PennController.css like:

    .Scale > div {
        margin: 1em;
    }

    Jeremy

    in reply to: changing question position #7076
    Jeremy
    Keymaster

    Hi,

    This sounds like a native-Ibex specific question. I think editing the Question controller would indeed be the obvious solution if you want to stick to native Ibex. You would move lines 150-151 (if (! (this.qp === undefined)) / this.element.append(this.qp);) below line 159 (this.element.append(table.append(tr.append(td.append(this.xl))));)

    Or you can use PennController, which was precisely design to give you more control over the design of you Ibex experiments 😉 For example:

    newTrial(
        newController("DashedSentence",{s: "This is a simple test sentence"})
            .print()
            .log()
            .wait()
            .remove()
        ,
        newScale("answer", "Answer1", "Answer2").button().log().print()
        ,
        newText("This is a question").print()
        ,
        getScale("answer").wait()
    )
    

    Jeremy

    in reply to: Restart trial #7073
    Jeremy
    Keymaster

    You cannot use getVar that way, as explained in this guide I mentioned earlier

    Your first attempt was on the right track, but maybe you forgot to include the trial number in addition to the selection index?

    const whichOne = (numbers, selectorName, ex) => numbers.map( number =>
        getSelector(selectorName).test.selected(getImage("o" + number))
            .success(
                newAudio("o" + number + "selected", "ex" + ex + "o" + number + ".m4a")
                    .play()
                    .wait()
                ,
                getVar("selected").set(number)
            )
    )
    

    and then use it like this:

    ...whichOne([1,2,3,4,5,6], "response", exNum)
    

    Jeremy

    in reply to: Restart trial #7071
    Jeremy
    Keymaster

    Hello,

    There are a couple problematic aspects with your code. First, elements are specific to trials, so you cannot define a Var element outside the scope of a newTrial. Second, your whichOne function runs the risk of an infinite recursive loop (although I have to say it’s a pretty smart way of testing many values without having to duplicate your code). I recommend you read this guide to get a better idea of when commands are executed

    All callback commands will run a series of commands when the corresponding element’s relevant event happens (eg. a click on a Button element). They’re mainly useful to escape the purely top-down execution of the code, in allowing for interactions to unfold while the main thread of the script is waiting somewhere. It is true that they can also be used to re-execute a pre-defined block of code, but I think you are overusing the callback command in your code

    I think what you want is this:

    const whichOne = (numbers, selectorName) => numbers.map( number =>
        getSelector(selectorName).test.selected(getImage("o" + number))
            .success(
                newAudio("o" + number + "selected", "o" + number + "Audio.m4a")
                    .play()
                    .wait()
                ,
                getVar("selected").set(number)
            )
    )
    
    const runPractice = (LP,RP,LO,RO,tag,correctChoice) => [
        clear()
        ,
        newCanvas("images", 1500, 750)
            .color("white")
            .add(  0 , 100 , newImage("p1", LP + ".jpeg" ).size(400, 400) )
            .add(450 , 100 , newImage("p2", LP + RP + ".jpeg").size(600,400) )
            .add(1100 , 100 , newImage("p3", RP + ".jpeg").size(400, 400) )
            .add(  0 , 500 , newImage("o1", LO + ".png") )
            .add(200 , 500 , newImage("o2", RO + ".png") )
            .add(550 , 500 , newImage("o3", LO + ".png") )
            .add(750 , 500 , newImage("o4", RO + ".png") )
            .add(1100 , 500 , newImage("o5", LO + ".png") )
            .add(1300, 500 , newImage("o6", RO + ".png") )
            .add( "center at 50%", "bottom at 100%", newButton("Go") )
            .print("center at 50vw","top at 2em")
        ,
        getButton("Go").wait().remove()
        ,
        newAudio("description", tag + ".m4a")
            .play()
            .wait()
        ,
        newSelector("response")
            .add( getImage("o1") , getImage("o2") , getImage("o3") , getImage("o4") , getImage("o5") , getImage("o6") )
            .wait()
        ,
        ...whichOne([1,2,3,4,5,6],"response")
        ,
        getVar("selected").test.is(row.correctChoice)
            .success( 
                newHtml("readyscreen", "readyscreen.html")
                    .center()
                    .print()
                ,
                getButton("Continue").print("center at 50%","bottom at 100%",getCanvas("images"))
            )
            .failure( getButton("runPracticeLaunch").click() )
    ]
    
    Template("examples.csv", row =>
        newTrial("practice",
            newVar("selected", 0)
            ,
            defaultImage.size(200,200)
            ,
            newButton("runPracticeLaunch")
                .callback(...runPractice(row.LP,row.RP,row.LO,row.RO,row.tag,row.correctChoice))
                .click()
            ,
            newButton("Continue")
                .center()
                .wait()
        )
    )

    I couldn’t test this code with your project’s material (feel free to share the demonstration link with me so I can do it) but I tried an non-Template non-Audio version of it which worked. Note that I’m printing the button onto the Canvas element because otherwise they appear below it

    Jeremy

    in reply to: video not displayed #7068
    Jeremy
    Keymaster

    Thank you Giorgio — I just replied by email

    For everybody else: there is a bug in one version of PennController 2.0.alpha where Video elements are printed as disabled by default, which adds an opaque gray layer on top of the player. Calling .enable() before calling .print() gets rid of that problem. This issue has been fixed for more recent releases

    Jeremy

    in reply to: video not displayed #7066
    Jeremy
    Keymaster

    Would you mind sharing your project’s demonstration link with me, either here or at support@pcibex.net?

    Jeremy

    in reply to: video not displayed #7064
    Jeremy
    Keymaster

    Hi Giogio,

    This code works well for me on PennController 1.8, 1.9 and 2.0.alpha. Do you have a defaultVideo.disable() anywhere before that by any chance? If not, the problem could come from the format of the video file. All browsers are supposed to support MP4 files, but note that having a .mp4 extension does not guarantee that the content of your file has indeed been encoded in MP4

    Jeremy

    in reply to: Eye-tracking #7061
    Jeremy
    Keymaster

    Hi Vasilisa,

    As explained in the documentation (my emphasis + edit):

    This script will take care of receiving and storing encoding data lines in subfolders and one file per participant. It will also output back files where the lines have been decoded. You can directly visit it [NB: your script] through your browser and type in the field that you see the “URL” key that was reported in your results file (something like httpsdomainofmyexperiment/pathtomyexperiment/vEry-l0ng-uniQu3-1dentif1er). Alternatively, you can directly append key at the end of the PHP script’s url (replacing key with the value from your results file) to get the output file — this is the method we will use in our analyses.

    In other words, your eye-tracking data will not be stored on the PCIbex Farm, and you should upload a PHP script to your webserver, as described in the documentation. If your PHP script is at https://my.server.xyz/myETScript.php, then open this URL in your browser and paste httpsfarmpcibexnetrKFZClH/af8e9d53-10c3-93c6-1799-6412f8639d0f in the input field and click “Submit” to get a CSV data file. Or use https://my.server.xyz/myETScript.php?experiment=httpsfarmpcibexnetrKFZClH/af8e9d53-10c3-93c6-1799-6412f8639d0f to access it directly, as illustrated in the Analyses section

    Jeremy

    in reply to: Nested callbacks and test.selected conditions problem #7060
    Jeremy
    Keymaster

    Hi,

    How about this?

    newTrial("WIPtrial",
        newButton("ContinueYes","[Clicking this should end trial]"),
        newButton("ContinueNo","[Clicking this will lock user out of participating and provide explanation]")
            .callback(
                clear(),
                newText("Explanation goes here").print()
            )
        ,
        newDropDown("DD2Drop","Please select a response")
            .add("Option1","Option2","Option3","Option4","Option5","Option6")
            .callback( getButton("ContinueYes").print() )
        ,
        newText("DD1Text","Yes goes to 2nd DropDown, No will lock the user out of participating (not implemented yet)")
            .print()
        ,
        newDropDown("DD1Drop","Please select a response")
            .add("Yes","No")
            .callback( self.test.selected("Yes")
                .success(
                    getButton("ContinueNo").remove(),
                    newText("DD2Text","Many choices DropDown").print(),
                    getDropDown("DD2Drop").print()
                )
                .failure(
                    getButton("ContinueYes").remove(),
                    getText("DD2Text").remove(),
                    getDropDown("DD2Drop").remove(),
                    getButton("ContinueNo").print()
                )
            )
            .print()
            .wait()
        ,
        getButton("ContinueYes").wait() // this can only complete when button is printed
    )
    

    Jeremy

    in reply to: Preventing interruptions and ensuring uniform presentation #7057
    Jeremy
    Keymaster

    Hello Matthias,

    1. You cannot prevent participants from leaving fullscreen

    2. You cannot disable the zoom function of the browser

    Points 1 and 2 fall under the more general idea that scripts cannot take control away from clients (same for, eg., forcibly placing the cursor at a specific position on the page)

    3. You can use .css("font", "italic small-caps bold 12px/30px Georgia, serif") on specific elements, or add CSS rules to files in your project’s Aesthetics folder. Note that those are technically preferences: if the font is not found on the client’s system, or if the client explicitly set their browser to overwrite sites’ preferences, the browser will choose a different font (this doesn’t happen very often when you specify a standard font)

    4. I’m not sure about this one, but it sounds like it would be beyond the scope of standardized browser specifications. Each browser and/or operating system probably has settings to enable that behavior though, I guess you could invite your participants to follow instructions to manually disable notifications while in fullscreen

    Jeremy

    in reply to: Adding an F/J key instead of a YES/NO scale #7053
    Jeremy
    Keymaster

    Hi Ugurcan,

    Your Var elements are not .global() so you cannot access them outside the parentheses of the containing newTrial command. Make sure to call .global() on them before calling .set

    Jeremy

    in reply to: Adding an F/J key instead of a YES/NO scale #7050
    Jeremy
    Keymaster

    Hi Ugurcan,

    Using a Key element drastically simplifies the logic: you just print a Text element that says “F: Yes, J: No” and create and wait for a Key element:

    newImage("Q1Image", "https:" + row.ImageURL1).size(703,398)
    ,
    newText("Q1", "<p style=font-size:22px;>Did you see this image in the video?</p>")
    ,
    newText("Q1instr","<strong>F: Yes</strong> &nbsp; &nbsp; <strong>J: No</strong>")
    ,
    getCanvas("testcanv")
        .remove(getVideo("eventTest"))
        .add("center at 50%","middle at 50%", getImage("Q1Image"))
        .add("center at 50%",475, getText("Q1"))
        .add("center at 50%",525, getText("Q1instr"))
    ,
    newKey("Q1resp", "FJ").wait()
    ,
    newVar("TQ1")
        .set(getKey("Q1resp"))

    Jeremy

Viewing 15 posts - 796 through 810 (of 1,522 total)