Skip to content

Commit 7c228bd

Browse files
Add effortCheck config parameter to control attention check
Co-authored-by: JamesPHoughton <4304478+JamesPHoughton@users.noreply.github.com>
1 parent 599d525 commit 7c228bd

5 files changed

Lines changed: 76 additions & 3 deletions

File tree

client/src/App.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ function InnerParticipant() {
5757
const introSequence = globals.get("recruitingBatchIntroSequence");
5858

5959
function introSteps() {
60-
const steps = [Consent, AttentionCheck, EquipmentCheck, EnterNickname];
60+
const steps = [Consent];
61+
62+
// Add AttentionCheck based on effortCheck config
63+
const effortCheck = batchConfig?.effortCheck ?? true; // default to true if not specified
64+
if (effortCheck !== false) {
65+
steps.push(AttentionCheck);
66+
}
67+
68+
steps.push(EquipmentCheck, EnterNickname);
6169

6270
if (introSequence?.introSteps) {
6371
introSequence.introSteps.forEach((step, index) => {

client/src/intro-exit/AttentionCheck.jsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import React, { useEffect, useState } from "react";
22
import { usePlayer } from "@empirica/core/player/classic/react";
3+
import { useGlobal } from "@empirica/core/player/react";
34
import { Button } from "../components/Button";
45

56
export function AttentionCheck({ next }) {
67
const [correctUntil, setCorrectUntil] = useState(undefined);
78
const [sentenceInput, setSentenceInput] = useState("");
89
const [loadedTime, setLoadedTime] = useState(-1);
910
const player = usePlayer();
10-
const originalString =
11-
"I agree to participate in this study to the best of my ability.";
11+
const globals = useGlobal();
12+
const batchConfig = globals?.get("recruitingBatchConfig");
13+
14+
// Get effortCheck config, default to true with default text
15+
const effortCheck = batchConfig?.effortCheck ?? true;
16+
const originalString =
17+
typeof effortCheck === "string"
18+
? effortCheck
19+
: "I agree to participate in this study to the best of my ability.";
1220

1321
useEffect(() => {
1422
console.log("Intro: Attention Check");

docs/batchConfig.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,36 @@ Set to false if you are not using webcams in your experiment, and you don't care
107107
Must be a boolean. If you do not wish to check participant audio, enter `"checkAudio": false`.
108108
Set this to false if you aren't using webcams OR microphones. Has no effect unless `checkVideo` is also set to false.
109109

110+
### `effortCheck`
111+
112+
Controls whether to show the sentence typing effort check during the intro steps. This is an optional parameter with three possible configurations:
113+
114+
- `"effortCheck": true` (default if not specified) - Shows the effort check with the default sentence: "I agree to participate in this study to the best of my ability."
115+
- `"effortCheck": false` - Skips the effort check entirely
116+
- `"effortCheck": "Your custom sentence here"` - Shows the effort check with a custom sentence that participants must type exactly
117+
118+
Example configurations:
119+
120+
```json
121+
{
122+
"effortCheck": false
123+
}
124+
```
125+
126+
```json
127+
{
128+
"effortCheck": true
129+
}
130+
```
131+
132+
```json
133+
{
134+
"effortCheck": "The quick brown fox jumps over the lazy dog"
135+
}
136+
```
137+
138+
This feature allows experiment designers to prioritize speed in the intro stages by skipping the effort check, or to customize the sentence participants must type.
139+
110140
### `introSequence`
111141

112142
The name of the sequence defined in `treatmentFile` to be shown to all participants prior to assignment to treatment condition

server/src/preFlight/validateBatchConfig.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,27 @@ test.skip("treatment name is not present in treatment file", () => {
250250
expect(result.success).toBe(false);
251251
// Todo: add check for error message
252252
});
253+
254+
test("effortCheck boolean true", () => {
255+
const config = JSON.parse(JSON.stringify(passingConfig));
256+
config.effortCheck = true;
257+
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
258+
});
259+
260+
test("effortCheck boolean false", () => {
261+
const config = JSON.parse(JSON.stringify(passingConfig));
262+
config.effortCheck = false;
263+
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
264+
});
265+
266+
test("effortCheck custom string", () => {
267+
const config = JSON.parse(JSON.stringify(passingConfig));
268+
config.effortCheck = "The quick brown fox jumps over the lazy dog";
269+
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
270+
});
271+
272+
test("effortCheck undefined/not provided", () => {
273+
const config = JSON.parse(JSON.stringify(passingConfig));
274+
// effortCheck is not set, should be optional and work fine
275+
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
276+
});

server/src/preFlight/validateBatchConfig.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ export const batchConfigSchema = z
183183
checkVideo: z.boolean({
184184
message: `Must be a boolean. If you do not wish to check participant video, enter "false"`,
185185
}),
186+
effortCheck: z
187+
.union([z.boolean(), z.string()])
188+
.optional(),
186189
})
187190
.strict()
188191
.superRefine((obj, ctx) => {

0 commit comments

Comments
 (0)