/** * 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 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); 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) { const xpForCurrentLevel = getXPForLevel(level); const xpForNextLevel = getXPForLevel(level + 1); const xpInLevel = Math.max(0, xp - xpForCurrentLevel); const xpNeeded = xpForNextLevel - xpForCurrentLevel; 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 }; } // 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) { 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 getUserXP:', 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); await db.query( 'UPDATE user_xp SET xp = ?, level = ? WHERE userId = ? AND guildId = ?', [newXP, newLevel, userId, guildId] ); try { await db.query( 'INSERT INTO xp_logs (userId, guildId, xpGained, source, multiplier, timestamp) VALUES (?, ?, ?, ?, ?, ?)', [userId, guildId, finalXP, source, multiplier, Date.now()] ); } catch {} return { oldXP: userXP.xp, newXP, oldLevel: userXP.level, newLevel, xpGained: finalXP, levelUp: newLevel > userXP.level }; } catch (err) { console.error('Erreur addXP:', 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 isChannelExcluded:', err); return false; } } // Obtenir le multiplicateur XP d'un utilisateur function getXPMultiplier(member, source = 'message') { let multiplier = 1.0; if (member.premiumSince) multiplier *= 1.2; 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 getLeaderboard:', 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 getUserRank:', err); return 0; } } module.exports = { getXPForLevel, getLevelFromXP, getXPForNextLevel, getXPProgress, getUserXP, addXP, isChannelExcluded, getXPMultiplier, getLeaderboard, getUserRank, };