Files
TetaRdPG/SPRINT4.md
Tetardtek 8c6777c980
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 1m2s
feat: PKCE auth + CI/CD deploy
- Frontend: PKCE flow (oauth.ts, AuthCallback code exchange, 401 interceptor)
- Backend: token introspection via SuperOAuth (no more JWT secret)
- User model: superOauthId (unified) replaces oauthId+provider
- Cookies httpOnly session + refresh token
- POST /auth/refresh endpoint
- Gitea CI workflow (vps-runner pattern)
- DB_SYNC env var for initial schema creation
2026-03-24 13:01:14 +01:00

293 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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