Forum Replies Created
-
AuthorPosts
-
Larissa_Cury
ParticipantWe have to erase the counter if the answer is right in case a participant get 1 error followed by a correct answer (which is allowed), not in case we have two sequential errors, I wrote it wrong above.
My attempt in Pcibex was this, but I got stuck…
// CREATE an error count outside "loop" so that it doesn't gets erased whenever a trial starts let errorNum = 0; Template("newStimuliShort.csv", row => newTrial("listOfNumbers", defaultText .cssContainer({ padding: '0.5em', 'text-align': 'center', "justify-content": 'center', "align-items": 'center' , 'font-size': '50px', }) .center() .print() , newMediaRecorder("recorder", "audio").log().record() // , // newTimer("recording", 60000).log().start() , newText("words", row.sequence) // Display sequences , newAudio("audio", row.audio) // play corresponding audio (which is in Portuguese) .play() , getAudio("audio").wait("first") // wait audio finishes , newAudio("beep", "beep.mp3") .play() , getAudio("beep").wait("first") // wait audio finishes , newVar("currLen").set(row.lenNumeric) // get current i length of "sequence" , newKey("NEXT", "SK") .wait() .log() , getKey("NEXT") .disable() // make sure we only have 1 answer - participant can only answer once , getKey("NEXT") .test.pressed("S") .success( newText("success", 'yey'), // if the answer is right, getVar("errorNum").set(0)) // make sure to erase the error count in case a participant get 1 error followed by a correct answer .failure( newVar("errorCount").set( errorNum + 1) // Increase error count by 1 ans store it in a variable called 'errorCount' , // I would need sth here to store the errors so that k + k generates errorCount = K , then I guess I could use .testIs() to see if errorCount === 2. If yes, then we should check if the current length equals the last length and break the experiment in case it's TRUE. Otherwise just erase the error count again and the experiment continues // newText("lastLen", row.lenNumeric).map((w,i) => <code>${w[i - 1]}</code>) // get the last length ---- COULDN'T DO IT!! // , newText("failure") // .text( getVar("errorCount") ) // I was displaying just to see if it was working .text(getVar("errorCount")) // I was displaying just to see if it was working .cssContainer({"font-size":"30px", "text-align":"center", "margin-top":"255px","font-family":"Comic Sans MS", "color":"red","white-space":"nowrap"}) ) , newTimer("wait-success",100) //timer for the success or failure messenge .start() .wait() , getText("success") .remove() , getText("failure") .remove() // , // getTimer("recording").wait() , getMediaRecorder("recorder").stop() ) );
PS: I tried to use 0 and 1 instead of letters for the keypress, but I couldn’t do it. I guess it was interpreting 0 and 1 as strings, not numbers, how would I overcome that as well ?
-
This reply was modified 1 year, 11 months ago by
Larissa_Cury. Reason: forgot to put block code
Larissa_Cury
ParticipantAll right! Thank you very much for taking the time to explain that to me!
Larissa_Cury
ParticipantHi, Jeremy! Things are much clearer now, thank you!!
I’ve read the documentation link you’ve sent me, thanks, but I’m still wondering about one thing:
If in the doc’s example,
newText("dots", "...").print()
.dots { text-decoration: underline; }
equals
newText("dots") .css("text-decoration","underline") .print()
Then how come the the separed .css manipulation for “words” in the separed file be different from the one we have with the
.css
in the code? From what I got from the doc, the.css
in the code points to the element itself (in the ex case, “dots”, in my case “word”), right? Hence, how can the separed one refer to all individual span classes and the .css one refer to all span classes, shouldn’t they both point to “words” ? (the element to each they’re attached to) ?Larissa_Cury
ParticipantHi, @Jeremy! Can you help me walk through it?
# PART 1:
// embed each word in a span, highlight the very first one newText("words", row.Words.split('_').map((w,i)=><code><span class='word ${i==0?'highlighted':''}'>${w}</span></code>).join(''))
1) We create newText called “words” which gets each word from the cell. All words are separated by “_”, hence, “a word” equals “a string separed by _”, which is what split(”) is doing
2) Involve the words in a span HTML class (I’m a bit confused here, but I guess it is to show the words in a box-like way?)
3) the map function gets the current element (each word (w)) and the current index (i). The condition says “if the current index equals 0, add the highlighted class to .word otherwise, just print the word {w}, which just has the class .word
4) Join the words back together in a string separed by the empty string# part 2:
.cssContainer("width","810px") // 3 times the space reserved for each word + horizontal padding .css({ display: 'flex', // items contained in the element will be rearranged smartly 'flex-direction': 'column', // stack items in columns 'flex-wrap': 'wrap', // items that overflow vertically will start on new columns 'font-size': '50px', height: '210px' // more than 3 times the space reserved for each word + vertical padding }) .print()
I was a bit confused here with the two css elements, the .cssContainer and the .css. At first, I supposed that the .cssContainer would modify the NewText element and the .css would modify the .word or .word highlighted classes, but if I change the font-size, it changes the fontsize of the text element, so I guess I’m wrong. Hence: Why do we have both .css and .cssContainer here?
Second question: “3 times the space reserved for each word + horizontal padding”. I couldn’t figure out waht “the space reserved for each word” means. Are we talking about the specifications in the .word class in the css file? (if yes, what is precisely the “space” reserved? the padding?)
# PART 3:
newVar("listOfWords", ""), // we'll update this Var element with the list of words tagged as desired newVar("highlightedWord").set(0) // this is the index of the highlighted word , newKey("NEXT", " ") .callback( // first make sure that the next index is within bounds getVar("highlightedWord").test.is(v=>v+1<row.Words.split('_').length).success( getVar("highlightedWord").set(v=>v+1) // increment the index of the highlighted word , getVar("listOfWords") // update listOfWords with appropriate tags .set(getVar("highlightedWord")) // first look up the index .set(v=>row.Words.split('_').map((w,i)=><code><span class='word ${i==v?'highlighted':''}'>${w}</span></code>).join('')) // now set the class as desired , getText("words").text( getVar("listOfWords") ) // update the content of the Text element ) )
1) I didn’t get the ‘check’ logic: getVar(“highlightedWord”).test.is(v=>v+1<row.Words.split(‘_’).length).success() ? Shouldn’t we test if i === 0 ? why then v + 1 ?
2) Ok, we increment the word index by one (to move on to the next word)
3) I get this part:.set(v=>row.Words.split('_').map((w,i)=>
<span class=’word ${i==v?’highlighted’:”}’>${w}</span>).join('')) // now set the class as desired
if the current word is === v, then add the highlight class, otherwise, just print the w , right?But I can’t understand the 2 lines before it.
4) we have to update the textElement, so we update the content of ‘words’ with the ‘list of words’ one.# Questions about the styling:
I also didn’t quite understand what css was updating what element, if I got it right, then:
# Updates the ‘words’ in general (all words) – then, why do we need the cssContainer back there?
.PennController-words .word { width: 230px; height: 60px; padding: 5px 15px; # around each word }
.word.highlighted
this is ok, this is the highlighted class 🙂When you mentioned “you could do 12 words as in your example too, just adjust the widths and heights accordingly to fit 4×4 words” which height and weight were you refering too? I changed the height of the .css (originally 210pc), but I don’t know if that was the right place to do so?
Sorry for the long post, I started learning ‘raw’ Js and now I guess I’m a little bit more able to understand PciBex code better, I really would like to understand it. Thanks in advance!
Larissa_Cury
ParticipantThank you VERY much, Jeremy! I have a few questions, but I’ll work on my own to try to solve them or to come up with more elaborated questions. Thank you very much, this is amazing!
Larissa_Cury
ParticipantTo illustrate it:
# Suppose >< represents a CSS border class to highlight the words:
1) Display n columns of words on the screen at the same time as the words are displayed in the csv file
2) Highlight the first word (I thought of a CSS class to do it)
3) When participant hits spacebar, the highlight goes to the next word below>Jason< Raheema Chassity
Oscar Bryce Carlito
Maleeka Nasreen Maureene
Janet Hishaam ChidieberePRESS SPACEBAR:
Jason Raheema Chassity
>Oscar< Bryce Carlito
Maleeka Nasreen Maureene
Janet Hishaam Chidiebere4) When the participants finishes the columns, the highlight class moves up to the first word of the next column
Jason Raheema Chassity
Oscar Bryce Carlito
Maleeka Nasreen Maureene
>Janet< Hishaam ChidieberePRESS SPACEBAR
Jason >Raheema< Chassity
Oscar Bryce Carlito
Maleeka Nasreen Maureene
Janet Hishaam ChidiebereLarissa_Cury
ParticipantHi, @Jeremy! Thank you very much! Could I add a key press too? For example, other than ” ” ? “If you finish before 1min, press K”, for ex? using the same logic with
failure
-
This reply was modified 1 year, 11 months ago by
Larissa_Cury. Reason: edit question
Larissa_Cury
ParticipantHi, Jeremy! Thank you very much!
Larissa_Cury
ParticipantHi, @Jeremy! Thank you very much! Let me ask you something, in case the participant finishes before 60min (which I don’t think will happen, but I have to think about it too, right), can I add a keypress to scape the time?
PS: I’ve made sure that the index is within bounds doing this in R: https://stackoverflow.com/questions/76244042/how-to-insert-strings-so-that-every-row-has-the-same-pattern?noredirect=1#comment134453942_76244042 🙂
Thank you once more! It’s working perfectly!
Larissa_Cury
ParticipantI’m trying to come up with a way to loop over the table and dynamically set
getText("words").text( row.Column2.split('_').join("<br>") )
so that it displays row.Column{n} as the dataset have, where n is the number of cols in the table and the index of each interation, but I’m really struggling with that, I don’t know if that would be the right way to achieve what I’m trying to achieve above…-
This reply was modified 1 year, 11 months ago by
Larissa_Cury. Reason: additional comments
Larissa_Cury
ParticipantI tried to add a
sequence
element, https://farm.pcibex.net/r/AqPhcF/ . I guess it worked! 🙂 Is there a better way, tho? I don’t think I can manipulate any of these messages, right?-
This reply was modified 1 year, 11 months ago by
Larissa_Cury.
Larissa_Cury
ParticipantHi, @Jeremy! Considering the error message, is is possible to put a trial before that?
My idea was: If I cannot change the text, then I’ll display a warning to the kid “Please, wait your teacher”, so that the kid/participant calls the teacher, who will press S and then the message shows up. I tried to do it like this, but the order isn’t changing:// 👉 Experimental trial: Template("new--Items_Wide.csv", row => newTrial("listOfWords", fullscreen() //enable full screen , newMediaRecorder("recorder", "audio").log().record() , newTimer("recording", 3000).log().start() // Start the timer now , newText("words", row.Column1.split('_').join("<br>")) // separate each word with a <br> tag (new line) .cssContainer({ padding: '0.5em', // add some to not get too close to the border 'text-align': 'center', // trying to make the words center on fullscreen -- NOT WORKING :( "justify-content": 'center', "align-items": 'center' , 'font-size': '50px', }) .print() , newKey("NEXT", " ") .callback( // use a callback to execute this in parallel to waiting for the timer getKey("NEXT").remove() // remove the NEXT button , getText("words").text( row.Column2.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() , getKey("NEXT").remove() // make sure to remove the button, in case the participant didn't get to the second list , getText("words").remove() , newText('time-is-up-msg', "Time is up!").print() , newButton('btn--finish--game', 'Finish Game').print().wait() ) ); // 👉 Completion screen -- WAIT THE TEACHER ///////////////////////////////////////// HERE newTrial("completion_screen", // Exit fullscreen: exitFullscreen() , // Print thank-you msg: newText("thankyou-msg", "Good job, now wait your teacher!") .center() .print() , newKey("NEXT", "S") // , // newButton("void", "") // .wait() ); // 👉 Send results: SendResults(); // 👉 Check if promise is fullfilled // 👉 Manually reject promise => insert dummy link // 👉 Store audio locally newTrial( newFunction("check upload", ()=>PennController.uploadRecordingsError) .test.is() .success( newText("confirmation", "The recordings were sent to the server. ") .print() ) .failure( newText("error", "Click on the link below to store data 👇") .color("red") .print() ) // , // newText("download-manually-msg", DownloadRecordingButton("Click here to download an archive of your recordings.") ) // .print() // , // newTimer("inifinite", 0) // .wait() );
Larissa_Cury
ParticipantHi, @Jeremy! [EDIT – UPDATE] I can display the words one below the other and the time seems to be ok (the whole trial is lasting the amount of time and not reseting time), but I’d like to avoid hard-coding this part:
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.Column2.split('_').join("<br>") ) // update the displayed list of words ) .print() // do not wait for a click, otherwise the timer might elapse before the click ,
A) I’d like to be able to have *n* columns as I want displayed dynamically based on the dataframe number of cols in the wide version. Otherwise, I’ll have to hard-code this part *n* times according to the amount of cols of my dataframe.
B) Or, in the long version, I’d like to be able to print as many rows as I want, instead of hard-coding each interval manually.Is there a way to do acheive either a or b? https://farm.pcibex.net/r/AqPhcF/
* Data:
DF: WIDE VERSION: ‘new–Items_Wide.csv”
DF: LONG VERSION: ‘new–items.csv”* Whole code:
Template("new--Items_Wide.csv", row => newTrial("listOfWords", newMediaRecorder("recorder").log().record() , newTimer("recording", 3000).log().start() // Start the timer now , newText("words", row.Column1.split('_').join("<br>")) // separate each word with a <br> tag (new line) .cssContainer({ padding: '0.5em', // add some to not get too close to the border 'text-align': 'center', // trying to make the words center on fullscreen -- NOT WORKING :( 'font-size': '50px', 'position': 'absolute', 'top': '50%', 'bottom': '50%', 'left': '50%', 'width': '100%' }) .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.Column2.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() ) );
-
This reply was modified 1 year, 11 months ago by
Larissa_Cury.
-
This reply was modified 1 year, 11 months ago by
Larissa_Cury.
Larissa_Cury
ParticipantI fixed letter A, I was using the wrong separator, but I’m still having issues with b)…
I would like to avoid having to hard code every single column name in the wide version or to use only the single column in the long version, because I’ll have many in the real experiment…-
This reply was modified 1 year, 11 months ago by
Larissa_Cury.
Larissa_Cury
ParticipantPs: I’ve just added a wide version of the data as well, if it’s better this way, called ‘new–Items_Wide’
-
This reply was modified 1 year, 11 months ago by
-
AuthorPosts