Forum Replies Created
-
AuthorPosts
-
utkuturk
ParticipantThe only sound file that is not a headache to work with is mp3. some browsers like firefox can be really picky about ‘encoding’ of the sound files or their bit rates. As for ‘previewing’ but not being able to play in the experiment is probably due to preview is using a different decoding then the experiment one. If you really need to use wav files, you can re-export them as 16-bit PCM, 44100 Hz.You can easily do that with the command line tool ffmpeg. go to the folder that all sound files exist, and run the following command:
for f in *.wav; do ffmpeg -i “$f” -acodec pcm_s16le -ar 44100 “${f%.wav}_16.wav”; done
utkuturk
ParticipantYes, you can store some of the trials answers as a variable, and then have a “gate” trial in which you check the variables and if they fail you show them a message with no visible button and automatically send results within the trial (so you can check if some people did it again). Here’s the code:
PennController.ResetPrefix(null); var attentionScore = 0; SendResults("send_results"); Sequence( "attn1", "attn2", "attn3", "attn4", "gate", "welcome", "trials", "send_results", "end" ); // --- Attention trials --- newTrial("attn1", newText("attn1-q", "What color is the sky?").print(), newButton("attn1-a", "Blue").print(), newButton("attn1-b", "Green").print(), newSelector("attn1-sel").add(getButton("attn1-a"), getButton("attn1-b")).log().wait(), getSelector("attn1-sel").test.selected(getButton("attn1-a")) .success(newFunction("attn1-fn", () => { attentionScore += 1; }).call()) ); newTrial("attn2", newText("attn2-q", "How many days are in a week?").print(), newButton("attn2-a", "7").print(), newButton("attn2-b", "5").print(), newSelector("attn2-sel").add(getButton("attn2-a"), getButton("attn2-b")).log().wait(), getSelector("attn2-sel").test.selected(getButton("attn2-a")) .success(newFunction("attn2-fn", () => { attentionScore += 1; }).call()) ); newTrial("attn3", newText("attn3-q", "What comes after Tuesday?").print(), newButton("attn3-a", "Wednesday").print(), newButton("attn3-b", "Monday").print(), newSelector("attn3-sel").add(getButton("attn3-a"), getButton("attn3-b")).log().wait(), getSelector("attn3-sel").test.selected(getButton("attn3-a")) .success(newFunction("attn3-fn", () => { attentionScore += 1; }).call()) ); newTrial("attn4", newText("attn4-q", "How many sides does a triangle have?").print(), newButton("attn4-a", "3").print(), newButton("attn4-b", "4").print(), newSelector("attn4-sel").add(getButton("attn4-a"), getButton("attn4-b")).log().wait(), getSelector("attn4-sel").test.selected(getButton("attn4-a")) .success(newFunction("attn4-fn", () => { attentionScore += 1; }).call()) ); // IMPORTANT TRIAL newTrial("gate", newVar("score").set(() => attentionScore), getVar("score").test.is(v => v > 3) .failure( newText("fail-txt", "Sorry, you did not pass the attention check.").print(), // hide send results comment but only here. newFunction("silent-send", () => { $("<style>.PennController-SendResults { visibility: hidden; height: 0; overflow: hidden; }</style>").appendTo("head"); }).call(), SendResults(), // immediately send results newButton().wait() // no visible button to skip or anything ) ); // --- Experiment trials --- newTrial("welcome", newText("welcome-txt", "Welcome! Press start to begin.").print(), newButton("welcome-btn", "Start").print().wait() ); newTrial("trials", newText("trial-txt", "This is the experiment sentence.").print(), newButton("trial-btn", "Next").print().wait() ); newTrial("end", newText("end-txt", "Thank you!").print(), newButton("end-btn", "Finish").print().wait() );utkuturk
ParticipantHi Laurel, I think you fixed it by using Regex as in: getTextInput(“yours”).test.text(new RegExp(“^”+row.name_4.trim()+”$”,”i”))
that is what I would suggested as well. But if you want to tidy it up a bit, you can use the following in the main part of the main.js
function cloudWord(id, name, fontSize) { return [ newText(id, name), getTextInput("yours").test.text(new RegExp("^"+name.trim()+"$","i")) .success(getText(id).css("font-size", fontSize).color("red").print().center()) .failure(getText(id).css("font-size", fontSize).print().center()) ]; }and then within the template code:
newText("choice","Here's what other people said").center().print(), newText(" ").center().print(), // Word cloud entries, matched against participant's response ...cloudWord("n1", row.name_1, row.font_1), ...cloudWord("n2", row.name_2, row.font_2), ...cloudWord("n3", row.name_3, row.font_3), ...cloudWord("n4", row.name_4, row.font_4), ...cloudWord("n5", row.name_5, row.font_5),utkuturk
ParticipantThere are many ways to do it. You can either use “fake-captcha” or host your own pcibex and have a backend and api to do real captcha (overkill) or you can do mouse tracking.
I use mouse tracking and tell participants sometimes they might be asked to check a box. Bot mouse movements and human mouse movements are different, pcibex already has support for mouse tracking.
Fake catpcha:
– Go to any captcha picture generator website. get couple of captcha images. put the image file names and answer text in a csv file and create a template trials like this:
`
Template(“captcha.csv”, row =>
newTrial(“captcha”,
newText(“title”, “Human Verification”).bold().print(),
newText(“instruction”, “Type the characters you see in the image:”).print(),
newImage(“captchaImg”, row.img).size(250, 80).print(),
newTextInput(“captchaInput”).print(),
newText(“error”, “Incorrect, please try again.”).color(“red”),
newButton(“Submit”).print()
.wait(
getTextInput(“captchaInput”)
.test.text(new RegExp(“^\\s*” + row.answer + “\\s*$”, “i”))
.failure(
getText(“error”).print(),
getTextInput(“captchaInput”).clear()
)
)
)
)
`Real captcha:
– Or start hosting your own pcibex. add google/amazon script api to your page template ( <script src=”https://www.google.com/recaptcha/api.js” async defer></script>)
– Then add trials like this to your pcibex code and then verify the tokens in your backend.`
newTrial(“captcha”,
newText(“instruction”, “Please complete the CAPTCHA to continue.”).print(),
newHtml(“recaptchaWidget”,
“<div class=’g-recaptcha’ data-sitekey=’YOUR_SITE_KEY’></div>”
).print(),
newFunction(“checkCaptcha”, () => new Promise(resolve => {
const interval = setInterval(() => {
const response = grecaptcha.getResponse();
if (response.length > 0) {
clearInterval(interval);
resolve();
}
}, 500);
})).call().wait(),
newButton(“Continue”).print().wait()
)
`Mouse tracking:
– Add mouse trackers and a random checkbox to subset of your trials.
– Track TrialN in your experiments`
Header(
newVar(“TrialN”, 0).global(),
)
.log(“trialN_header”, getVar(“TrialN”))
`– When you create a template code for your filler or experimental trials, add an if statement like this and add mouse tracker start, randomcheckbox, and mouse tracker stop.
`
Template(“experiment.csv”, row =>
newTrial(“exp”,
getVar(“TrialN”).test.is(v => v % 20 === 0).success(
newMouseTracker(“mouse”).log().start()
),// rest of your experiment code doing normal experiment stuff…
// clear everything on the screen
getVar(“TrialN”).test.is(v => v % 20 === 0).success(
//some checkbox code
,
getMouseTracker(“mouse”).stop()
),`May 6, 2026 at 11:34 pm in reply to: Regarding the MediaRecorder Upload Hosting on PCIbex Farm and Data Protection #11152utkuturk
ParticipantHello. PCIbex Farm does not provide hosting services. You can use this tutorial to have your own AWS server and s3 bucket: https://www.utkuturk.com/posts/aws-s3-pcibex/
As for data security, you should talk to your IRB. Good things to remember is to encryption at-rest and also not having a public access.
utkuturk
ParticipantI have solved the problem by using a dummy timer from this thread: https://www.pcibex.net/forums/topic/controller-or-timer-conditional/
I would be happy to know if there can be any improvement in this code.
Here’s the solution:
// Practice Trials Template("PracticePreambles.csv", (row) => newTrial( "practice", newTimer(300).start().wait(), //white screen before the trial newText("Preamble", row.preamble) .center() .cssContainer({ "margin-right": "1em" }) .print(), newTimer("hurry", 3000).start(), newTimer("dummy", 1) .callback( newTextInput("answer") .settings.before(getText("Preamble")) .log("validate") .lines(1) .cssContainer("display", "flex") .print() .wait( getTextInput("answer") .test.text(/^(.{10,500})$/) .failure( newText("<b>Please write more.</b>") .settings.color("red") .print() ) ), getTimer("hurry").stop() ) .start(), getTimer("hurry").wait() // add timelimit ) .log("Preamble", row.preamble) // add these three columns to the results lines of these Template-based trials .log("Condition", row.condition) .log("ItemNumber", row.itemnum) ); -
AuthorPosts