From c09214cc60592c96dc8c4f1263db41fff6457b97 Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Tue, 16 Jul 2024 11:38:08 -0400 Subject: [PATCH 1/9] Adding helper method for leaderboard --- src/commandDetails/coin/leaderboard.ts | 81 ++++---------------------- src/utils/leaderboards.ts | 72 +++++++++++++++++++++++ 2 files changed, 84 insertions(+), 69 deletions(-) create mode 100644 src/utils/leaderboards.ts diff --git a/src/commandDetails/coin/leaderboard.ts b/src/commandDetails/coin/leaderboard.ts index 25c24f31..eb676236 100644 --- a/src/commandDetails/coin/leaderboard.ts +++ b/src/commandDetails/coin/leaderboard.ts @@ -1,79 +1,13 @@ import { container, SapphireClient } from '@sapphire/framework'; -import { EmbedBuilder } from 'discord.js'; import { CodeyCommandDetails, - getUserFromMessage, SapphireMessageExecuteType, SapphireMessageResponse, + getUserFromMessage, } from '../../codeyCommand'; import { getCoinBalanceByUserId, getCoinLeaderboard } from '../../components/coin'; import { getCoinEmoji } from '../../components/emojis'; -import { DEFAULT_EMBED_COLOUR } from '../../utils/embeds'; - -// 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 getCoinLeaderboardEmbed = async ( - client: SapphireClient, - userId: string, -): Promise => { - // Get extra users to filter bots later - let leaderboard = await getCoinLeaderboard(LEADERBOARD_LIMIT_FETCH); - const leaderboardArray: string[] = []; - // Initialize user's coin balance if they have not already - const userBalance = await getCoinBalanceByUserId(userId); - let previousBalance = -1; - let position = 0; - let rank = 0; - let offset = 0; - let i = 0; - let absoluteCount = 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 (i >= leaderboard.length) { - break; - } - const userCoinEntry = leaderboard[i++]; - const user = await client.users.fetch(userCoinEntry.user_id).catch(() => null); - if (user?.bot) continue; - if (previousBalance === userCoinEntry.balance) { - previousBalance = userCoinEntry.balance; - // rank does not change - } else { - previousBalance = userCoinEntry.balance; - rank = absoluteCount + 1; - } - // count how many total users have been processed: - absoluteCount++; - if (userCoinEntry.user_id === userId) { - position = rank; - } - if (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY) { - const userCoinEntryText = `${rank}\\. <@${userCoinEntry.user_id}> - ${ - userCoinEntry.balance - } ${getCoinEmoji()}`; - leaderboardArray.push(userCoinEntryText); - } - } - const leaderboardText = leaderboardArray.join('\n'); - const leaderboardEmbed = new EmbedBuilder() - .setColor(DEFAULT_EMBED_COLOUR) - .setTitle('Codey Coin Leaderboard') - .setDescription(leaderboardText); - leaderboardEmbed.addFields([ - { - name: 'Your Position', - value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${getCoinEmoji()}.`, - }, - ]); - return leaderboardEmbed; -}; +import { getLeaderboardEmbed } from '../../utils/leaderboards'; const coinLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( client, @@ -81,7 +15,16 @@ const coinLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( _args, ): Promise => { const userId = getUserFromMessage(messageFromUser).id; - return { embeds: [await getCoinLeaderboardEmbed(client, userId)] }; + const leaderboardEmbed = await getLeaderboardEmbed( + client, + userId, + getCoinLeaderboard, + (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.balance} ${getCoinEmoji()}`, + getCoinBalanceByUserId, + 'Codey Coin Leaderboard', + getCoinEmoji(), + ); + return { embeds: [leaderboardEmbed] }; }; export const coinLeaderboardCommandDetails: CodeyCommandDetails = { diff --git a/src/utils/leaderboards.ts b/src/utils/leaderboards.ts new file mode 100644 index 00000000..cc2975ab --- /dev/null +++ b/src/utils/leaderboards.ts @@ -0,0 +1,72 @@ +import { EmbedBuilder, Emoji } from 'discord.js'; +import { SapphireClient } from '@sapphire/framework'; +import { DEFAULT_EMBED_COLOUR } from '../utils/embeds'; + +const LEADERBOARD_LIMIT_DISPLAY = 10; +const LEADERBOARD_LIMIT_FETCH = LEADERBOARD_LIMIT_DISPLAY * 2; + +type GetLeaderboardData = (limit: number, offset?: number) => Promise; +type FormatLeaderboardEntry = (entry: any, rank: number) => string; +type GetUserBalance = (userId: string) => Promise; + +const getLeaderboardEmbed = async ( + client: SapphireClient, + userId: string, + getLeaderboardData: GetLeaderboardData, + formatLeaderboardEntry: FormatLeaderboardEntry, + getUserBalance: GetUserBalance, + leaderboardTitle: string, + leaderboardEmoji: string | Emoji, +): Promise => { + let leaderboard = await getLeaderboardData(LEADERBOARD_LIMIT_FETCH); + const leaderboardArray: string[] = []; + const userBalance = await getUserBalance(userId); + let previousBalance = -1; + let position = 0; + let rank = 0; + let offset = 0; + let i = 0; + let absoluteCount = 0; + const emojiString = typeof leaderboardEmoji === 'string' ? leaderboardEmoji : leaderboardEmoji.toString(); + + while (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY || position === 0) { + if (i === LEADERBOARD_LIMIT_FETCH) { + offset += LEADERBOARD_LIMIT_FETCH; + leaderboard = await getLeaderboardData(LEADERBOARD_LIMIT_FETCH, offset); + i = 0; + } + if (i >= leaderboard.length) { + break; + } + const entry = leaderboard[i++]; + const user = await client.users.fetch(entry.user_id).catch(() => null); + if (user?.bot) continue; + if (previousBalance === entry.balance) { + previousBalance = entry.balance; + } else { + previousBalance = entry.balance; + rank = absoluteCount + 1; + } + absoluteCount++; + if (entry.user_id === userId) { + position = rank; + } + if (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY) { + leaderboardArray.push(formatLeaderboardEntry(entry, rank)); + } + } + const leaderboardText = leaderboardArray.join('\n'); + const leaderboardEmbed = new EmbedBuilder() + .setColor(DEFAULT_EMBED_COLOUR) + .setTitle(leaderboardTitle) + .setDescription(leaderboardText); + leaderboardEmbed.addFields([ + { + name: 'Your Position', + value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${emojiString}.`, + }, + ]); + return leaderboardEmbed; +}; + +export { getLeaderboardEmbed }; From 4de0920aa4408deeb2704a7d9c08b60bc237f75c Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Tue, 16 Jul 2024 13:02:15 -0400 Subject: [PATCH 2/9] Adding necessary database tables --- src/components/db.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/components/db.ts b/src/components/db.ts index 19dad417..85ac7b93 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -100,6 +100,40 @@ const initUserCoinTable = async (db: Database): Promise => { ); }; +const initBlackjackGameInfo = async (db: Database): Promise => { + await db.run( + ` + CREATE TABLE IF NOT EXISTS blackjack_game_info ( + id INTEGER PRIMARY KEY NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + user_id VARCHAR(255) NOT NULL, + bet INTEGER NOT NULL, + result VARCHAR(20) NOT NULL, -- 'win', 'loss', 'draw' + net_gain_loss INTEGER NOT NULL + ) + `, + ); + await db.run( + 'CREATE INDEX IF NOT EXISTS ix_blackjack_game_info_user_id ON blackjack_game_info (user_id)', + ); +}; + +const initBlackjackPlayerStats = async (db: Database): Promise => { + await db.run( + ` + CREATE TABLE IF NOT EXISTS blackjack_player_stats ( + user_id VARCHAR(255) PRIMARY KEY NOT NULL, + games_played INTEGER NOT NULL DEFAULT 0, + games_won INTEGER NOT NULL DEFAULT 0, + games_lost INTEGER NOT NULL DEFAULT 0, + net_gain_loss INTEGER NOT NULL DEFAULT 0, + winrate REAL NOT NULL DEFAULT 0.0 + ) + `, + ); +}; + + const initUserProfileTable = async (db: Database): Promise => { await db.run( ` @@ -230,6 +264,8 @@ const initTables = async (db: Database): Promise => { await initUserCoinBonusTable(db); await initUserCoinLedgerTable(db); await initUserCoinTable(db); + await initBlackjackGameInfo(db); + await initBlackjackPlayerStats(db); await initUserProfileTable(db); await initRpsGameInfo(db); await initConnectFourGameInfo(db); From f57d38836a13804e450651e144dbb0b8462f17ac Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Tue, 16 Jul 2024 14:11:03 -0400 Subject: [PATCH 3/9] Fixing linting and format issues --- src/commandDetails/coin/leaderboard.ts | 2 +- src/components/db.ts | 1 - src/utils/leaderboards.ts | 15 +++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/commandDetails/coin/leaderboard.ts b/src/commandDetails/coin/leaderboard.ts index eb676236..3e525d5e 100644 --- a/src/commandDetails/coin/leaderboard.ts +++ b/src/commandDetails/coin/leaderboard.ts @@ -1,4 +1,4 @@ -import { container, SapphireClient } from '@sapphire/framework'; +import { container } from '@sapphire/framework'; import { CodeyCommandDetails, SapphireMessageExecuteType, diff --git a/src/components/db.ts b/src/components/db.ts index 85ac7b93..01f4087f 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -133,7 +133,6 @@ const initBlackjackPlayerStats = async (db: Database): Promise => { ); }; - const initUserProfileTable = async (db: Database): Promise => { await db.run( ` diff --git a/src/utils/leaderboards.ts b/src/utils/leaderboards.ts index cc2975ab..496d3dfd 100644 --- a/src/utils/leaderboards.ts +++ b/src/utils/leaderboards.ts @@ -5,8 +5,13 @@ import { DEFAULT_EMBED_COLOUR } from '../utils/embeds'; const LEADERBOARD_LIMIT_DISPLAY = 10; const LEADERBOARD_LIMIT_FETCH = LEADERBOARD_LIMIT_DISPLAY * 2; -type GetLeaderboardData = (limit: number, offset?: number) => Promise; -type FormatLeaderboardEntry = (entry: any, rank: number) => string; +interface LeaderboardEntry { + user_id: string; + balance: number; +} + +type GetLeaderboardData = (limit: number, offset?: number) => Promise; +type FormatLeaderboardEntry = (entry: LeaderboardEntry, rank: number) => string; type GetUserBalance = (userId: string) => Promise; const getLeaderboardEmbed = async ( @@ -27,8 +32,10 @@ const getLeaderboardEmbed = async ( let offset = 0; let i = 0; let absoluteCount = 0; - const emojiString = typeof leaderboardEmoji === 'string' ? leaderboardEmoji : leaderboardEmoji.toString(); - + + const emojiString = + typeof leaderboardEmoji === 'string' ? leaderboardEmoji : leaderboardEmoji.toString(); + while (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY || position === 0) { if (i === LEADERBOARD_LIMIT_FETCH) { offset += LEADERBOARD_LIMIT_FETCH; From e571933c65e03130fb5da425e94dd14f872f730d Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Tue, 16 Jul 2024 14:16:21 -0400 Subject: [PATCH 4/9] Removing unecessary Emoji string conversion --- src/utils/leaderboards.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utils/leaderboards.ts b/src/utils/leaderboards.ts index 496d3dfd..0ca7eec2 100644 --- a/src/utils/leaderboards.ts +++ b/src/utils/leaderboards.ts @@ -33,9 +33,6 @@ const getLeaderboardEmbed = async ( let i = 0; let absoluteCount = 0; - const emojiString = - typeof leaderboardEmoji === 'string' ? leaderboardEmoji : leaderboardEmoji.toString(); - while (leaderboardArray.length < LEADERBOARD_LIMIT_DISPLAY || position === 0) { if (i === LEADERBOARD_LIMIT_FETCH) { offset += LEADERBOARD_LIMIT_FETCH; @@ -70,7 +67,7 @@ const getLeaderboardEmbed = async ( leaderboardEmbed.addFields([ { name: 'Your Position', - value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${emojiString}.`, + value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${leaderboardEmoji}.`, }, ]); return leaderboardEmbed; From 9b9618b8a11037ca3c910a6019a81d07136523e1 Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Fri, 26 Jul 2024 00:14:01 -0400 Subject: [PATCH 5/9] Adding blackjack leaderboard commands --- src/commandDetails/coin/leaderboard.ts | 4 +- .../games/blackjackLeaderboards/total.ts | 43 ++++++++++++++++++ .../games/blackjackLeaderboards/winrate.ts | 43 ++++++++++++++++++ src/commands/games/blackjackLeaderboards.ts | 32 +++++++++++++ src/components/db.ts | 19 -------- src/components/games/blackjack.ts | 2 +- src/components/games/blackjackLeaderboards.ts | 45 +++++++++++++++++++ src/utils/leaderboards.ts | 28 +++++++----- src/utils/updateWiki.ts | 3 ++ 9 files changed, 186 insertions(+), 33 deletions(-) create mode 100644 src/commandDetails/games/blackjackLeaderboards/total.ts create mode 100644 src/commandDetails/games/blackjackLeaderboards/winrate.ts create mode 100644 src/commands/games/blackjackLeaderboards.ts create mode 100644 src/components/games/blackjackLeaderboards.ts diff --git a/src/commandDetails/coin/leaderboard.ts b/src/commandDetails/coin/leaderboard.ts index 3e525d5e..9458b266 100644 --- a/src/commandDetails/coin/leaderboard.ts +++ b/src/commandDetails/coin/leaderboard.ts @@ -19,9 +19,9 @@ const coinLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( client, userId, getCoinLeaderboard, - (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.balance} ${getCoinEmoji()}`, + (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.balance} coins`, getCoinBalanceByUserId, - 'Codey Coin Leaderboard', + 'Coin Leaderboard', getCoinEmoji(), ); return { embeds: [leaderboardEmbed] }; diff --git a/src/commandDetails/games/blackjackLeaderboards/total.ts b/src/commandDetails/games/blackjackLeaderboards/total.ts new file mode 100644 index 00000000..c1c1bbcc --- /dev/null +++ b/src/commandDetails/games/blackjackLeaderboards/total.ts @@ -0,0 +1,43 @@ +import { container } from '@sapphire/framework'; +import { + CodeyCommandDetails, + SapphireMessageExecuteType, + SapphireMessageResponse, + getUserFromMessage, +} from '../../../codeyCommand'; +import { getCoinEmoji } from '../../../components/emojis'; +import { getLeaderboardEmbed } from '../../../utils/leaderboards'; +import { getNetTotalBlackjackBalanceByUserId,getBlackjackNetTotalLeaderboard } from '../../../components/games/blackjackLeaderboards'; + +const blackjackNetTotalLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( + client, + messageFromUser, + _args, +): Promise => { + const userId = getUserFromMessage(messageFromUser).id; + const leaderboardEmbed = await getLeaderboardEmbed( + client, + userId, + getBlackjackNetTotalLeaderboard, + (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.net_gain_loss ?? 0} coins`, + getNetTotalBlackjackBalanceByUserId, + 'Blackjack Net Total Leaderboard', + getCoinEmoji(), + ); + return { embeds: [leaderboardEmbed] }; +}; + +export const blackjackTotalLeaderboardCommandDetails: CodeyCommandDetails = { + name: 'total', + aliases: ['t'], + description: 'Get the current blackjack net gain/loss leaderboard.', + detailedDescription: `**Examples:** +\`${container.botPrefix}blackjackleaderboards total\` +\`${container.botPrefix}blackjackleaderboards t\``, + + isCommandResponseEphemeral: false, + messageWhenExecutingCommand: 'Getting the current blackjack net gain/loss leaderboard...', + executeCommand: blackjackNetTotalLeaderboardExecuteCommand, + options: [], + subcommandDetails: {}, +}; diff --git a/src/commandDetails/games/blackjackLeaderboards/winrate.ts b/src/commandDetails/games/blackjackLeaderboards/winrate.ts new file mode 100644 index 00000000..129b9bba --- /dev/null +++ b/src/commandDetails/games/blackjackLeaderboards/winrate.ts @@ -0,0 +1,43 @@ +import { container } from '@sapphire/framework'; +import { + CodeyCommandDetails, + SapphireMessageExecuteType, + SapphireMessageResponse, + getUserFromMessage, +} from '../../../codeyCommand'; +import { getCoinEmoji } from '../../../components/emojis'; +import { getLeaderboardEmbed } from '../../../utils/leaderboards'; +import { getWinrateBlackjackByUserId, getBlackjackWinrateLeaderboard } from '../../../components/games/blackjackLeaderboards'; + +const blackjackWinrateLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( + client, + messageFromUser, + _args, +): Promise => { + const userId = getUserFromMessage(messageFromUser).id; + const leaderboardEmbed = await getLeaderboardEmbed( + client, + userId, + getBlackjackWinrateLeaderboard, + (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.winrate} %`, + getWinrateBlackjackByUserId, + 'Blackjack Winrate Leaderboard', + '%', + ); + return { embeds: [leaderboardEmbed] }; +}; + +export const blackjackWinrateLeaderboardCommandDetails: CodeyCommandDetails = { + name: 'winrate', + aliases: ['wr'], + description: 'Get the current blackjack winrate leaderboard.', + detailedDescription: `**Examples:** +\`${container.botPrefix}blackjackleaderboards winrate\` +\`${container.botPrefix}blackjackleaderboards wr\``, + + isCommandResponseEphemeral: false, + messageWhenExecutingCommand: 'Getting the current blackjack winrate leaderboard...', + executeCommand: blackjackWinrateLeaderboardExecuteCommand, + options: [], + subcommandDetails: {}, +}; diff --git a/src/commands/games/blackjackLeaderboards.ts b/src/commands/games/blackjackLeaderboards.ts new file mode 100644 index 00000000..f61c8899 --- /dev/null +++ b/src/commands/games/blackjackLeaderboards.ts @@ -0,0 +1,32 @@ +import { Command, container } from '@sapphire/framework'; +import { CodeyCommand, CodeyCommandDetails } from '../../codeyCommand'; +import { blackjackWinrateLeaderboardCommandDetails } from '../../commandDetails/games/blackjackLeaderboards/winrate'; +import { blackjackTotalLeaderboardCommandDetails } from '../../commandDetails/games/blackjackLeaderboards/total'; + +const blackjackLeaderboardsCommandDetails: CodeyCommandDetails = { + name: 'blackjackleaderboards', + aliases: ['blackjacklb', 'bjlb'], + description: 'Handle blackjack leaderboard functions.', + detailedDescription: `**Examples:** +\`${container.botPrefix}blackjackleaderboards winrate @Codey\` +\`${container.botPrefix}blackjackleaderboards total @Codey\``, + options: [], + subcommandDetails: { + winrate: blackjackWinrateLeaderboardCommandDetails, + total: blackjackTotalLeaderboardCommandDetails, + }, + defaultSubcommandDetails: blackjackWinrateLeaderboardCommandDetails, +}; + +export class GamesBlackjackLeaderboardsCommand extends CodeyCommand { + details = blackjackLeaderboardsCommandDetails; + + public constructor(context: Command.Context, options: Command.Options) { + super(context, { + ...options, + aliases: blackjackLeaderboardsCommandDetails.aliases, + description: blackjackLeaderboardsCommandDetails.description, + detailedDescription: blackjackLeaderboardsCommandDetails.detailedDescription, + }); + } +} diff --git a/src/components/db.ts b/src/components/db.ts index 01f4087f..bed88a7c 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -100,24 +100,6 @@ const initUserCoinTable = async (db: Database): Promise => { ); }; -const initBlackjackGameInfo = async (db: Database): Promise => { - await db.run( - ` - CREATE TABLE IF NOT EXISTS blackjack_game_info ( - id INTEGER PRIMARY KEY NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - user_id VARCHAR(255) NOT NULL, - bet INTEGER NOT NULL, - result VARCHAR(20) NOT NULL, -- 'win', 'loss', 'draw' - net_gain_loss INTEGER NOT NULL - ) - `, - ); - await db.run( - 'CREATE INDEX IF NOT EXISTS ix_blackjack_game_info_user_id ON blackjack_game_info (user_id)', - ); -}; - const initBlackjackPlayerStats = async (db: Database): Promise => { await db.run( ` @@ -263,7 +245,6 @@ const initTables = async (db: Database): Promise => { await initUserCoinBonusTable(db); await initUserCoinLedgerTable(db); await initUserCoinTable(db); - await initBlackjackGameInfo(db); await initBlackjackPlayerStats(db); await initUserProfileTable(db); await initRpsGameInfo(db); diff --git a/src/components/games/blackjack.ts b/src/components/games/blackjack.ts index 5b0dc18e..59ccc65b 100644 --- a/src/components/games/blackjack.ts +++ b/src/components/games/blackjack.ts @@ -10,7 +10,7 @@ export type BlackjackHand = Card[]; export type GameState = { stage: BlackjackStage; playerCards: BlackjackHand; - playerValue: number[]; + playerValue: number[]; dealerCards: BlackjackHand; dealerValue: number[]; bet: number; diff --git a/src/components/games/blackjackLeaderboards.ts b/src/components/games/blackjackLeaderboards.ts new file mode 100644 index 00000000..98f08af2 --- /dev/null +++ b/src/components/games/blackjackLeaderboards.ts @@ -0,0 +1,45 @@ +import _, { uniqueId } from 'lodash'; +import { openDB } from '../db'; + + +export const getNetTotalBlackjackBalanceByUserId = async (userId: string): Promise => { + const db = await openDB(); + const res = await db.get('SELECT net_gain_loss FROM blackjack_player_stats WHERE user_id = ?', userId); + return _.get(res, 'net_gain_loss', 0); +}; + +export const getWinrateBlackjackByUserId = async (userId: string): Promise => { + const db = await openDB(); + const res = await db.get('SELECT winrate FROM blackjack_player_stats WHERE user_id = ?', userId); + return _.get(res, 'winrate', 0); +} + +export const getBlackjackWinrateLeaderboard = async (limit: number, offset = 0) => { + const db = await openDB(); + const res = await db.all( + ` + SELECT user_id, winrate + FROM blackjack_player_stats + ORDER BY winrate DESC + LIMIT ? OFFSET ? + `, + limit, + offset, + ); + return res; +}; + +export const getBlackjackNetTotalLeaderboard = async (limit: number, offset = 0) => { + const db = await openDB(); + const res = await db.all( + ` + SELECT user_id, net_gain_loss + FROM blackjack_player_stats + ORDER BY net_gain_loss DESC + LIMIT ? OFFSET ? + `, + limit, + offset, + ); + return res; +}; \ No newline at end of file diff --git a/src/utils/leaderboards.ts b/src/utils/leaderboards.ts index 0ca7eec2..f745b556 100644 --- a/src/utils/leaderboards.ts +++ b/src/utils/leaderboards.ts @@ -7,26 +7,28 @@ const LEADERBOARD_LIMIT_FETCH = LEADERBOARD_LIMIT_DISPLAY * 2; interface LeaderboardEntry { user_id: string; - balance: number; + balance?: number; + winrate?: number; + net_gain_loss?: number; } type GetLeaderboardData = (limit: number, offset?: number) => Promise; type FormatLeaderboardEntry = (entry: LeaderboardEntry, rank: number) => string; -type GetUserBalance = (userId: string) => Promise; +type GetUserStatistic = (userId: string) => Promise; const getLeaderboardEmbed = async ( client: SapphireClient, userId: string, getLeaderboardData: GetLeaderboardData, formatLeaderboardEntry: FormatLeaderboardEntry, - getUserBalance: GetUserBalance, + getUserStatistic: GetUserStatistic, leaderboardTitle: string, leaderboardEmoji: string | Emoji, ): Promise => { let leaderboard = await getLeaderboardData(LEADERBOARD_LIMIT_FETCH); const leaderboardArray: string[] = []; - const userBalance = await getUserBalance(userId); - let previousBalance = -1; + const userStatistic = await getUserStatistic(userId); + let previousValue: number | undefined = undefined; let position = 0; let rank = 0; let offset = 0; @@ -45,10 +47,12 @@ const getLeaderboardEmbed = async ( const entry = leaderboard[i++]; const user = await client.users.fetch(entry.user_id).catch(() => null); if (user?.bot) continue; - if (previousBalance === entry.balance) { - previousBalance = entry.balance; + + const currentValue = entry.balance ?? entry.winrate ?? entry.net_gain_loss; + if (previousValue === currentValue) { + previousValue = currentValue; } else { - previousBalance = entry.balance; + previousValue = currentValue; rank = absoluteCount + 1; } absoluteCount++; @@ -59,7 +63,8 @@ const getLeaderboardEmbed = async ( leaderboardArray.push(formatLeaderboardEntry(entry, rank)); } } - const leaderboardText = leaderboardArray.join('\n'); + + const leaderboardText = leaderboardArray.join('\n') || 'No entries available.'; const leaderboardEmbed = new EmbedBuilder() .setColor(DEFAULT_EMBED_COLOUR) .setTitle(leaderboardTitle) @@ -67,10 +72,11 @@ const getLeaderboardEmbed = async ( leaderboardEmbed.addFields([ { name: 'Your Position', - value: `You are currently **#${position}** in the leaderboard with ${userBalance} ${leaderboardEmoji}.`, + value: `You are currently **#${position}** in the leaderboard with ${userStatistic} ${leaderboardEmoji}.`, }, ]); + return leaderboardEmbed; }; -export { getLeaderboardEmbed }; +export { getLeaderboardEmbed }; \ No newline at end of file diff --git a/src/utils/updateWiki.ts b/src/utils/updateWiki.ts index 2277e712..21b5f964 100644 --- a/src/utils/updateWiki.ts +++ b/src/utils/updateWiki.ts @@ -188,6 +188,9 @@ export const updateWiki = async (): Promise => { const subDir = `${commandDetailsDir}/${dir}`; const files = await readdir(subDir); for (const file of files) { + if (file === 'blackjackLeaderboards') { // Skip blackjackLeaderboards until it can be fixed in this wiki! + continue; + } const filePath = `${subDir}/${file}`; const content = await readFile(filePath, 'utf-8'); const match = content.match(commandDetailsPattern); From e64834ec335d5f600e9a9493d093d2cd66009ba5 Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Fri, 26 Jul 2024 01:08:37 -0400 Subject: [PATCH 6/9] Integrating leaderboards with Blackjack game --- src/commandDetails/games/blackjack.ts | 20 +++++++++---- .../games/blackjackLeaderboards/total.ts | 11 +++++-- .../games/blackjackLeaderboards/winrate.ts | 13 ++++++--- src/components/db.ts | 6 ++++ src/components/games/blackjackLeaderboards.ts | 29 +++++++++++++++++++ 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/commandDetails/games/blackjack.ts b/src/commandDetails/games/blackjack.ts index 2776598d..3dd8bd9d 100644 --- a/src/commandDetails/games/blackjack.ts +++ b/src/commandDetails/games/blackjack.ts @@ -34,6 +34,7 @@ import { startGame, } from '../../components/games/blackjack'; import { pluralize } from '../../utils/pluralize'; +import { logBlackjackGameResult } from '../../components/games/blackjackLeaderboards'; // CodeyCoin constants const DEFAULT_BET = 10; @@ -121,6 +122,7 @@ const getBalanceChange = (game: GameState): number => { const getEmbedColourFromGame = (game: GameState): keyof typeof Colors => { if (game.stage === BlackjackStage.DONE) { const balance = getBalanceChange(game); + // Player lost coins if (balance < 0) { return 'Red'; @@ -138,9 +140,10 @@ const getEmbedColourFromGame = (game: GameState): keyof typeof Colors => { }; // Retrieve game status at different states -const getDescriptionFromGame = (game: GameState): string => { +const getDescriptionFromGame = async (game: GameState, author: string): Promise => { const amountDiff = Math.abs(getBalanceChange(game)); if (game.stage === BlackjackStage.DONE) { + await logBlackjackGameResult(author, game.bet, getBalanceChange(game), game.surrendered); // Player surrendered if (game.surrendered) { return `You surrendered and lost **${amountDiff}** Codey ${pluralize( @@ -170,14 +173,15 @@ const getDescriptionFromGame = (game: GameState): string => { }; // Display embed to play game -const getEmbedFromGame = (game: GameState): EmbedBuilder => { +const getEmbedFromGame = async (game: GameState, author: string): Promise => { const embed = new EmbedBuilder().setTitle('Blackjack'); embed.setColor(getEmbedColourFromGame(game)); + const description = await getDescriptionFromGame(game, author); embed.addFields([ // Show bet amount and game description - { name: `Bet: ${game.bet} ${getCoinEmoji()}`, value: getDescriptionFromGame(game) }, + { name: `Bet: ${game.bet} ${getCoinEmoji()}`, value: description }, // Show player and dealer value and hands { name: `Player: ${game.playerValue.join(' or ')}`, @@ -192,6 +196,7 @@ const getEmbedFromGame = (game: GameState): EmbedBuilder => { return embed; }; + // End the game const closeGame = (playerId: string, balanceChange = 0) => { endGame(playerId); @@ -239,9 +244,10 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( return 'Please finish your current game before starting another one!'; } + const embed = await getEmbedFromGame(game, author); // Show game initial state and setup reactions const msg = await message.reply({ - embeds: [getEmbedFromGame(game)], + embeds: [embed], components: game?.stage != BlackjackStage.DONE ? [optionRow] : [], fetchReply: true, }); @@ -261,9 +267,10 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( // Wait for user action game = await performActionFromReaction(reactCollector, author); + const updatedEmbed = await getEmbedFromGame(game!, author); // Return next game state - await msg.edit({ embeds: [getEmbedFromGame(game!)] }); + await msg.edit({ embeds: [updatedEmbed] }); await reactCollector.update({ components: [optionRow] }); } catch { // If player has not acted within time limit, consider it as quitting the game @@ -278,7 +285,8 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( } if (game) { // Update game embed - await msg.edit({ embeds: [getEmbedFromGame(game)], components: [] }); + const finalEmbed = await getEmbedFromGame(game, author); + await msg.edit({ embeds: [finalEmbed], components: [] }); // End the game closeGame(author, getBalanceChange(game)); } diff --git a/src/commandDetails/games/blackjackLeaderboards/total.ts b/src/commandDetails/games/blackjackLeaderboards/total.ts index c1c1bbcc..13cbf137 100644 --- a/src/commandDetails/games/blackjackLeaderboards/total.ts +++ b/src/commandDetails/games/blackjackLeaderboards/total.ts @@ -19,8 +19,15 @@ const blackjackNetTotalLeaderboardExecuteCommand: SapphireMessageExecuteType = a client, userId, getBlackjackNetTotalLeaderboard, - (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.net_gain_loss ?? 0} coins`, - getNetTotalBlackjackBalanceByUserId, + (entry, rank) => { + const netGainLoss = entry.net_gain_loss ?? 0; + const formattedNetGainLoss = netGainLoss < 0 ? `(${netGainLoss})` : netGainLoss.toString(); + return `${rank}\\. <@${entry.user_id}> - ${formattedNetGainLoss} coins`; + }, + async (id) => { + const netGainLoss = await getNetTotalBlackjackBalanceByUserId(id); + return netGainLoss < 0 ? `(${netGainLoss})` : netGainLoss.toString(); + }, 'Blackjack Net Total Leaderboard', getCoinEmoji(), ); diff --git a/src/commandDetails/games/blackjackLeaderboards/winrate.ts b/src/commandDetails/games/blackjackLeaderboards/winrate.ts index 129b9bba..92441e37 100644 --- a/src/commandDetails/games/blackjackLeaderboards/winrate.ts +++ b/src/commandDetails/games/blackjackLeaderboards/winrate.ts @@ -5,7 +5,6 @@ import { SapphireMessageResponse, getUserFromMessage, } from '../../../codeyCommand'; -import { getCoinEmoji } from '../../../components/emojis'; import { getLeaderboardEmbed } from '../../../utils/leaderboards'; import { getWinrateBlackjackByUserId, getBlackjackWinrateLeaderboard } from '../../../components/games/blackjackLeaderboards'; @@ -19,10 +18,16 @@ const blackjackWinrateLeaderboardExecuteCommand: SapphireMessageExecuteType = as client, userId, getBlackjackWinrateLeaderboard, - (entry, rank) => `${rank}\\. <@${entry.user_id}> - ${entry.winrate} %`, - getWinrateBlackjackByUserId, + (entry, rank) => { + const formattedWinrate = entry.winrate ? (entry.winrate * 100).toFixed(2) + ' %' : 'N/A'; + return `${rank}\\. <@${entry.user_id}> - ${formattedWinrate}` + }, + async (id) => { + const winrate = await getWinrateBlackjackByUserId(id); + return winrate ? (winrate * 100).toFixed(2) + ' %' : 'N/A'; + }, 'Blackjack Winrate Leaderboard', - '%', + '', ); return { embeds: [leaderboardEmbed] }; }; diff --git a/src/components/db.ts b/src/components/db.ts index bed88a7c..1c5d1a26 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -113,6 +113,12 @@ const initBlackjackPlayerStats = async (db: Database): Promise => { ) `, ); + await db.run( + `CREATE INDEX IF NOT EXISTS idx_net_gain_loss ON blackjack_player_stats (net_gain_loss)` + ); + await db.run( + `CREATE INDEX IF NOT EXISTS idx_winrate ON blackjack_player_stats (winrate)` + ); }; const initUserProfileTable = async (db: Database): Promise => { diff --git a/src/components/games/blackjackLeaderboards.ts b/src/components/games/blackjackLeaderboards.ts index 98f08af2..f548504f 100644 --- a/src/components/games/blackjackLeaderboards.ts +++ b/src/components/games/blackjackLeaderboards.ts @@ -42,4 +42,33 @@ export const getBlackjackNetTotalLeaderboard = async (limit: number, offset = 0) offset, ); return res; +}; + +export const logBlackjackGameResult = async (userId: string, bet: number, netGainLoss: number, surrendered: boolean) => { + const db = await openDB(); + const playerStats = await db.get('SELECT * FROM blackjack_player_stats WHERE user_id = ?', userId); + + let gamesPlayed = 1; + let gamesWon = netGainLoss > 0 ? 1 : 0; + let gamesLost = (netGainLoss < 0 || surrendered) ? 1 : 0; + + if (playerStats) { + gamesPlayed += playerStats.games_played; + gamesWon += playerStats.games_won; + gamesLost += playerStats.games_lost; + netGainLoss = playerStats.net_gain_loss + netGainLoss; + + const winrate = gamesWon / gamesPlayed; + + await db.run( + 'UPDATE blackjack_player_stats SET games_played = ?, games_won = ?, games_lost = ?, net_gain_loss = ?, winrate = ? WHERE user_id = ?', + gamesPlayed, gamesWon, gamesLost, netGainLoss, winrate, userId + ); + } else { + const winrate = gamesWon / gamesPlayed; + await db.run( + 'INSERT INTO blackjack_player_stats (user_id, games_played, games_won, games_lost, net_gain_loss, winrate) VALUES (?, ?, ?, ?, ?, ?)', + userId, gamesPlayed, gamesWon, gamesLost, netGainLoss, winrate + ); + } }; \ No newline at end of file From 838ccd6dd626de1550bca84a005af38883044ec4 Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Fri, 26 Jul 2024 01:12:26 -0400 Subject: [PATCH 7/9] Cleaning up code --- src/commandDetails/games/blackjack.ts | 3 +- .../games/blackjackLeaderboards/total.ts | 5 +- .../games/blackjackLeaderboards/winrate.ts | 7 ++- src/components/db.ts | 6 +- src/components/games/blackjack.ts | 2 +- src/components/games/blackjackLeaderboards.ts | 58 +++++++++++++++---- src/utils/leaderboards.ts | 2 +- src/utils/updateWiki.ts | 3 +- 8 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/commandDetails/games/blackjack.ts b/src/commandDetails/games/blackjack.ts index 3dd8bd9d..68825cd8 100644 --- a/src/commandDetails/games/blackjack.ts +++ b/src/commandDetails/games/blackjack.ts @@ -122,7 +122,7 @@ const getBalanceChange = (game: GameState): number => { const getEmbedColourFromGame = (game: GameState): keyof typeof Colors => { if (game.stage === BlackjackStage.DONE) { const balance = getBalanceChange(game); - + // Player lost coins if (balance < 0) { return 'Red'; @@ -196,7 +196,6 @@ const getEmbedFromGame = async (game: GameState, author: string): Promise { endGame(playerId); diff --git a/src/commandDetails/games/blackjackLeaderboards/total.ts b/src/commandDetails/games/blackjackLeaderboards/total.ts index 13cbf137..3ea0da0b 100644 --- a/src/commandDetails/games/blackjackLeaderboards/total.ts +++ b/src/commandDetails/games/blackjackLeaderboards/total.ts @@ -7,7 +7,10 @@ import { } from '../../../codeyCommand'; import { getCoinEmoji } from '../../../components/emojis'; import { getLeaderboardEmbed } from '../../../utils/leaderboards'; -import { getNetTotalBlackjackBalanceByUserId,getBlackjackNetTotalLeaderboard } from '../../../components/games/blackjackLeaderboards'; +import { + getNetTotalBlackjackBalanceByUserId, + getBlackjackNetTotalLeaderboard, +} from '../../../components/games/blackjackLeaderboards'; const blackjackNetTotalLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( client, diff --git a/src/commandDetails/games/blackjackLeaderboards/winrate.ts b/src/commandDetails/games/blackjackLeaderboards/winrate.ts index 92441e37..e796a652 100644 --- a/src/commandDetails/games/blackjackLeaderboards/winrate.ts +++ b/src/commandDetails/games/blackjackLeaderboards/winrate.ts @@ -6,7 +6,10 @@ import { getUserFromMessage, } from '../../../codeyCommand'; import { getLeaderboardEmbed } from '../../../utils/leaderboards'; -import { getWinrateBlackjackByUserId, getBlackjackWinrateLeaderboard } from '../../../components/games/blackjackLeaderboards'; +import { + getWinrateBlackjackByUserId, + getBlackjackWinrateLeaderboard, +} from '../../../components/games/blackjackLeaderboards'; const blackjackWinrateLeaderboardExecuteCommand: SapphireMessageExecuteType = async ( client, @@ -20,7 +23,7 @@ const blackjackWinrateLeaderboardExecuteCommand: SapphireMessageExecuteType = as getBlackjackWinrateLeaderboard, (entry, rank) => { const formattedWinrate = entry.winrate ? (entry.winrate * 100).toFixed(2) + ' %' : 'N/A'; - return `${rank}\\. <@${entry.user_id}> - ${formattedWinrate}` + return `${rank}\\. <@${entry.user_id}> - ${formattedWinrate}`; }, async (id) => { const winrate = await getWinrateBlackjackByUserId(id); diff --git a/src/components/db.ts b/src/components/db.ts index 1c5d1a26..b4b30219 100644 --- a/src/components/db.ts +++ b/src/components/db.ts @@ -114,11 +114,9 @@ const initBlackjackPlayerStats = async (db: Database): Promise => { `, ); await db.run( - `CREATE INDEX IF NOT EXISTS idx_net_gain_loss ON blackjack_player_stats (net_gain_loss)` - ); - await db.run( - `CREATE INDEX IF NOT EXISTS idx_winrate ON blackjack_player_stats (winrate)` + `CREATE INDEX IF NOT EXISTS idx_net_gain_loss ON blackjack_player_stats (net_gain_loss)`, ); + await db.run(`CREATE INDEX IF NOT EXISTS idx_winrate ON blackjack_player_stats (winrate)`); }; const initUserProfileTable = async (db: Database): Promise => { diff --git a/src/components/games/blackjack.ts b/src/components/games/blackjack.ts index 59ccc65b..5b0dc18e 100644 --- a/src/components/games/blackjack.ts +++ b/src/components/games/blackjack.ts @@ -10,7 +10,7 @@ export type BlackjackHand = Card[]; export type GameState = { stage: BlackjackStage; playerCards: BlackjackHand; - playerValue: number[]; + playerValue: number[]; dealerCards: BlackjackHand; dealerValue: number[]; bet: number; diff --git a/src/components/games/blackjackLeaderboards.ts b/src/components/games/blackjackLeaderboards.ts index f548504f..964c85b9 100644 --- a/src/components/games/blackjackLeaderboards.ts +++ b/src/components/games/blackjackLeaderboards.ts @@ -1,10 +1,12 @@ -import _, { uniqueId } from 'lodash'; +import _ from 'lodash'; import { openDB } from '../db'; - export const getNetTotalBlackjackBalanceByUserId = async (userId: string): Promise => { const db = await openDB(); - const res = await db.get('SELECT net_gain_loss FROM blackjack_player_stats WHERE user_id = ?', userId); + const res = await db.get( + 'SELECT net_gain_loss FROM blackjack_player_stats WHERE user_id = ?', + userId, + ); return _.get(res, 'net_gain_loss', 0); }; @@ -12,9 +14,17 @@ export const getWinrateBlackjackByUserId = async (userId: string): Promise { +export const getBlackjackWinrateLeaderboard = async ( + limit: number, + offset = 0, +): Promise => { const db = await openDB(); const res = await db.all( ` @@ -29,7 +39,15 @@ export const getBlackjackWinrateLeaderboard = async (limit: number, offset = 0) return res; }; -export const getBlackjackNetTotalLeaderboard = async (limit: number, offset = 0) => { +interface NetGainLoss { + user_id: string; + net_gain_loss: number; +} + +export const getBlackjackNetTotalLeaderboard = async ( + limit: number, + offset = 0, +): Promise => { const db = await openDB(); const res = await db.all( ` @@ -44,13 +62,21 @@ export const getBlackjackNetTotalLeaderboard = async (limit: number, offset = 0) return res; }; -export const logBlackjackGameResult = async (userId: string, bet: number, netGainLoss: number, surrendered: boolean) => { +export const logBlackjackGameResult = async ( + userId: string, + bet: number, + netGainLoss: number, + surrendered: boolean, +): Promise => { const db = await openDB(); - const playerStats = await db.get('SELECT * FROM blackjack_player_stats WHERE user_id = ?', userId); + const playerStats = await db.get( + 'SELECT * FROM blackjack_player_stats WHERE user_id = ?', + userId, + ); let gamesPlayed = 1; let gamesWon = netGainLoss > 0 ? 1 : 0; - let gamesLost = (netGainLoss < 0 || surrendered) ? 1 : 0; + let gamesLost = netGainLoss < 0 || surrendered ? 1 : 0; if (playerStats) { gamesPlayed += playerStats.games_played; @@ -62,13 +88,23 @@ export const logBlackjackGameResult = async (userId: string, bet: number, netGai await db.run( 'UPDATE blackjack_player_stats SET games_played = ?, games_won = ?, games_lost = ?, net_gain_loss = ?, winrate = ? WHERE user_id = ?', - gamesPlayed, gamesWon, gamesLost, netGainLoss, winrate, userId + gamesPlayed, + gamesWon, + gamesLost, + netGainLoss, + winrate, + userId, ); } else { const winrate = gamesWon / gamesPlayed; await db.run( 'INSERT INTO blackjack_player_stats (user_id, games_played, games_won, games_lost, net_gain_loss, winrate) VALUES (?, ?, ?, ?, ?, ?)', - userId, gamesPlayed, gamesWon, gamesLost, netGainLoss, winrate + userId, + gamesPlayed, + gamesWon, + gamesLost, + netGainLoss, + winrate, ); } -}; \ No newline at end of file +}; diff --git a/src/utils/leaderboards.ts b/src/utils/leaderboards.ts index f745b556..61377212 100644 --- a/src/utils/leaderboards.ts +++ b/src/utils/leaderboards.ts @@ -79,4 +79,4 @@ const getLeaderboardEmbed = async ( return leaderboardEmbed; }; -export { getLeaderboardEmbed }; \ No newline at end of file +export { getLeaderboardEmbed }; diff --git a/src/utils/updateWiki.ts b/src/utils/updateWiki.ts index 21b5f964..81669b49 100644 --- a/src/utils/updateWiki.ts +++ b/src/utils/updateWiki.ts @@ -188,7 +188,8 @@ export const updateWiki = async (): Promise => { const subDir = `${commandDetailsDir}/${dir}`; const files = await readdir(subDir); for (const file of files) { - if (file === 'blackjackLeaderboards') { // Skip blackjackLeaderboards until it can be fixed in this wiki! + if (file === 'blackjackLeaderboards') { + // Skip blackjackLeaderboards until it can be fixed in this wiki! continue; } const filePath = `${subDir}/${file}`; From 7327b9180a2a58efdfb7acfd9986167c1445eda8 Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Sat, 27 Jul 2024 20:54:43 -0400 Subject: [PATCH 8/9] Fixing total coin bug --- src/commandDetails/games/blackjack.ts | 11 ++++++----- src/components/games/blackjackLeaderboards.ts | 13 ++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commandDetails/games/blackjack.ts b/src/commandDetails/games/blackjack.ts index 68825cd8..1f61a1f0 100644 --- a/src/commandDetails/games/blackjack.ts +++ b/src/commandDetails/games/blackjack.ts @@ -34,7 +34,7 @@ import { startGame, } from '../../components/games/blackjack'; import { pluralize } from '../../utils/pluralize'; -import { logBlackjackGameResult } from '../../components/games/blackjackLeaderboards'; +import { adjustBlackjackGameResult } from '../../components/games/blackjackLeaderboards'; // CodeyCoin constants const DEFAULT_BET = 10; @@ -140,10 +140,9 @@ const getEmbedColourFromGame = (game: GameState): keyof typeof Colors => { }; // Retrieve game status at different states -const getDescriptionFromGame = async (game: GameState, author: string): Promise => { +const getDescriptionFromGame = async (game: GameState): Promise => { const amountDiff = Math.abs(getBalanceChange(game)); if (game.stage === BlackjackStage.DONE) { - await logBlackjackGameResult(author, game.bet, getBalanceChange(game), game.surrendered); // Player surrendered if (game.surrendered) { return `You surrendered and lost **${amountDiff}** Codey ${pluralize( @@ -197,7 +196,9 @@ const getEmbedFromGame = async (game: GameState, author: string): Promise { +const closeGame = async (playerId: string, game: GameState) => { + const balanceChange = getBalanceChange(game); + adjustBlackjackGameResult(playerId, balanceChange); endGame(playerId); adjustCoinBalanceByUserId(playerId, balanceChange, UserCoinEvent.Blackjack); }; @@ -287,7 +288,7 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( const finalEmbed = await getEmbedFromGame(game, author); await msg.edit({ embeds: [finalEmbed], components: [] }); // End the game - closeGame(author, getBalanceChange(game)); + closeGame(author, game); } }; diff --git a/src/components/games/blackjackLeaderboards.ts b/src/components/games/blackjackLeaderboards.ts index 964c85b9..f8602943 100644 --- a/src/components/games/blackjackLeaderboards.ts +++ b/src/components/games/blackjackLeaderboards.ts @@ -62,11 +62,9 @@ export const getBlackjackNetTotalLeaderboard = async ( return res; }; -export const logBlackjackGameResult = async ( +export const adjustBlackjackGameResult = async ( userId: string, - bet: number, - netGainLoss: number, - surrendered: boolean, + balanceChange: number, ): Promise => { const db = await openDB(); const playerStats = await db.get( @@ -75,14 +73,15 @@ export const logBlackjackGameResult = async ( ); let gamesPlayed = 1; - let gamesWon = netGainLoss > 0 ? 1 : 0; - let gamesLost = netGainLoss < 0 || surrendered ? 1 : 0; + let gamesWon = balanceChange > 0 ? 1 : 0; + let gamesLost = balanceChange < 0 ? 1 : 0; + let netGainLoss = balanceChange; if (playerStats) { gamesPlayed += playerStats.games_played; gamesWon += playerStats.games_won; gamesLost += playerStats.games_lost; - netGainLoss = playerStats.net_gain_loss + netGainLoss; + netGainLoss += playerStats.net_gain_loss; const winrate = gamesWon / gamesPlayed; From 11d5d5aaab9fc871fb42fc204d53a988fc7964cf Mon Sep 17 00:00:00 2001 From: Sagar Patel <2sagarpatel2@gmail.com> Date: Sat, 27 Jul 2024 21:09:33 -0400 Subject: [PATCH 9/9] Fixing argument bug --- src/commandDetails/games/blackjack.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commandDetails/games/blackjack.ts b/src/commandDetails/games/blackjack.ts index 1f61a1f0..6efa91cb 100644 --- a/src/commandDetails/games/blackjack.ts +++ b/src/commandDetails/games/blackjack.ts @@ -172,12 +172,12 @@ const getDescriptionFromGame = async (game: GameState): Promise => { }; // Display embed to play game -const getEmbedFromGame = async (game: GameState, author: string): Promise => { +const getEmbedFromGame = async (game: GameState): Promise => { const embed = new EmbedBuilder().setTitle('Blackjack'); embed.setColor(getEmbedColourFromGame(game)); - const description = await getDescriptionFromGame(game, author); + const description = await getDescriptionFromGame(game); embed.addFields([ // Show bet amount and game description { name: `Bet: ${game.bet} ${getCoinEmoji()}`, value: description }, @@ -244,7 +244,7 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( return 'Please finish your current game before starting another one!'; } - const embed = await getEmbedFromGame(game, author); + const embed = await getEmbedFromGame(game); // Show game initial state and setup reactions const msg = await message.reply({ embeds: [embed], @@ -267,7 +267,7 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( // Wait for user action game = await performActionFromReaction(reactCollector, author); - const updatedEmbed = await getEmbedFromGame(game!, author); + const updatedEmbed = await getEmbedFromGame(game!); // Return next game state await msg.edit({ embeds: [updatedEmbed] }); @@ -285,7 +285,7 @@ const blackjackExecuteCommand: SapphireMessageExecuteType = async ( } if (game) { // Update game embed - const finalEmbed = await getEmbedFromGame(game, author); + const finalEmbed = await getEmbedFromGame(game); await msg.edit({ embeds: [finalEmbed], components: [] }); // End the game closeGame(author, game);