Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@ function InnerParticipant() {
const introSequence = globals.get("recruitingBatchIntroSequence");

function introSteps() {
const steps = [Consent, AttentionCheck, EquipmentCheck, EnterNickname];
const steps = [Consent];

// Add AttentionCheck based on effortCheck config
const effortCheck = batchConfig?.effortCheck ?? true; // default to true if not specified
if (effortCheck !== false) {
steps.push(AttentionCheck);
}

steps.push(EquipmentCheck, EnterNickname);

if (introSequence?.introSteps) {
introSequence.introSteps.forEach((step, index) => {
Expand Down
12 changes: 10 additions & 2 deletions client/src/intro-exit/AttentionCheck.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import React, { useEffect, useState } from "react";
import { usePlayer } from "@empirica/core/player/classic/react";
import { useGlobal } from "@empirica/core/player/react";
import { Button } from "../components/Button";

export function AttentionCheck({ next }) {
const [correctUntil, setCorrectUntil] = useState(undefined);
const [sentenceInput, setSentenceInput] = useState("");
const [loadedTime, setLoadedTime] = useState(-1);
const player = usePlayer();
const originalString =
"I agree to participate in this study to the best of my ability.";
const globals = useGlobal();
const batchConfig = globals?.get("recruitingBatchConfig");

// Get effortCheck config, default to true with default text
const effortCheck = batchConfig?.effortCheck ?? true;
const originalString =
typeof effortCheck === "string"
? effortCheck
: "I agree to participate in this study to the best of my ability.";

useEffect(() => {
console.log("Intro: Attention Check");
Expand Down
30 changes: 30 additions & 0 deletions docs/batchConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,36 @@ Set to false if you are not using webcams in your experiment, and you don't care
Must be a boolean. If you do not wish to check participant audio, enter `"checkAudio": false`.
Set this to false if you aren't using webcams OR microphones. Has no effect unless `checkVideo` is also set to false.

### `effortCheck`

Controls whether to show the sentence typing effort check during the intro steps. This is an optional parameter with three possible configurations:

- `"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."
- `"effortCheck": false` - Skips the effort check entirely
- `"effortCheck": "Your custom sentence here"` - Shows the effort check with a custom sentence that participants must type exactly

Example configurations:

```json
{
"effortCheck": false
}
```

```json
{
"effortCheck": true
}
```

```json
{
"effortCheck": "The quick brown fox jumps over the lazy dog"
}
```

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.

### `introSequence`

The name of the sequence defined in `treatmentFile` to be shown to all participants prior to assignment to treatment condition
Expand Down
24 changes: 24 additions & 0 deletions server/src/preFlight/validateBatchConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,27 @@ test.skip("treatment name is not present in treatment file", () => {
expect(result.success).toBe(false);
// Todo: add check for error message
});

test("effortCheck boolean true", () => {
const config = JSON.parse(JSON.stringify(passingConfig));
config.effortCheck = true;
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
});

test("effortCheck boolean false", () => {
const config = JSON.parse(JSON.stringify(passingConfig));
config.effortCheck = false;
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
});

test("effortCheck custom string", () => {
const config = JSON.parse(JSON.stringify(passingConfig));
config.effortCheck = "The quick brown fox jumps over the lazy dog";
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
});

test("effortCheck undefined/not provided", () => {
const config = JSON.parse(JSON.stringify(passingConfig));
// effortCheck is not set, should be optional and work fine
expect(() => validateBatchConfig(config)).not.to.throw(ValidationError);
});
3 changes: 3 additions & 0 deletions server/src/preFlight/validateBatchConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ export const batchConfigSchema = z
checkVideo: z.boolean({
message: `Must be a boolean. If you do not wish to check participant video, enter "false"`,
}),
effortCheck: z
.union([z.boolean(), z.string()])
.optional(),
})
.strict()
.superRefine((obj, ctx) => {
Expand Down