Prize Pool et Économie
Cette section détaille le système d'économie virtuelle du jeu, incluant la gestion du prize pool, des frais d'entrée, et de la distribution des gains.
PrizePoolService (prize-pool.service.ts)
Service qui gère la distribution de la monnaie virtuelle en fin de partie.
Méthodes principales
async distributePrizePool(game: OnGoingGame)
Description : Distribue le prize pool de la partie aux joueurs.
Paramètres :
game: Partie terminée
Logique de distribution :
- Identifie les gagnants (équipe ou joueur unique)
- Filtre les bots (ne reçoivent pas de monnaie)
- Calcule les montants :
- 2/3 du prize pool → gagnants (divisé équitablement)
- 1/3 du prize pool → perdants (prix de consolation, divisé équitablement)
- Crédite les comptes via
UserService - Log des distributions
Cas particuliers :
- Dernier survivant : Reçoit 2/3 du prize pool
- Aucun gagnant (tous morts) : Prize pool divisé équitablement entre tous
- Bots : Exclus de la distribution
Retour : Promise<void>
private async creditWinners(winners: Player[], amount: number)
Description : Crédite les comptes des gagnants.
Paramètres :
winners: Liste des joueurs gagnantsamount: Montant total à distribuer
Actions :
- Filtre les bots
- Calcule montant par gagnant
- Crédite chaque compte via
UserService.addVirtualCurrency()
Retour : Promise<void>
private async creditLosers(losers: Player[], amount: number)
Description : Crédite les comptes des perdants (prix de consolation).
Paramètres :
losers: Liste des joueurs perdantsamount: Montant total à distribuer
Logique : Identique à creditWinners mais avec 1/3 du prize pool
Retour : Promise<void>
async refundPlayer(firebaseUid: string, amount: number)
Description : Rembourse un joueur (si partie annulée ou joueur expulsé).
Paramètres :
firebaseUid: Firebase UID du joueuramount: Montant à rembourser
Actions : Crédite le compte via UserService.addVirtualCurrency()
Retour : Promise<void>
Intégration avec OnGoingGame
Propriétés liées à l'économie
OnGoingGame
{
prizePool: number, // Cagnotte accumulée
entryFee: number, // Frais d'entrée (0-100 coins)
// ...
}
Flux du prize pool
1. Configuration de la partie
const game = new OnGoingGame({
entryFee: 50, // Admin définit les frais
prizePool: 0 // Initialisé à 0
});
2. Joueurs rejoignent
// Pour chaque joueur rejoignant:
if (game.entryFee > 0) {
// Vérifier solde
if (user.virtualCurrencyBalance >= game.entryFee) {
// Débiter
await userService.deductVirtualCurrency(
user.firebaseUid,
game.entryFee
);
// Ajouter au prize pool
game.prizePool += game.entryFee;
} else {
// Refuser l'accès
throw new Error('Insufficient funds');
}
}
3. Fin de partie
await prizePoolService.distributePrizePool(game);
4. Distribution calculée
const winnersShare = Math.floor(game.prizePool * 2 / 3);
const losersShare = game.prizePool - winnersShare;
const amountPerWinner = Math.floor(winnersShare / realWinners.length);
const amountPerLoser = Math.floor(losersShare / realLosers.length);
Intégration avec UserService
Méthodes utilisées
async addVirtualCurrency(firebaseUid: string, amount: number)
Description : Ajoute de la monnaie virtuelle au solde d'un utilisateur.
Paramètres :
firebaseUid: Firebase UIDamount: Montant à ajouter
Actions : Incrémente virtualCurrencyBalance
Retour : Promise<void>
async deductVirtualCurrency(firebaseUid: string, amount: number)
Description : Déduit de la monnaie virtuelle du solde d'un utilisateur.
Paramètres :
firebaseUid: Firebase UIDamount: Montant à déduire
Validation : Solde suffisant
Actions : Décrémente virtualCurrencyBalance
Retour : Promise<void>
Scénarios d'économie
1. Partie avec frais d'entrée
Configuration :
- entryFee: 50 coins
- 4 joueurs rejoignent
Accumulation :
- Prize pool = 50 × 4 = 200 coins
Distribution :
- Gagnants (2 joueurs) : 2/3 × 200 = 133 coins → 66 coins chacun
- Perdants (2 joueurs) : 1/3 × 200 = 66 coins → 33 coins chacun
Bilan : Total distribué = 132 + 66 = 198 coins (arrondi inférieur)
2. Partie sans frais
Configuration :
- entryFee: 0 coins
Résultat :
- Prize pool = 0
- Aucune distribution
- Pas de transaction de monnaie
3. Partie annulée
Situation : Admin quitte avant démarrage
Actions :
- Remboursement automatique via
refundPlayer() - Chaque joueur récupère son frais d'entrée
- Prize pool retourne à 0
4. Joueur expulsé (kick)
Situation : Admin expulse un joueur de la salle d'attente
Actions :
- Remboursement du frais d'entrée
- Déduction du prize pool
- Notification au joueur expulsé
5. Dernier survivant (Battle Royale)
Situation : Un seul joueur reste en vie
Distribution :
- Gagnant unique : 2/3 du prize pool
- Perdants (morts) : 1/3 divisé entre tous
Validation des frais d'entrée
Configuration de la partie
Lors de la création de partie, validation du entryFee :
- Min : 0 coins (gratuit)
- Max : 100 coins
- Type : Entier positif
Vérification avant de rejoindre
if (game.entryFee > 0) {
const user = await userService.getUserByFirebaseUid(firebaseUid);
if (user.virtualCurrencyBalance < game.entryFee) {
throw new Error('Insufficient funds');
}
}
Monnaie Virtuelle
Solde par défaut
Nouveaux utilisateurs :
- Balance initiale : 1000 coins
Sources de gains
- Parties gagnées : 2/3 du prize pool divisé
- Parties perdues : 1/3 du prize pool divisé (consolation)
- Bonus futurs : Quêtes, achievements, événements (non implémentés)
Dépenses
- Frais d'entrée : 0-100 coins par partie
- Boutique : 300-1500 coins par item
Équilibrage
Le système est conçu pour que :
- Les gagnants gagnent plus que ce qu'ils ont dépensé (ROI positif)
- Les perdants récupèrent une partie de leur investissement
- La monnaie circule dans l'économie
- Les joueurs doivent jouer pour acheter des items premium
Gestion d'erreurs
Fonds insuffisants
Scénario : Joueur tente de rejoindre une partie payante sans solde suffisant
Réponse :
{
error: 'INSUFFICIENT_FUNDS',
message: 'You do not have enough virtual currency',
required: 50,
current: 30
}
Erreur de distribution
Scénario : Erreur lors du crédit d'un compte
Actions :
- Log de l'erreur
- Tentative de rollback si possible
- Notification admin via logs
Logging
Tous les événements économiques sont loggés :
- Débit de frais d'entrée
- Ajout au prize pool
- Distribution aux gagnants
- Distribution aux perdants
- Remboursements
Format :
[PrizePoolService] Distributing 200 coins to 4 players
[PrizePoolService] Winner user123 received 66 coins
[PrizePoolService] Loser user456 received 33 coins
Extensions possibles
Bonus et multiplicateurs
- Bonus de victoire consécutive
- Multiplicateurs saisonniers
- Bonus de première partie du jour
Leaderboard économique
- Classement par richesse
- Classement par gains totaux
- Récompenses pour top players
Transactions
- Transactions MongoDB pour garantir consistance
- Rollback automatique en cas d'erreur
- Audit trail des transactions