222 lines
5.6 KiB
JavaScript
222 lines
5.6 KiB
JavaScript
/**
|
|
* Fonctions utilitaires pour le système XP
|
|
*/
|
|
|
|
const db = require('../database/db.js');
|
|
|
|
// Formule de calcul de l'XP nécessaire pour atteindre un niveau
|
|
// XP total nécessaire = 5 * (level^2) + (50 * level) + 100
|
|
// Exemples :
|
|
// - Niveau 1 : 5 * 1^2 + 50 * 1 + 100 = 155 XP total
|
|
// - Niveau 2 : 5 * 2^2 + 50 * 2 + 100 = 220 XP total
|
|
// - Niveau 3 : 5 * 3^2 + 50 * 3 + 100 = 295 XP total
|
|
function getXPForLevel(level) {
|
|
if (level <= 0) return 0;
|
|
return Math.floor(5 * Math.pow(level, 2) + 50 * level + 100);
|
|
}
|
|
|
|
// Calculer le niveau à partir de l'XP total
|
|
function getLevelFromXP(xp) {
|
|
if (xp < 0) return 0;
|
|
|
|
let level = 0;
|
|
let requiredXP = getXPForLevel(level + 1);
|
|
|
|
// Trouver le niveau en vérifiant l'XP nécessaire
|
|
while (xp >= requiredXP) {
|
|
level++;
|
|
requiredXP = getXPForLevel(level + 1);
|
|
}
|
|
|
|
return level;
|
|
}
|
|
|
|
// Calculer l'XP nécessaire pour le prochain niveau
|
|
function getXPForNextLevel(level) {
|
|
return getXPForLevel(level + 1);
|
|
}
|
|
|
|
// Calculer l'XP progress dans le niveau actuel
|
|
function getXPProgress(xp, level) {
|
|
// XP nécessaire pour atteindre le niveau actuel
|
|
const xpForCurrentLevel = getXPForLevel(level);
|
|
// XP nécessaire pour atteindre le prochain niveau
|
|
const xpForNextLevel = getXPForLevel(level + 1);
|
|
|
|
// XP dans le niveau actuel (différence entre l'XP total et l'XP du niveau actuel)
|
|
const xpInLevel = Math.max(0, xp - xpForCurrentLevel);
|
|
// XP nécessaire pour passer au niveau suivant
|
|
const xpNeeded = xpForNextLevel - xpForCurrentLevel;
|
|
|
|
// Éviter la division par zéro
|
|
if (xpNeeded <= 0) {
|
|
return {
|
|
current: xpInLevel,
|
|
needed: 100,
|
|
percentage: 0
|
|
};
|
|
}
|
|
|
|
const percentage = Math.max(0, Math.min(100, Math.floor((xpInLevel / xpNeeded) * 100)));
|
|
|
|
return {
|
|
current: xpInLevel,
|
|
needed: xpNeeded,
|
|
percentage: percentage
|
|
};
|
|
}
|
|
|
|
// Obtenir ou créer un utilisateur dans la table XP
|
|
async function getUserXP(userId, guildId) {
|
|
try {
|
|
const [rows] = await db.query(
|
|
'SELECT * FROM user_xp WHERE userId = ? AND guildId = ?',
|
|
[userId, guildId]
|
|
);
|
|
|
|
if (rows.length === 0) {
|
|
// Créer l'utilisateur avec 0 XP
|
|
await db.query(
|
|
'INSERT INTO user_xp (userId, guildId, xp, level) VALUES (?, ?, 0, 0)',
|
|
[userId, guildId]
|
|
);
|
|
return {
|
|
userId,
|
|
guildId,
|
|
xp: 0,
|
|
level: 0,
|
|
lastMessageTime: 0,
|
|
totalMessages: 0,
|
|
totalVoiceTime: 0,
|
|
lastVoiceJoin: 0,
|
|
lastBumpTime: 0
|
|
};
|
|
}
|
|
|
|
return rows[0];
|
|
} catch (err) {
|
|
console.error('Erreur lors de la récupération de l\'XP:', err);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Ajouter de l'XP à un utilisateur
|
|
async function addXP(userId, guildId, xpGained, source = 'message', multiplier = 1.0) {
|
|
try {
|
|
const userXP = await getUserXP(userId, guildId);
|
|
if (!userXP) return null;
|
|
|
|
const finalXP = Math.floor(xpGained * multiplier);
|
|
const newXP = userXP.xp + finalXP;
|
|
const newLevel = getLevelFromXP(newXP);
|
|
|
|
// Mettre à jour l'XP et le niveau
|
|
await db.query(
|
|
'UPDATE user_xp SET xp = ?, level = ? WHERE userId = ? AND guildId = ?',
|
|
[newXP, newLevel, userId, guildId]
|
|
);
|
|
|
|
// Logger le gain d'XP (optionnel, pour debugging)
|
|
try {
|
|
await db.query(
|
|
'INSERT INTO xp_logs (userId, guildId, xpGained, source, multiplier, timestamp) VALUES (?, ?, ?, ?, ?, ?)',
|
|
[userId, guildId, finalXP, source, multiplier, Date.now()]
|
|
);
|
|
} catch (logErr) {
|
|
// Ignorer les erreurs de log
|
|
}
|
|
|
|
return {
|
|
oldXP: userXP.xp,
|
|
newXP,
|
|
oldLevel: userXP.level,
|
|
newLevel,
|
|
xpGained: finalXP,
|
|
levelUp: newLevel > userXP.level
|
|
};
|
|
} catch (err) {
|
|
console.error('Erreur lors de l\'ajout d\'XP:', err);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Vérifier si un salon est exclus de l'XP
|
|
async function isChannelExcluded(channelId, guildId) {
|
|
try {
|
|
const [rows] = await db.query(
|
|
'SELECT * FROM xp_excluded_channels WHERE channelId = ? AND guildId = ?',
|
|
[channelId, guildId]
|
|
);
|
|
return rows.length > 0;
|
|
} catch (err) {
|
|
console.error('Erreur lors de la vérification de l\'exclusion:', err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Obtenir le multiplicateur XP d'un utilisateur (booster, vocal, etc.)
|
|
function getXPMultiplier(member, source = 'message') {
|
|
let multiplier = 1.0;
|
|
|
|
// Vérifier si l'utilisateur est booster (1.2x)
|
|
if (member.premiumSince) {
|
|
multiplier *= 1.2;
|
|
}
|
|
|
|
// Multiplicateur vocal : 1.0x après 5 minutes de vocal (selon Issue #11)
|
|
// Note: Cette fonction est appelée toutes les 10 minutes, donc on applique déjà le bonus
|
|
if (source === 'voice') {
|
|
// Le bonus vocal est déjà appliqué car on gagne de l'XP toutes les 10 minutes
|
|
// Donc on considère qu'on a déjà passé plus de 5 minutes
|
|
multiplier *= 1.0; // Pas de changement, mais on pourrait ajouter un bonus ici
|
|
}
|
|
|
|
return multiplier;
|
|
}
|
|
|
|
// Obtenir le classement des utilisateurs par XP
|
|
async function getLeaderboard(guildId, limit = 10) {
|
|
try {
|
|
const [rows] = await db.query(
|
|
'SELECT * FROM user_xp WHERE guildId = ? ORDER BY xp DESC LIMIT ?',
|
|
[guildId, limit]
|
|
);
|
|
return rows;
|
|
} catch (err) {
|
|
console.error('Erreur lors de la récupération du classement:', err);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Obtenir la position d'un utilisateur dans le classement
|
|
async function getUserRank(userId, guildId) {
|
|
try {
|
|
const userXP = await getUserXP(userId, guildId);
|
|
if (!userXP) return 0;
|
|
|
|
const [rows] = await db.query(
|
|
'SELECT COUNT(*) as count FROM user_xp WHERE guildId = ? AND xp > ?',
|
|
[guildId, userXP.xp]
|
|
);
|
|
|
|
return (rows[0]?.count || 0) + 1;
|
|
} catch (err) {
|
|
console.error('Erreur lors de la récupération du rang:', err);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getXPForLevel,
|
|
getLevelFromXP,
|
|
getXPForNextLevel,
|
|
getXPProgress,
|
|
getUserXP,
|
|
addXP,
|
|
isChannelExcluded,
|
|
getXPMultiplier,
|
|
getLeaderboard,
|
|
getUserRank,
|
|
};
|
|
|