diff --git a/src/commandDetails/coin/info.ts b/src/commandDetails/coin/info.ts index dd447ef5..57761f26 100644 --- a/src/commandDetails/coin/info.ts +++ b/src/commandDetails/coin/info.ts @@ -42,7 +42,7 @@ const coinInfoExecuteCommand: SapphireMessageExecuteType = async ( export const coinInfoCommandDetails: CodeyCommandDetails = { name: 'info', aliases: ['information, i'], - description: 'Get info about CodeyCoin.', + description: 'Get info about Codey coin.', detailedDescription: `**Examples:** \`${container.botPrefix}coin info\` \`${container.botPrefix}coin information\` diff --git a/src/commandDetails/coin/leaderboard.ts b/src/commandDetails/coin/leaderboard.ts index 7e4bc3f0..cb7df7a5 100644 --- a/src/commandDetails/coin/leaderboard.ts +++ b/src/commandDetails/coin/leaderboard.ts @@ -6,31 +6,39 @@ import { SapphireMessageExecuteType, SapphireMessageResponse, } from '../../codeyCommand'; -import { - getCoinBalanceByUserId, - getCurrentCoinLeaderboard, - UserCoinEntry, -} from '../../components/coin'; +import { getCoinBalanceByUserId, getCoinLeaderboard } from '../../components/coin'; import { getCoinEmoji } from '../../components/emojis'; import { DEFAULT_EMBED_COLOUR } from '../../utils/embeds'; -// How many people are shown on the leaderboard -const limit = 10; +// Number of users to display on leaderboard +const LEADERBOARD_LIMIT_DISPLAY = 10; +// Number of users to fetch for leaderboard +const LEADERBOARD_LIMIT_FETCH = LEADERBOARD_LIMIT_DISPLAY * 2; -const getCurrentCoinLeaderboardEmbed = async ( +const getCoinLeaderboardEmbed = async ( client: SapphireClient, - leaderboard: UserCoinEntry[], - currentUserId: string, + userId: string, ): Promise => { - // Initialise user's coin balance if they have not already - const userBalance = await getCoinBalanceByUserId(currentUserId); - let currentPosition = 0; - + // Get extra users to filter bots later + let leaderboard = await getCoinLeaderboard(LEADERBOARD_LIMIT_FETCH); const leaderboardArray: string[] = []; - let rank = 0; + // Initialize user's coin balance if they have not already + const userBalance = await getCoinBalanceByUserId(userId); let previousBalance = -1; - for (let i = 0; i < leaderboard.length && leaderboardArray.length < limit; i++) { - const userCoinEntry = leaderboard[i]; + let position = 0; + let rank = 0; + let offset = 0; + let i = 0; + while (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY || position === 0) { + if (i === LEADERBOARD_LIMIT_FETCH) { + offset += LEADERBOARD_LIMIT_FETCH; + leaderboard = await getCoinLeaderboard(LEADERBOARD_LIMIT_FETCH, offset); + i = 0; + } + if (leaderboard.length === 0) { + break; + } + const userCoinEntry = leaderboard[i++]; let user: User; try { user = await client.users.fetch(userCoinEntry.user_id); @@ -38,54 +46,53 @@ const getCurrentCoinLeaderboardEmbed = async ( continue; } if (user.bot) continue; - const userTag = user?.tag ?? ''; - const cleanUserTag = userTag - .split('~') - .join('\\~') - .split('*') - .join('\\*') - .split('_') - .join('\\_') - .split('`') - .join('\\`'); if (previousBalance !== userCoinEntry.balance) { previousBalance = userCoinEntry.balance; rank = rank + 1; } - const userCoinEntryText = `${rank}. ${cleanUserTag} - ${ - userCoinEntry.balance - } ${getCoinEmoji()}`; - if (userCoinEntry.user_id === currentUserId) { - currentPosition = rank; + if (userCoinEntry.user_id === userId) { + position = rank; + } + if (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY) { + const userTag = user?.tag ?? ''; + const cleanUserTag = userTag + .split('~') + .join('\\~') + .split('*') + .join('\\*') + .split('_') + .join('\\_') + .split('`') + .join('\\`'); + const userCoinEntryText = `${rank}. ${cleanUserTag} - ${ + userCoinEntry.balance + } ${getCoinEmoji()}`; + leaderboardArray.push(userCoinEntryText); } - leaderboardArray.push(userCoinEntryText); } - const currentLeaderboardText = leaderboardArray.join('\n'); - const currentLeaderboardEmbed = new MessageEmbed() + const leaderboardText = leaderboardArray.join('\n'); + const leaderboardEmbed = new MessageEmbed() .setColor(DEFAULT_EMBED_COLOUR) - .setTitle('CodeyCoin Leaderboard') - .setDescription(currentLeaderboardText); - - currentLeaderboardEmbed.addFields({ + .setTitle('Codey Coin Leaderboard') + .setDescription(leaderboardText); + leaderboardEmbed.addFields({ name: 'Your Position', - value: `You are currently **#${currentPosition}** in the leaderboard with ${userBalance} ${getCoinEmoji()}.`, + value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${getCoinEmoji()}.`, }); - return currentLeaderboardEmbed; + return leaderboardEmbed; }; -const coinCurrentLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( +const coinLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( client, messageFromUser, _args, ): Promise => { const userId = getUserFromMessage(messageFromUser).id; - // Get extra users to filter bots later - const leaderboard = await getCurrentCoinLeaderboard(limit * 2); - return { embeds: [await getCurrentCoinLeaderboardEmbed(client, leaderboard, userId)] }; + return { embeds: [await getCoinLeaderboardEmbed(client, userId)] }; }; -export const coinCurrentLeaderboardCommandDetails: CodeyCommandDetails = { +export const coinLeaderboardCommandDetails: CodeyCommandDetails = { name: 'leaderboard', aliases: ['lb'], description: 'Get the current coin leaderboard.', @@ -95,7 +102,7 @@ export const coinCurrentLeaderboardCommandDetails: CodeyCommandDetails = { isCommandResponseEphemeral: false, messageWhenExecutingCommand: 'Getting the current coin leaderboard...', - executeCommand: coinCurrentLeaderboardExecuteCommand, + executeCommand: coinLeaderboardExecuteCommand, options: [], subcommandDetails: {}, }; diff --git a/src/commands/coin/coin.ts b/src/commands/coin/coin.ts index ae5e85a1..eedb8502 100644 --- a/src/commands/coin/coin.ts +++ b/src/commands/coin/coin.ts @@ -3,7 +3,7 @@ import { CodeyCommand, CodeyCommandDetails } from '../../codeyCommand'; import { coinAdjustCommandDetails } from '../../commandDetails/coin/adjust'; import { coinCheckCommandDetails } from '../../commandDetails/coin/check'; import { coinInfoCommandDetails } from '../../commandDetails/coin/info'; -import { coinCurrentLeaderboardCommandDetails } from '../../commandDetails/coin/leaderboard'; +import { coinLeaderboardCommandDetails } from '../../commandDetails/coin/leaderboard'; import { coinUpdateCommandDetails } from '../../commandDetails/coin/update'; const coinCommandDetails: CodeyCommandDetails = { @@ -26,7 +26,7 @@ const coinCommandDetails: CodeyCommandDetails = { check: coinCheckCommandDetails, info: coinInfoCommandDetails, update: coinUpdateCommandDetails, - leaderboard: coinCurrentLeaderboardCommandDetails, + leaderboard: coinLeaderboardCommandDetails, }, defaultSubcommandDetails: coinCheckCommandDetails, }; diff --git a/src/commands/profile/profile.ts b/src/commands/profile/profile.ts index 42c223ec..89fbe8a3 100644 --- a/src/commands/profile/profile.ts +++ b/src/commands/profile/profile.ts @@ -69,7 +69,7 @@ export class ProfileCommand extends SubCommandPluginCommand { ); } } - // add codeycoins onto the fields as well + // add Codey coins onto the fields as well const userCoins = (await getCoinBalanceByUserId(user.id))!.toString(); profileDisplay.addField('Codey Coins', userCoins, true); // display last updated last diff --git a/src/components/coin.ts b/src/components/coin.ts index 94ad126a..98950e35 100644 --- a/src/components/coin.ts +++ b/src/components/coin.ts @@ -146,16 +146,17 @@ export const changeDbCoinBalanceByUserId = async ( /* Get the leaderboard for the current coin amounts. */ -export const getCurrentCoinLeaderboard = async (limit = 10): Promise => { +export const getCoinLeaderboard = async (limit: number, offset = 0): Promise => { const db = await openDB(); const res = await db.all( ` SELECT user_id, balance FROM user_coin ORDER BY balance DESC - LIMIT ? + LIMIT ? OFFSET ? `, limit, + offset, ); return res; };