trifocus / index.html
SaidAmchghal's picture
Add 2 files
73c2f0b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TriFocus - Cognitive Training App</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.05); opacity: 0.9; }
}
.pulse-animation {
animation: pulse 2s infinite;
}
.countdown {
font-size: 5rem;
font-weight: bold;
color: #3b82f6;
}
.reaction-dot {
width: 60px;
height: 60px;
border-radius: 50%;
position: absolute;
cursor: pointer;
transition: transform 0.1s;
}
.reaction-dot:active {
transform: scale(0.9);
}
.stroop-card {
width: 200px;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
border-radius: 12px;
margin: 10px;
cursor: pointer;
transition: all 0.2s;
}
.stroop-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.sequence-item {
width: 70px;
height: 70px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
margin: 10px;
transition: all 0.2s;
}
.sequence-item:hover {
transform: scale(1.05);
}
.progress-bar {
height: 8px;
border-radius: 4px;
transition: width 0.3s ease;
}
.radial-progress {
--value: 0;
--size: 120px;
--thickness: 12px;
}
.fade-in {
animation: fadeIn 0.5s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.language-selector {
position: relative;
display: inline-block;
}
.language-dropdown {
display: none;
position: absolute;
right: 0;
background-color: white;
min-width: 120px;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.1);
z-index: 1;
border-radius: 8px;
overflow: hidden;
}
.language-selector:hover .language-dropdown {
display: block;
}
.language-option {
padding: 10px 16px;
display: flex;
align-items: center;
cursor: pointer;
transition: background-color 0.2s;
}
.language-option:hover {
background-color: #f3f4f6;
}
.language-flag {
width: 20px;
margin-right: 8px;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen font-sans">
<!-- App Container -->
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<div class="flex items-center">
<div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-xl mr-3">TF</div>
<h1 class="text-3xl font-bold text-gray-800">TriFocus</h1>
</div>
<div class="flex space-x-4 items-center">
<!-- Language Selector -->
<div class="language-selector">
<button class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700 flex items-center">
<i class="fas fa-globe mr-1"></i>
<span id="currentLanguage">EN</span>
</button>
<div class="language-dropdown mt-1">
<div class="language-option" onclick="changeLanguage('en')">
<img src="https://flagcdn.com/w20/gb.png" class="language-flag" alt="English">
<span>English</span>
</div>
<div class="language-option" onclick="changeLanguage('fr')">
<img src="https://flagcdn.com/w20/fr.png" class="language-flag" alt="Français">
<span>Français</span>
</div>
<div class="language-option" onclick="changeLanguage('ar')">
<img src="https://flagcdn.com/w20/sa.png" class="language-flag" alt="العربية">
<span>العربية</span>
</div>
</div>
</div>
<button id="historyBtn" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700">
<i class="fas fa-history"></i>
</button>
<button id="settingsBtn" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700">
<i class="fas fa-cog"></i>
</button>
</div>
</header>
<!-- Main Content Area -->
<main id="mainContent">
<!-- Home Screen -->
<section id="homeScreen" class="fade-in">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold text-gray-800 mb-4" data-i18n="welcome">Welcome to TriFocus</h2>
<p class="text-gray-600 mb-6" data-i18n="welcome_sub">Train your cognitive skills with our three specialized modules. Choose your training mode below.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div class="bg-blue-50 rounded-lg p-6 border border-blue-100 hover:border-blue-300 transition-all cursor-pointer" onclick="startExpressSession()">
<div class="flex items-center mb-3">
<div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white mr-3">
<i class="fas fa-bolt"></i>
</div>
<h3 class="text-lg font-semibold text-gray-800" data-i18n="express_session">Express Session</h3>
</div>
<p class="text-gray-600 text-sm" data-i18n="express_desc">Complete all 3 modules in sequence for a comprehensive cognitive assessment.</p>
</div>
<div class="bg-purple-50 rounded-lg p-6 border border-purple-100 hover:border-purple-300 transition-all cursor-pointer" onclick="showModuleSelection()">
<div class="flex items-center mb-3">
<div class="w-10 h-10 rounded-full bg-purple-500 flex items-center justify-center text-white mr-3">
<i class="fas fa-sliders-h"></i>
</div>
<h3 class="text-lg font-semibold text-gray-800" data-i18n="individual_module">Individual Module</h3>
</div>
<p class="text-gray-600 text-sm" data-i18n="individual_desc">Focus on one specific cognitive skill with a single module.</p>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h4 class="font-medium text-gray-700 mb-2" data-i18n="last_session">Your last session score:</h4>
<div class="flex items-center">
<div class="radial-progress text-blue-500" style="--value: 72; --size: 3rem; --thickness: 4px;">72</div>
<div class="ml-4">
<p class="text-sm text-gray-600" data-i18n="score_was">Your focus score was <span class="font-semibold">72/100</span></p>
<div class="w-full bg-gray-200 rounded-full h-2 mt-1">
<div class="bg-blue-500 h-2 rounded-full" style="width: 72%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-bold text-gray-800 mb-4" data-i18n="your_progress">Your Progress</h2>
<div class="grid grid-cols-3 gap-4 mb-4">
<div class="text-center">
<div class="radial-progress text-blue-500 mx-auto mb-2" style="--value: 85;">85</div>
<p class="text-xs font-medium text-gray-600" data-i18n="reaction">Reaction</p>
</div>
<div class="text-center">
<div class="radial-progress text-purple-500 mx-auto mb-2" style="--value: 68;">68</div>
<p class="text-xs font-medium text-gray-600" data-i18n="attention">Attention</p>
</div>
<div class="text-center">
<div class="radial-progress text-green-500 mx-auto mb-2" style="--value: 76;">76</div>
<p class="text-xs font-medium text-gray-600" data-i18n="memory">Memory</p>
</div>
</div>
<div class="flex justify-between items-center">
<div>
<p class="text-sm font-medium text-gray-700" data-i18n="current_level">Current Level: <span class="font-bold">Novice</span></p>
<div class="w-full bg-gray-200 rounded-full h-2 mt-1">
<div class="bg-yellow-500 h-2 rounded-full" style="width: 45%"></div>
</div>
</div>
<div class="text-right">
<p class="text-xs text-gray-500" data-i18n="next_badge">Next badge at 100 points</p>
<div class="inline-block bg-yellow-100 rounded-full p-1">
<i class="fas fa-medal text-yellow-500"></i>
</div>
</div>
</div>
</div>
</section>
<!-- Module Selection Screen -->
<section id="moduleSelectionScreen" class="hidden fade-in">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<div class="flex items-center mb-6">
<button onclick="backToHome()" class="mr-4 p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700">
<i class="fas fa-arrow-left"></i>
</button>
<h2 class="text-2xl font-bold text-gray-800" data-i18n="select_module">Select a Module</h2>
</div>
<div class="grid grid-cols-1 gap-4">
<div class="bg-blue-50 rounded-lg p-6 border border-blue-100 hover:border-blue-300 transition-all cursor-pointer" onclick="startModule('reaction')">
<div class="flex items-center mb-3">
<div class="w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white mr-4">
<i class="fas fa-hand-pointer"></i>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-800" data-i18n="reaction_tap">Reaction Tap</h3>
<p class="text-sm text-gray-600" data-i18n="reaction_desc">Test your reaction speed</p>
</div>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-sm">
<span class="font-medium text-gray-700" data-i18n="best">Best: </span>
<span class="font-bold text-blue-600">215ms</span>
</div>
<span class="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30% weight</span>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-6 border border-purple-100 hover:border-purple-300 transition-all cursor-pointer" onclick="startModule('stroop')">
<div class="flex items-center mb-3">
<div class="w-12 h-12 rounded-full bg-purple-500 flex items-center justify-center text-white mr-4">
<i class="fas fa-palette"></i>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-800" data-i18n="color_match">Color Match</h3>
<p class="text-sm text-gray-600" data-i18n="stroop_desc">Stroop test for selective attention</p>
</div>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-sm">
<span class="font-medium text-gray-700" data-i18n="best">Best: </span>
<span class="font-bold text-purple-600">92% accuracy</span>
</div>
<span class="bg-purple-100 text-purple-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">40% weight</span>
</div>
</div>
<div class="bg-green-50 rounded-lg p-6 border border-green-100 hover:border-green-300 transition-all cursor-pointer" onclick="startModule('sequence')">
<div class="flex items-center mb-3">
<div class="w-12 h-12 rounded-full bg-green-500 flex items-center justify-center text-white mr-4">
<i class="fas fa-brain"></i>
</div>
<div>
<h3 class="text-lg font-semibold text-gray-800" data-i18n="sequence_recall">Sequence Recall</h3>
<p class="text-sm text-gray-600" data-i18n="sequence_desc">Challenge your working memory</p>
</div>
</div>
<div class="flex justify-between items-center mt-4">
<div class="text-sm">
<span class="font-medium text-gray-700" data-i18n="best">Best: </span>
<span class="font-bold text-green-600">8 items</span>
</div>
<span class="bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30% weight</span>
</div>
</div>
</div>
</div>
</section>
<!-- Countdown Screen -->
<section id="countdownScreen" class="hidden">
<div class="flex flex-col items-center justify-center h-64">
<h2 id="moduleTitle" class="text-2xl font-bold text-gray-800 mb-8"></h2>
<div class="countdown" id="countdown">3</div>
<p class="text-gray-600 mt-4" data-i18n="get_ready">Get ready...</p>
</div>
</section>
<!-- Reaction Tap Game -->
<section id="reactionGame" class="hidden">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="reaction_tap">Reaction Tap</h2>
<p class="text-gray-600 mb-4" data-i18n="tap_instruction">Tap the dot as soon as it appears</p>
<div class="flex justify-between items-center mb-6">
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="trials">Trials: </span>
<span id="reactionTrials" class="font-bold">0/10</span>
</div>
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="avg_reaction">Avg. reaction: </span>
<span id="avgReaction" class="font-bold">-</span>
</div>
</div>
<div class="relative bg-gray-100 rounded-lg h-64 w-full" id="reactionArea">
<div id="reactionDot" class="reaction-dot bg-blue-500 hidden"></div>
</div>
<div class="mt-6">
<div class="flex justify-between text-sm text-gray-600 mb-1">
<span data-i18n="progress">Progress</span>
<span id="reactionProgressText">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div id="reactionProgress" class="progress-bar bg-blue-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
</div>
</section>
<!-- Stroop Test Game -->
<section id="stroopGame" class="hidden">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="color_match">Color Match</h2>
<p class="text-gray-600 mb-4" data-i18n="stroop_instruction">Select the color of the text, not the word itself</p>
<div class="flex justify-between items-center mb-6">
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="questions">Questions: </span>
<span id="stroopTrials" class="font-bold">0/12</span>
</div>
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="accuracy">Accuracy: </span>
<span id="stroopAccuracy" class="font-bold">-</span>
</div>
</div>
<div class="flex flex-col items-center mb-8">
<div id="stroopQuestion" class="stroop-card bg-white shadow-md text-3xl mb-8">WORD</div>
<div class="grid grid-cols-2 gap-4">
<div class="stroop-card bg-red-500 text-white" onclick="checkStroopAnswer('red')" data-i18n="red">Red</div>
<div class="stroop-card bg-blue-500 text-white" onclick="checkStroopAnswer('blue')" data-i18n="blue">Blue</div>
<div class="stroop-card bg-green-500 text-white" onclick="checkStroopAnswer('green')" data-i18n="green">Green</div>
<div class="stroop-card bg-yellow-500 text-white" onclick="checkStroopAnswer('yellow')" data-i18n="yellow">Yellow</div>
</div>
</div>
<div class="mt-6">
<div class="flex justify-between text-sm text-gray-600 mb-1">
<span data-i18n="progress">Progress</span>
<span id="stroopProgressText">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div id="stroopProgress" class="progress-bar bg-purple-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
</div>
</section>
<!-- Sequence Recall Game -->
<section id="sequenceGame" class="hidden">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<h2 class="text-2xl font-bold text-gray-800 mb-2" data-i18n="sequence_recall">Sequence Recall</h2>
<p class="text-gray-600 mb-4" data-i18n="sequence_instruction">Memorize and repeat the sequence</p>
<div class="flex justify-between items-center mb-6">
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="level">Level: </span>
<span id="sequenceLevel" class="font-bold">1</span>
</div>
<div>
<span class="text-sm font-medium text-gray-700" data-i18n="best">Best: </span>
<span id="sequenceBest" class="font-bold">5 items</span>
</div>
</div>
<div id="sequenceDisplayArea" class="flex justify-center mb-8">
<!-- Sequence items will appear here -->
</div>
<div id="sequenceInputArea" class="grid grid-cols-3 gap-4 mb-8">
<!-- Input buttons will appear here -->
</div>
<div class="mt-6">
<div class="flex justify-between text-sm text-gray-600 mb-1">
<span data-i18n="progress">Progress</span>
<span id="sequenceProgressText">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div id="sequenceProgress" class="progress-bar bg-green-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
</div>
</section>
<!-- Results Screen -->
<section id="resultsScreen" class="hidden fade-in">
<div class="bg-white rounded-xl shadow-md p-6 mb-6">
<div class="flex items-center mb-6">
<button onclick="backToHome()" class="mr-4 p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700">
<i class="fas fa-arrow-left"></i>
</button>
<h2 class="text-2xl font-bold text-gray-800" data-i18n="session_results">Session Results</h2>
</div>
<div class="flex flex-col items-center mb-8">
<div class="radial-progress text-blue-500 mb-4" style="--value: 78;">78</div>
<h3 class="text-xl font-bold text-gray-800 mb-2" data-i18n="focus_score">Your Focus Score</h3>
<p class="text-gray-600 mb-6" data-i18n="better_than">Better than 65% of your previous sessions</p>
<div class="w-full bg-gray-100 rounded-full h-4 mb-6">
<div class="bg-gradient-to-r from-blue-500 via-purple-500 to-green-500 h-4 rounded-full" style="width: 78%"></div>
</div>
</div>
<div class="grid grid-cols-1 gap-6 mb-8">
<div class="bg-blue-50 rounded-lg p-4">
<div class="flex justify-between items-center mb-2">
<h4 class="font-medium text-gray-700" data-i18n="reaction_tap">Reaction Tap</h4>
<span class="bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30%</span>
</div>
<div class="flex justify-between items-center">
<div>
<p class="text-sm text-gray-600" data-i18n="avg_reaction">Avg. reaction: <span class="font-semibold">248ms</span></p>
<p class="text-sm text-gray-600" data-i18n="accuracy">Accuracy: <span class="font-semibold">90%</span></p>
</div>
<div class="text-right">
<div class="text-lg font-bold text-blue-600">24/30</div>
<p class="text-xs text-gray-500" data-i18n="score">Score</p>
</div>
</div>
</div>
<div class="bg-purple-50 rounded-lg p-4">
<div class="flex justify-between items-center mb-2">
<h4 class="font-medium text-gray-700" data-i18n="color_match">Color Match</h4>
<span class="bg-purple-100 text-purple-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">40%</span>
</div>
<div class="flex justify-between items-center">
<div>
<p class="text-sm text-gray-600" data-i18n="avg_time">Avg. time: <span class="font-semibold">1.8s</span></p>
<p class="text-sm text-gray-600" data-i18n="accuracy">Accuracy: <span class="font-semibold">83%</span></p>
</div>
<div class="text-right">
<div class="text-lg font-bold text-purple-600">32/40</div>
<p class="text-xs text-gray-500" data-i18n="score">Score</p>
</div>
</div>
</div>
<div class="bg-green-50 rounded-lg p-4">
<div class="flex justify-between items-center mb-2">
<h4 class="font-medium text-gray-700" data-i18n="sequence_recall">Sequence Recall</h4>
<span class="bg-green-100 text-green-800 text-xs font-medium px-2.5 py-0.5 rounded" data-i18n="weight">30%</span>
</div>
<div class="flex justify-between items-center">
<div>
<p class="text-sm text-gray-600" data-i18n="max_sequence">Max sequence: <span class="font-semibold">6 items</span></p>
<p class="text-sm text-gray-600" data-i18n="avg_time">Avg. time: <span class="font-semibold">3.2s</span></p>
</div>
<div class="text-right">
<div class="text-lg font-bold text-green-600">22/30</div>
<p class="text-xs text-gray-500" data-i18n="score">Score</p>
</div>
</div>
</div>
</div>
<div class="bg-yellow-50 rounded-lg p-4 border border-yellow-200">
<h4 class="font-medium text-gray-700 mb-2" data-i18n="recommendations">Recommendations</h4>
<ul class="list-disc pl-5 text-sm text-gray-700 space-y-1">
<li data-i18n="recommendation1">Practice Color Match to improve your selective attention</li>
<li data-i18n="recommendation2">Try morning sessions when your reaction time is typically faster</li>
<li data-i18n="recommendation3">Take a 5-minute break between sessions for better focus</li>
</ul>
</div>
</div>
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-bold text-gray-800 mb-4" data-i18n="earned_badges">Earned Badges</h2>
<div class="flex space-x-4">
<div class="text-center">
<div class="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center text-blue-500 mx-auto mb-2">
<i class="fas fa-bolt text-xl"></i>
</div>
<p class="text-xs font-medium text-gray-600" data-i18n="quick_reflexes">Quick Reflexes</p>
</div>
<div class="text-center">
<div class="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center text-purple-500 mx-auto mb-2">
<i class="fas fa-brain text-xl"></i>
</div>
<p class="text-xs font-medium text-gray-600" data-i18n="memory_builder">Memory Builder</p>
</div>
<div class="text-center opacity-40">
<div class="w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center text-gray-400 mx-auto mb-2">
<i class="fas fa-trophy text-xl"></i>
</div>
<p class="text-xs font-medium text-gray-600" data-i18n="master_focus">Master Focus</p>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="mt-12 text-center text-gray-500 text-sm">
<p>TriFocus © 2023 - Cognitive Training App</p>
</footer>
</div>
<script>
// Game state variables
let currentModule = '';
let sessionType = '';
let reactionTimes = [];
let stroopAnswers = [];
let sequenceLevel = 1;
let currentLanguage = 'en';
// Translation dictionary
const translations = {
en: {
welcome: "Welcome to TriFocus",
welcome_sub: "Train your cognitive skills with our three specialized modules. Choose your training mode below.",
express_session: "Express Session",
express_desc: "Complete all 3 modules in sequence for a comprehensive cognitive assessment.",
individual_module: "Individual Module",
individual_desc: "Focus on one specific cognitive skill with a single module.",
last_session: "Your last session score:",
score_was: "Your focus score was",
your_progress: "Your Progress",
reaction: "Reaction",
attention: "Attention",
memory: "Memory",
current_level: "Current Level:",
next_badge: "Next badge at 100 points",
select_module: "Select a Module",
reaction_tap: "Reaction Tap",
reaction_desc: "Test your reaction speed",
best: "Best:",
weight: "weight",
color_match: "Color Match",
stroop_desc: "Stroop test for selective attention",
sequence_recall: "Sequence Recall",
sequence_desc: "Challenge your working memory",
get_ready: "Get ready...",
tap_instruction: "Tap the dot as soon as it appears",
trials: "Trials:",
avg_reaction: "Avg. reaction:",
progress: "Progress",
stroop_instruction: "Select the color of the text, not the word itself",
questions: "Questions:",
accuracy: "Accuracy:",
red: "Red",
blue: "Blue",
green: "Green",
yellow: "Yellow",
sequence_instruction: "Memorize and repeat the sequence",
level: "Level:",
session_results: "Session Results",
focus_score: "Your Focus Score",
better_than: "Better than 65% of your previous sessions",
recommendations: "Recommendations",
recommendation1: "Practice Color Match to improve your selective attention",
recommendation2: "Try morning sessions when your reaction time is typically faster",
recommendation3: "Take a 5-minute break between sessions for better focus",
earned_badges: "Earned Badges",
quick_reflexes: "Quick Reflexes",
memory_builder: "Memory Builder",
master_focus: "Master Focus",
score: "Score",
avg_time: "Avg. time:",
max_sequence: "Max sequence:"
},
fr: {
welcome: "Bienvenue sur TriFocus",
welcome_sub: "Entraînez vos capacités cognitives avec nos trois modules spécialisés. Choisissez votre mode d'entraînement ci-dessous.",
express_session: "Session Express",
express_desc: "Complétez les 3 modules en séquence pour une évaluation cognitive complète.",
individual_module: "Module Individuel",
individual_desc: "Concentrez-vous sur une compétence cognitive spécifique avec un seul module.",
last_session: "Votre score de la dernière session :",
score_was: "Votre score de concentration était",
your_progress: "Votre Progrès",
reaction: "Réaction",
attention: "Attention",
memory: "Mémoire",
current_level: "Niveau Actuel :",
next_badge: "Prochain badge à 100 points",
select_module: "Sélectionnez un Module",
reaction_tap: "Tape Réaction",
reaction_desc: "Testez votre vitesse de réaction",
best: "Meilleur :",
weight: "pondération",
color_match: "Correspondance Couleur",
stroop_desc: "Test Stroop pour l'attention sélective",
sequence_recall: "Rappel de Séquence",
sequence_desc: "Défiez votre mémoire de travail",
get_ready: "Préparez-vous...",
tap_instruction: "Tapez sur le point dès qu'il apparaît",
trials: "Essais :",
avg_reaction: "Moy. réaction :",
progress: "Progression",
stroop_instruction: "Sélectionnez la couleur du texte, pas le mot lui-même",
questions: "Questions :",
accuracy: "Précision :",
red: "Rouge",
blue: "Bleu",
green: "Vert",
yellow: "Jaune",
sequence_instruction: "Mémorisez et répétez la séquence",
level: "Niveau :",
session_results: "Résultats de la Session",
focus_score: "Votre Score de Concentration",
better_than: "Mieux que 65% de vos sessions précédentes",
recommendations: "Recommandations",
recommendation1: "Pratiquez Correspondance Couleur pour améliorer votre attention sélective",
recommendation2: "Essayez des sessions matinales lorsque votre temps de réaction est généralement plus rapide",
recommendation3: "Prenez une pause de 5 minutes entre les sessions pour une meilleure concentration",
earned_badges: "Badges Obtenus",
quick_reflexes: "Réflexes Rapides",
memory_builder: "Bâtisseur de Mémoire",
master_focus: "Maître de la Concentration",
score: "Score",
avg_time: "Moy. temps :",
max_sequence: "Séquence max :"
},
ar: {
welcome: "مرحبًا بكم في TriFocus",
welcome_sub: "قم بتدريب مهاراتك المعرفية من خلال وحداتنا الثلاث المتخصصة. اختر نمط التدريب الخاص بك أدناه.",
express_session: "جلسة سريعة",
express_desc: "أكمل جميع الوحدات الثلاث بالتسلسل لتقييم معرفي شامل.",
individual_module: "وحدة فردية",
individual_desc: "ركز على مهارة معرفية محددة مع وحدة واحدة.",
last_session: "نتيجة جلستك الأخيرة:",
score_was: "كانت درجة تركيزك",
your_progress: "تقدمك",
reaction: "رد الفعل",
attention: "الانتباه",
memory: "الذاكرة",
current_level: "المستوى الحالي:",
next_badge: "الشارة التالية عند 100 نقطة",
select_module: "اختر وحدة",
reaction_tap: "النقر السريع",
reaction_desc: "اختبر سرعة رد فعلك",
best: "الأفضل:",
weight: "الوزن",
color_match: "مطابقة الألوان",
stroop_desc: "اختبار ستروب للانتباه الانتقائي",
sequence_recall: "تذكر التسلسل",
sequence_desc: "تحدي ذاكرتك العاملة",
get_ready: "استعد...",
tap_instruction: "انقر على النقطة بمجرد ظهورها",
trials: "المحاولات:",
avg_reaction: "متوسط رد الفعل:",
progress: "التقدم",
stroop_instruction: "اختر لون النص وليس الكلمة نفسها",
questions: "الأسئلة:",
accuracy: "الدقة:",
red: "أحمر",
blue: "أزرق",
green: "أخضر",
yellow: "أصفر",
sequence_instruction: "احفظ التسلسل وكرره",
level: "المستوى:",
session_results: "نتائج الجلسة",
focus_score: "درجة تركيزك",
better_than: "أفضل من 65% من جلساتك السابقة",
recommendations: "التوصيات",
recommendation1: "تدرب على مطابقة الألوان لتحسين انتباهك الانتقائي",
recommendation2: "جرب الجلسات الصباحية عندما يكون وقت رد فعلك أسرع عادةً",
recommendation3: "خذ استراحة لمدة 5 دقائق بين الجلسات لتحسين التركيز",
earned_badges: "شارات مكتسبة",
quick_reflexes: "ردود فعل سريعة",
memory_builder: "باني الذاكرة",
master_focus: "سيد التركيز",
score: "النتيجة",
avg_time: "متوسط الوقت:",
max_sequence: "أقصى تسلسل:"
}
};
// DOM elements
const homeScreen = document.getElementById('homeScreen');
const moduleSelectionScreen = document.getElementById('moduleSelectionScreen');
const countdownScreen = document.getElementById('countdownScreen');
const reactionGame = document.getElementById('reactionGame');
const stroopGame = document.getElementById('stroopGame');
const sequenceGame = document.getElementById('sequenceGame');
const resultsScreen = document.getElementById('resultsScreen');
const moduleTitle = document.getElementById('moduleTitle');
const countdown = document.getElementById('countdown');
// Navigation functions
function showModuleSelection() {
homeScreen.classList.add('hidden');
moduleSelectionScreen.classList.remove('hidden');
}
function backToHome() {
homeScreen.classList.remove('hidden');
moduleSelectionScreen.classList.add('hidden');
countdownScreen.classList.add('hidden');
reactionGame.classList.add('hidden');
stroopGame.classList.add('hidden');
sequenceGame.classList.add('hidden');
resultsScreen.classList.add('hidden');
}
function startExpressSession() {
sessionType = 'express';
startModule('reaction');
}
function startModule(module) {
currentModule = module;
homeScreen.classList.add('hidden');
moduleSelectionScreen.classList.add('hidden');
countdownScreen.classList.remove('hidden');
// Set module title
switch(module) {
case 'reaction':
moduleTitle.textContent = document.querySelector('[data-i18n="reaction_tap"]').textContent;
break;
case 'stroop':
moduleTitle.textContent = document.querySelector('[data-i18n="color_match"]').textContent;
break;
case 'sequence':
moduleTitle.textContent = document.querySelector('[data-i18n="sequence_recall"]').textContent;
break;
}
// Start countdown
let counter = 3;
countdown.textContent = counter;
const countdownInterval = setInterval(() => {
counter--;
countdown.textContent = counter;
if (counter <= 0) {
clearInterval(countdownInterval);
startGame();
}
}, 1000);
}
function startGame() {
countdownScreen.classList.add('hidden');
switch(currentModule) {
case 'reaction':
setupReactionGame();
reactionGame.classList.remove('hidden');
break;
case 'stroop':
setupStroopGame();
stroopGame.classList.remove('hidden');
break;
case 'sequence':
setupSequenceGame();
sequenceGame.classList.remove('hidden');
break;
}
}
function finishModule() {
// Hide all game screens
reactionGame.classList.add('hidden');
stroopGame.classList.add('hidden');
sequenceGame.classList.add('hidden');
if (sessionType === 'express') {
// Move to next module in express session
if (currentModule === 'reaction') {
startModule('stroop');
} else if (currentModule === 'stroop') {
startModule('sequence');
} else {
// All modules completed, show results
showResults();
}
} else {
// Single module mode, show results
showResults();
}
}
function showResults() {
resultsScreen.classList.remove('hidden');
}
// Reaction Tap Game
function setupReactionGame() {
reactionTimes = [];
document.getElementById('reactionTrials').textContent = '0/10';
document.getElementById('avgReaction').textContent = '-';
document.getElementById('reactionProgress').style.width = '0%';
document.getElementById('reactionProgressText').textContent = '0%';
const reactionDot = document.getElementById('reactionDot');
reactionDot.classList.add('hidden');
// Start first trial after a random delay
setTimeout(startReactionTrial, Math.random() * 2000 + 1000);
}
function startReactionTrial() {
const reactionArea = document.getElementById('reactionArea');
const reactionDot = document.getElementById('reactionDot');
// Position dot randomly within area
const maxX = reactionArea.offsetWidth - reactionDot.offsetWidth;
const maxY = reactionArea.offsetHeight - reactionDot.offsetHeight;
const posX = Math.floor(Math.random() * maxX);
const posY = Math.floor(Math.random() * maxY);
reactionDot.style.left = `${posX}px`;
reactionDot.style.top = `${posY}px`;
// Show dot and start timer
reactionDot.classList.remove('hidden');
reactionDot.startTime = Date.now();
// Set timeout for missed taps (1.5 seconds)
reactionDot.timeout = setTimeout(() => {
reactionDot.classList.add('hidden');
recordReactionTime(null); // null indicates a miss
// Start next trial if not finished
if (reactionTimes.length < 10) {
setTimeout(startReactionTrial, Math.random() * 1000 + 500);
} else {
finishModule();
}
}, 1500);
}
function recordReactionTime(time) {
const reactionDot = document.getElementById('reactionDot');
clearTimeout(reactionDot.timeout);
reactionDot.classList.add('hidden');
if (time !== null) {
reactionTimes.push(time);
}
// Update UI
const completedTrials = reactionTimes.length;
document.getElementById('reactionTrials').textContent = `${completedTrials}/10`;
// Calculate average reaction time (only for successful taps)
const successfulTrials = reactionTimes.filter(t => t !== null);
if (successfulTrials.length > 0) {
const avg = Math.round(successfulTrials.reduce((a, b) => a + b, 0) / successfulTrials.length);
document.getElementById('avgReaction').textContent = `${avg}ms`;
}
// Update progress
const progress = (completedTrials / 10) * 100;
document.getElementById('reactionProgress').style.width = `${progress}%`;
document.getElementById('reactionProgressText').textContent = `${progress}%`;
// Start next trial or finish
if (completedTrials < 10) {
setTimeout(startReactionTrial, Math.random() * 1000 + 500);
} else {
setTimeout(finishModule, 1000);
}
}
// Add click event to reaction dot
document.getElementById('reactionDot').addEventListener('click', function() {
const reactionTime = Date.now() - this.startTime;
recordReactionTime(reactionTime);
});
// Stroop Test Game
function setupStroopGame() {
stroopAnswers = [];
document.getElementById('stroopTrials').textContent = '0/12';
document.getElementById('stroopAccuracy').textContent = '-';
document.getElementById('stroopProgress').style.width = '0%';
document.getElementById('stroopProgressText').textContent = '0%';
// Start first question
showStroopQuestion();
}
const colorWords = ['RED', 'BLUE', 'GREEN', 'YELLOW'];
const colors = ['red', 'blue', 'green', 'yellow'];
function showStroopQuestion() {
const questionElement = document.getElementById('stroopQuestion');
// Randomly select a word and color (different from word)
const word = colorWords[Math.floor(Math.random() * colorWords.length)];
let color = colors[Math.floor(Math.random() * colors.length)];
// Ensure color is different from word (case-insensitive)
while (color.toUpperCase() === word) {
color = colors[Math.floor(Math.random() * colors.length)];
}
// Store correct answer
questionElement.dataset.correctAnswer = color;
// Apply color to text
questionElement.textContent = word;
questionElement.style.color = color;
// Start timer for this question
questionElement.startTime = Date.now();
}
function checkStroopAnswer(selectedColor) {
const questionElement = document.getElementById('stroopQuestion');
const correctAnswer = questionElement.dataset.correctAnswer;
const responseTime = Date.now() - questionElement.startTime;
// Record answer
stroopAnswers.push({
correct: selectedColor === correctAnswer,
time: responseTime
});
// Update UI
const completedQuestions = stroopAnswers.length;
document.getElementById('stroopTrials').textContent = `${completedQuestions}/12`;
// Calculate accuracy
const correctAnswers = stroopAnswers.filter(a => a.correct).length;
const accuracy = Math.round((correctAnswers / completedQuestions) * 100);
document.getElementById('stroopAccuracy').textContent = `${accuracy}%`;
// Update progress
const progress = (completedQuestions / 12) * 100;
document.getElementById('stroopProgress').style.width = `${progress}%`;
document.getElementById('stroopProgressText').textContent = `${progress}%`;
// Show next question or finish
if (completedQuestions < 12) {
setTimeout(showStroopQuestion, 500);
} else {
setTimeout(finishModule, 1000);
}
}
// Sequence Recall Game
function setupSequenceGame() {
sequenceLevel = 1;
document.getElementById('sequenceLevel').textContent = '1';
document.getElementById('sequenceProgress').style.width = '0%';
document.getElementById('sequenceProgressText').textContent = '0%';
// Clear display and input areas
const displayArea = document.getElementById('sequenceDisplayArea');
const inputArea = document.getElementById('sequenceInputArea');
displayArea.innerHTML = '';
inputArea.innerHTML = '';
// Create input buttons (1-9)
for (let i = 1; i <= 9; i++) {
const button = document.createElement('div');
button.className = 'sequence-item bg-gray-100 text-gray-800';
button.textContent = i;
button.onclick = function() { checkSequenceInput(i); };
inputArea.appendChild(button);
}
// Start first level
startSequenceLevel();
}
function startSequenceLevel() {
const displayArea = document.getElementById('sequenceDisplayArea');
displayArea.innerHTML = '';
// Generate random sequence
const sequence = [];
for (let i = 0; i < sequenceLevel; i++) {
sequence.push(Math.floor(Math.random() * 9) + 1);
}
// Display sequence with delay between items
let index = 0;
const displayInterval = setInterval(() => {
if (index >= sequence.length) {
clearInterval(displayInterval);
// After displaying all items, wait a bit then clear for user input
setTimeout(() => {
displayArea.innerHTML = '';
// Now waiting for user input
}, 500);
return;
}
const item = document.createElement('div');
item.className = 'sequence-item bg-blue-500 text-white';
item.textContent = sequence[index];
displayArea.appendChild(item);
index++;
}, 1000);
// Store sequence and reset user input
displayArea.dataset.sequence = sequence.join(',');
displayArea.dataset.userInput = '';
}
function checkSequenceInput(number) {
const displayArea = document.getElementById('sequenceDisplayArea');
const sequence = displayArea.dataset.sequence.split(',').map(Number);
let userInput = displayArea.dataset.userInput ?
displayArea.dataset.userInput.split(',').map(Number) : [];
// Add new input
userInput.push(number);
displayArea.dataset.userInput = userInput.join(',');
// Check if input matches sequence so far
for (let i = 0; i < userInput.length; i++) {
if (userInput[i] !== sequence[i]) {
// Incorrect - level failed
levelFailed();
return;
}
}
// Check if sequence complete
if (userInput.length === sequence.length) {
levelCompleted();
}
}
function levelCompleted() {
// Update progress
const progress = (sequenceLevel / 8) * 100;
document.getElementById('sequenceProgress').style.width = `${progress}%`;
document.getElementById('sequenceProgressText').textContent = `${Math.min(progress, 100)}%`;
if (sequenceLevel < 8) {
// Next level
sequenceLevel++;
document.getElementById('sequenceLevel').textContent = sequenceLevel;
setTimeout(startSequenceLevel, 1000);
} else {
// Max level reached
setTimeout(finishModule, 1000);
}
}
function levelFailed() {
// Show failure feedback
const displayArea = document.getElementById('sequenceDisplayArea');
displayArea.innerHTML = '<div class="text-red-500 font-bold">Incorrect sequence</div>';
// After delay, show results
setTimeout(() => {
finishModule();
}, 1500);
}
// Language functions
function changeLanguage(lang) {
currentLanguage = lang;
document.getElementById('currentLanguage').textContent = lang.toUpperCase();
translatePage();
}
function translatePage() {
const elements = document.querySelectorAll('[data-i18n]');
elements.forEach(element => {
const key = element.getAttribute('data-i18n');
if (translations[currentLanguage] && translations[currentLanguage][key]) {
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
element.placeholder = translations[currentLanguage][key];
} else {
element.textContent = translations[currentLanguage][key];
}
}
});
// RTL support for Arabic
if (currentLanguage === 'ar') {
document.body.setAttribute('dir', 'rtl');
document.body.style.textAlign = 'right';
} else {
document.body.setAttribute('dir', 'ltr');
document.body.style.textAlign = 'left';
}
}
// Initialize with English
changeLanguage('en');
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=SaidAmchghal/trifocus" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>