Add Game Genres chart

This commit is contained in:
baz 2025-05-05 04:03:08 +01:00
parent 1d7c48f2ea
commit 065758bdf3

View File

@ -0,0 +1,187 @@
const { createCanvas } = require('canvas');
const { Chart } = require('chart.js/auto');
const fs = require('fs');
const { getUserRegistration, getBeatenGames, checkGameStorageId } = require('../../databaseHelperFunctions.js');
const { getGameJson, getGenres } = require('../../igdbHelperFunctions.js');
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('chartgamegenres')
.setDescription('Generate a bar chart of the different genres of the games you have beat')
.addUserOption(option => option.setName('user').setDescription('The user to check'))
.addIntegerOption(option => option.setName('year').setDescription('The year to check').addChoices({ name: '2024', value: 2024 }, { name: '2025', value: 2025 }))
.addBooleanOption(option => option.setName('ignoreadventure').setDescription('Exclude the Adventure genre from the bar chart')),
async execute(interaction) {
await interaction.deferReply();
let user = interaction.user;
const userOption = interaction.options.getUser('user');
const yearOption = interaction.options.getInteger('year');
const ignoreadventure = interaction.options.getBoolean('ignoreadventure');
if (userOption) {
user = userOption;
}
const userDatabaseEntry = await getUserRegistration(user);
if (!userDatabaseEntry) return interaction.editReply({ content: `Issue checking registration with "${user.username}".`, ephemeral: true });
let beatenGamesDatabaseEntries;
if (yearOption) {
beatenGamesDatabaseEntries = await getBeatenGames(userDatabaseEntry.id);
if (beatenGamesDatabaseEntries && beatenGamesDatabaseEntries.length > 0) {
beatenGamesDatabaseEntries = await beatenGamesDatabaseEntries.filter(entry => {
const date = new Date(entry.updatedAt);
return date.getFullYear() === yearOption;
});
}
}
else {
beatenGamesDatabaseEntries = await getBeatenGames(userDatabaseEntry.id);
}
if (!beatenGamesDatabaseEntries || beatenGamesDatabaseEntries.length == 0) {
const embed = new EmbedBuilder()
.setTitle(`${user.username}'s beat games age`)
.setDescription(`${user.username} has not beat any games`)
.setColor(0xFF0000);
return interaction.editReply({ embeds: [embed] });
}
const beatGameIGDBEntries = [];
for (let i = 0; i < beatenGamesDatabaseEntries.length; i++) {
const game = await checkGameStorageId(beatenGamesDatabaseEntries[i].gameId);
const json = await getGameJson(String.prototype.concat('where id = ', game.igdb_id, '; fields *;'));
beatGameIGDBEntries.push(json[0]);
}
const genres = [];
const counts = [];
for (let i = 0; i < beatGameIGDBEntries.length; i++) {
if (beatGameIGDBEntries[i].genres) {
for (let j = 0; j < beatGameIGDBEntries[i].genres.length; j++) {
const genre = await getGenres(beatGameIGDBEntries[i].genres[j]);
genres.push(genre);
}
}
}
genres.forEach(item => {
counts[item] = (counts[item] || 0) + 1;
});
const sortedCounts = Object.entries(counts).sort((a, b) => b[1] - a[1]);
const keys = Object.keys(sortedCounts);
const labels = [];
const values = [];
for (let i = 0; i < keys.length; i++) {
const genre = keys[i];
if (ignoreadventure && sortedCounts[genre][0] == 'Adventure')
{
continue;
}
labels.push(sortedCounts[genre][0]);
values.push(sortedCounts[genre][1]);
}
// Create a canvas
const canvas = createCanvas(1920, 1080);
// Chart data
const data = {
labels: labels,
datasets: [
{
label: 'Game Genres',
data: values,
borderColor: '#5865F2',
backgroundColor: 'rgba(88, 101, 242, 0.5)',
borderWidth: 8,
},
],
};
const config = {
type: 'bar',
data: data,
options: {
scales: {
x: {
title: {
display: true,
text: 'Genres',
font: {
size: 48,
family: 'Tahoma',
},
color: 'white',
},
grid: {
color: 'rgba(255, 255, 255, 0.5)',
lineWidth: 0,
},
ticks: {
color: 'white',
font: {
size: 24,
family: 'Tahoma',
},
},
},
y: {
beginAtZero: true,
title: {
display: true,
text: 'Occurrences of genre',
font: {
size: 48,
family: 'Tahoma',
},
color: 'white',
},
grid: {
color: 'rgba(255, 255, 255, 0.5)',
lineWidth: 2,
},
ticks: {
stepSize: 1,
},
},
},
plugins: {
title: {
display: true,
text: `${user.username}'s most common game genres`,
font: {
size: 64,
family: 'Tahoma',
},
color: 'white',
},
},
},
};
// Create the chart
const chart = new Chart(canvas, config);
// Save the chart as an image
const buffer = canvas.toBuffer('image/png');
fs.writeFileSync('./tempbeattimeline.png', buffer);
// Use the image in your embed
return interaction.editReply({
files: ['./tempbeattimeline.png'],
});
},
};