Jeremy

Forum Replies Created

Viewing 15 posts - 646 through 660 (of 1,522 total)
  • Author
    Posts
  • in reply to: Self Paced Reading Timed Reminder #7537
    Jeremy
    Keymaster

    Hi,

    Yes, you can use a Key element and its callback command to (re)start a Timer element whenever the space bar is pressed, and display the message after that timer has elapsed:

    newController("DashedSentence", {s: "Hello world, bye Earth"}).print()
    ,
    newText("reminder", "<em>Press Space to see the next word</em>").center().print()
    ,
    newTimer("reminder timer",2000)
    ,
    newKey(" ")
      .callback(
        getTimer("reminder timer").stop(),
        getText("reminder").hidden(),
        getTimer("reminder timer").start().wait(),
        getText("reminder").visible()
      )
    ,
    getController("DashedSentence").wait().remove()
    ,
    getText("reminder").remove()
    ,
    newButton("Continue")
      .print()
      .wait()

    Jeremy

    in reply to: html layout/event times/selector vs. scale/ compatibility #7536
    Jeremy
    Keymaster

    Hi,

    Is there a way to provide feedback according to the condition of the wrong trial?

    Could you pass it in a column? Like newText("negative feedback", variable_practice.negative_feedback ). Or you could map a condition column to each message using a Javascript hash:

    newText("negative feedback", {
      appropriate: "Wrong answer!",
      inappropriate: "This sentence is not appropriate because in the picture ABC is depicted",
      infelicitous: "This sentence is not felicitous because blablabla"
    }[variable_practice.condition] )

    Latin Square: Does the system recognize to load the items belonging to a single group, by simply adding the column “Group” to the template? Should I specify something in the code?

    Yes it does: PennController will choose one value out of all the different values listed in the Group column, and only use the rows that contain that selected value in that Group column to generate trials, as explained here

    (Should the items belonging to Group 1 be lined up one after the other or is it ok if the table loads line 1 belonging to Group 1, line 2 belonging to Group 2 etc… )

    It doesn’t matter how you order your rows. PennController will list the different values in an alphanumeric order, and automatically pick one based on the value of the counter: if you have 3 groups named “A”, “B” and “C” and a participant takes your experiment with a counter value of 5, PennController will only use the rows where the Group column is “C” (because the mapping is {0->A; 1->B; 2->C} and 5 modulo 3 is 2)

    Jeremy

    in reply to: Missing data rows in the results file #7533
    Jeremy
    Keymaster

    Hi,

    The message informs you that your project contains more than 100,000 results lines, and that you will only be served results files up to 100,000 lines. The solution is to download the results in multiple batches, only including series of submissions that total fewer than 100,000 results lines at a time (refresh the page after you download a batch, as sometimes memory gets clogged). Then you can concatenate the multiple CSV files that you’ll have downloaded into a single one on your local machine if you like (on Unix systems, you can do it very quickly with a command like cat results*.csv > results_all.csv)

    I recommend you unpublish your experiment when you do that, to avoid missing new incoming data in the process, and once all your results have securely been downloaded to a safe location, delete them from the farm to free up space in our database, to make saving and accessing future data faster, and to avoid facing this situation again. (Remember to publish the experiment again if you plan on collecting more data)

    Jeremy

    in reply to: Comprehension question and rshuffle in self-paced reading #7532
    Jeremy
    Keymaster

    Hi,

    1. You could do newScale("answer", ...[row.Answer1,row.Answer2].sort(v=>0.5-Math.random())

    2. You can reuse the exact same code in Sequence that you use in seq. If your question is about labeling your trials so they start by “Target_” or “Filler_” like they do when you manually list them in an array (following the native-Ibex syntax) the answer is simply pass the labels you want as the first argument of newTrial. If your two types of trials are listed in the same CSV table, it’s a good idea to include a column (named Type, for example) that reports the trial’s type, so you can do this:

    Template("demo_data.csv", row =>
        newTrial( row.Type+"_trial" ,

    Jeremy

    in reply to: change the sittings of screen width. #7531
    Jeremy
    Keymaster

    Hi,

    One option would be to identify the longest text you have and create a Canvas element of a size that would fit it, then print that Canvas element scaled to fit the page. The text will probably appear a little small on some screens, but that’s the only way you can make sure it will fit on a single line. A width of 115em seemed to display fine:

    newCanvas("container", "115em", "5em")
        .scaling("page")
        .print("center at 50vw","auto")
    ,
    newController("DashedSentence", {s: row.sentence})
        .print( "center at 50%", 0, getCanvas("container") )

    Jeremy

    in reply to: html layout/event times/selector vs. scale/ compatibility #7527
    Jeremy
    Keymaster

    Hi,

    I have noticed that the calculation of RT within the script is reported in the results, but it’s not correctly reported if I pass the table in R with the tidyverse function.
    Do you know what might be the reason?

    By “the tidyverse” function, do you mean this?

    tidied_results <- tidied_results %>%
      mutate(reaction_time = selection_time - canvas_time,
            correct = if_else(condition == selection, 1, 0))

    This piece of code calculates reaction times post-data-collection, based on the timestamps of each event reported in the results file. In our messages, we had discussed using a Var element to calculate reaction times during runtime and report them as an extra column in every row of the corresponding trial. That solution doesn’t require the table transformation illustrated in the piece of code above

    I guess I have to make a column for the expected key each trial of the practice, then after each answer it should check whether the key match or not, if the pressed key is different it should provide the feedback like a text message, and a counter must go up of 1. If the counter at the end of the practice is higher than, let’s say 5, it should reload the trial practice, if it’s below 5, it should load the experimental trial.

    This is what I would do indeed. You don’t need to write (non-PennController) javascript code for that, PennController will provide you with what you need

    I’ll illustrate with an example here, as I lack information to give a solution adapted to your case, and I actually think doing that would obscure the reasoning anyway. In this example, I want the participant to give more than 2 correct responses before they can proceed:

    Sequence(
        "prepractice",
        randomize("practice"),
        "postpractice"
    )
    
    // (Re)set the Var element to 0 before running the practice session
    newTrial("prepractice", newVar("practice_score").global().set(0) )
    
    // Very simple trial structure for illustration
    Template( "table.csv" , row =>
      newTrial( "practice",
        newText( row.question ).print()
        ,
        newScale("answer", "Yes", "No")
            .button()
            .print()
            .wait()
            .test.selected( row.correct )  // Increment if correct answer
            .success( getVar("practice_score").set(v=>v+1) )
      )
    )
    
    newTrial("postpractice",
        // Check the value after the practice session
        getVar("practice_score").test.is(v=>v>2) 
            .failure(
                newText("Sorry, you do not meet the threshold").print()
                ,
                newButton("Take the practice again").print().wait()
                ,
                // jump will make the experiment go back to "prepractice" after this trial
                jump("prepractice")
            )
    )

    This is the table I used:

    question,correct
    say yes,Yes
    say no,No
    don't say yes,No
    don't say no,Yes

    Let me know if you have questions

    Jeremy

    in reply to: TextInput?? #7520
    Jeremy
    Keymaster

    Hello,

    The documentation page your message links to is outdated. The message at the top of the page invites you to consult the new documentation instead:

    You are reading an outdated documentation. Please visit the new documentation instead.

    That being said, the piece of code given in the documentation works well. The problem with your script is that you replaced the whole content of main.js with just that piece of code, instead of inserting it inside a newTrial that would come after PennController.ResetPrefix(null). I strongly encourage you to read the tutorial to get more familiar with PennController script

    Jeremy

    in reply to: Pairing two lists together #7514
    Jeremy
    Keymaster

    Hello,

    This is actually a question that regularly comes back. If you have the same number of words and sentence frames, and you can pair them in any possible ways, you could do something like this. List the sentence frames and the words in the same table:

    Sentence,Word
    Hello _!,world
    Bye _...,Earth

    Then you can do something like this:

    words = []
    
    Template( row => newTrial("dummy", words.push(row.Word)) )
    
    Template( row =>
      newTrial( "mytrial",
        fisherYates(words),
        word = words.pop()
        ,
        newButton( row.Sentence.replace('_',word) ).print().wait()
      )
    )

    Jeremy

    in reply to: Shuffling blocks while maintaining order in the block #7512
    Jeremy
    Keymaster

    Hi,

    I’ll be assuming that your trials are labeled "block1", "block2", "block3" and "block4". Then you can do this:

    PennController.ResetPrefix(null)
    
    var blocks = ["block1","block2","block3","block4"];
    fisherYates(blocks);
    
    Sequence("training", ...blocks)

    Jeremy

    in reply to: can't load results #7510
    Jeremy
    Keymaster

    Hello,

    The database says there are 28 submissions associated with that project, collected via the demonstration link on November 14-15 (only one on the 15th). There is a single submission collected via the data-collection link, from today 11:55UTC

    Do you experience the issue for both sets of results?

    Jeremy

    in reply to: Several questions about the TextInput element #7504
    Jeremy
    Keymaster

    Check your parentheses: and should attach to the Html element’s test command (as it does in the bit of code that I gave) not to the Button element

    Jeremy

    in reply to: Several questions about the TextInput element #7501
    Jeremy
    Keymaster

    Hello,

    The expression $("#alter") is a jQuery expression, where you can select an element by targeting its id attribute in the string simply by prefixing a # character. Your input element’s id being “sum”, you can get a jQuery object pointing to it using $("#sum")

    You can use a Function element to dynamically test the value of that input element in the Button’s wait command:

    newButton("Continue")
        .print()
        .wait(
            getHtml("demographics").test.complete()
              .failure( getHtml("demographics").warn() )
              .and(
                newFunction(()=>$("#sum").val())
                    .test.is(100)
                    .failure( newText("must be 100").print() )
              )
        )

    (Note that your original code has getHtml("consent") where it should have getHtml("demographics"))

    Jeremy

    in reply to: Troubleshooting #7500
    Jeremy
    Keymaster

    Hi,

    There is no “twice” option for the Audio element’s play command. The “once” option is only there to prevent a second play from looping after it’s been called with “loop” a first time

    Even if passing “twice” made the element play twice, the program would have no way of guessing that you want a 3000ms pause between the two playbacks

    Why don’t you just do

    newAudio("Audio", row.Audio).play().wait()
    ,
    newTimer(3000).start().wait()
    ,
    getAudio("Audio").play().wait()

    ?

    Jeremy

    in reply to: results not downloading #7496
    Jeremy
    Keymaster

    Hi,

    I don’t experience any problems or unusual delays when downloading results for my projects. Does the problem persist on your end, and if so, would you mind sharing your project’s demonstration link with me?

    Jeremy

    in reply to: unable to download 'results' #7495
    Jeremy
    Keymaster

    Hello Danny,

    Runtime is probably a factor that matters, for the reason you mention (server load). However, browser should not matter when it comes to sending the results to the server (it does matter if, for example, you use the MediaRecorder or EyeTracker elements, which are poorly supported by Safari, if supported at all)

    The most important factor regarding data transfer is the amount of data being transferred: if a submission contains thousands of lines, storing them in the server’s database will take time, and as incoming results accumulate, the risk of crash due to overload increases

    Jeremy

Viewing 15 posts - 646 through 660 (of 1,522 total)