Forum Replies Created
-
AuthorPosts
-
btaParticipant
I have figured out a solution, which I’m sharing below (I’ve put this code in a .js file that I added under “modules”).
I use it in my
Sequence()
as inSequence( sepChunkWithChunk("theSeparator", 1, "theStimuli", 2) )
, which does what I described in my previous post (*except that it doesn’t add a separator after the final stimulus, which I did on purpose*).// this code below lets you put something like sepChunkWithChunk("separators", 1, "stimuli", 2) into the Sequence // this works so that, if you have a Trial (in a Template) named "separators" and a Trial (in a Template) named "stimuli", … // …it will present trials from the "stimuli" in chunks of 2, with each chunk separated by 1 trial from "separators" // (NOTE: there will be a "separators" chunk between chunks of "stimuli" — meaning if there are 4 chunks of "stimuli", only 3 "separators" chunks will be alreadyUsed) function SepChunkWithChunk(sep, nSep, main, nMain) { assert(typeof(nSep)=="number" && nSep>0, "nSep should be a number greater than 0"); assert(typeof(nMain)=="number" && nMain>0, "nMain should be a number greater than 0"); this.args = [sep, main]; this.run = function(arrays) { var alreadyUsedSep = []; var alreadyUsedMain = []; let sep = arrays[0]; let main = arrays[1]; var numChunksForMain = Math.ceil(main.length / nMain); // calculates the number of chunks of 'main' are necessary to show all items from 'main' var totalNumUsedFromMain = 0; // counter for tallying number of items used from 'main' var chunkedAndSeparatedArray = []; // this array will house the order of all trials, randomized into chunks of 'main' separated by chunks of 'sep' for (let i = 1; i <= numChunksForMain; ++i) { // run this loop as many times as there are chunks of 'main' counterMain = 0; counterSep = 0; // create a chunk with 'nMain' elements by looping 'nMain' times // STOP LOOPING if it's already pulled out all trials from 'main' // (this will happen if, e.g., you have 8 trials in 'main' and 'nMain' is set to something like 5 — two chunks are needed, but the second chunk should only have 3 elements) while (counterMain < nMain && totalNumUsedFromMain < main.length) { // generate a random number between 0 and (main.length-1): r = Math.floor(Math.random()*main.length); // keep generating a new random number until the random number generated hasn't been used before // (this has the effect of blocking the repetition of items from 'main' that have already been added to 'chunkedAndSeparatedArray') while (alreadyUsedMain.includes(r)) { r = Math.floor(Math.random()*main.length); } // now that a unique random number has been generated, add it to the array of random numbers that have been used alreadyUsedMain.push(r); // add the rTH trial from 'main' to 'chunkedAndSeparatedArray' chunkedAndSeparatedArray.push(main[r]); // increase counters ++counterMain; ++totalNumUsedFromMain; } // create a chunk with 'nSep' elements by looping 'nSep' times // DON'T RUN THIS LOOP if the last chunk of 'main' has just been added to 'chunkedAndSeparatedArray' if (i != (numChunksForMain)){ while (counterSep < nSep) { // generate a random number between 0 and (sep.length-1): r = Math.floor(Math.random()*sep.length); // keep generating a new random number until the random number generated hasn't been used before // UNLESS all the trials from 'sep' have already been used // (this has the effect of allowing separator trials to be re-used just in case the number of separators needed is greater than the number of unique trials in 'sep') while (alreadyUsedSep.includes(r) && sep.length > alreadyUsedSep.length ) { r = Math.floor(Math.random()*sep.length); } // now that a unique random number has been generated, add it to the array of random numbers that have been used alreadyUsedSep.push(r); // add the rTH trial from 'sep' to 'chunkedAndSeparatedArray' chunkedAndSeparatedArray.push(sep[r]); // increase counter ++counterSep; } } } // return the finalized Array, which will have all the trials of 'main' in a raondomized order // moreover, between every chunk of 'nMain' trials, there is a chunk of random 'nSep' trials from 'sep' return chunkedAndSeparatedArray; } } function sepChunkWithChunk(sep, nSep, main, nMain) { return new SepChunkWithChunk(sep, nSep, main, nMain); }
btaParticipantGreat that worked perfectly!
btaParticipantThank you, this worked great!
btaParticipantThank you so much, this is so helpful! I find it challenging to think this way, but I’m starting to get used to it.
btaParticipantOh great, thanks! This is very helpful. I did not know that all JS functions are run from the start, even when the calls to those functions are made within instances of PennController
test.is
.The one thing that I didn’t mention before is that I did want to reuse the image multiple times, which I think would just mean using the series of
test.is
statements every time I reuse the image. Is that right?
(i.e., it seems to me that all of thesenewImage
s cannot have the same name —something like testerImage— because every timenewImage
is called it needs to have a unique identifier; and because of that, there’s no way to use a single line of code likegetImage("testerImage")
to call back that same image.)btaParticipantGreat, yes, that worked! Thank you!
-
AuthorPosts