'use client' /** * Breakpilot Drive - Test & Lern-Wizard * * Interaktiver Wizard zum Kennenlernen aller Breakpilot Drive Features: * - Game Dashboard Funktionen * - API Integration * - WebGL Embedding * - Quiz-System * - Lernniveau-Anpassung * - Statistiken & Leaderboards */ import { useState, useEffect, useCallback } from 'react' import Link from 'next/link' // ============================================== // Types // ============================================== type StepStatus = 'pending' | 'active' | 'completed' | 'failed' interface WizardStep { id: string name: string icon: string status: StepStatus testable?: boolean } interface TestResult { name: string status: 'passed' | 'failed' | 'pending' message: string details?: string } // ============================================== // Constants // ============================================== const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000' const GAME_URL = process.env.NEXT_PUBLIC_GAME_URL || 'http://localhost:3001' const STEPS: WizardStep[] = [ { id: 'welcome', name: 'Willkommen', icon: '๐ŸŽฎ', status: 'pending' }, { id: 'overview', name: 'Dashboard Uebersicht', icon: '๐Ÿ“Š', status: 'pending' }, { id: 'stats', name: 'Statistiken', icon: '๐Ÿ“ˆ', status: 'pending' }, { id: 'leaderboard', name: 'Leaderboard', icon: '๐Ÿ†', status: 'pending' }, { id: 'webgl', name: 'WebGL Embedding', icon: '๐ŸŽฏ', status: 'pending', testable: true }, { id: 'api', name: 'API Integration', icon: '๐Ÿ”Œ', status: 'pending', testable: true }, { id: 'quiz', name: 'Quiz-System', icon: 'โ“', status: 'pending' }, { id: 'learning', name: 'Lernniveau', icon: '๐Ÿ“š', status: 'pending' }, { id: 'summary', name: 'Zusammenfassung', icon: 'โœ…', status: 'pending' }, ] const EDUCATION_CONTENT: Record = { 'welcome': { title: 'Willkommen bei Breakpilot Drive!', content: [ 'Breakpilot Drive ist ein **Endless Runner Lernspiel** fuer Schueler der Klassen 2-6.', 'Das Spiel kombiniert Spielspass mit Lernen:', 'โ€ข Fahre so weit wie moeglich', 'โ€ข Beantworte Quiz-Fragen um Punkte zu sammeln', 'โ€ข Das System passt sich automatisch an dein Lernniveau an', 'In diesem Wizard lernst du alle Admin-Features kennen und testest die Integration.', ], tips: [ 'Das Spiel laeuft auf Port 3001 als Unity WebGL Build', 'Die API-Endpoints sind unter /api/game/* verfuegbar', ], }, 'overview': { title: 'Das Game Dashboard', content: [ 'Das Dashboard unter **/admin/game** bietet drei Hauptbereiche:', '**1. Uebersicht-Tab:**', 'โ€ข Statistik-Karten mit KPIs (Spieler, Sessions, Genauigkeit)', 'โ€ข Top 5 Leaderboard', 'โ€ข Schnellzugriff-Buttons', '**2. Spielen-Tab:**', 'โ€ข Embedded WebGL Game im iframe', 'โ€ข Direkt im Admin-Panel spielbar', '**3. Statistiken-Tab:**', 'โ€ข Genauigkeit nach Fach', 'โ€ข Aktivitaets-Feed', 'โ€ข Lernniveau-Verteilung', ], tips: [ 'Die Tabs sind oben im Dashboard als Buttons sichtbar', 'Klicke auf "Aktualisieren" um die neuesten Daten zu laden', ], }, 'stats': { title: 'Statistiken verstehen', content: [ 'Die Statistik-Karten zeigen wichtige KPIs:', '**Aktive Spieler heute:** Anzahl der Spieler mit mindestens einer Session heute', '**Spielsessions:** Gesamtzahl aller abgeschlossenen Spielsessions', '**Quiz-Fragen beantwortet:** Kumulative Anzahl beantworteter Fragen', '**Durchschnittliche Genauigkeit:** Prozent der richtig beantworteten Fragen', '**Gesamte Spielzeit:** Summe aller Spielzeiten in Stunden', 'Trends zeigen die Veraenderung zur Vorwoche.', ], tips: [ 'Gruene Trends = Verbesserung', 'Rote Trends = Bereich mit Aufmerksamkeitsbedarf', ], }, 'leaderboard': { title: 'Leaderboard & Gamification', content: [ 'Das Leaderboard motiviert Schueler durch:', '**Ranking:** Top 5 Spieler nach Gesamtpunktzahl', '**Goldene Medaille:** Platz 1 ist besonders hervorgehoben', '**Genauigkeit:** Zeigt wie viele Fragen richtig beantwortet wurden', 'Spaeter kommen hinzu:', 'โ€ข Klassen-Ranglisten', 'โ€ข Wochen/Monats-Ranglisten', 'โ€ข Achievements & Badges', ], tips: [ 'Leaderboards koennen pro Klasse oder schulweit sein', 'Datenschutz: Nur Vornamen + erster Buchstabe des Nachnamens werden gezeigt', ], }, 'webgl': { title: 'WebGL Embedding', content: [ 'Das Spiel wird als **Unity WebGL Build** eingebettet:', '**Technologie:**', 'โ€ข Unity 6 (Version 6000.0)', 'โ€ข Universal Render Pipeline (URP)', 'โ€ข WebAssembly (WASM) fuer Performance', '**Embedding:**', 'โ€ข Das Spiel laeuft in einem iframe auf Port 3001', 'โ€ข Parameter wie ?embed=true optimieren fuer Einbettung', 'โ€ข Fullscreen und Gamepad werden unterstuetzt', '**Wichtig:** Der Game-Container muss laufen:', '`docker-compose --profile game up -d`', ], tips: [ 'Bei Ladefehlern: Container-Status pruefen', 'CORS muss korrekt konfiguriert sein', ], }, 'api': { title: 'API Integration', content: [ 'Die Game API stellt folgende Endpoints bereit:', '**GET /api/game/learning-level**', 'โ†’ Aktuelles Lernniveau des Spielers', '**GET /api/game/questions?difficulty=3&count=5**', 'โ†’ Quiz-Fragen basierend auf Schwierigkeit', '**POST /api/game/session**', 'โ†’ Spielsession speichern (Score, Zeit, Antworten)', '**GET /api/game/achievements**', 'โ†’ Freigeschaltete Achievements', '**GET /api/game/leaderboard?limit=10**', 'โ†’ Top-Spieler Rangliste', ], tips: [ 'Alle Endpoints erfordern JWT-Token in Produktion', 'Im Dev-Modus ist Auth optional', ], }, 'quiz': { title: 'Das Quiz-System', content: [ 'Quiz-Fragen erscheinen waehrend des Spiels:', '**Quick-Modus (5 Sekunden):**', 'โ€ข 2-3 Antwortmoeglichkeiten', 'โ€ข Wird durch visuelle Trigger ausgeloest (Bruecke, Baum)', 'โ€ข Schnelle Punkte bei richtiger Antwort', '**Pause-Modus (unbegrenzt):**', 'โ€ข 4 Antwortmoeglichkeiten', 'โ€ข Spieler kann nachdenken', 'โ€ข Mehr Punkte moeglich', '**Faecher:** Mathematik, Deutsch, Englisch', '**LLM-Generierung:** Fragen werden dynamisch erstellt', ], tips: [ 'Fragen werden im Valkey-Cache gespeichert', 'Schwierigkeit passt sich automatisch an', ], }, 'learning': { title: 'Adaptives Lernniveau', content: [ 'Das System passt sich automatisch an:', '**5 Lernstufen:**', 'โ€ข Level 1: Klasse 2-3 (Beginner)', 'โ€ข Level 2: Klasse 3-4 (Elementary)', 'โ€ข Level 3: Klasse 4-5 (Intermediate)', 'โ€ข Level 4: Klasse 5-6 (Advanced)', 'โ€ข Level 5: Klasse 6+ (Expert)', '**Anpassung:**', 'โ€ข โ‰ฅ80% richtig ueber 10 Fragen โ†’ Level Up', 'โ€ข <40% richtig ueber 5 Fragen โ†’ Level Down', 'โ€ข Schwache Faecher werden identifiziert', '**State Engine:** Nutzt die bestehende Breakpilot State Machine', ], tips: [ 'Eltern sehen das Niveau ihrer Kinder im Dashboard', 'Lehrer sehen Klassen-Durchschnitte', ], }, 'summary': { title: 'Zusammenfassung', content: [ 'Du hast alle Breakpilot Drive Features kennengelernt:', 'โœ… Dashboard mit Uebersicht, Spielen, Statistiken', 'โœ… Statistik-Karten und KPIs', 'โœ… Leaderboard & Gamification', 'โœ… WebGL Embedding', 'โœ… API Integration', 'โœ… Quiz-System mit Quick/Pause-Modus', 'โœ… Adaptives Lernniveau', '**Naechste Schritte:**', 'โ€ข Teste das Dashboard unter /admin/game', 'โ€ข Starte den Game-Container', 'โ€ข Spiele eine Runde im "Spielen"-Tab', ], tips: [ 'Bei Fragen: Siehe docs/breakpilot-drive/README.md', 'API-Doku: docs/breakpilot-drive/architecture.md', ], }, } // ============================================== // Components // ============================================== function WizardStepper({ steps, currentStep, onStepClick }: { steps: WizardStep[] currentStep: number onStepClick: (index: number) => void }) { return (
{steps.map((step, index) => (
{index < steps.length - 1 && (
)}
))}
) } function EducationCard({ stepId }: { stepId: string }) { const content = EDUCATION_CONTENT[stepId] if (!content) return null return (

๐Ÿ“– {content.title}

{content.content.map((line, index) => (

$1') .replace(/`(.*?)`/g, '$1') }} /> ))}

{content.tips && content.tips.length > 0 && (

๐Ÿ’ก Tipps:

{content.tips.map((tip, index) => (

โ€ข {tip}

))}
)}
) } function TestResultCard({ results }: { results: TestResult[] }) { return (

Test-Ergebnisse

{results.map((result, index) => (
{result.status === 'passed' ? 'โœ“' : result.status === 'failed' ? 'โœ—' : 'โ—‹'}

{result.name}

{result.message}

{result.details && ( {result.details} )}
))}
) } function InteractiveDemo({ stepId }: { stepId: string }) { // Step-specific interactive demos if (stepId === 'stats') { return (

Live-Vorschau: Statistik-Karten

{[ { label: 'Aktive Spieler', value: '42', icon: '๐Ÿ‘ฅ', color: 'blue' }, { label: 'Genauigkeit', value: '78%', icon: 'โœ“', color: 'green' }, { label: 'Spielzeit', value: '156h', icon: 'โฑ๏ธ', color: 'purple' }, ].map((stat) => (
{stat.icon}

{stat.value}

{stat.label}

))}
) } if (stepId === 'leaderboard') { return (

Live-Vorschau: Leaderboard

{[ { rank: 1, name: 'Max M.', score: 25000, color: 'yellow' }, { rank: 2, name: 'Lisa K.', score: 23500, color: 'slate' }, { rank: 3, name: 'Tim S.', score: 21000, color: 'orange' }, ].map((entry) => (
{entry.rank} {entry.name}
{entry.score.toLocaleString()} Punkte
))}
) } if (stepId === 'learning') { return (

Live-Vorschau: Lernniveau

{[ { subject: 'Mathematik', level: 3.2, color: 'blue' }, { subject: 'Deutsch', level: 2.8, color: 'green' }, { subject: 'Englisch', level: 3.5, color: 'purple' }, ].map((item) => (
{item.subject} Level {item.level.toFixed(1)}
))}
) } return null } // ============================================== // Main Component // ============================================== export default function GameWizardPage() { const [currentStep, setCurrentStep] = useState(0) const [steps, setSteps] = useState(STEPS) const [testResults, setTestResults] = useState([]) const [isLoading, setIsLoading] = useState(false) const currentStepData = steps[currentStep] const isWelcome = currentStepData?.id === 'welcome' const isSummary = currentStepData?.id === 'summary' // Test functions const runWebGLTest = useCallback(async () => { setIsLoading(true) const results: TestResult[] = [] // Test 1: Game URL erreichbar try { const response = await fetch(GAME_URL, { mode: 'no-cors' }) results.push({ name: 'Game Server Erreichbarkeit', status: 'passed', message: 'Der Game-Server antwortet', details: GAME_URL, }) } catch { results.push({ name: 'Game Server Erreichbarkeit', status: 'failed', message: 'Game-Server nicht erreichbar. Container gestartet?', details: 'docker-compose --profile game up -d', }) } // Test 2: Iframe simulieren results.push({ name: 'Iframe Embedding', status: 'passed', message: 'Iframe-Einbettung ist konfiguriert', details: '?embed=true', }) setTestResults(results) setIsLoading(false) // Update step status const allPassed = results.every(r => r.status === 'passed') setSteps(prev => prev.map(s => s.id === 'webgl' ? { ...s, status: allPassed ? 'completed' : 'failed' } : s )) }, []) const runAPITest = useCallback(async () => { setIsLoading(true) const results: TestResult[] = [] // Test 1: Learning Level API try { const response = await fetch(`${BACKEND_URL}/api/game/learning-level?user_id=test-user`) if (response.ok) { const data = await response.json() results.push({ name: 'Learning Level Endpoint', status: 'passed', message: 'API antwortet korrekt', details: `Level: ${data.overall_level || 'Mock'}`, }) } else { results.push({ name: 'Learning Level Endpoint', status: 'failed', message: `HTTP ${response.status}`, }) } } catch { results.push({ name: 'Learning Level Endpoint', status: 'failed', message: 'Backend nicht erreichbar', details: 'docker-compose up -d backend', }) } // Test 2: Questions API try { const response = await fetch(`${BACKEND_URL}/api/game/questions?difficulty=3&count=2`) if (response.ok) { const data = await response.json() results.push({ name: 'Questions Endpoint', status: 'passed', message: 'Quiz-Fragen API funktioniert', details: `${data.questions?.length || 0} Fragen`, }) } else { results.push({ name: 'Questions Endpoint', status: 'failed', message: `HTTP ${response.status}`, }) } } catch { results.push({ name: 'Questions Endpoint', status: 'failed', message: 'Endpoint nicht erreichbar', }) } // Test 3: Leaderboard API try { const response = await fetch(`${BACKEND_URL}/api/game/leaderboard?limit=5`) if (response.ok) { results.push({ name: 'Leaderboard Endpoint', status: 'passed', message: 'Leaderboard API funktioniert', }) } else { results.push({ name: 'Leaderboard Endpoint', status: 'failed', message: `HTTP ${response.status}`, }) } } catch { results.push({ name: 'Leaderboard Endpoint', status: 'failed', message: 'Endpoint nicht erreichbar', }) } setTestResults(results) setIsLoading(false) // Update step status const passedCount = results.filter(r => r.status === 'passed').length setSteps(prev => prev.map(s => s.id === 'api' ? { ...s, status: passedCount >= 2 ? 'completed' : 'failed' } : s )) }, []) const goToNext = () => { if (currentStep < steps.length - 1) { setSteps(prev => prev.map((step, idx) => idx === currentStep && step.status === 'pending' ? { ...step, status: 'completed' } : step )) setCurrentStep(prev => prev + 1) setTestResults([]) } } const goToPrev = () => { if (currentStep > 0) { setCurrentStep(prev => prev - 1) setTestResults([]) } } const handleStepClick = (index: number) => { setCurrentStep(index) setTestResults([]) } return (
{/* Header */}

๐ŸŽฎ Breakpilot Drive - Lern-Wizard

Interaktive Tour durch alle Game-Features

โ† Zurueck zum Dashboard
{/* Stepper */}
{/* Content */}
{/* Step Header */}
{currentStepData?.icon}

Schritt {currentStep + 1}: {currentStepData?.name}

{currentStep + 1} von {steps.length}

{/* Education Card */} {/* Interactive Demo */} {/* Test Section for testable steps */} {currentStepData?.testable && (
{testResults.length === 0 ? (
) : ( )}
)} {/* Welcome Start Button */} {isWelcome && (
)} {/* Summary Actions */} {isSummary && (
๐Ÿ“Š Zum Dashboard
)} {/* Navigation */} {!isWelcome && (
{!isSummary && ( )}
)}
{/* Footer Info */}
Breakpilot Drive - Endless Runner Lernspiel fuer Klasse 2-6
) }