$studentId]); if (!$row) { v2_response_error(404, 'not_found', 'Schüler*in nicht gefunden.'); } $locale = $row['locale_pref'] ?? (($row['easy_language'] ?? false) ? 'de-AT-easy' : 'de-AT-standard'); // Level-Unlocks für alle Module dieser Schüler*in $unlocks = v2_db_all(" SELECT module_slug, highest_unlocked_level, highest_completed_level, best_score_per_level, attempts_per_level FROM student_level_unlock_v2 WHERE student_id = :id ", [':id' => $studentId]); $levelUnlocks = []; foreach ($unlocks as $u) { $levelUnlocks[$u['module_slug']] = [ 'highestUnlocked' => $u['highest_unlocked_level'], 'highestCompleted' => $u['highest_completed_level'], 'bestScorePerLevel' => $u['best_score_per_level'] ? json_decode($u['best_score_per_level'], true) : null, 'attemptsPerLevel' => $u['attempts_per_level'] ? json_decode($u['attempts_per_level'], true) : null, ]; } v2_response_ok([ 'studentId' => (int) $row['id'], 'displayName' => $row['display_name'] ?? $row['username'], 'avatarSlug' => $row['avatar_slug'] ?? 'fuchs-explorer', 'avatarUrl' => V2_BASE_URL . '/assets/avatars/avatar-' . ($row['avatar_slug'] ?? 'fuchs-explorer') . '.png', 'easyLanguage' => (bool) ($row['easy_language'] ?? false), 'locale' => $locale, 'country' => $row['country_pref'] ?? 'AT', 'nachteilsausgleich' => (bool) ($row['nachteilsausgleich'] ?? false), 'classId' => (int) $row['class_id'], 'className' => $row['class_name'] ?? '', 'schoolName' => $row['school_name'] ?? '', 'preferences' => [ 'soundOn' => true, 'musicOn' => false, 'highContrast' => (bool) ($row['high_contrast'] ?? false), 'reducedMotion' => (bool) ($row['reduced_motion'] ?? false), 'screenReader' => (bool) ($row['screen_reader'] ?? false), 'textScale' => $row['text_scale'] ?? 'normal', ], 'levelUnlocks' => $levelUnlocks, ]);