diff --git a/wiki/Achievement-System.md b/wiki/Achievement-System.md new file mode 100644 index 0000000..fc840bc --- /dev/null +++ b/wiki/Achievement-System.md @@ -0,0 +1,479 @@ +# 🏆 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 +