Skip to content
Merged
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
34 changes: 34 additions & 0 deletions Projects/The Stroop Interference Grid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# The Stroop Interference Grid // Cognitive Control

The Stroop Interference Grid is a high-fidelity psychological focus simulator built to address the attention-training constraints outlined in **Issue #745**. By continuously tasking users to override their immediate reading impulses and evaluate stimulus mismatch states, the platform trains selective focus and fluid override execution under severe time limits. Built entirely client-side using native modern web specifications.

---

## Technical Capabilities & Core Specifications

### 1. Visual Scaffolding & Theme Geometry (`style.css`)

- **Strict Real Estate Viewport Constraints:** Anchors all control decks inside an anti-shiver container frame (`max-width: 1200px`, `height: 760px`) to prevent structural degradation across fluctuating display resolutions.
- **Jitter-Proof Monospaced Typography Docks:** Countdown loading indicators, active rule headers, current scores, and record milestones use dedicated monospaced font declarations (`ui-monospace`, `Consolas`), ensuring data updates cause zero layout jitter.
- **Component Utility States:** \* `.color-target-btn`: Elegant, responsive tile buttons hosting hidden index assignments that map a balanced, high-contrast accessible hexadecimal color palette.
- `.grid-shake`: Attached globally to the playground node stack to execute a violent keyframe vibration animation sequence (`@keyframes grid-shake`) when input mismatches or clock expirations hit.

### 2. Random Shuffling & Evaluation Pipelines (`script.js`)

- **Combinatorial Mismatch Generator:** Iterates the core configuration pool to generate asymmetric target variables where the word string value explicitly mismatches its element text ink styling (e.g., text displays "RED" inside a vibrant emerald green background vector).
- **Fisher-Yates Position Scrambler:** To break muscle memory adaptations, a shuffle routine randomizes button assignments inside `#target-grid` completely every round.
- **High-Speed Clock Interpolator:** Tracks a precise `2000ms` round constraint window via a `requestAnimationFrame` loop, binding clock progress to a smooth visual loading bar track.
- **Acoustic Feedback Synthesis (Web Audio API):** Leverages a native browser `AudioContext` graph to generate synthesized electronic wave alerts on the fly, avoiding broken external MP3/WAV media path dependencies.

---

## Workspace Directory Layout

```text
The Stroop Interference Grid/
├── index.html # Structural Semantic Dashboard Layout and Stimulus Nodes
├── style.css # Shuffled Keypad Layout, Color Pools, and Matrix Vibrations
├── script.js # High-Speed Countdown Timer and Fisher-Yates Scramble Engine
├── project.json # Architecture Manifest Descriptor Metadata
└── README.md # Technical Engineering Specifications Documentation
```
52 changes: 52 additions & 0 deletions Projects/The Stroop Interference Grid/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>The Stroop Interference Grid</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="app-container">
<aside class="sidebar">
<div class="app-header">
<div class="app-logo">S</div>
<h1 class="app-title">Stroop</h1>
<span class="app-subtitle">Cognitive Control</span>
</div>
<div class="metrics-dashboard">
<div class="metric-card">
<span class="metric-label">Current Streak</span>
<span class="metric-value" id="streak-display">0</span>
</div>
<div class="metric-card">
<span class="metric-label">Best Streak</span>
<span class="metric-value" id="best-display">0</span>
</div>
<div class="metric-card">
<span class="metric-label">Total Rounds</span>
<span class="metric-value" id="rounds-display">0</span>
</div>
<div class="metric-card">
<span class="metric-label">Accuracy</span>
<span class="metric-value" id="accuracy-display">0%</span>
</div>
</div>
<button id="reset-btn" class="btn-primary">Reset Simulation Suite</button>
</aside>
<main class="main-content" id="main-content">
<div class="playground">
<div class="rule-banner" id="rule-banner">RULE: TAP THE TEXT COLOR</div>
<div class="stimulus-area">
<div class="timer-track">
<div class="timer-fill" id="timer-fill"></div>
</div>
<div class="stroop-stimulus" id="stroop-stimulus">RED</div>
</div>
<div class="target-grid" id="target-grid"></div>
</div>
</main>
</div>
<script src="script.js"></script>
</body>
</html>
14 changes: 14 additions & 0 deletions Projects/The Stroop Interference Grid/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "The Stroop Interference Grid",
"description": "An ultra-premium cognitive control training tool based on the psychological Stroop Effect. The system forces the brain to override automatic processing habits by dynamically altering target evaluation rules each round between text meaning and ink color constraints. Features include high-frequency component position randomization using automated Fisher-Yates array shuffling passes to block muscle memory adaptations, a high-precision 2-second countdown interval timer tracked down to millisecond boundaries, and native client LocalStorage persistence hooks mapping streak records.",
"entry": "index.html",
"tags": [
"HTML",
"CSS",
"JavaScript"
],
"author": {
"name": "Shruti Narsulwar",
"github": "shrutiii01"
}
}
235 changes: 235 additions & 0 deletions Projects/The Stroop Interference Grid/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
(function(){
'use strict';

const COLORS = [
{ id:'red', name:'Red', hex:'#ef4444' },
{ id:'blue', name:'Blue', hex:'#3b82f6' },
{ id:'green', name:'Green', hex:'#10b981' },
{ id:'yellow', name:'Yellow', hex:'#f59e0b' },
{ id:'purple', name:'Purple', hex:'#a855f7' }
];

const STATE = {
running: false,
currentWordId: '',
currentInkId: '',
currentRule: '',
correctAnswer: '',
streak: 0,
bestStreak: 0,
totalRounds: 0,
correctRounds: 0,
timerRAF: null,
timerTimeout: null,
roundStartTime: 0,
locked: false
};

const el = {
streak: document.getElementById('streak-display'),
best: document.getElementById('best-display'),
rounds: document.getElementById('rounds-display'),
accuracy: document.getElementById('accuracy-display'),
resetBtn: document.getElementById('reset-btn'),
mainContent: document.getElementById('main-content'),
ruleBanner: document.getElementById('rule-banner'),
stimulus: document.getElementById('stroop-stimulus'),
targetGrid: document.getElementById('target-grid'),
timerFill: document.getElementById('timer-fill')
};

let audioCtx = null;

function shuffleArray(arr){
for(let i=arr.length-1;i>0;i--){
const j=Math.floor(Math.random()*(i+1));
[arr[i],arr[j]]=[arr[j],arr[i]];
}
return arr;
}

function loadBestStreak(){
try{
const d=JSON.parse(localStorage.getItem('stroop-best'));
if(d&&typeof d.bestStreak==='number') STATE.bestStreak=d.bestStreak;
}catch(e){}
}

function saveBestStreak(){
if(STATE.streak>STATE.bestStreak){
STATE.bestStreak=STATE.streak;
try{
localStorage.setItem('stroop-best',JSON.stringify({bestStreak:STATE.bestStreak}));
}catch(e){}
}
}

function updateStats(){
const acc=STATE.totalRounds>0?Math.round((STATE.correctRounds/STATE.totalRounds)*100):0;
el.streak.textContent=STATE.streak;
el.best.textContent=STATE.bestStreak;
el.rounds.textContent=STATE.totalRounds;
el.accuracy.textContent=acc+'%';
}

function stopTimer(){
if(STATE.timerRAF){cancelAnimationFrame(STATE.timerRAF);STATE.timerRAF=null;}
if(STATE.timerTimeout){clearTimeout(STATE.timerTimeout);STATE.timerTimeout=null;}
}

function updateTimerBar(){
if(!STATE.running)return;
const elapsed=performance.now()-STATE.roundStartTime;
const pct=Math.max(0,1-elapsed/2000);
el.timerFill.style.width=(pct*100)+'%';
if(pct>0){
STATE.timerRAF=requestAnimationFrame(updateTimerBar);
}
}

function startRoundTimer(){
STATE.roundStartTime=performance.now();
el.timerFill.className='timer-fill';
el.timerFill.style.width='100%';
STATE.timerRAF=requestAnimationFrame(updateTimerBar);
STATE.timerTimeout=setTimeout(function(){
if(STATE.running) handleTimeout();
},2000);
}

function playCorrectTone(){
try{
if(!audioCtx) audioCtx=new(window.AudioContext||window.webkitAudioContext)();
if(audioCtx.state==='suspended') audioCtx.resume();
const osc=audioCtx.createOscillator();
const gain=audioCtx.createGain();
osc.type='sine';
osc.frequency.setValueAtTime(880,audioCtx.currentTime);
gain.gain.setValueAtTime(0.25,audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001,audioCtx.currentTime+0.12);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start(audioCtx.currentTime);
osc.stop(audioCtx.currentTime+0.12);
}catch(e){}
}

function renderButtons(){
const shuffled=shuffleArray([...COLORS]);
el.targetGrid.innerHTML='';
shuffled.forEach(function(color){
const btn=document.createElement('button');
btn.className='color-target-btn';
btn.dataset.color=color.id;
const badge=document.createElement('span');
badge.className='color-badge';
badge.style.background=color.hex;
const label=document.createElement('span');
label.className='color-name';
label.textContent=color.name;
btn.appendChild(badge);
btn.appendChild(label);
btn.addEventListener('click',function(){handleChoice(color.id);});
el.targetGrid.appendChild(btn);
});
}

function generateStimulus(){
const shuffled=shuffleArray([...COLORS]);
const wordColor=shuffled[0];
const inkColor=shuffled[1];
STATE.currentWordId=wordColor.id;
STATE.currentInkId=inkColor.id;
STATE.currentRule=Math.random()<0.5?'color':'meaning';
STATE.correctAnswer=STATE.currentRule==='color'?inkColor.id:wordColor.id;
el.stimulus.textContent=wordColor.name.toUpperCase();
el.stimulus.style.color=inkColor.hex;
const isColorRule=STATE.currentRule==='color';
el.ruleBanner.textContent=isColorRule?'RULE: TAP THE TEXT COLOR':'RULE: TAP THE WORD MEANING';
el.ruleBanner.style.borderColor=isColorRule?'#3b82f6':'#a855f7';
el.ruleBanner.style.color=isColorRule?'#3b82f6':'#a855f7';
el.ruleBanner.classList.add('rule-text-mode');
renderButtons();
}

function nextRound(){
generateStimulus();
STATE.running=true;
STATE.locked=false;
startRoundTimer();
}

function handleChoice(chosen){
if(!STATE.running||STATE.locked)return;
STATE.locked=true;
STATE.running=false;
stopTimer();
STATE.totalRounds++;
if(chosen===STATE.correctAnswer){
STATE.streak++;
STATE.correctRounds++;
saveBestStreak();
updateStats();
el.timerFill.classList.add('correct');
playCorrectTone();
setTimeout(function(){nextRound();},150);
}else{
STATE.streak=0;
saveBestStreak();
updateStats();
el.timerFill.classList.add('incorrect');
el.mainContent.classList.remove('grid-shake');
void el.mainContent.offsetWidth;
el.mainContent.classList.add('grid-shake');
setTimeout(function(){
el.mainContent.classList.remove('grid-shake');
nextRound();
},400);
}
}

function handleTimeout(){
if(!STATE.running||STATE.locked)return;
STATE.locked=true;
STATE.running=false;
STATE.streak=0;
STATE.totalRounds++;
saveBestStreak();
updateStats();
el.timerFill.classList.add('incorrect');
el.mainContent.classList.remove('grid-shake');
void el.mainContent.offsetWidth;
el.mainContent.classList.add('grid-shake');
setTimeout(function(){
el.mainContent.classList.remove('grid-shake');
nextRound();
},400);
}

function resetGame(){
stopTimer();
STATE.running=false;
STATE.locked=false;
STATE.streak=0;
STATE.totalRounds=0;
STATE.correctRounds=0;
el.mainContent.classList.remove('grid-shake');
el.timerFill.className='timer-fill';
el.timerFill.style.width='100%';
updateStats();
setTimeout(function(){nextRound();},200);
}

function init(){
loadBestStreak();
updateStats();
el.resetBtn.addEventListener('click',resetGame);
setTimeout(function(){nextRound();},300);
}

if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded',init);
}else{
init();
}
})();
Loading
Loading