Files
2026-03-15 12:22:42 +01:00

177 lines
4.9 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
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,
};