Add Wiki Achievement System page

This commit is contained in:
2025-09-23 14:07:07 +02:00
parent 5c01dce9a9
commit 9a704a59f3

479
wiki/Achievement-System.md Normal file
View File

@@ -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 = `
<div class="achievement-icon">${achievement.icon}</div>
<div class="achievement-text">
<h3>${achievement.name}</h3>
<p>${achievement.description}</p>
<span class="points">+${achievement.points} Punkte</span>
</div>
`;
document.body.appendChild(notification);
// Animation
setTimeout(() => {
notification.classList.add('show');
}, 100);
// Entfernen nach 5 Sekunden
setTimeout(() => {
notification.remove();
}, 5000);
}
```
## 🔍 Monitoring
### Logs überwachen
```bash
# Live-Logs anzeigen
tail -f /var/log/ninjaserver_achievements.log
# Letzte Ausführung prüfen
grep "Daily achievement check completed" /var/log/ninjaserver_achievements.log | tail -1
# Fehler-Logs anzeigen
grep "ERROR" /var/log/ninjaserver_achievements.log
```
### Datenbank-Status prüfen
```sql
-- Achievement-Statistiken
SELECT
COUNT(*) as total_achievements,
COUNT(CASE WHEN is_active = true THEN 1 END) as active_achievements
FROM achievements;
-- Spieler-Statistiken
SELECT
COUNT(DISTINCT player_id) as players_with_achievements,
COUNT(*) as total_earned_achievements
FROM player_achievements
WHERE is_completed = true;
-- Top-Spieler
SELECT
p.firstname,
p.lastname,
COUNT(pa.id) as achievements,
SUM(a.points) as total_points
FROM players p
JOIN player_achievements pa ON p.id = pa.player_id
JOIN achievements a ON pa.achievement_id = a.id
WHERE pa.is_completed = true
GROUP BY p.id, p.firstname, p.lastname
ORDER BY total_points DESC
LIMIT 10;
```
## 🛠️ Wartung
### Neue Achievements hinzufügen
1. Achievement in `achievements` Tabelle einfügen:
```sql
INSERT INTO achievements (name, description, category, condition_type, condition_value, icon, points)
VALUES ('Neues Achievement', 'Beschreibung', 'consistency', 'runs_count', 5, '🏆', 25);
```
2. Logik in entsprechenden PostgreSQL Funktionen erweitern
3. API Endpoints testen
### Achievement deaktivieren
```sql
UPDATE achievements SET is_active = false WHERE name = 'Achievement-Name';
```
### Daten zurücksetzen
```sql
-- Alle Spieler-Achievements löschen
DELETE FROM player_achievements;
-- Achievement-Statistiken zurücksetzen
UPDATE achievements SET created_at = NOW();
```
### Achievement-Import/Export
```bash
# Export
pg_dump -t achievements -t player_achievements ninjaserver > achievements_backup.sql
# Import
psql ninjaserver < achievements_backup.sql
```
## 📈 Performance
### Indizierung
```sql
-- Performance-Indizes
CREATE INDEX CONCURRENTLY idx_player_achievements_player_id
ON player_achievements(player_id);
CREATE INDEX CONCURRENTLY idx_player_achievements_achievement_id
ON player_achievements(achievement_id);
CREATE INDEX CONCURRENTLY idx_player_achievements_completed
ON player_achievements(is_completed) WHERE is_completed = true;
```
### Batch-Processing
- **Effiziente Verarbeitung** aller Spieler in einem Durchgang
- **Transaktionale Sicherheit** für Datenkonsistenz
- **Fehlerbehandlung** für einzelne Spieler
### Caching
- **Achievement-Definitionen** werden gecacht
- **Spieler-Statistiken** werden bei Änderungen neu berechnet
- **Leaderboard** wird periodisch aktualisiert
### Zeitzone-Behandlung
- **Korrekte Zeitzone** (Europe/Berlin) für alle Zeitberechnungen
- **Saisonale Achievements** berücksichtigen lokale Zeit
- **Tägliche Prüfung** erfolgt zur richtigen Zeit
## 🔒 Sicherheit
### API-Schutz
- **Alle Endpoints** über bestehende Authentifizierung
- **Admin-Endpoints** erfordern erweiterte Berechtigung
- **Rate Limiting** für häufige Anfragen
### SQL-Injection
- **Parametrisierte Queries** in allen Funktionen
- **Input-Validierung** vor Datenbankzugriff
- **Escape-Funktionen** für dynamische Inhalte
### Datenvalidierung
- **Eingabe-Validierung** in allen API-Endpoints
- **Typ-Überprüfung** für alle Parameter
- **Bereichs-Validierung** für numerische Werte
### Fehlerbehandlung
- **Umfassende Error-Handling** in allen Funktionen
- **Logging** aller Fehler und Warnungen
- **Graceful Degradation** bei Systemfehlern
## 🎯 Best Practices
### Achievement-Design
- **Klare Bedingungen** für alle Achievements
- **Angemessene Punkte** basierend auf Schwierigkeit
- **Motivierende Beschreibungen** für Spieler
### Performance-Optimierung
- **Batch-Processing** für große Datenmengen
- **Indizierung** für häufige Abfragen
- **Caching** für statische Daten
### Wartbarkeit
- **Modulare Struktur** für einfache Erweiterungen
- **Dokumentation** aller Funktionen
- **Tests** für kritische Komponenten
---
**Erstellt am**: $(date)
**Version**: 1.0.0
**Autor**: Ninja Cross Parkour System