# TetaRdPG — Brief Sprint 4

> Statut : ⬜ À lancer
> Objectif : Succès individuels + Succès communautaires + Hall of Fame + Profil joueur enrichi
> Stack : NestJS · MySQL · TypeORM
> Prérequis : Sprint 3 livré ✅ (items, forge, craft, economy, twitch)
> Source design : `TetaRdPG/Sprint 4 _ Focus Succès & Hall of Fame.docx` + `Annexes/5. Système de succès.docx`

---

## Scope Sprint 4

### ✅ In scope

- Entité `achievements` — catalogue de succès avec critères de déblocage
- Entité `player_achievements` — suivi progression par joueur
- 5 catégories : Progression, Combat, Zones, Équipements, Économie
- Récompenses au déblocage : Or, XP bonus, titres honorifiques
- Entité `community_goals` — objectifs collectifs (monstres tués, TetardCoin cumulés)
- Barre de progression communautaire
- Récompenses communautaires : boosts globaux temporaires (XP/loot)
- Hall of Fame mensuel — classement contributeurs + badges
- Interface profil enrichi : badges, titres, % progression succès
- Seeds : 15 succès individuels + 3 objectifs communautaires
- API : voir section dédiée

### ❌ Out of scope

- Notifications Twitch temps réel (extension Twitch) — Sprint 5
- GIGABOSS communautaire (événement 72h) — Sprint événements
- Marché communautaire (échange joueurs) — Sprint économie avancée
- Guildes et alliances — Sprint social
- Boutique événementielle — Sprint économie avancée
- Frontend React complet

---

## Décisions de design (game-designer)

| Décision | Valeur | Justification |
|----------|--------|---------------|
| Tracking succès | Event-driven : chaque action (combat, craft, forge, level) émet un check | Pas de cron — cohérent avec le pattern lazy du projet |
| Catégories succès | 5 : progression, combat, zones, equipment, economy | GDD §5.1 |
| Paliers succès | 3 niveaux par succès (bronze/silver/gold) | Engagement long terme |
| Récompenses déblocage | Or + titre. Pas d'item pour éviter la complexité inventaire Sprint 4 | Simplification — items récompense = Sprint 5 |
| Titres joueur | 1 titre actif à la fois, affiché sur le profil | GDD §4 titres liés aux zones |
| Community goals | Reset mensuel, contribution individuelle trackée | GDD §5.2 |
| Hall of Fame | Classement mensuel, top 10, badges persistants | GDD §5.3 |
| Boost communautaire | Stocké en DB, appliqué comme multiplicateur dans combat/craft | Ex: +20% XP pendant 3j |
| Progression communautaire | Compteur global incrémenté à chaque action qualifiante | Pas de WebSocket — poll GET |

---

## Schéma DB

### `achievements`
```
id uuid PK
key varchar(50) UNIQUE        -- 'combat_100', 'level_50', 'zone_marais_complete'
name varchar(100)
description text
category varchar(20)           -- 'progression' | 'combat' | 'zones' | 'equipment' | 'economy'
tier varchar(10)               -- 'bronze' | 'silver' | 'gold'
criteria_type varchar(30)      -- 'combat_wins' | 'level_reached' | 'gold_accumulated' | ...
criteria_value int             -- seuil à atteindre
reward_gold int default 0
reward_title varchar(100) NULL -- titre débloqué (nullable)
```

### `player_achievements`
```
id uuid PK
character_id uuid FK characters
achievement_id uuid FK achievements
progress int default 0          -- compteur courant
unlocked boolean default false
unlocked_at timestamp NULL
```

### `community_goals`
```
id uuid PK
name varchar(100)
description text
criteria_type varchar(30)       -- 'total_monsters_killed' | 'total_tetardcoin' | ...
target_value bigint             -- objectif collectif
current_value bigint default 0
reward_type varchar(30)         -- 'xp_boost' | 'loot_boost'
reward_multiplier decimal(3,2)  -- ex: 1.20 = +20%
reward_duration_hours int       -- durée du boost
period_start date
period_end date
completed boolean default false
completed_at timestamp NULL
```

### `community_contributions`
```
id uuid PK
community_goal_id uuid FK community_goals
character_id uuid FK characters
contribution_value bigint default 0
```

### `hall_of_fame`
```
id uuid PK
character_id uuid FK characters
period varchar(7)               -- '2026-04' format YYYY-MM
rank int
contribution_total bigint
badge varchar(50)               -- 'top1_april_2026'
```

### `active_boosts` (communautaires)
```
id uuid PK
boost_type varchar(30)          -- 'xp_boost' | 'loot_boost'
multiplier decimal(3,2)
expires_at timestamp
source_goal_id uuid FK community_goals
```

---

## Seeds

### Succès individuels (15)

| Key | Nom | Catégorie | Tier | Critère | Seuil | Récompense Or | Titre |
|-----|-----|-----------|------|---------|-------|---------------|-------|
| `combat_10` | Apprenti Guerrier | combat | bronze | combat_wins | 10 | 50 | — |
| `combat_100` | Guerrier Aguerri | combat | silver | combat_wins | 100 | 200 | Guerrier Aguerri |
| `combat_1000` | Légende du Combat | combat | gold | combat_wins | 1000 | 1000 | Légende |
| `level_10` | Aventurier | progression | bronze | level_reached | 10 | 100 | — |
| `level_50` | Héros | progression | silver | level_reached | 50 | 500 | Héros |
| `level_100` | Légende Vivante | progression | gold | level_reached | 100 | 2000 | Légende Vivante |
| `gold_1000` | Marchand | economy | bronze | gold_accumulated | 1000 | 100 | — |
| `gold_10000` | Négociant | economy | silver | gold_accumulated | 10000 | 500 | Négociant |
| `gold_100000` | Magnat | economy | gold | gold_accumulated | 100000 | 2000 | Magnat |
| `forge_5` | Apprenti Forgeron | equipment | bronze | forge_upgrades | 5 | 100 | — |
| `forge_25` | Maître Forgeron | equipment | silver | forge_upgrades | 25 | 500 | Maître Forgeron |
| `forge_100` | Forgeron Légendaire | equipment | gold | forge_upgrades | 100 | 2000 | Forgeron Légendaire |
| `craft_5` | Artisan Novice | equipment | bronze | craft_completed | 5 | 75 | — |
| `craft_25` | Artisan Confirmé | equipment | silver | craft_completed | 25 | 300 | Artisan |
| `craft_100` | Grand Artisan | equipment | gold | craft_completed | 100 | 1500 | Grand Artisan |

### Objectifs communautaires (3)

| Nom | Critère | Cible | Boost | Durée |
|-----|---------|-------|-------|-------|
| Chasse aux Monstres | total_monsters_killed | 10 000 | +20% XP | 72h |
| Trésor Communautaire | total_gold_earned | 1 000 000 | +15% loot | 48h |
| Fièvre de la Forge | total_forge_upgrades | 500 | +10% XP | 48h |

---

## API Sprint 4

```
# Succès individuels
GET  /api/achievements                  → catalogue complet des succès
GET  /api/achievements/me               → progression du joueur (avec %)
POST /api/achievements/claim/:id        → réclamer la récompense d'un succès débloqué

# Succès communautaires
GET  /api/community/goals               → objectifs en cours + barre progression
GET  /api/community/goals/:id/top       → top 10 contributeurs d'un objectif
GET  /api/community/boosts              → boosts actifs (multiplicateurs en cours)

# Hall of Fame
GET  /api/halloffame/current            → classement du mois en cours
GET  /api/halloffame/:period            → classement historique (ex: 2026-04)

# Profil enrichi
GET  /api/profile/me                    → stats + titre actif + badges + succès count
PUT  /api/profile/title                 → { title: "Héros" } → changer titre actif
```

---

## Architecture modules

```
src/
├── achievement/
│   ├── achievement.entity.ts
│   ├── player-achievement.entity.ts
│   ├── achievement.module.ts
│   ├── achievement.service.ts       → check + unlock logic
│   ├── achievement.controller.ts
│   └── achievement.listener.ts      → écoute events combat/craft/forge/levelup
├── community/
│   ├── community-goal.entity.ts
│   ├── community-contribution.entity.ts
│   ├── active-boost.entity.ts
│   ├── community.module.ts
│   ├── community.service.ts
│   └── community.controller.ts
├── halloffame/
│   ├── hall-of-fame.entity.ts
│   ├── halloffame.module.ts
│   ├── halloffame.service.ts        → calcul mensuel + badge attribution
│   └── halloffame.controller.ts
├── profile/
│   ├── profile.module.ts
│   ├── profile.service.ts
│   └── profile.controller.ts
└── database/
    ├── achievements-seed.ts
    └── community-goals-seed.ts
```

---

## Intégration modules existants

### CombatService — émission événements succès

```typescript
// Après résolution combat — émettre pour achievement tracker
if (result.winner === 'player') {
  this.eventEmitter.emit('achievement.check', {
    characterId: character.id,
    type: 'combat_wins',
    increment: 1,
  });
  this.eventEmitter.emit('community.contribute', {
    characterId: character.id,
    type: 'total_monsters_killed',
    increment: 1,
  });
}
```

### ForgeService / CraftService — même pattern

```typescript
// Après forge réussie
this.eventEmitter.emit('achievement.check', {
  characterId, type: 'forge_upgrades', increment: 1,
});
this.eventEmitter.emit('community.contribute', {
  characterId, type: 'total_forge_upgrades', increment: 1,
});
```

### Boosts actifs — application dans CombatEngine

```typescript
// Dans CombatService — vérifier boosts communautaires actifs
const xpBoost = await this.communityService.getActiveMultiplier('xp_boost');
rewards.xp = Math.floor(baseXp * xpBoost); // xpBoost = 1.0 si aucun boost
```

---

## Migration TypeORM

```
Sprint4Achievements — 6 tables :
  achievements, player_achievements,
  community_goals, community_contributions,
  hall_of_fame, active_boosts

+ ALTER characters ADD active_title VARCHAR(100) NULL
+ ALTER characters ADD total_gold_earned BIGINT DEFAULT 0  -- tracking cumulé pour succès
```

---

## Critères de validation integrator

- [ ] `GET /api/achievements` → 15 succès seedés, 5 catégories
- [ ] `POST /api/combat/start` → victoire → `player_achievements.progress` incrémenté pour `combat_wins`
- [ ] 10 victoires → succès `combat_10` débloqué automatiquement
- [ ] `GET /api/achievements/me` → progression visible avec %
- [ ] `POST /api/achievements/claim/:id` → or crédité, titre disponible
- [ ] Claim succès déjà réclamé → 400
- [ ] `PUT /api/profile/title` → titre actif changé
- [ ] `GET /api/profile/me` → titre, badges, count succès
- [ ] `GET /api/community/goals` → 3 objectifs avec barre progression
- [ ] Combat victoire → `community_contributions` incrémentée
- [ ] `GET /api/community/goals/:id/top` → top 10 contributeurs
- [ ] Objectif communautaire atteint → boost créé dans `active_boosts`
- [ ] `GET /api/community/boosts` → multiplicateur actif
- [ ] Combat avec boost actif → XP = baseXp × multiplier
- [ ] Boost expiré → non retourné par GET
- [ ] `GET /api/halloffame/current` → classement mois en cours
- [ ] Sans cookie → 401 sur toutes les routes protégées
- [ ] Level up → `player_achievements.progress` incrémenté pour `level_reached`
- [ ] Forge → incrémente `forge_upgrades` + `total_forge_upgrades` communautaire
