# 🏆 Achievement System Umfassende Dokumentation des Achievement-Systems für das Ninja Cross Parkour System. ## 📊 System-Übersicht Das Achievement-System besteht aus: - **32 verschiedene Achievements** in 4 Kategorien - **Automatische tägliche Vergabe** am Ende des Tages - **REST API Endpoints** für Frontend-Integration - **PostgreSQL Funktionen** für effiziente Verarbeitung ## 🎯 Achievement-Kategorien ### 1. Konsistenz-basierte Achievements - **Erste Schritte** 👶 - Erste Zeit aufgezeichnet (5 Punkte) - **Durchhalter** 💪 - 3 Versuche an einem Tag (10 Punkte) - **Fleißig** 🔥 - 5 Versuche an einem Tag (15 Punkte) - **Besessen** 😤 - 10 Versuche an einem Tag (25 Punkte) - **Regelmäßig** 📅 - 5 verschiedene Tage gespielt (20 Punkte) - **Stammgast** ⭐ - 10 verschiedene Tage gespielt (30 Punkte) - **Treue** 💎 - 20 verschiedene Tage gespielt (50 Punkte) - **Veteran** 🏆 - 50 verschiedene Tage gespielt (100 Punkte) ### 2. Verbesserungs-basierte Achievements - **Fortschritt** 📈 - Persönliche Bestzeit um 5 Sekunden verbessert (15 Punkte) - **Durchbruch** ⚡ - Persönliche Bestzeit um 10 Sekunden verbessert (25 Punkte) - **Transformation** 🔄 - Persönliche Bestzeit um 15 Sekunden verbessert (40 Punkte) - **Perfektionist** ✨ - Persönliche Bestzeit um 20 Sekunden verbessert (60 Punkte) ### 3. Saisonale Achievements - **Wochenend-Krieger** 🏁 - Am Wochenende gespielt (10 Punkte) - **Nachmittags-Sportler** ☀️ - Zwischen 14-18 Uhr gespielt (10 Punkte) - **Frühaufsteher** 🌅 - Vor 10 Uhr gespielt (15 Punkte) - **Abend-Sportler** 🌙 - Nach 18 Uhr gespielt (10 Punkte) ### 4. Monatliche Achievements - **Januar-Krieger** ❄️ bis **Dezember-Dynamo** 🎄 (je 20 Punkte) ### 5. Jahreszeiten-Achievements - **Frühjahrs-Fighter** 🌱 - Im Frühling gespielt (30 Punkte) - **Sommer-Sportler** ☀️ - Im Sommer gespielt (30 Punkte) - **Herbst-Held** 🍂 - Im Herbst gespielt (30 Punkte) - **Winter-Warrior** ❄️ - Im Winter gespielt (30 Punkte) ## 🗄️ Datenbank-Schema ### Tabelle: `achievements` ```sql - id (uuid, PK) - name (varchar) - Achievement-Name - description (text) - Beschreibung - category (varchar) - Kategorie - condition_type (varchar) - Bedingungstyp - condition_value (integer) - Bedingungswert - icon (varchar) - Emoji-Icon - points (integer) - Punkte - is_active (boolean) - Aktiv - created_at (timestamp) ``` ### Tabelle: `player_achievements` ```sql - id (uuid, PK) - player_id (uuid, FK) - Verweis auf players.id - achievement_id (uuid, FK) - Verweis auf achievements.id - earned_at (timestamp) - Wann erreicht - progress (integer) - Fortschritt - is_completed (boolean) - Abgeschlossen - created_at (timestamp) ``` ## 🔧 PostgreSQL Funktionen ### `check_consistency_achievements(player_uuid)` Überprüft alle Konsistenz-basierten Achievements für einen Spieler. **Logik:** - Zählt Gesamtläufe des Spielers - Zählt Läufe pro Tag - Zählt verschiedene Spieltage - Vergibt entsprechende Achievements ### `check_improvement_achievements(player_uuid)` Überprüft alle Verbesserungs-basierten Achievements für einen Spieler. **Logik:** - Ermittelt persönliche Bestzeit - Berechnet Verbesserung seit erster Zeit - Vergibt entsprechende Achievements ### `check_seasonal_achievements(player_uuid)` Überprüft alle saisonalen und monatlichen Achievements für einen Spieler. **Logik:** - Prüft Wochentag (Wochenende) - Prüft Tageszeit (morgens, nachmittags, abends) - Prüft Monat (Januar bis Dezember) - Prüft Jahreszeit (Frühling, Sommer, Herbst, Winter) ### `check_all_achievements(player_uuid)` Führt alle Achievement-Überprüfungen für einen Spieler aus. ## 🚀 API Endpoints ### GET `/api/achievements` Alle verfügbaren Achievements abrufen. **Response:** ```json { "success": true, "data": [ { "id": "uuid", "name": "Erste Schritte", "description": "Absolviere deinen ersten Lauf", "category": "consistency", "condition_type": "runs_count", "condition_value": 1, "icon": "👶", "points": 5, "is_active": true } ] } ``` ### GET `/api/achievements/player/:playerId` Achievements eines bestimmten Spielers abrufen. **Response:** ```json { "success": true, "data": [ { "id": "uuid", "achievement_id": "uuid", "name": "Erste Schritte", "description": "Absolviere deinen ersten Lauf", "icon": "👶", "points": 5, "progress": 1, "is_completed": true, "earned_at": "2024-01-01T00:00:00Z" } ] } ``` ### GET `/api/achievements/player/:playerId/stats` Achievement-Statistiken eines Spielers abrufen. **Response:** ```json { "success": true, "data": { "total_achievements": 32, "completed_achievements": 5, "total_points": 150, "earned_points": 75, "completion_percentage": 15.6 } } ``` ### POST `/api/achievements/check/:playerId` Achievements für einen Spieler manuell überprüfen. **Request:** ```json { "achievement_id": "uuid" } ``` ### POST `/api/achievements/daily-check` Tägliche Achievement-Überprüfung für alle Spieler ausführen. **Response:** ```json { "success": true, "message": "Daily achievement check completed", "players_checked": 150, "achievements_awarded": 25 } ``` ### GET `/api/achievements/leaderboard?limit=10` Bestenliste der Spieler nach Achievement-Punkten. **Response:** ```json { "success": true, "data": [ { "player_id": "uuid", "firstname": "Max", "lastname": "Mustermann", "total_points": 500, "completed_achievements": 15, "rank": 1 } ] } ``` ## 📅 Automatisierung ### Tägliches Script ```bash # Manuell ausführen node scripts/daily_achievements.js # Cron-Job einrichten node scripts/setup_cron.js setup # Cron-Job Status prüfen node scripts/setup_cron.js status # Cron-Job entfernen node scripts/setup_cron.js remove ``` ### Cron-Schedule - **Zeit**: Täglich um 23:59 Uhr - **Log**: `/var/log/ninjaserver_achievements.log` ### Script-Details ```javascript // scripts/daily_achievements.js const { checkAllAchievements } = require('../models/Achievement'); async function dailyCheck() { try { // Alle Spieler abrufen const players = await getAllPlayers(); let totalAwarded = 0; for (const player of players) { const awarded = await checkAllAchievements(player.id); totalAwarded += awarded; } console.log(`Daily check completed: ${totalAwarded} achievements awarded`); } catch (error) { console.error('Daily check failed:', error); } } ``` ## 🎮 Frontend-Integration ### Beispiel: Achievement-Liste laden ```javascript async function loadAchievements(playerId) { try { const response = await fetch(`/api/achievements/player/${playerId}`); const data = await response.json(); if (data.success) { data.data.forEach(achievement => { const status = achievement.is_completed ? '✅' : '❌'; console.log(`${achievement.icon} ${achievement.name}: ${status}`); }); } } catch (error) { console.error('Error loading achievements:', error); } } ``` ### Beispiel: Statistiken anzeigen ```javascript async function loadStats(playerId) { try { const response = await fetch(`/api/achievements/player/${playerId}/stats`); const data = await response.json(); if (data.success) { const stats = data.data; document.getElementById('total-points').textContent = stats.total_points; document.getElementById('completed').textContent = `${stats.completed_achievements}/${stats.total_achievements}`; document.getElementById('percentage').textContent = `${stats.completion_percentage}%`; } } catch (error) { console.error('Error loading stats:', error); } } ``` ### Beispiel: Achievement-Animation ```javascript function showAchievementNotification(achievement) { const notification = document.createElement('div'); notification.className = 'achievement-notification'; notification.innerHTML = `
${achievement.description}
+${achievement.points} Punkte