From 5b5d9fa59ec7ccd6872194b8187b19003a12d53a Mon Sep 17 00:00:00 2001
From: baz <bazzadobs@live.co.uk>
Date: Tue, 3 Jun 2025 23:49:05 +0100
Subject: [PATCH] Add averagebeatlength command

---
 commands/100-games/averagebeatlength.js | 67 +++++++++++++++++++++++++
 igdbHelperFunctions.js                  | 25 +++++++++
 2 files changed, 92 insertions(+)
 create mode 100644 commands/100-games/averagebeatlength.js

diff --git a/commands/100-games/averagebeatlength.js b/commands/100-games/averagebeatlength.js
new file mode 100644
index 0000000..7256ae8
--- /dev/null
+++ b/commands/100-games/averagebeatlength.js
@@ -0,0 +1,67 @@
+const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
+const { getUserRegistration, getBeatenGames, checkGameStorageId } = require('../../databaseHelperFunctions.js');
+const { getGameJson, getTimesToBeat } = require('../../igdbHelperFunctions.js');
+
+module.exports = {
+    data: new SlashCommandBuilder()
+    .setName('averagebeatlength')
+    .setDescription('Calculate the average runtime of a game from a users beat game list.')
+    .addUserOption(option => option.setName('user').setDescription('The user to check')),
+    async execute(interaction) {
+        await interaction.deferReply();
+
+        let user = interaction.user;
+        const userOption = interaction.options.getUser('user');
+
+        if (userOption) {
+            user = userOption;
+        }
+
+        const userDatabaseEntry = await getUserRegistration(user);
+        if (!userDatabaseEntry) return interaction.editReply({ content: `Issue checking registration with "${user.username}".`, ephemeral: true });
+
+        const beatenGamesDatabaseEntries = await getBeatenGames(userDatabaseEntry.id);
+
+        if (!beatenGamesDatabaseEntries || beatenGamesDatabaseEntries.length == 0) {
+            const embed = new EmbedBuilder()
+            .setTitle(`${user.username}'s average beat game length`)
+            .setDescription(`${user.username} has not beat any games`)
+            .setColor(0xFF0000);
+            return interaction.editReply({ embeds: [embed] });
+        }
+
+        const gameIds = [];
+
+        for (let i = 0; i < beatenGamesDatabaseEntries.length; i++) {
+            const game = await checkGameStorageId(beatenGamesDatabaseEntries[i].gameId);
+            gameIds.push(game.igdb_id);
+        }
+
+        const beatGameIGDBEntries = await getGameJson(String.prototype.concat(`where id = (${gameIds}); fields *; limit ${gameIds.length};`));
+
+        const timings = [];
+        const timeData = await getTimesToBeat(`where game_id = (${gameIds}); fields *; limit ${gameIds.length};`);
+
+        for (let i = 0; i < timeData.length; i++)
+        {
+            if (timeData[i])
+            {
+                if (timeData[i].normally) { timings.push(timeData[i].normally / 3600); }
+                else if (timeData[i].hastily) { timings.push(timeData[i].hastily / 3600); }
+            }
+        }
+
+        const average = Math.floor(timings.reduce((sum, num) => sum + num, 0) / timings.length);
+        const desc = `The average length of a game ${user.displayName} has beaten is **${average} hours**.`;
+
+        const embed = new EmbedBuilder()
+        .setColor(0x6441a5)
+        .setThumbnail(user.avatarURL())
+        .setTitle(`${user.displayName}'s average beat game length`)
+        .setDescription(desc)
+        .setFooter({ text: 'The Ochulus • 100 Games Challenge', iconURL: interaction.client.user.avatarURL() })
+        .setTimestamp();
+
+        return interaction.editReply({ embeds: [embed] });
+    },
+};
\ No newline at end of file
diff --git a/igdbHelperFunctions.js b/igdbHelperFunctions.js
index 08b6d71..1412475 100644
--- a/igdbHelperFunctions.js
+++ b/igdbHelperFunctions.js
@@ -261,6 +261,30 @@ async function getTimeToBeat(id) {
     return gameTimeToBeats;
 }
 
+async function getTimesToBeat(body) {
+        let gameTimeToBeats;
+
+    await fetch(
+        'https://api.igdb.com/v4/game_time_to_beats',
+        { method: 'POST',
+        headers: {
+            'Accept': 'application/json',
+            'Client-ID': `${process.env.igdbClientId}`,
+            'Authorization': `Bearer ${process.env.igdbAccessToken}`,
+        },
+        body: body,
+    })
+    .then(response => response.json())
+    .then(response => {
+      gameTimeToBeats = response;
+    })
+    .catch(err => {
+        console.error(err);
+    });
+
+    return gameTimeToBeats;
+}
+
 module.exports = {
     getCoverURL,
     getPlatformID,
@@ -272,4 +296,5 @@ module.exports = {
     getGenres,
     getFranchise,
     getTimeToBeat,
+    getTimesToBeat,
 };
\ No newline at end of file