CP_AUTOMATION/CognitivePrism/my-project/cognitive-docs/Doc/VPSM.mdc
2025-12-12 19:54:54 +05:30

1927 lines
62 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Response Requirement
**Every AI response must start with:**
"Inshallah lets start"
**Modal Identification:**
At the beginning of each response, identify the current AI model being used by stating its official name.
---
## 🎯 Core Test Specifications
### Test Structure (CRITICAL)
- **Practice Phase:** 20 trials (adolescents) or 25 trials (adults) with feedback
- **Main Test Phase:** 15 memory sets across 5 triads
- **Adolescents:** 5 triads of (1-letter, 3-letter, 5-letter) = 650 probe trials total
- **Adults:** 5 triads of (2-pair, 4-pair, 6-pair) = 800 probe trials total
- **Total Test:** Practice + Main (670 or 825 total probe trials)
- **Timing:**
- Fixation cross: 0.3s (300ms)
- Memory set item display: 1.1s (adolescents) / 1.3s (adults) per item
- Retention interval: 1.0s (1000ms)
- Probe display: 6.0s (adolescents) / 4.5s (adults) per probe
- Feedback (practice only): 1.0s (correct) / 1.5s (incorrect) / 1.0s (timeout)
- Inter-trial interval: 0.3s (300ms) recommended
- **Probe Types:**
- **Positive probes:** Item WAS in memory set (correct answer: Yes)
- **Negative probes:** Item was NOT in memory set (correct answer: No)
### Age Groups
#### 1. **Adolescents (14-18 years):**
- **Stimuli:** Single letters only (A-Z)
- **Memory set sizes:** 1, 3, 5 letters
- **Probe response time:** 6 seconds per probe
- **Memory item display:** 1.1 seconds per letter
- **Practice:** 1-letter span (K) with 20 probe trials
- **Main task:** 5 triads alternating 1→3→5 letter spans
- **Probe distribution per span:**
- 1-letter: 30 probes per set
- 3-letter: 50 probes per set
- 5-letter: 50 probes per set
- **Total main probes:** 650 trials
- **Instructions:** Casual, encouraging, game-like language
- **Example:** Memory set = [A, D, F] → Probe = D → Answer: Yes (positive)
#### 2. **Adults (18-22 years):**
- **Stimuli:** Alphanumeric pairs (Letter + Number, e.g., K7, C9, R2)
- **Memory set sizes:** 2, 4, 6 pairs
- **Probe response time:** 4.5 seconds per probe
- **Memory item display:** 1.3 seconds per pair
- **Practice:** 2-pair span (C9, B3) with 25 probe trials
- **Main task:** 5 triads alternating 2→4→6 pair spans
- **Probe distribution per span:**
- 2-pair: 30 probes per set
- 4-pair: 65 probes per set
- 6-pair: 65 probes per set
- **Total main probes:** 800 trials
- **Instructions:** Formal, concise, professional language
- **Example:** Memory set = [K7, C9] → Probe = C9 → Answer: Yes (positive)
---
## 🔑 Critical Implementation Rules
### Core Task Concept (HIGHEST PRIORITY)
```javascript
// WORKING MEMORY TASK: Serial Recognition Paradigm
// PHASE 1: ENCODING (Memory Set Presentation)
// Items shown sequentially, one at a time
// Adolescent example: A → D → F (each for 1.1s)
// Adult example: K7 → C9 → R2 (each for 1.3s)
// Participant must MEMORIZE these items during presentation
// PHASE 2: RETENTION INTERVAL
// Blank screen for 1 second
// Participant holds items in working memory (no external cues)
// Critical for measuring active maintenance
// PHASE 3: RECOGNITION (Probe Trials)
// Single items shown one at a time
// Participant decides: "Was this item in the memory set?"
//
// POSITIVE PROBE (Target): Item WAS in set
// Example: Memory set = [A, D, F], Probe = D
// Correct answer: YES
//
// NEGATIVE PROBE (Non-Target): Item was NOT in set
// Example: Memory set = [A, D, F], Probe = G
// Correct answer: NO
// PHASE 4: REPEAT PROBES
// All probes for current memory set are tested
// Then move to next memory set
// Continue until all 15 memory sets complete
// KEY MEASURE: Accuracy and Reaction Time across different memory loads
// Larger memory sets → Greater cognitive load → Performance decline
```
### Memory Set Presentation Rules
```javascript
// Sequential Presentation (CRITICAL):
// - Items appear ONE AT A TIME (never all at once)
// - Each item displays for fixed duration (1.1s or 1.3s)
// - No overlap between items
// - Blank screen between items (optional, use fixation or immediate next)
// Display Requirements:
// - Centered on screen
// - Large, clear font (text-4xl or text-5xl)
// - White text on black background
// - High contrast for easy reading
// Adolescent Display:
// - Single letters: A, B, C, D, E, F, G, etc.
// - Uppercase only
// - Display duration: 1.1 seconds per letter
// Adult Display:
// - Alphanumeric pairs: A1, B2, C3, K7, etc.
// - Letter (uppercase) + Number (1-9)
// - Display duration: 1.3 seconds per pair
```
### Probe Trial Distribution
```javascript
// CRITICAL: Predetermined sequences (NOT randomized)
// Follow exact probe order from PDF for both age groups
// Adolescent Practice (1-letter span: K):
// - Total probes: 20
// - Positive probes (K): 10 trials
// - Negative probes (A, M, R, L, B, T, C, D, S, F): 10 trials
// - Probe sequence must match PDF exactly
// Adult Practice (2-pair span: C9, B3):
// - Total probes: 25
// - Positive probes (C9 or B3): 13 trials
// - Negative probes (A1, D4, F2, H8, K7, L1, etc.): 12 trials
// - Probe sequence must match PDF exactly
// Main Task Structure:
// - 15 memory sets total (5 triads)
// - Each triad contains one set of each span size
// - Alternating pattern: Small → Medium → Large
// - Adolescents: 1 → 3 → 5 letters (repeated 5 times)
// - Adults: 2 → 4 → 6 pairs (repeated 5 times)
// Probe counts per memory set:
// Adolescents:
// 1-letter sets: 30 probes each
// 3-letter sets: 50 probes each
// 5-letter sets: 50 probes each
// Adults:
// 2-pair sets: 30 probes each
// 4-pair sets: 65 probes each
// 6-pair sets: 65 probes each
```
### Response Handling (CRITICAL)
```javascript
// Response Method:
// - Two buttons: "Yes" and "No"
// - Position: Centered at bottom of screen
// - Always visible during probe display
// - Button styling: White border, white text on black background
// Response Logic:
// - Click "Yes" if probe was in memory set (Positive/Target)
// - Click "No" if probe was NOT in memory set (Negative/Non-Target)
// Response Window:
// - Adolescents: 6000ms (6 seconds) from probe onset
// - Adults: 4500ms (4.5 seconds) from probe onset
// - Accept ONLY first response (prevent double-clicks)
// - Highlight selected button with light blue border immediately
// Response Recording:
// - Record WHICH button pressed ("Yes" or "No")
// - Record reaction time (RT) from probe onset to button press
// - Record accuracy (1 = correct, 0 = incorrect)
// - Record timestamp of response
// Timeout Handling:
// - If no response within window → "Time is up!" message (1 second)
// - Record as: participantResponse = "No Response"
// - Record accuracy = 0 (incorrect)
// - Record reactionTime = null (do NOT include in RT calculations)
```
### Feedback Rules (PRACTICE ONLY)
```javascript
// Practice Phase Feedback:
1. Correct Response (Positive probe + "Yes" OR Negative probe + "No"):
→ Display: "Correct! You remembered it right."
→ Duration: 1 second
→ Style: White text, centered, bold
2. Incorrect Response (Positive probe + "No" OR Negative probe + "Yes"):
→ Display: "That's okay—try to remember the set carefully."
→ Duration: 1.5 seconds
→ Style: White text, centered, bold
3. No Response (timeout):
→ Display: "Please press your choice quickly!"
→ Duration: 1 second
→ Style: White text, centered, bold
→ Optional: Soft alert tone
// Practice Block Feedback (After each practice session):
// - If accuracy ≥ 70%:
// "Great work! You're getting the hang of it."
// Duration: 2 seconds
//
// - If accuracy < 70%:
// "Let's try again! Focus and respond a bit faster."
// Duration: 2 seconds
// Main Test: NO FEEDBACK shown to participants
// - Only "Time is up!" on timeout
// - Light blue border on selected button is the only visual confirmation
// - All performance tracking happens silently in background
```
### Visual Feedback
```javascript
// On Response:
// - Selected button ("Yes" or "No") gets light blue border immediately
// - Border style: ring-4 ring-blue-400 (Tailwind CSS)
// - Border remains visible during feedback/transition
// - Clear visual confirmation of button press
// Timeout Display:
// - Full screen message: "Time is up!"
// - White text, bold, centered on black background
// - Display for 1 second
// - Then proceed to next probe/trial
```
---
## 🎨 Design Requirements
### Visual Design Principles
- **Clean, simple, high-contrast** - black background throughout entire test
- **Responsive:** 345px to large screens (mobile-first design)
- **Minimal animations** - no distracting effects during memory/probe phases
- **High visibility:** Centered stimuli, clear buttons, large readable fonts
- **Age-appropriate design:**
- **Adolescent:** Encouraging, game-like language ("Memory Challenge Game")
- **Adult:** Professional, clinical language ("Memory Challenge Game")
### Technology Stack
- **Framework:** React with JavaScript (jsx)
- **Styling:** Tailwind CSS only (core utilities only - no custom compiler)
- **Animations:** Framer Motion (minimal use - fade transitions only)
- **State Management:** React Hooks (useState, useEffect, useRef, useCallback, useMemo)
- **Timing:** performance.now() or Date.now() for precise RT measurement
### Stimulus Display Specifications
```javascript
// Memory Set Item Display:
// - Position: Center of screen
// - Font size: text-5xl or text-6xl (large, readable)
// - Font weight: bold
// - Color: White (#FFFFFF)
// - Background: Black (#000000)
// - Display duration: 1.1s (adolescent) / 1.3s (adult)
// Adolescent Stimuli:
// - Single uppercase letters: A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
// - Font: Clean sans-serif (default system font)
// - Example: "A" or "K" or "R"
// Adult Stimuli:
// - Alphanumeric pairs: Letter (A-Z) + Digit (1-9)
// - Format: {Letter}{Digit} with NO space (e.g., "K7", "C9", "B3")
// - Font: Clean sans-serif (default system font)
// - Example: "K7" or "C9" or "R2"
// Probe Display:
// - Same styling as memory set items
// - Position: Center of screen
// - Remain visible for full response window (6s or 4.5s)
// - Disappear after response OR timeout
// Response Buttons:
// - Two buttons: "Yes" and "No"
// - Position: Centered horizontally at bottom of screen
// - Spacing: Adequate gap between buttons (minimum 20px)
// - Button styling:
// - Border: 2px solid white (border-2 border-white)
// - Background: Transparent or dark gray
// - Text: White, bold, large (text-xl)
// - Padding: px-8 py-4 (touch-friendly)
// - Border radius: rounded-lg
// - Hover effect: Slight scale or brightness change
// - Selected: ring-4 ring-blue-400 (light blue border)
// - Minimum touch target: 44x44px (accessibility)
```
### Animation Standards
```javascript
// Minimal animations to maintain task integrity:
// Fixation Cross:
// - Simple fade in/out (duration: 200ms)
// - No complex motion
// Memory Set Items:
// - Instant appearance (no fade/scale)
// - Sharp onset for precise encoding timing
// - Instant disappearance
// Probe Items:
// - Instant appearance (no fade/scale)
// - Sharp onset for RT measurement accuracy
// Feedback (Practice):
// - Gentle fade in (duration: 200ms)
// - Fade out before next trial (duration: 200ms)
// Screen Transitions:
// - Simple fade between screens (duration: 300ms)
// - No sliding, scaling, or complex animations
// Button Interactions:
// - Immediate highlight on press (no delay)
// - Subtle scale on hover (scale: 1.02)
// DO NOT USE:
// - Complex entry/exit animations during task
// - Parallax effects
// - Particle effects
// - Distracting motion that could interfere with memory encoding
```
---
## 📱 Screen Flow (Sequential Development)
### Development Order (ONE SCREEN AT A TIME)
#### 1. IntroScreen ✅
**Purpose:** Welcome screen, age selection, task overview
**Components needed:**
- Age group selector (14-18 vs 18-22 radio buttons or buttons)
- Task title and brief explanation
- "Begin Test" / "Start" button
- Welcome header and instructions
**Required files:**
- `components/screens/VPSM/IntroScreen.jsx`
- `constants/vpsmInstructions.js`
**Key content:**
- **Title:** "Working Memory Challenge Game" (adolescent) or "Working Memory Assessment" (adult)
- **Brief explanation:** What is working memory, what participants will do
- **Age selection:** Clear buttons or options for 14-18 vs 18-22
- **Next step:** Transition to detailed instructions
**Adolescent Introduction:**
```
"Welcome to the Memory Challenge Game!
You will see a set of letters appear on the screen one by one.
After a short pause, you will be shown a letter and need to decide
whether it was part of the set you just saw.
If you saw it before, press Yes; if not, press No.
Take your time and try to respond as quickly as you can.
Don't worry if it seems tricky at first - we'll start with a few
practice rounds to get you ready."
```
**Adult Introduction:**
```
"Welcome to the Memory Challenge Game!
You will see sequences of letter-number pairs (for example: A1, C3)
appear on the screen one by one.
After a few seconds, you will be shown a series of letter-number pairs
and need to decide if it was part of the sequence you just saw.
If you saw it before, press Yes; if not, press No.
This is just a practice round, so relax and get used to how the game works!"
```
---
#### 2. PracticeInstructionsScreen ✅
**Purpose:** Detailed task instructions before practice
**Components needed:**
- Detailed task explanation
- Visual examples (optional diagrams/illustrations)
- Step-by-step trial flow explanation
- "Let's Go!" / "Begin Practice" button
**Required files:**
- `components/screens/VPSM/PracticeInstructionsScreen.jsx`
**Instructions Content:**
**Adolescents (14-18):**
```
"How the Memory Game Works:
1. REMEMBER: You'll see letters appear one by one (like A... D... F).
Watch carefully and try to remember all of them!
2. WAIT: There will be a short pause after the letters disappear.
3. DECIDE: You'll see ONE letter at a time and must answer:
- Was this letter in the set you just saw?
- Press YES if it was in the set
- Press NO if it was NOT in the set
Example:
- Memory set: A, D, F
- Probe shows "D" → Press YES ✓ (D was in the set)
- Probe shows "G" → Press NO ✓ (G was NOT in the set)
The number of letters may increase as you go, making it more challenging!
Ready to practice? When you're ready, tap 'Let's Go!' below."
```
**Adults (18-22):**
```
"Task Instructions:
1. ENCODING PHASE:
You will see letter-number pairs presented sequentially
(e.g., K7 → C9 → R2)
Memorize each pair as it appears
2. RETENTION INTERVAL:
Brief pause (1 second) - maintain items in memory
3. RECOGNITION PHASE:
Individual pairs will be shown one at a time
Decide: "Was this pair in the memory set?"
- Press YES if the pair was present (Target)
- Press NO if the pair was absent (Non-Target)
Example:
- Memory set: K7, C9, R2
- Probe: C9 → Correct response: YES (Target)
- Probe: A1 → Correct response: NO (Non-Target)
The memory load will increase throughout the task (2, 4, or 6 pairs).
When ready to begin practice, press 'Let's Go!' below."
```
---
#### 3. PracticeScreen ✅
**Purpose:** Practice trials with feedback to learn the task
**Components needed:**
- Fixation cross display (+)
- Memory set item display (sequential presentation)
- Retention interval (blank screen)
- Probe item display
- Two response buttons (Yes/No)
- Feedback display (practice only)
- Trial counter ("Trial 1/20" or "Trial 1/25")
- Response detection and timing system
**Required files:**
- `components/screens/VPSM/PracticeScreen.jsx`
- `components/shared/VPSM/MemorySetDisplay.jsx` (sequential item presentation)
- `components/shared/VPSM/ProbeDisplay.jsx` (single item + Yes/No buttons)
- `components/shared/VPSM/ResponseButtons.jsx` (Yes/No buttons)
- `components/shared/VPSM/FeedbackDisplay.jsx` (practice feedback)
- `components/shared/VPSM/FixationCross.jsx` (white + symbol)
- `hooks/vpsm/usePracticeScreen.js`
- `utils/vpsmTimer.js`
**Practice Trials (EXACT sequence from Research PDF):**
**Adolescents (20 trials, 1-letter span: K):**
```javascript
const ADOLESCENT_PRACTICE_TRIALS = [
{ trial: 1, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 2, memorySet: ['K'], probe: 'A', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 3, memorySet: ['K'], probe: 'M', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 4, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 5, memorySet: ['K'], probe: 'R', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 6, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 7, memorySet: ['K'], probe: 'L', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 8, memorySet: ['K'], probe: 'B', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 9, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 10, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 11, memorySet: ['K'], probe: 'T', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 12, memorySet: ['K'], probe: 'C', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 13, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 14, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 15, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 16, memorySet: ['K'], probe: 'D', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 17, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 18, memorySet: ['K'], probe: 'S', type: 'Negative', correctResponse: 'No', responseTime: 6 },
{ trial: 19, memorySet: ['K'], probe: 'K', type: 'Positive', correctResponse: 'Yes', responseTime: 6 },
{ trial: 20, memorySet: ['K'], probe: 'F', type: 'Negative', correctResponse: 'No', responseTime: 6 }
];
```
**Adults (25 trials, 2-pair span: C9, B3):**
```javascript
const ADULT_PRACTICE_TRIALS = [
{ trial: 1, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 2, memorySet: ['C9', 'B3'], probe: 'A1', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 3, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 4, memorySet: ['C9', 'B3'], probe: 'D4', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 5, memorySet: ['C9', 'B3'], probe: 'F2', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 6, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 7, memorySet: ['C9', 'B3'], probe: 'H8', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 8, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 9, memorySet: ['C9', 'B3'], probe: 'K7', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 10, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 11, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 12, memorySet: ['C9', 'B3'], probe: 'L1', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 13, memorySet: ['C9', 'B3'], probe: 'D4', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 14, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 15, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 16, memorySet: ['C9', 'B3'], probe: 'F2', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 17, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 18, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 19, memorySet: ['C9', 'B3'], probe: 'H8', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 20, memorySet: ['C9', 'B3'], probe: 'A1', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 21, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 22, memorySet: ['C9', 'B3'], probe: 'B3', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 },
{ trial: 23, memorySet: ['C9', 'B3'], probe: 'K7', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 24, memorySet: ['C9', 'B3'], probe: 'D4', type: 'Negative', correctResponse: 'No', responseTime: 4.5 },
{ trial: 25, memorySet: ['C9', 'B3'], probe: 'C9', type: 'Positive', correctResponse: 'Yes', responseTime: 4.5 }
];
```
**Trial Flow (Complete Sequence):**
1. **Fixation Cross**
- Display: White "+" centered on black screen
- Duration: 300ms
- Purpose: Focus attention, prepare for encoding
2. **Memory Set Presentation** (CRITICAL - Sequential Display)
- Display each item ONE AT A TIME
- Adolescents: Each letter for 1.1 seconds
- Adults: Each alphanumeric pair for 1.3 seconds
- Items appear in sequence with NO overlap
- Example (3-letter): Show "A" (1.1s) → Show "F" (1.1s) → Show "R" (1.1s)
- Total encoding time = (number of items) × (display time per item)
3. **Retention Interval**
- Blank black screen
- Duration: 1 second (1000ms)
- Purpose: Active memory maintenance without external cues
4. **Probe Display + Response Window**
- Display: Single item centered + Yes/No buttons at bottom
- Adolescents: 6 seconds to respond
- Adults: 4.5 seconds to respond
- Accept ONLY first button press (prevent double-clicks)
- Highlight selected button with light blue border immediately
5. **Response Handling**
- If response given: Record button ("Yes"/"No"), RT, accuracy
- If timeout: Display "Time is up!" (1 second)
- Selected button shows light blue border
6. **Feedback Display (PRACTICE ONLY)**
- Correct: "Correct! You remembered it right." (1 second)
- Incorrect: "That's okay—try to remember the set carefully." (1.5 seconds)
- Timeout: "Please press your choice quickly!" (1 second, optional soft tone)
7. **Inter-trial Interval**
- Blank black screen
- Duration: 300ms
- Clear previous displays, prepare for next probe
8. **Next Probe or Next Memory Set**
- If more probes for current memory set: Go to step 1 (fixation for next probe)
- If all probes complete: Move to next memory set (start from step 1 with new memory set)
**Critical Rules:**
- Memory set shown ONCE at beginning, then all probes tested
- Show feedback after EACH probe trial in practice
- Track accuracy but don't show running score
- Exact timing is critical for valid RT measurement
---
#### 4. PracticeCompleteScreen ✅
**Purpose:** Transition from practice to main task
**Components needed:**
- Completion message
- Encouragement
- "Let's Go!" / "Begin Main Task" button
**Required files:**
- `components/screens/VPSM/PracticeCompleteScreen.jsx`
**Messages (from PDF):**
**Adolescents:**
```
"Great job finishing the practice! Now get ready for the real task.
Tap 'Let's Go!' below and the game begins!"
```
**Adults:**
```
"Great job finishing the practice! Now get ready for the real task.
Tap 'Let's Go!' below and the game begins!"
```
**Additional Information (Optional):**
- Don't show accuracy scores from practice
- Simple, encouraging transition
- Clear call-to-action button
---
#### 5. MainTestScreen ✅
**Purpose:** Main assessment - 15 memory sets across 5 triads
**Components needed:**
- All PracticeScreen components (except feedback display)
- NO feedback display (except timeout message)
- Progress tracking (Memory Set counter: "Set 1/15", optional probe counter)
- Data collection for all trials
- Continuous flow across all 15 memory sets
**Required files:**
- `components/screens/VPSM/MainTestScreen.jsx`
- `hooks/vpsm/useMainTestScreen.js`
- `utils/vpsmDataCollection.js`
- `constants/vpsmTrialSequences.js` (ALL main task trials from PDF)
**Main Task Structure:**
**Adolescents: 5 Triads, 15 Memory Sets, 650 Total Probes**
```javascript
// Triad 1 (Sets 1-3):
// Set 1: 1-letter (G) → 30 probes
// Set 2: 3-letter (A, F, R) → 50 probes
// Set 3: 5-letter (B, D, H, L, Q) → 50 probes
// Triad 2 (Sets 4-6):
// Set 4: 1-letter (E) → 30 probes
// Set 5: 3-letter (S, J, M) → 50 probes
// Set 6: 5-letter (F, N, I, R, V) → 50 probes
// Triad 3 (Sets 7-9):
// Set 7: 1-letter (K) → 30 probes
// Set 8: 3-letter (I, S, V) → 50 probes
// Set 9: 5-letter (B, X, E, S, O) → 50 probes
// Triad 4 (Sets 10-12):
// Set 10: 1-letter (U) → 30 probes
// Set 11: 3-letter (G, Q, T) → 50 probes
// Set 12: 5-letter (C, G, M, Q, W) → 50 probes
// Triad 5 (Sets 13-15):
// Set 13: 1-letter (M) → 30 probes
// Set 14: 3-letter (B, W, L) → 50 probes
// Set 15: 5-letter (H, L, P, T, Z) → 50 probes
// Total: (5 × 30) + (5 × 50) + (5 × 50) = 150 + 250 + 250 = 650 probes
```
**Adults: 5 Triads, 15 Memory Sets, 800 Total Probes**
```javascript
// Triad 1 (Sets 1-3):
// Set 1: 2-pair (B1, D3) → 30 probes
// Set 2: 4-pair (H6, J4, M2, R8) → 65 probes
// Set 3: 6-pair (F5, K9, L7, P3, T2, U6) → 65 probes
// Triad 2 (Sets 4-6):
// Set 4: 2-pair (C2, F4) → 30 probes
// Set 5: 4-pair (L8, Q1, G5, S3) → 65 probes
// Set 6: 6-pair (A7, D9, R6, U2, K3, V4) → 65 probes
// Triad 3 (Sets 7-9):
// Set 7: 2-pair (G1, E7) → 30 probes
// Set 8: 4-pair (N6, T4, P7, H9) → 65 probes
// Set 9: 6-pair (B5, C8, F2, J6, W3, Z1) → 65 probes
// Triad 4 (Sets 10-12):
// Set 10: 2-pair (J5, H2) → 30 probes
// Set 11: 4-pair (M8, Q5, K4, S7) → 65 probes
// Set 12: 6-pair (A3, C6, G8, L9, P2, Y5) → 65 probes
// Triad 5 (Sets 13-15):
// Set 13: 2-pair (K6, N3) → 30 probes
// Set 14: 4-pair (E4, G7, R1, T6) → 65 probes
// Set 15: 6-pair (B8, D2, F9, H5, X4, Z7) → 65 probes
// Total: (5 × 30) + (5 × 65) + (5 × 65) = 150 + 325 + 325 = 800 probes
```
**Main Task Instructions (Displayed before main task begins):**
**Adolescents:**
```
"Now it's time for the full game!
You will see a set of letters appear on the screen one by one.
After a short pause, you will see a series of letters and need to
decide whether it was part of the set you just saw.
Use the Yes or No buttons to make your choice.
The number of letters may gradually increase, making the game more challenging.
Stay sharp and have fun!"
```
**Adults:**
```
"Now it's time for the full game!
You will see a set of letter-number pairs appear on the screen one by one.
After a short pause, you will see a series of letter-number pairs and need
to decide whether it was part of the set you just saw.
Use the Yes or No buttons to make your choice.
The number of pairs may gradually increase, making the game more challenging.
Stay sharp and have fun!"
```
**Trial Flow (Same as practice, minus feedback):**
1. Fixation Cross (+): 300ms
2. Memory Set Presentation: Sequential items (1.1s or 1.3s each)
3. Retention Interval: 1 second blank screen
4. Probe Display + Buttons: 6s or 4.5s response window
5. Response Handling:
- Button press: Light blue border on selected button (only visual confirmation)
- Timeout: "Time is up!" (1 second)
6. Inter-trial Interval: 300ms black screen
7. Next Probe: Repeat steps 1-6 for all probes of current memory set
8. Next Memory Set: After all probes complete, move to next set
**Critical Differences from Practice:**
- NO feedback shown (except "Time is up!" on timeout)
- Light blue border is the ONLY response confirmation
- Track all metrics silently in background
- Show memory set progress (e.g., "Memory Set 3/15")
- Optional: Show probe progress within set (e.g., "Probe 12/50")
- Continuous flow - no breaks between sets unless designed
**Data Collection (Silent - No Display):**
- Record every probe trial response
- Calculate accuracy per memory set
- Calculate RT per memory set
- Track performance by span size (1/3/5 or 2/4/6)
- Identify patterns (speed-accuracy tradeoff, memory capacity limits)
---
#### 6. ResultsScreen ✅
**Purpose:** Display performance summary and export data
**Components needed:**
- Performance metrics display
- Accuracy breakdown (overall, by span size)
- Reaction time statistics (overall, by span size)
- Memory capacity analysis
- Data export functionality (JSON + CSV)
- Restart/Continue option
**Required files:**
- `components/screens/VPSM/ResultsScreen.jsx`
- `components/shared/VPSM/MetricsCard.jsx`
- `utils/vpsmCalculations.js`
- `utils/vpsmDataExport.js`
**Metrics to Calculate (from PDF Scoring Manual):**
```javascript
// RAW COUNTS:
// - Total Probe Trials: 650 (adolescent) or 800 (adult)
// - Total Rounds Answered: Count of trials with response
// - Total Rounds Not Answered: Count of timeouts
// - Correct Responses: Sum of trials with score = 1
// - Incorrect Responses: Sum of trials with score = 0
// ACCURACY METRICS (Percentage):
// Overall Accuracy:
// (Correct Responses / Total Probe Trials) × 100
// Accuracy by Span Size:
// Adolescents:
// 1-Letter Accuracy: (Correct 1-letter / Total 1-letter) × 100
// 3-Letter Accuracy: (Correct 3-letter / Total 3-letter) × 100
// 5-Letter Accuracy: (Correct 5-letter / Total 5-letter) × 100
// Adults:
// 2-Pair Accuracy: (Correct 2-pair / Total 2-pair) × 100
// 4-Pair Accuracy: (Correct 4-pair / Total 4-pair) × 100
// 6-Pair Accuracy: (Correct 6-pair / Total 6-pair) × 100
// REACTION TIME METRICS (Milliseconds):
// CRITICAL: Calculate RT ONLY for correctly answered trials
// Overall Mean RT:
// Average RT across ALL correct responses
// Mean RT by Span Size:
// Adolescents:
// 1-Letter Mean RT: Average RT for correct 1-letter trials
// 3-Letter Mean RT: Average RT for correct 3-letter trials
// 5-Letter Mean RT: Average RT for correct 5-letter trials
// Adults:
// 2-Pair Mean RT: Average RT for correct 2-pair trials
// 4-Pair Mean RT: Average RT for correct 4-pair trials
// 6-Pair Mean RT: Average RT for correct 6-pair trials
// MEMORY SPAN ANALYSIS:
// Working Memory Capacity Estimate:
// Highest span size where accuracy ≥ 75%
// Example: If 3-letter accuracy = 82% but 5-letter accuracy = 68%
// → Estimated capacity = 3 items
// RT Slope Analysis:
// Measure increase in RT as memory load increases
// Slope = (RT_large - RT_small) / (span_large - span_small)
// Example: (RT_5letter - RT_1letter) / (5 - 1)
// Indicates search strategy: Serial vs. Parallel processing
// ADDITIONAL METRICS:
// Response Bias:
// Proportion of "Yes" responses (should be ~50% if no bias)
// YesBias = (Total "Yes" / Total Responses) × 100
// Timeout Rate:
// (Total Timeouts / Total Trials) × 100
```
**Completion Messages (from PDF):**
**Adolescents:**
```
"Awesome work! You've completed this challenge — stay sharp,
the next one is coming up!"
```
**Adults:**
```
"Well done! You've successfully finished this task —
let's move on to the next part."
```
**Display Format:**
```javascript
// Results Screen Layout:
// 1. COMPLETION MESSAGE (top)
// Age-appropriate message
// 2. OVERALL PERFORMANCE CARD
// - Total Trials: 650 or 800
// - Total Correct: XXX
// - Overall Accuracy: XX.X%
// - Overall Mean RT: XXXms
// 3. PERFORMANCE BY SPAN SIZE (3 cards side-by-side)
// Adolescents:
// [1-Letter] [3-Letter] [5-Letter]
// Adults:
// [2-Pair] [4-Pair] [6-Pair]
//
// Each card shows:
// - Trials: XX
// - Correct: XX
// - Accuracy: XX.X%
// - Mean RT: XXXms
// 4. WORKING MEMORY CAPACITY ESTIMATE
// - Display highest span with ≥75% accuracy
// - Simple interpretation message
// - Example: "Your working memory capacity is approximately 4-5 items"
// 5. RT SLOPE ANALYSIS (Optional - Advanced)
// - Graph or text showing RT increase with memory load
// - Interpretation: Serial vs. Parallel search strategy
// 6. DATA EXPORT SECTION
// - "Download Results (JSON)" button
// - "Download Results (CSV)" button
// - Timestamp and filename generation
// 7. NAVIGATION BUTTONS
// - "Restart Test" (go back to intro)
// - "Next Assessment" (continue to next test in battery)
```
**Interpretation Guidance:**
```javascript
// Accuracy Interpretation:
// - ≥85%: Excellent working memory
// - 70-84%: Good working memory
// - 60-69%: Average working memory
// - <60%: May indicate difficulties with working memory
// RT Interpretation:
// - Faster RT with high accuracy: Efficient processing
// - Slower RT with high accuracy: Careful, accurate processing
// - Faster RT with low accuracy: Impulsive responding
// - Slower RT with low accuracy: Processing difficulties
// Span Analysis:
// - Accuracy decreases with larger spans: Normal pattern
// - RT increases with larger spans: Normal serial search pattern
// - Flat RT across spans: Possible parallel processing (rare)
// Capacity Estimate:
// Adolescents:
// - 1-letter capacity: Below average
// - 3-letter capacity: Average
// - 5-letter capacity: Above average
// Adults:
// - 2-pair capacity: Below average
// - 4-pair capacity: Average
// - 6-pair capacity: Above average
```
---
## 📁 File Structure Requirements
### Project Organization
```
src/
├── components/
│ ├── screens/
│ │ └── VPSM/
│ │ ├── IntroScreen.jsx
│ │ ├── PracticeInstructionsScreen.jsx
│ │ ├── PracticeScreen.jsx
│ │ ├── PracticeCompleteScreen.jsx
│ │ ├── MainTestScreen.jsx
│ │ ├── ResultsScreen.jsx
│ │ └── SternbergTask.jsx (main orchestrator)
│ └── shared/
│ └── VPSM/
│ ├── MemorySetDisplay.jsx (sequential item presentation)
│ ├── ProbeDisplay.jsx (single item display)
│ ├── ResponseButtons.jsx (Yes/No buttons)
│ ├── FeedbackDisplay.jsx (practice feedback)
│ ├── FixationCross.jsx (white + symbol)
│ ├── TrialCounter.jsx (e.g., "Set 5/15", "Probe 12/50")
│ └── MetricsCard.jsx (results display)
├── hooks/
│ └── vpsm/
│ ├── usePracticeScreen.js
│ └── useMainTestScreen.js
├── utils/
│ ├── vpsmTimer.js (timing management)
│ ├── vpsmDataCollection.js (trial data recording)
│ ├── vpsmCalculations.js (accuracy, RT, capacity analysis)
│ ├── vpsmDataExport.js (JSON/CSV export)
│ └── vpsmAnimations.js (minimal Framer Motion)
├── constants/
│ ├── vpsmConfig.js (timing, spans, response windows)
│ ├── vpsmInstructions.js (all text content)
│ └── vpsmTrialSequences.js (all practice + main trials from PDF)
└── public/
└── images/
└── vpsm/
└── (optional instruction diagrams)
```
---
## 🚫 Important Constraints
### NEVER Do This
1. ❌ Show all memory set items simultaneously (must be sequential)
2. ❌ Randomize trial order (must follow PDF sequences exactly)
3. ❌ Show feedback during main test (except timeout message)
4. ❌ Allow response before probe appears
5. ❌ Allow more than 6s/4.5s probe response window
6. ❌ Skip practice phase
7. ❌ Accept response after time window expires
8. ❌ Calculate RT for trials without responses or incorrect responses
9. ❌ Use localStorage or sessionStorage for critical data
10. ❌ Create complex distracting animations during encoding/probe phases
11. ❌ Show running score/accuracy during main test
12. ❌ Mix probe types from different memory sets
13. ❌ Present retention interval for less than 1 second
14. ❌ Include timeout trials in RT mean calculations
### ALWAYS Do This
1. ✅ Present memory set items sequentially (ONE AT A TIME)
2. ✅ Follow exact trial sequences from PDF (all practice + main trials)
3. ✅ Implement precise timing (fixation, encoding, retention, probe)
4. ✅ Show feedback ONLY during practice phase
5. ✅ Use light blue border for button selection highlight
6. ✅ Display "Time is up!" on timeout (1 second)
7. ✅ Present items in WHITE text on BLACK background
8. ✅ Keep Yes/No buttons visible at bottom throughout probe display
9. ✅ Track all metrics silently during main test
10. ✅ Calculate accuracy across all trials (including timeouts as incorrect)
11. ✅ Calculate RT ONLY for correct responses
12. ✅ Use black background throughout entire test
13. ✅ Implement age-specific response times (6s vs 4.5s)
14. ✅ Analyze performance by memory span size
15. ✅ Estimate working memory capacity from accuracy patterns
16. ✅ Complete all probes for a memory set before moving to next set
17. ✅ Show memory set once, then test all probes sequentially
---
## 🔧 Development Workflow
### Step-by-Step Process
1. **Current Phase:** Developer specifies which screen to create
2. **AI Creates:** Complete screen with all required files and components
3. **AI Asks:** "Screen [Name] complete. Proceed to [NextScreen]?"
4. **Developer:** Approves or requests changes
5. **Repeat:** Until all 6 screens are complete
### Code Quality Standards
- Use functional components with hooks
- Separate concerns (logic, UI, data, timing)
- Add detailed comments for complex timing logic
- Follow consistent naming conventions
- Use Tailwind for ALL styling (core utilities only)
- Handle edge cases (timeout, rapid clicking, double-tap)
- Create reusable components (memory display, probe display)
- Optimize re-renders with useMemo/useCallback
- Precise timing with useRef for timestamps
- Clean up all timeouts/intervals on component unmount
### State Management Pattern
```javascript
// Main App State (useContext or props)
const [testState, setTestState] = useState({
currentScreen: 'intro',
// 'intro' | 'practiceInstructions' | 'practice' |
// 'practiceComplete' | 'mainTest' | 'results'
ageGroup: null, // 'adolescent' | 'adult'
phase: 'practice', // 'practice' | 'main'
currentMemorySetIndex: 0, // 0-14 (15 memory sets in main task)
currentProbeIndex: 0, // Index within current memory set's probes
practiceData: [], // All practice trial records
mainTestData: [] // All main test trial records
});
// Per-Screen State (Practice/Main Test)
const [memorySetState, setMemorySetState] = useState({
// Memory Set Encoding Phase
showFixation: false,
encodingPhase: false,
currentEncodingItem: null, // Current item being displayed
encodingItemIndex: 0, // Index in memory set (0 to span-1)
memorySet: [], // Full memory set (e.g., ['A', 'D', 'F'])
// Retention Phase
retentionPhase: false,
// Probe Phase
probePhase: false,
currentProbe: null, // { probe, type, correctResponse }
probeStartTime: null,
// Response Phase
responseGiven: false,
selectedButton: null, // 'Yes' | 'No' | null
responseTime: null,
// Feedback Phase (practice only)
showFeedback: false,
feedbackMessage: null
});
```
---
## 📊 Data Recording Requirements
### Trial Data Structure
Every probe trial must record:
```javascript
{
// Trial Identification
roundNumber: number, // Sequential across entire test (1-670 or 1-825)
phase: 'practice' | 'main',
trialNumber: number, // Within phase (1-20/25 practice, 1-650/800 main)
// Memory Set Information
memorySetNumber: number, // 1-15 (main task only)
triadNumber: number, // 1-5 (main task only)
memorySet: string[], // e.g., ['A', 'D', 'F'] or ['K7', 'C9']
memorySetSize: number, // 1/3/5 or 2/4/6 (span size)
// Probe Information
probeNumber: number, // 1-N within current memory set
probe: string, // e.g., 'D' or 'K7'
probeType: 'Positive' | 'Negative', // Target or Non-Target
// Correct Response
correctResponse: 'Yes' | 'No',
// Participant Response
participantResponse: 'Yes' | 'No' | 'No Response',
responseAccuracy: 0 | 1, // 1 = correct, 0 = incorrect/timeout
reactionTime: number | null, // ms from probe onset (null if timeout)
// Timestamps
timestamp: number, // Trial start time (Date.now())
probeOnsetTimestamp: number, // Exact probe display time
responseTimestamp: number | null // Exact button press time (null if timeout)
}
```
### Data Export Format
```javascript
// Export as both JSON and CSV
{
participantInfo: {
ageGroup: 'adolescent' | 'adult',
testDate: string, // ISO format
testStartTime: string,
testEndTime: string,
totalDuration: number // seconds
},
summary: {
// Overall Counts
totalProbeTrials: 650 | 800,
totalRoundsAnswered: number,
totalRoundsNotAnswered: number,
correctResponses: number,
incorrectResponses: number,
// Overall Performance
overallAccuracy: number, // percentage (1 decimal)
overallMeanRT: number, // milliseconds (rounded)
// Performance by Span Size
spanPerformance: {
// Adolescents:
span1: {
totalTrials: 150, // 5 sets × 30 probes
correct: number,
incorrect: number,
accuracy: number, // percentage
meanRT: number // ms (only correct trials)
},
span3: {
totalTrials: 250, // 5 sets × 50 probes
correct: number,
incorrect: number,
accuracy: number,
meanRT: number
},
span5: {
totalTrials: 250, // 5 sets × 50 probes
correct: number,
incorrect: number,
accuracy: number,
meanRT: number
}
// Adults:
// span2, span4, span6 (same structure)
},
// Working Memory Analysis
estimatedCapacity: number, // Highest span with ≥75% accuracy
rtSlope: number, // ms per item increase
responseBias: number, // % "Yes" responses (should be ~50%)
timeoutRate: number // % trials with timeout
},
mainTestData: [/* all 650 or 800 main trial records */],
practiceData: [/* all 20 or 25 practice trial records */]
}
```
### CSV Export Columns
```javascript
// CSV Headers (match PDF scoring manual):
"Round Number",
"Memory Set Size",
"Probe Item",
"Probe Type",
"Participant Response",
"Response Accuracy",
"Reaction Time (ms)"
// Example rows:
// 1, 1, G, Positive, Yes, 1, 1250
// 2, 1, A, Negative, No, 1, 980
// 3, 1, G, Positive, Yes, 1, 1100
```
---
## 🎭 Animation Specifications
### Framer Motion Animations (utils/vpsmAnimations.js)
```javascript
// Minimal animations to maintain task integrity and timing precision
export const fadeIn = {
initial: { opacity: 0 },
animate: { opacity: 1 },
transition: { duration: 0.3 }
};
export const fixationFade = {
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.15 }
};
export const feedbackAppear = {
initial: { opacity: 0, scale: 0.95 },
animate: { opacity: 1, scale: 1 },
transition: { duration: 0.2 }
};
export const buttonHighlight = {
initial: { scale: 1 },
animate: { scale: 1.02 },
transition: { duration: 0.1 }
};
// NO animations during memory set encoding or probe display
// Sharp, instant appearance/disappearance for accurate timing
// Keep focus on memory task, not visual effects
```
---
## 🎯 Trial Timing Flow (CRITICAL)
### Complete Memory Set + Probe Cycle
```javascript
// FOR EACH MEMORY SET (15 total in main task):
// ===== ENCODING PHASE =====
1. Fixation Cross (300ms)
- White "+" centered on black screen
- Prepare attention for memory encoding
2. Memory Item Display (Sequential)
- Display FIRST item: 1.1s (adolescent) or 1.3s (adult)
- Display SECOND item: 1.1s or 1.3s
- Display THIRD item: 1.1s or 1.3s
- ... (continue for all items in memory set)
- Total encoding time = (span size) × (item duration)
Examples:
- 1-letter (G): 1 × 1.1s = 1.1s total
- 3-letter (A,F,R): 3 × 1.1s = 3.3s total
- 5-letter (B,D,H,L,Q): 5 × 1.1s = 5.5s total
- 2-pair (C9,B3): 2 × 1.3s = 2.6s total
- 4-pair (H6,J4,M2,R8): 4 × 1.3s = 5.2s total
- 6-pair (F5,K9,L7,P3,T2,U6): 6 × 1.3s = 7.8s total
3. Retention Interval (1000ms)
- Blank black screen
- Participant holds memory set in mind
- No external cues - pure working memory maintenance
// ===== PROBE TESTING PHASE (Repeat for ALL probes) =====
FOR EACH PROBE in current memory set:
4. Fixation Cross (300ms)
- Prepare for next probe
5. Probe Display + Response Window
- Display: Single item (probe) + Yes/No buttons
- Duration: 6s (adolescent) or 4.5s (adult)
- Wait for response OR timeout
If Response:
- Record button press ("Yes" or "No")
- Highlight button with light blue border
- Calculate RT (response timestamp - probe onset timestamp)
- Determine accuracy (correct = 1, incorrect = 0)
If Timeout:
- Display "Time is up!" (1 second)
- Record: participantResponse = "No Response"
- Record: accuracy = 0, RT = null
6. Feedback (PRACTICE ONLY)
- Correct: "Correct! You remembered it right." (1s)
- Incorrect: "That's okay—try to remember the set carefully." (1.5s)
- Timeout: "Please press your choice quickly!" (1s)
- Main test: SKIP (no feedback except timeout message)
7. Inter-trial Interval (300ms)
- Blank black screen
- Clear displays, prepare for next probe
8. NEXT PROBE
- Go to step 4 (fixation for next probe)
- Continue until all probes for this memory set complete
// ===== NEXT MEMORY SET =====
9. After all probes complete:
- Return to step 1 (fixation for new memory set encoding)
- Load next memory set from triad sequence
- Continue until all 15 memory sets complete
// Total Time Estimates:
// Adolescent (650 probes):
// - Average trial: ~8-10 seconds
// - Total test: ~90-100 minutes
// Adult (800 probes):
// - Average trial: ~7-9 seconds
// - Total test: ~90-120 minutes
```
### Timeout Handling
```javascript
// If no response within probe window (6s or 4.5s):
1. Cancel probe display
2. Show "Time is up!" message
- Full screen, white text, bold, centered
- Display for 1 second
3. Record trial as:
- participantResponse: "No Response"
- responseAccuracy: 0 (incorrect)
- reactionTime: null (NOT recorded)
4. Practice only: Show timeout feedback
5. Inter-trial interval (300ms)
6. Proceed to next probe
// Important: Do NOT count timeouts in RT calculations
// Only include trials with actual responses in RT means
```
---
## 📋 Scoring Logic (CRITICAL)
### Response Classification
```javascript
// CORRECT RESPONSE (score = 1):
// Positive Probe + "Yes":
if (probeType === 'Positive' && participantResponse === 'Yes') {
responseAccuracy = 1;
correctResponses++;
// Record reaction time
reactionTime = responseTimestamp - probeOnsetTimestamp;
// Add to RT array for span-specific analysis
rtsBySpan[memorySetSize].push(reactionTime);
}
// Negative Probe + "No":
if (probeType === 'Negative' && participantResponse === 'No') {
responseAccuracy = 1;
correctResponses++;
// Record reaction time
reactionTime = responseTimestamp - probeOnsetTimestamp;
rtsBySpan[memorySetSize].push(reactionTime);
}
// INCORRECT RESPONSE (score = 0):
// Positive Probe + "No" (Miss):
if (probeType === 'Positive' && participantResponse === 'No') {
responseAccuracy = 0;
incorrectResponses++;
// Do NOT record RT
}
// Negative Probe + "Yes" (False Alarm):
if (probeType === 'Negative' && participantResponse === 'Yes') {
responseAccuracy = 0;
incorrectResponses++;
// Do NOT record RT
}
// Timeout (No Response):
if (participantResponse === 'No Response') {
responseAccuracy = 0;
incorrectResponses++;
reactionTime = null;
// Do NOT record RT
}
```
### Accuracy Calculations
```javascript
// Overall Accuracy:
overallAccuracy = (totalCorrect / totalProbeTrials) × 100;
// Example: (585 / 650) × 100 = 90.0%
// Accuracy by Span Size:
// Adolescents:
span1Accuracy = (correctSpan1 / totalSpan1Trials) × 100;
// Example: (142 / 150) × 100 = 94.7%
span3Accuracy = (correctSpan3 / totalSpan3Trials) × 100;
// Example: (218 / 250) × 100 = 87.2%
span5Accuracy = (correctSpan5 / totalSpan5Trials) × 100;
// Example: (192 / 250) × 100 = 76.8%
// Adults: Same logic for span2, span4, span6
// Expected Pattern:
// - Accuracy should DECREASE as span size increases
// - This demonstrates working memory capacity limits
// - Flat accuracy across spans may indicate guessing or issues
```
### Reaction Time Calculations
```javascript
// CRITICAL: Only include CORRECT responses in RT calculations
// Overall Mean RT:
const correctTrialsWithRT = allTrials.filter(t =>
t.responseAccuracy === 1 && t.reactionTime !== null
);
overallMeanRT = sum(correctTrialsWithRT.map(t => t.reactionTime)) / correctTrialsWithRT.length;
// Mean RT by Span Size:
const span1CorrectRTs = allTrials
.filter(t => t.memorySetSize === 1 && t.responseAccuracy === 1 && t.reactionTime !== null)
.map(t => t.reactionTime);
span1MeanRT = sum(span1CorrectRTs) / span1CorrectRTs.length;
// Repeat for span3, span5 (or span2, span4, span6 for adults)
// Example Results:
// Span 1: Mean RT = 980ms
// Span 3: Mean RT = 1350ms
// Span 5: Mean RT = 1680ms
// Expected Pattern:
// - RT should INCREASE as span size increases
// - Indicates serial exhaustive search through memory
// - Slope of ~40-60ms per item is typical
```
### Working Memory Capacity Estimation
```javascript
// Determine highest span size with accuracy ≥ 75%
function estimateCapacity(spanPerformance) {
const spans = Object.keys(spanPerformance).sort((a, b) =>
parseInt(a.replace('span', '')) - parseInt(b.replace('span', ''))
);
let estimatedCapacity = 0;
for (const span of spans) {
const spanSize = parseInt(span.replace('span', ''));
if (spanPerformance[span].accuracy >= 75) {
estimatedCapacity = spanSize;
} else {
break; // Stop at first span below threshold
}
}
return estimatedCapacity;
}
// Example:
// Span 1: 95% accuracy → Capacity ≥ 1
// Span 3: 87% accuracy → Capacity ≥ 3
// Span 5: 68% accuracy → Capacity = 3 (stopped before 5)
// Estimated Capacity: 3-4 items
// Interpretation:
// Adolescents:
// 1 item: Below average working memory
// 3 items: Average working memory (typical)
// 5 items: Above average working memory
// Adults:
// 2 pairs: Below average
// 4 pairs: Average (typical)
// 6 pairs: Above average
```
### RT Slope Analysis
```javascript
// Calculate rate of RT increase per memory item
function calculateRTSlope(spanPerformance) {
const spans = Object.keys(spanPerformance).map(s => ({
size: parseInt(s.replace('span', '')),
rt: spanPerformance[s].meanRT
})).filter(s => s.rt !== null);
// Simple linear regression or two-point calculation
// Using smallest and largest spans:
const smallSpan = spans[0];
const largeSpan = spans[spans.length - 1];
const slope = (largeSpan.rt - smallSpan.rt) / (largeSpan.size - smallSpan.size);
return Math.round(slope);
}
// Example:
// 1-letter: 980ms
// 5-letter: 1680ms
// Slope = (1680 - 980) / (5 - 1) = 700 / 4 = 175ms per item
// Interpretation:
// - 30-60ms/item: Fast serial search or parallel processing
// - 60-100ms/item: Typical serial exhaustive search
// - >100ms/item: Slower processing, potential difficulties
```
### Response Bias Detection
```javascript
// Check for response bias (should be ~50% "Yes" responses)
function calculateResponseBias(trials) {
const responsesGiven = trials.filter(t => t.participantResponse !== 'No Response');
const yesResponses = responsesGiven.filter(t => t.participantResponse === 'Yes').length;
const yesBias = (yesResponses / responsesGiven.length) × 100;
return Math.round(yesBias * 10) / 10; // 1 decimal
}
// Interpretation:
// - 45-55%: No significant bias (ideal)
// - >60%: Liberal bias (tendency to say "Yes")
// - <40%: Conservative bias (tendency to say "No")
// Note: Since probe types are balanced ~50/50,
// healthy performance should show ~50% "Yes" responses
```
---
## 🔧 Key Constants to Define
### vpsmConfig.js
```javascript
export const VPSM_CONFIG = {
// Test Structure
PRACTICE_TRIALS_ADOLESCENT: 20,
PRACTICE_TRIALS_ADULT: 25,
MAIN_MEMORY_SETS: 15,
TRIADS: 5,
// Span Sizes
ADOLESCENT_SPANS: [1, 3, 5], // letters
ADULT_SPANS: [2, 4, 6], // alphanumeric pairs
// Probe Counts (per memory set)
ADOLESCENT_PROBES: {
span1: 30,
span3: 50,
span5: 50
},
ADULT_PROBES: {
span2: 30,
span4: 65,
span6: 65
},
// Total Probe Counts
TOTAL_PROBES_ADOLESCENT: 650, // (5 × 30) + (5 × 50) + (5 × 50)
TOTAL_PROBES_ADULT: 800, // (5 × 30) + (5 × 65) + (5 × 65)
// Timing (milliseconds)
TIMING: {
FIXATION_DURATION: 300,
MEMORY_ITEM_DURATION_ADOLESCENT: 1100,
MEMORY_ITEM_DURATION_ADULT: 1300,
RETENTION_INTERVAL: 1000,
PROBE_RESPONSE_WINDOW_ADOLESCENT: 6000,
PROBE_RESPONSE_WINDOW_ADULT: 4500,
FEEDBACK_DURATION_CORRECT: 1000,
FEEDBACK_DURATION_INCORRECT: 1500,
TIMEOUT_MESSAGE_DURATION: 1000,
INTER_TRIAL_INTERVAL: 300
},
// UI Constants
BUTTON_HIGHLIGHT_COLOR: 'ring-blue-400',
BACKGROUND_COLOR: 'black',
TEXT_COLOR: 'white',
STIMULUS_FONT_SIZE: 'text-5xl',
BUTTONS: ['Yes', 'No'],
// Probe Types
PROBE_TYPES: {
POSITIVE: 'Positive', // Target - was in memory set
NEGATIVE: 'Negative' // Non-Target - was NOT in memory set
},
// Capacity Estimation
CAPACITY_THRESHOLD: 75, // % accuracy threshold for capacity estimate
// Response Bias Thresholds
BIAS_THRESHOLDS: {
LIBERAL_CUTOFF: 60, // >60% "Yes" = liberal bias
CONSERVATIVE_CUTOFF: 40 // <40% "Yes" = conservative bias
}
};
```
### vpsmCalculations.js
```javascript
// Purpose: Calculate all performance metrics from trial data
export const calculateVpsmMetrics = (trialData, ageGroup) => {
// Filter main test trials only (exclude practice)
const mainTrials = trialData.filter(t => t.phase === 'main');
// Determine spans based on age group
const spans = ageGroup === 'adolescent'
? [1, 3, 5]
: [2, 4, 6];
// Count responses
const totalRoundsAnswered = mainTrials.filter(
t => t.participantResponse !== 'No Response'
).length;
const totalRoundsNotAnswered = mainTrials.filter(
t => t.participantResponse === 'No Response'
).length;
// Count correct/incorrect
const correctResponses = mainTrials.filter(
t => t.responseAccuracy === 1
).length;
const incorrectResponses = mainTrials.filter(
t => t.responseAccuracy === 0
).length;
// Calculate overall accuracy
const overallAccuracy = (correctResponses / mainTrials.length) * 100;
// Calculate overall mean RT (correct responses only)
const correctRTs = mainTrials
.filter(t => t.responseAccuracy === 1 && t.reactionTime !== null)
.map(t => t.reactionTime);
const overallMeanRT = correctRTs.length > 0
? correctRTs.reduce((sum, rt) => sum + rt, 0) / correctRTs.length
: null;
// Calculate performance by span size
const spanPerformance = {};
spans.forEach(span => {
const spanTrials = mainTrials.filter(t => t.memorySetSize === span);
const spanCorrect = spanTrials.filter(t => t.responseAccuracy === 1);
const spanRTs = spanCorrect
.filter(t => t.reactionTime !== null)
.map(t => t.reactionTime);
spanPerformance[`span${span}`] = {
totalTrials: spanTrials.length,
correct: spanCorrect.length,
incorrect: spanTrials.length - spanCorrect.length,
accuracy: (spanCorrect.length / spanTrials.length) * 100,
meanRT: spanRTs.length > 0
? spanRTs.reduce((sum, rt) => sum + rt, 0) / spanRTs.length
: null
};
});
// Estimate working memory capacity
let estimatedCapacity = 0;
for (const span of spans) {
if (spanPerformance[`span${span}`].accuracy >= 75) {
estimatedCapacity = span;
} else {
break;
}
}
// Calculate RT slope
const spanWithRTs = spans
.map(span => ({
size: span,
rt: spanPerformance[`span${span}`].meanRT
}))
.filter(s => s.rt !== null);
let rtSlope = null;
if (spanWithRTs.length >= 2) {
const smallest = spanWithRTs[0];
const largest = spanWithRTs[spanWithRTs.length - 1];
rtSlope = (largest.rt - smallest.rt) / (largest.size - smallest.size);
}
// Calculate response bias
const responsesGiven = mainTrials.filter(
t => t.participantResponse !== 'No Response'
);
const yesResponses = responsesGiven.filter(
t => t.participantResponse === 'Yes'
).length;
const responseBias = (yesResponses / responsesGiven.length) * 100;
// Calculate timeout rate
const timeoutRate = (totalRoundsNotAnswered / mainTrials.length) * 100;
return {
// Overall Counts
totalProbeTrials: mainTrials.length,
totalRoundsAnswered,
totalRoundsNotAnswered,
correctResponses,
incorrectResponses,
// Overall Performance
overallAccuracy: Math.round(overallAccuracy * 10) / 10,
overallMeanRT: overallMeanRT ? Math.round(overallMeanRT) : null,
// Span-Specific Performance
spanPerformance: Object.fromEntries(
Object.entries(spanPerformance).map(([key, value]) => [
key,
{
...value,
accuracy: Math.round(value.accuracy * 10) / 10,
meanRT: value.meanRT ? Math.round(value.meanRT) : null
}
])
),
// Working Memory Analysis
estimatedCapacity,
rtSlope: rtSlope ? Math.round(rtSlope) : null,
responseBias: Math.round(responseBias * 10) / 10,
timeoutRate: Math.round(timeoutRate * 10) / 10
};
};
// Interpretation helpers
export const interpretCapacity = (capacity, ageGroup) => {
if (ageGroup === 'adolescent') {
if (capacity >= 5) return 'Above average working memory capacity';
if (capacity >= 3) return 'Average working memory capacity';
if (capacity >= 1) return 'Below average working memory capacity';
return 'Difficulty with working memory tasks';
} else {
if (capacity >= 6) return 'Above average working memory capacity';
if (capacity >= 4) return 'Average working memory capacity';
if (capacity >= 2) return 'Below average working memory capacity';
return 'Difficulty with working memory tasks';
}
};
export const interpretRTSlope = (slope) => {
if (slope === null) return 'Insufficient data';
if (slope < 60) return 'Fast serial search or possible parallel processing';
if (slope < 100) return 'Typical serial exhaustive search pattern';
return 'Slower processing - may indicate working memory difficulties';
};
export const interpretResponseBias = (bias) => {
if (bias > 60) return 'Liberal response bias (tendency to respond "Yes")';
if (bias < 40) return 'Conservative response bias (tendency to respond "No")';
return 'No significant response bias detected';
};
```
---
## 📝 Development Notes
### Critical Reminders
1. **Follow PDF exactly** - All practice + main trials must match document precisely
2. **Sequential presentation** - Memory items shown ONE AT A TIME (never all at once)
3. **Timing precision** - Use performance.now() for accurate RT measurement
4. **RT calculation** - Only include correct responses in mean RT calculations
5. **Capacity analysis** - This is a primary outcome measure - ensure accuracy
6. **No feedback in main test** - Only show timeout message, no correct/incorrect feedback
7. **Complete all probes** - Test all probes for a memory set before moving to next set
8. **Span progression** - Alternating 1→3→5 or 2→4→6 pattern across 5 triads
9. **Age-appropriate** - Different stimuli, timings, and language for each age group
### Common Pitfalls to Avoid
- ❌ Showing all memory items simultaneously (must be sequential)
- ❌ Including incorrect responses in RT means
- ❌ Including timeout trials in RT calculations
- ❌ Showing feedback during main test (except timeout)
- ❌ Randomizing trial order (must follow PDF exactly)
- ❌ Using wrong item display time (1.1s vs 1.3s)
- ❌ Using wrong probe window (6s vs 4.5s)
- ❌ Forgetting retention interval (1 second blank screen)
- ❌ Not clearing timeouts on component unmount
- ❌ Not handling rapid/duplicate button presses
- ❌ Calculating accuracy without including timeouts as incorrect
- ❌ Testing probes before showing full memory set
### Performance Optimization
- Use useCallback for event handlers to prevent re-renders
- Use useRef for timers and timestamps (no re-renders needed)
- Use useMemo for trial sequences and span calculations
- Debounce button clicks to prevent double-taps
- Clean up all timeouts/intervals on unmount
- Lazy load results calculations until test completion
- Minimize state updates during encoding/probe phases
- Pre-calculate trial sequences to avoid runtime computation
### Accessibility Considerations
- High contrast text (white on black)
- Large, readable font sizes (text-5xl minimum)
- Clear button labels ("Yes" and "No")
- Keyboard support (Y key = Yes, N key = No)
- Screen reader announcements for phase transitions
- Focus management between screens
- Touch-friendly button sizes (minimum 44x44px)
- Clear visual feedback on button press (light blue border)
---
## 🎓 Learning Resources
### Key Concepts to Understand
1. **Working Memory:** Temporary storage and manipulation of information
2. **Memory Span:** Maximum number of items that can be held in working memory
3. **Serial Exhaustive Search:** Mental process of checking each item sequentially
4. **Recognition vs. Recall:** Identifying previously seen items (easier than recall)
5. **Cognitive Load:** Difficulty increases with larger memory sets
6. **Positive vs. Negative Probes:** Targets (in set) vs. Non-Targets (not in set)
7. **RT Slope:** Rate of RT increase with memory load (search efficiency)
8. **Capacity Limits:** Individual differences in working memory capacity
### React Patterns Used
- Custom hooks for complex state logic (useMemorySetManagement)
- useRef for timers and timestamps (performance optimization)
- useCallback for optimized event handlers
- useMemo for trial sequence calculations
- Framer Motion for minimal animations
- Context API for global test state (optional)
- Compound components pattern
- Sequential state machines for trial flow
---
**FINAL REMINDER:**
This is a psychological research tool measuring working memory capacity. Precision in:
- **Sequential presentation** of memory items (ONE AT A TIME)
- **Timing accuracy** (encoding, retention, probe windows)
- **Data collection** (every probe trial recorded accurately)
- **RT measurement** (millisecond precision)
- **Calculations** (only correct responses in RT means)
is ABSOLUTELY CRITICAL for valid assessment.
Always refer back to the PDF for exact specifications. When in doubt, follow the PDF exactly.
The Sternberg paradigm is a validated scientific instrument - maintain its integrity through precise implementation.