Zonies-Bot/functions/level/generate_level_card.js

89 lines
3.1 KiB
JavaScript

const { createCanvas, loadImage } = require('canvas');
const path = require('path');
/**
* Calculates the XP required for the next level
* @param {number} currentLevel - Current user level
* @returns {number} XP required for next level
*/
function calculateNextLevelXP(currentLevel) {
// Using the inverse of the level calculation formula from xpSystem.js
// level = 0.47 * sqrt(xp)
// Therefore, xp = (level/0.47)^2
return Math.ceil(Math.pow((currentLevel + 1) / 0.47, 2));
}
/**
* Generates a level card image for a user
* @param {Object} user - User object containing id, username, xp, and level
* @returns {Promise<Buffer>} - Returns a buffer containing the generated image
*/
async function generateLevelCard(user) {
// Create canvas with dimensions matching the background image
const canvas = createCanvas(1516, 662);
const ctx = canvas.getContext('2d');
try {
// Load background image
const background = await loadImage(path.join(__dirname, '../../assets/level_clean.png'));
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
// Load progress bar fill image
const progressFill = await loadImage(path.join(__dirname, '../../assets/progress_fill.png'));
// Calculate XP progress using the same formula as xpSystem.js
const currentLevelXP = Math.floor(Math.pow(user.level / 0.47, 2));
const nextLevelXP = Math.floor(calculateNextLevelXP(user.level));
const xpInLevel = user.xp - currentLevelXP;
const xpForLevel = nextLevelXP - currentLevelXP;
// Clamp progress between 0 and 1
const progress = Math.max(0, Math.min(1, xpInLevel / xpForLevel));
// Clamp displayed XP to not exceed xpForLevel
const displayXP = Math.min(Math.max(0, xpInLevel), xpForLevel);
// Draw username
ctx.font = 'bold 60px Arial';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'left';
ctx.fillText(user.username, 420, 250);
// Draw level
ctx.font = 'bold 48px Arial';
ctx.fillStyle = '#FFD700'; // Gold color for level
ctx.fillText(`Level ${user.level}`, 420, 330);
// Progress bar dimensions and position
const progressBarX = 472;
const progressBarY = 388;
const progressBarWidth = 800;
const progressBarHeight = 60;
// Draw progress bar fill
ctx.drawImage(
progressFill,
progressBarX,
progressBarY,
progressBarWidth * progress,
progressBarHeight
);
// Draw XP progress text inside the bar, right-aligned
ctx.font = 'bold 36px Arial';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = 'center';
ctx.fillText(
`${displayXP}/${xpForLevel} XP`,
progressBarX + progressBarWidth / 2,
progressBarY + progressBarHeight / 2 + 12 // adjust as needed
);
// Convert canvas to buffer
return canvas.toBuffer('image/png');
} catch (error) {
console.error('Error generating level card:', error);
throw error;
}
}
module.exports = generateLevelCard;