Jeremy

Forum Replies Created

Viewing 15 posts - 1,351 through 1,365 (of 1,522 total)
  • Author
    Posts
  • in reply to: Multiple choice buttons and recording responses #5084
    Jeremy
    Keymaster

    Hi,

    The commands in your script are executed in the order in which they appear, from the top down, and the wait command halts the execution of the script until the relevant event happens. This is why creating 4 buttons with 4 wait commands in a top-down sequence will only get to the next buttons after the previous wait commands are released, ie your participant will have to click the earlier buttons to get to the later ones.

    Also, you cannot create multiple buttons using one newButton command the way you’re trying to do it. When in doubt check the documentation page for the element type. What you want is either a Scale element where you define 4 options with the texts you want, or print the four buttons on the page without calling .wait on them, and add them to a Selector element, on which you do call the .wait command (which will release execution when one of the items in the Selector, that is one of your four buttons, is clicked).

    Then use .log on your Scale or Selector element and it will add a line in your results file reporting which option/item was clicked.

    Note that there exists a different .log command that you should insert immediately after the closing parenthesis of newTrial, which lets you append columns to every row that the corresponding trial reports in the results file. This is the command you’ll use to keep track of your participant’s and each trial’s info. Take a look at the “Template” and “participant” pages of the tutorial to see an illustration of how to use it.

    Jeremy

    in reply to: Comparing Labeled Text Elements #5079
    Jeremy
    Keymaster

    Hi!

    I don’t know why it’s not working, I’d have to double-check that. In the meantime, you can use a Var element as a proxy:

    newVar("RespVar"),newVar("LexVar")
    ,
    getText("Resp").setVar("RespVar"),
    getText("Lex").setVar("LexVar")
    ,
    getVar("RespVar")
        .test.is( getVar("LexVar") )
        .success(
            newText("Correct!")
                .print()
            ,
            newTimer(1000)
                .start()
                .wait()
            ,
            getVar("Acc").set(1)
        )
        .failure (
            newText("Incorrect!")
                .print()
            ,
            newTimer(1000)
                .start()
                .wait()
            ,
            getVar("Acc").set(0)
        )

    Jeremy

    in reply to: Centering / tabs #5077
    Jeremy
    Keymaster

    Hi again Jan,

    This is possible, and it sounds like a very simple thing to do, but it turns out to be quite complex to get that rendering with webpages. You would need to define CSS rules targeting the components of your Scale element. Note that Scale elements render their options using the <table><tr><td> format. The least complicated way to do that is probably to use constant widths for your options.

    Best,
    Jeremy

    in reply to: Progress bar #5076
    Jeremy
    Keymaster

    Hello Jan,

    Yes, you can set the showProgressBar and progressBarText variables, as described in Ibex’s manual. Example:

    PennController.ResetPrefix(null);
    var showProgressBar = false;
    
    newTrial( newButton("Test").print().wait() )

    Jeremy

    in reply to: Track Mouse Position #5072
    Jeremy
    Keymaster

    Hi Valeria,

    Yes, getting the mouse’s coordinates upon click is actually easy enough, but you should make sure it’s really what you want. Keep in mind that different participants will have pages of different heights and widths. If you consider checking the mouse’s coordinates upon click, ask yourself whether it wouldn’t make more sense to place multiple clickable elements on your page, e.g. in the form of transparent canvases.

    For example, this bit of script uses a MouseTracker element to keep track of the mouse’s coordinates and checks them later:

    newVar("mousex"),newVar("mousey")
    ,
    newMouseTracker("mouse")
        .callback( (x,y) => [getVar("mousex").set(x)._runPromises(),getVar("mousey").set(y)._runPromises()] )
        .start()
    ,
    newCanvas( "wholescreen" , "100vw" , "100vh" ).print( "top at 0" , "left at 0" )
    ,
    newSelector().add( getCanvas("wholescreen") ).wait()
    ,
    getVar("mousex").test.is( v=>v<100 )
        .success( newText("The mouse is very much toward the left").print( 100 , getVar("mousey") , getCanvas("wholescreen") ) )
    ,
    getVar("mousey").test.is( v=>v<100 )
        .success( newText("The mouse is very much toward the top").print( getVar("mousex") , 100 , getCanvas("wholescreen") ) )

    But this other bit of script does almost the same thing more simply:

    newCanvas("left", 100 , "100vh").print("left at 0", "top at 0"),
    newCanvas("top", "100vw" , 100).print("left at 0", "top at 0")
    ,
    newSelector()
        .add( getCanvas("left") )
        .callback( newText("The mouse is very much toward the left").print(100,"middle at 50vh") )
    ,
    newSelector()
        .add( getCanvas("top") )
        .callback( newText("The mouse is very much toward the top").print("center at 50vw",100) )

    Feel free to tell me more about how your experiment will use the mouse's coordinates

    Jeremy

    in reply to: email address encryption #5070
    Jeremy
    Keymaster

    Hi Nicolas,

    TL;DR: robust encryption/decryption in javascript is definitely possible but not straightforward, but maybe you don’t need it anyway

    As Florian said, if your goal is simply to keep track of your participants and your recruiting platform already provides unique IDs, I strongly recommend you just use that instead.

    If you still need to use an encryption method, most browsers now implement the SubtleCrypto API. There are some limitations though: some browsers like Edge do not support some algorithms, and most importantly, the API will only work on secure domains (the PCIbex Farm uses a secure domain).

    If your goal is to store encrypted email addresses in your results file that only you can later decrypt, you will need an algorithm that takes a public encryption key and a private decryption key. There are a few of those, one of them is the ECDSA, illustrated here. You would also need to export your public key, as illustrated here.

    Jeremy

    in reply to: conditions in self-paced reading experiment #5069
    Jeremy
    Keymaster

    No, I was referring to "correct", not row.CorrectN. By column names I meant the columns that get added to each line of your results file, as I describe above in my explanations of how newTrial().log works.

    Jeremy

    in reply to: conditions in self-paced reading experiment #5065
    Jeremy
    Keymaster

    Almost there, you just didn’t change the "correct" column names, nor did you use a different name for your last Scale element

    in reply to: conditions in self-paced reading experiment #5063
    Jeremy
    Keymaster

    Hi,

    The use .log is admittedly confusing, as there are two main types of .log commands: the .log command on an element and the .log command on newTrial(). The first type will add one or more rows to your results file reporting information about the relevant event(s) associated with the element in question, the second type will add a column to every row corresponding to the trial in question.

    In your code, you should move the three lines .log( "correct" , row.Correct1), .log( "correct" , row.Correct2) and .log( "correct" , row.Correct3) and stack them immediately after the closing parenthesis of your newTrial command (ie. before your last closing parenthesis, which corresponds to your Template command). You can take a look at the code on this page of the tutorial for an illustration of how .log is used. You should also use unique strings instead of re-using "correct" three times, as those will correspond to column names in your results file, and having multiple columns with the same name will be confusing when analyzing your data.

    In addition to that, you also want to use .log() (nothing between the parentheses) on all three of your Scale elements, so they each add a row to your results file when a selection happens.

    Finally, I see that you renamed your first Scale element, but your two last Scale elements still share the same name (“correct”) which, again, will be confusing when analyzing your data as you’ll have multiple rows reporting events about similarly-named elements. I suggest your use something like "whicharticle" as the name of your last Scale element.

    Jeremy

    in reply to: Eye-tracking and physio integartion #5060
    Jeremy
    Keymaster

    I see. Because of the very nature of PCIbex, hardware communication seems complicated, at best, so the most promising implementation I see would still need to use URLs.

    In any case, as you said, I don’t think PennController would be the right tool to collect this kind of data, in this kind of setup. Not only is it ill-designed for wired communication, it’s also javascript-based, which means a time resolution of tens of milliseconds at best.

    I’m also curious as to how you measure an increase in skin conductance in an online setting: do you specifically recruit participants who have access to a machine that can collect this sort of physiological data? Are they students in a program?

    Jeremy

    in reply to: Eye-tracking and physio integartion #5057
    Jeremy
    Keymaster

    Hi Daniel,

    I am not familiar with BIOPAC, and I’m not sure I understand your question. There is an EyeTracker element in PennController, but it is not very accurate and I haven’t spent much time developing it, which is why I never documented it. The way it currently works, it sends the data it collects to a distant URL, so you’d need to set up some interface to retrieve your data on some server, in much the same way that collecting audio recordings works (though the method is not fully transposable). Everything else is saved in the results file of your experiment.

    Feel free to elaborate on your questions

    Jeremy

    in reply to: Force response? #5056
    Jeremy
    Keymaster

    Hi again,

    Unfortunately unless you .logged the relevant element, your results file will not contain the timestamp you are looking for. Do you happen to have the timestamp of any event occurring between the participant’s pressing the space key and when they start typing the first letter in the TextInput? If you’ll be collecting more data with your script, just add .log() to the Key element preceding your TextInput.

    Header effectively creates a trial that gets executed at the beginning of every single trial, that’s why you also get the start and end timestamps of the Header trials in the results file, but they won’t be of much help to you in this case I’m afraid

    Jeremy

    in reply to: Track Mouse Position #5050
    Jeremy
    Keymaster

    Hi Irene,

    Actually yes, there is a MouseTracker element in PCIbex, though it’s not officially documented. One concern with it is that it rapidly increases the size of the results file, as it reports a pair of numbers (the X and Y coordinates) every few milliseconds. Since you’re currently limited to 64MB on the PCIbex Farm, it practically imposes drastic limitations there.

    I helped someone set up an experiment with the MouseTracker element on their own personal server and they were able to get good data, so if you are still interested and have access to a personal server, let me know and I can help you setting things up (it’s actually quite simple).

    Jeremy

    in reply to: html code with embedded script #5049
    Jeremy
    Keymaster

    Hi,

    Yes, it’s possible, I actually implemented an earlier version of this script before myself

    Since you said you’re clueless when it comes to javascript, I don’t know how much of the script below you’ll understand, but it is a full, functional script:

    PennController.ResetPrefix(null)
    
    // The Farm's jQuery library is outdated, we need to polyfill a couple methods
    jQuery.prototype.on = function(...args) { return jQuery.prototype.bind.apply(this, args); }
    jQuery.prototype.prop = function(...args) { return jQuery.prototype.attr.apply(this, args); }
    // Let's dynamically load the HeadphoneCheck script
    var HeadphoneCheckScriptTag = document.createElement("script");
    HeadphoneCheckScriptTag.src = "https://s3.amazonaws.com/mcd-headphone-check/v1.0/src/HeadphoneCheck.min.js";
    document.head.appendChild( HeadphoneCheckScriptTag );
    
    newTrial(
        newButton("check", "Start Heaphone Check")
            .print()
        ,
        // This Canvas will contain the test itself
        newCanvas("headphonecheck", 500,500)
            .print()
        ,
        // The HeadphoneCheck module fills the element whose id is "hc-container"
        newFunction( () => getCanvas("headphonecheck")._element.jQueryElement.attr("id", "hc-container") ).call()
        ,
        getButton("check")
            .wait()
            .remove()
        ,
        // Create this Text element, but don't print it just yet
        newText("failure", "Sorry, you failed the heaphone check")
        ,
        // This is where it all happens
        newFunction( () => {
            $(document).on('hcHeadphoneCheckEnd', function(event, data) {
                getCanvas("headphonecheck").remove()._runPromises();
                if (data.didPass) getButton("dummy").click()._runPromises();
                else getText("failure").print()._runPromises()
            });
            HeadphoneCheck.runHeadphoneCheck() 
        }).call()
        ,
        // This is an invisible button that's clicked in the function above upon success
        newButton("dummy").wait()
    )

    Jeremy

    in reply to: Force response? #5047
    Jeremy
    Keymaster

    Hi,

    My code (the first one) should replace these two lines from the script you posted:

    getTextInput("inputanswer")
        .wait()

    Let me know if you did not get the code to work

    Jeremy

Viewing 15 posts - 1,351 through 1,365 (of 1,522 total)