Jeremy

Forum Replies Created

Viewing 15 posts - 106 through 120 (of 1,522 total)
  • Author
    Posts
  • in reply to: Results log not complete #10613
    Jeremy
    Keymaster

    Hi,

    I don’t immediately see a problem with your code. Would you be able to share a link to your experiment with me (even if it’s not on the PCIbex Farm), here or at support@pcibex.net so I can take a closer look?

    Jeremy

    in reply to: Logging Question Chosen-Option #10609
    Jeremy
    Keymaster

    Hi Juliana,

    Unfortunately the Question controller was written in a way that it reports the content of the selected answer, not its index. However, since you are logging the content of both questions, you can compare the content of the answer to those columns and determine the index of the chosen answer, which you can then compare to the expected index. For example, here is a line from a test-run of mine, with a header line with column names before it for clarity:

    ReceptionTime,MD5,Controller,Item,Element,Label,Group,PennElementType,PennElementName,Parameter,Value,EventTime,Frase1,Frase2,Condition,Item,Group,Expected,Correct,Time,Comments
    752,REDACTED,PennController,11,0,item,NULL,Controller-Question,Question,NULL,Ou hoje ou amanhã fomos à praia.,1684831742806,Ou hoje ou amanhã iremos à praia.,Ou hoje ou amanhã fomos à praia.,TREINO,1,U,1,NULL,1967

    In R for example, and assuming results only contain rows for that Question controller, I would do something like this:

    results$AnswerIndex <- 1 + (results$Value == results$Frase2)
    results$Accurate <- results$AnswerIndex == results$Expected

    Note, however, that the Question controller already comes with a hasCorrect option, so you could do newController("Question", {q: "", as: [variable.Frase1, variable.Frase2], hasCorrect: parseInt(variable.Expected)-1}). Then you'd have a 1 reported for correct answers and a 0 for incorrect answers

    Jeremy

    in reply to: Resource preloading problem #10606
    Jeremy
    Keymaster

    Hi,

    You have two problematic file references in your table:

    • 34c_schoolbuls.mp3
    • 36c_tableware.mp3

    The former contains a typo (which I highlighted in boldface) the latter is absent from the zip file

    Jeremy

    Jeremy
    Keymaster

    In that case use two randomizes in seq, like this:

    var blocks = [
      seq(randomize("trials_study"),randomize("trials_test")),
      // ...
    

    Jeremy

    Jeremy
    Keymaster

    Hi Yev,

    If your first block consists of all the trials labeled “trials_study” and those named “trials_test” and you want them randomly (unevenly) shuffled, you could replace randomize("block_1") from the code above with randomize(anyOf("trials_study","trials_test")). If you’d rather have them evenly shuffled, use rshuffle("trials_study","trials_test")

    Jeremy

    in reply to: Collums not being found for a SelfPacedReading task #10598
    Jeremy
    Keymaster

    Hello Lorrainy,

    The error messages are correct: your table contains no columns named “Pergunta” or “Frase”. They do, however, contain two columns named “pergunta” and “frase”

    That being said, your table uses ; as a separator, which is not currently supported by PennController. Replace them with , (commas) and, along with the two edits I just hinted at, your experiment will run smoothly

    Jeremy

    in reply to: Downloading zip files from the external server #10596
    Jeremy
    Keymaster

    Hello,

    You’re using AddHost in place of PreloadZip

    Also delete the trailing slash after .zip in the zip file’s URL

    Jeremy

    in reply to: Displaying n words on screen #10594
    Jeremy
    Keymaster

    You could test the value of the Var element right after you increment it in the callback to see if the updated index goes beyond the number of words, and if so, wait for a key press on K to stop the timer:

    newKey("NEXT", " ")
        .callback(
            getVar("nextWordStartsAt").test.is(v=>v<row.Words.split('_').length).success(
                getVar("listOfWords")
                    .set(getVar("nextWordStartsAt"))
                    .set(v=>row.Words.split('_').slice(v,v+10).join("<br>"))
                ,
                getText("words").text( getVar("listOfWords") )
                ,
                getVar("nextWordStartsAt")
                    .set(v=>v+10) // update the index
                    .test.is(v=>v>=row.Words.split('_').length).success( // if the index is greater than the # of words
                        newKey("K").wait() // wait for a key press on K
                        ,
                        getTimer("recording").stop() // stop the timer
                    )
            )
        )

    Jeremy

    in reply to: Displaying n words on screen #10588
    Jeremy
    Keymaster

    Hi,

    Just add .failure( getTimer("recording").stop() ) to the test on the index for the next 10 words:

    newKey("NEXT", " ")
        .callback(
            getVar("nextWordStartsAt").test.is(v=>v<row.Words.split('_').length).success(
                getVar("listOfWords")
                    .set(getVar("nextWordStartsAt"))
                    .set(v=>row.Words.split('_').slice(v,v+10).join("<br>"))
                ,
                getText("words").text( getVar("listOfWords") )
                ,
                getVar("nextWordStartsAt").set(v=>v+10)
            )  // stop the timer if all the words have been exhausted
            .failure( getTimer("recording").stop() )

    Jeremy

    in reply to: Issues using setConsent on InitiateRecorder #10587
    Jeremy
    Keymaster

    Hello Shayne,

    My bad, the command is .consent, not .setConsent

    Jeremy

    in reply to: Randomly present a subset of items #10583
    Jeremy
    Keymaster

    Hi Hailin,

    You could use the custom pick function. Assuming all your critical items have labels that start with exp. and all your filler items have labels that start with fil. it would look something like this:

    var shuffleSequence = seq(
      shuffle(
        pick( randomize(startsWith("exp.")) , 10),
        pick( randomize(startsWith("fil.")) , 30)
      )
    )

    Jeremy

    in reply to: Displaying n words on screen #10582
    Jeremy
    Keymaster

    Hi,

    In that case what I would do is list all the words in a single cell (named “Words” for example) and use Var elements to dynamically update the content of the Text element upon pressing the key:

    Template("new--Items_Wide.csv", row =>
      newTrial("listOfWords",
        fullscreen()
        ,
        newMediaRecorder("recorder", "audio").log().record()
        ,
        newTimer("recording", 3000).log().start()
        ,
        newText("words", row.Words.split('_').slice(0,10).join("<br>")) // use slice to get the 10 first words
            .cssContainer({
               padding: '0.5em',
              'text-align': 'center',
              "justify-content": 'center',
              "align-items": 'center' ,
              'font-size': '50px',
            })
            .print()
        ,
        newVar("listOfWords", ""), // we'll set this Var element to the next list of words
        newVar("nextWordStartsAt").set(10) // this is the index where the next 10 words start
        ,
        newKey("NEXT", " ")
            .callback(
                // first make sure that the index is within bounds
                getVar("nextWordStartsAt").test.is(v=>v<row.Words.split('_').length).success(
                    // set listOfWords to the next words
                    getVar("listOfWords")
                        .set(getVar("nextWordStartsAt")) // first look up the index
                        .set(v=>row.Words.split('_').slice(v,v+10).join("<br>")) // then use the index+slice to get the next 10 words
                    ,
                    getText("words").text( getVar("listOfWords") ) // update the content of the Text element
                    ,
                    getVar("nextWordStartsAt").set(v=>v+10) // the next list of 10 words starts 10 words further
                )
            )
        ,
        getTimer("recording").wait()
        ,
        getMediaRecorder("recorder").stop()
        ,
        getText("words").remove()
        ,
        newText('time-is-up-msg', "Time is up!").print()
        ,
        newButton('btn--finish--game', 'Finish Game').print().wait()
      )
    )

    Jeremy

    in reply to: Help with recording audio? #10581
    Jeremy
    Keymaster

    [ EDIT : changed setConsent for consent ]

    Hi,

    You can use .consent on InitiateRecorder() to change the consent message:

    InitiateRecorder("https://myserver/uploadVoices/saveRecordings.php"
    ,
    "<b><center>RESEARCHER, click on the button below to <b style=color:red;>authorize</b> audio recording in the browser 👇</b></center>"
    ).label("first-trial")
    .consent("I Consent")
    

    Regarding the error message, you could use the hack described in this post to replace the message

    Jeremy

    • This reply was modified 2 years, 1 month ago by Jeremy. Reason: changed setConsent for consent
    in reply to: Help with recording audio? #10561
    Jeremy
    Keymaster

    Hi,

    You cannot change the error message, as it is hard-coded in the MediaRecorder element. What you are doing is create a new trial, and printing a Text element in that trial depending on whether the upload succeeded or failed (note that the trial needs to come after the upload attempt for uploadRecordingsError to be set)

    You can change/set the consent text in the InitiateRecorder command, but you cannot omit that trial, because it is when the browser requests access to the recording device: without it it would simply be impossible to record anything

    Jeremy

    in reply to: Displaying n words on screen #10560
    Jeremy
    Keymaster

    Hello,

    Template scans the table and produces one output per row. So the idea is, you use Template( row => newTrial to generate one trial per row. Listing one word per row is not the ideal way to go if you want to display several of them at the same time on the page, ie. during the same trial

    What you could do is store one list of words per cell, separated with a character of your choice, say .. Here is what it would look like:

    Template("items.csv", row =>
      newTrial("listOfWords",
        newMediaRecorder("recorder").log().record()
        ,
        newTimer("recording", 3000).log().start()   // Start the timer now
        ,
        newText("words", row.words1.split('.').join("<br>")) // separate each word with a <br> tag (new line)
            .cssContainer({
              "border-radius": '25px',
              border: '2px solid #73AD21',
              padding: '0.5em'  // add some to not get too close to the border
            })
            .print()
        ,
        newButton("NEXT", "Next words!")
            .callback(  // use a callback to execute this in parallel to waiting for the timer
                getButton("NEXT").remove() // remove the NEXT button
                ,
                getText("words").text( row.words2.split('.').join("<br>") ) // update the displayed list of words
            )
            .print()
            // do not wait for a click, otherwise the timer might elapse before the click
        ,
        getTimer("recording").wait() // wait for the timer to end
        ,
        getMediaRecorder("recorder").stop()
        ,
        getButton("NEXT").remove() // make sure to remove the button, in case the participant didn't get to the second list
        ,
        getText("words").remove()
        ,
        newText('a', "Time is up!").print()
        ,
        newButton('btn--finish--game', 'Finish Game').print().wait()
      )
    )

    Example items.csv:

    words1,words2
    hello.world,bye.earth
    ibex.is.awesome,pcibex.rocks

    Jeremy

Viewing 15 posts - 106 through 120 (of 1,522 total)