import React, { useState, useEffect, useCallback, useRef } from 'react'; import { Button } from '../components/ui/Button'; import { ArrowLeft, Play, RefreshCw, Trophy, Lightbulb, Zap, AlertTriangle, Cpu, Timer, ShieldAlert } from 'lucide-react'; import { StorageService } from '../services/storageService'; import confetti from 'canvas-confetti'; interface GameProps { onExit: () => void; } type LogicPattern = 'arithmetic' | 'geometric' | 'alternating' | 'squares'; interface SequenceData { sequence: (number | string)[]; answer: number; options: number[]; explanation: string; } export const LogicFuses: React.FC = ({ onExit }) => { const [isPlaying, setIsPlaying] = useState(false); const [gameOver, setGameOver] = useState(false); const [score, setScore] = useState(0); const [highScore, setHighScore] = useState(0); const [currentRound, setCurrentRound] = useState(null); const [timeLeft, setTimeLeft] = useState(15000); // 15 seconds const [isCorrect, setIsCorrect] = useState(null); const timerRef = useRef(0); const startTimeRef = useRef(0); useEffect(() => { const loadHighScore = async () => { const profile = await StorageService.getProfile(); if (profile?.highScores?.truth) setHighScore(profile.highScores.truth); }; loadHighScore(); return () => cancelAnimationFrame(timerRef.current); }, []); const playTone = (freq: number, type: OscillatorType = 'sine', duration = 0.1) => { try { const ctx = new (window.AudioContext || (window as any).webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = type; osc.frequency.setValueAtTime(freq, ctx.currentTime); gain.gain.setValueAtTime(0.1, ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + duration); osc.connect(gain); gain.connect(ctx.destination); osc.start(); osc.stop(ctx.currentTime + duration); } catch (e) {} }; const generateRound = useCallback(() => { const types: LogicPattern[] = ['arithmetic', 'geometric', 'alternating', 'squares']; const type = types[Math.floor(Math.random() * types.length)]; let seq: number[] = []; let answer = 0; let explanation = ""; if (type === 'arithmetic') { const start = Math.floor(Math.random() * 20); const diff = Math.floor(Math.random() * 10) + 2; seq = [0, 1, 2, 3, 4].map(i => start + i * diff); explanation = `Add ${diff} to each number.`; } else if (type === 'geometric') { const start = Math.floor(Math.random() * 5) + 1; const ratio = Math.floor(Math.random() * 2) + 2; // 2 or 3 seq = [0, 1, 2, 3, 4].map(i => start * Math.pow(ratio, i)); explanation = `Multiply by ${ratio} each time.`; } else if (type === 'alternating') { const start = Math.floor(Math.random() * 10); const d1 = Math.floor(Math.random() * 5) + 1; const d2 = Math.floor(Math.random() * 5) + 1; let curr = start; for (let i = 0; i < 5; i++) { seq.push(curr); curr += (i % 2 === 0) ? d1 : d2; } explanation = `Alternating additions of ${d1} and ${d2}.`; } else { const start = Math.floor(Math.random() * 5) + 1; seq = [0, 1, 2, 3, 4].map(i => Math.pow(start + i, 2)); explanation = "Sequence of squares."; } const missingIdx = Math.floor(Math.random() * 3) + 1; // Don't hide first or last usually answer = seq[missingIdx]; const displaySeq: (number | string)[] = [...seq]; displaySeq[missingIdx] = "?"; // Generate options const options = new Set(); options.add(answer); while (options.size < 4) { const offset = (Math.floor(Math.random() * 10) + 1) * (Math.random() > 0.5 ? 1 : -1); const fake = Math.max(0, answer + offset); if (fake !== answer) options.add(fake); } setCurrentRound({ sequence: displaySeq, answer, options: Array.from(options).sort((a, b) => a - b), explanation }); setIsCorrect(null); setTimeLeft(15000); startTimeRef.current = Date.now(); }, []); const handleGameOver = useCallback(() => { setIsPlaying(false); setGameOver(true); playTone(100, 'sawtooth', 0.5); const karmaEarned = Math.floor(score / 50); // Add transaction description StorageService.addPoints(karmaEarned, score, 'game_reward', 'Logic Fuses Session'); if (score > highScore) { setHighScore(score); StorageService.saveHighScore('truth', score); // Reusing truth slot } }, [score, highScore]); const handleAnswer = (val: number) => { if (!isPlaying || !currentRound || isCorrect !== null) return; if (val === currentRound.answer) { setIsCorrect(true); const timeBonus = Math.floor(timeLeft / 100); setScore(prev => prev + 100 + timeBonus); playTone(800, 'sine', 0.1); setTimeout(() => { generateRound(); }, 600); } else { setIsCorrect(false); handleGameOver(); } }; const updateTimer = useCallback(() => { if (!isPlaying || isCorrect !== null) return; const elapsed = Date.now() - startTimeRef.current; const remaining = Math.max(0, 15000 - elapsed); setTimeLeft(remaining); if (remaining === 0) { handleGameOver(); } else { timerRef.current = requestAnimationFrame(updateTimer); } }, [isPlaying, isCorrect, handleGameOver]); useEffect(() => { if (isPlaying) { timerRef.current = requestAnimationFrame(updateTimer); } else { cancelAnimationFrame(timerRef.current); } return () => cancelAnimationFrame(timerRef.current); }, [isPlaying, updateTimer]); const startGame = () => { setScore(0); setGameOver(false); setIsPlaying(true); generateRound(); }; return (
{/* Background Decor - Industrial Theme */}
{/* Animated Bolts/Grid */}
{[...Array(36)].map((_, i) => (
))}
{isPlaying && (
Score {score}
)}
{!isPlaying && !gameOver && (

Logic Fuses

Analyze the numerical current. Identify the pattern and replace the missing fuse before the system overloads.

Pattern Recognition
15.0s
)} {isPlaying && currentRound && (
{/* Electrical Panel Container */}
{/* Timer LED Bar */}
Voltage Stability {(timeLeft/1000).toFixed(1)}V
{[...Array(20)].map((_, i) => { const percentage = (timeLeft / 15000) * 100; const isActive = (i / 20) * 100 < percentage; return (
); })}
{/* Number Display Grid */}
{currentRound.sequence.map((num, i) => (
{num === '?' && isCorrect === true ? currentRound.answer : num}
))}
{/* Option Buttons */}
{currentRound.options.map((opt, i) => ( ))}
{/* Industrial Labels */}
System-ID: LOGIC_CORE_V3

Select the Missing Key

)} {gameOver && (

Overload

System synchronization failed due to pattern error.

Last Valid Round Pattern

{currentRound?.explanation}

Final Intelligence Units

{score}

)}
); };