From c0871d099329f898e5e1d4ec4f1dc364a7701451 Mon Sep 17 00:00:00 2001 From: guams Date: Sun, 29 Jun 2025 08:59:11 +0200 Subject: [PATCH] added closing poll feature --- src/database.js | 49 ++++++++++++++++++++++++++++++ src/main.js | 79 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 110 insertions(+), 18 deletions(-) diff --git a/src/database.js b/src/database.js index 5c203b5..391fa6f 100644 --- a/src/database.js +++ b/src/database.js @@ -22,9 +22,53 @@ async function findPollCreatedByUserAndOpened(userId) { "SELECT poll_id, question FROM poll WHERE creator=$1 and opened=true", [userId] ); + return response.rows[0]; +} + +async function findVoteIdByVoteOptionAndPollId(voteOption, pollId) { + const response = await DATABASE_CLIENT.query( + "SELECT vote_id FROM vote WHERE vote_option=$1 AND poll_id=$2", + [voteOption, pollId] + ); + return response.rows[0]; +} + +async function findBetValueMultiplierForPoll(pollId) { + const response = await DATABASE_CLIENT.query( + "SELECT vote_id, (1 + (1 - (SUM(vote_member.bet_value) / total.sum))) AS cote " + + "FROM vote_member " + + "CROSS JOIN (SELECT SUM(bet_value) " + + "AS sum FROM vote_member WHERE poll_id=$1) " + + "AS total " + + "WHERE poll_id=$1 " + + "GROUP BY vote_id, total.sum", + [pollId] + ); return response.rows; } +async function findUsersAndBetValueByVoteId(voteId) { + const response = await DATABASE_CLIENT.query( + "SELECT user_id, bet_value FROM vote_member WHERE vote_id=$1", + [voteId] + ); + return response.rows; +} + +async function addPointsToUser(userId, betValue) { + await DATABASE_CLIENT.query( + "UPDATE member SET points = points + $1 WHERE user_id = $2", + [betValue, userId] + ); +} + +async function closePoll(pollId) { + await DATABASE_CLIENT.query( + "UPDATE poll SET opened = false WHERE poll_id=$1", + [pollId] + ); +} + async function findUserById(userId, guildId) { const response = await DATABASE_CLIENT.query( "SELECT username, points, bet_value FROM member WHERE user_id=$1 AND guild_id=$2", @@ -122,3 +166,8 @@ exports.findBetValueForUser = findBetValueForUser; exports.bet = bet; exports.substractUserPoints = substractUserPoints; exports.insertVoteOptions = insertVoteOptions; +exports.findVoteIdByVoteOptionAndPollId = findVoteIdByVoteOptionAndPollId; +exports.findBetValueMultiplierForPoll = findBetValueMultiplierForPoll; +exports.findUsersAndBetValueByVoteId = findUsersAndBetValueByVoteId; +exports.addPointsToUser = addPointsToUser; +exports.closePoll = closePoll; \ No newline at end of file diff --git a/src/main.js b/src/main.js index d99eb72..8184866 100644 --- a/src/main.js +++ b/src/main.js @@ -17,7 +17,12 @@ const { insertUserIntoDB, isLastPollCreatedByUserOpen, findPollCreatedByUserAndOpened, - findUserById, findUserVoteForPoll, findBetValueForUser, bet, insertVoteOptions + findUserById, + findUserVoteForPoll, + findBetValueForUser, + bet, + insertVoteOptions, findVoteIdByVoteOptionAndPollId, findBetValueMultiplierForPoll, findUsersAndBetValueByVoteId, + addPointsToUser, closePoll } = require('./database'); const {TOKEN} = require('../config.json'); const {v4: uuidv4} = require('uuid'); @@ -33,11 +38,11 @@ client.once(Events.ClientReady, async readyClient => { }); client.on(Events.InteractionCreate, async interaction => { + await createGuildAndUserIfNecessary(interaction.guildId, interaction.user); if (interaction.isCommand()) { const {commandName} = interaction; - await createGuildAndUserIfNecessary(interaction.guildId, interaction.user); switch (commandName) { - case POLL_COMMAND_NAME: + case POLL_COMMAND_NAME: { if (await isLastPollCreatedByUserOpen(interaction.user.id)) { await interaction.showModal(buildPollModal()); } else { @@ -47,23 +52,59 @@ client.on(Events.InteractionCreate, async interaction => { }) } break; - case CLOSE_COMMAND_NAME: - const response = findPollCreatedByUserAndOpened(interaction.user.id); - if (response.length) { - // Logique pour fermer le poll - // [ - // { - // poll_id: '9b02d63e-5e4b-411e-bb65-2f412f65b21f', - // question: 'coucou' - // } - // ] + } + case CLOSE_COMMAND_NAME: { + const actualOpenedPollCreatedByUser = await findPollCreatedByUserAndOpened(interaction.user.id); + + if (!actualOpenedPollCreatedByUser) { + await interaction.reply({ + flags: MessageFlags.Ephemeral, + content: `<@${interaction.user.id}>, tu n'as actuellement aucun sondage en cours.` + }); + break; } + + const optionSendedByUser = interaction.options.data[0].value; + let winnerVoteId = await findVoteIdByVoteOptionAndPollId(optionSendedByUser, actualOpenedPollCreatedByUser.poll_id); + + if (!winnerVoteId) { + await interaction.reply({ + flags: MessageFlags.Ephemeral, + content: `<@${interaction.user.id}>, L'option **${optionSendedByUser}** n'existe pas.` + }); + break; + } + winnerVoteId = winnerVoteId.vote_id; + + const voteIdsWithMultipliers = await findBetValueMultiplierForPoll(actualOpenedPollCreatedByUser.poll_id); + let winnerCote; + + for (const voteIdWithMultiplier of voteIdsWithMultipliers) { + const usersThatVotedActualVoteId = await findUsersAndBetValueByVoteId(voteIdWithMultiplier.vote_id); + + if (voteIdWithMultiplier.vote_id === winnerVoteId) { + winnerCote = Number.parseFloat(voteIdWithMultiplier.cote); + for (const user of usersThatVotedActualVoteId) { + const gain = Math.round(user.bet_value * winnerCote); + await addPointsToUser(user.user_id, gain); + } + } + } + + await closePoll(actualOpenedPollCreatedByUser.poll_id); + + const out = winnerCote ? ((Math.round(winnerCote * 100) / 100 - 1) * 100) : 0; + + await interaction.reply({ + content: `@everyone le sondage **${actualOpenedPollCreatedByUser.question}** est terminé ! L'issue gagnante est **${optionSendedByUser}** avec une côte de ${out.toFixed(2)}%` + }); break; - case PROFIL_COMMAND_NAME: + } + case PROFIL_COMMAND_NAME: { let concernedUser; if (interaction.options.data.length) { concernedUser = interaction.options.data[0].user; - if (!await userExistsInDB(concernedUser.id)) { + if (!await userExistsInDB(concernedUser.id, interaction.guildId)) { await insertUserIntoDB(concernedUser.id, interaction.guildId, concernedUser.username); } } else { @@ -83,11 +124,14 @@ client.on(Events.InteractionCreate, async interaction => { .setColor(Colors.Aqua); await interaction.reply({embeds: [profilEmbed]}); break; - case BET_COMMAND_NAME: + } + case BET_COMMAND_NAME: { break; - default: + } + default: { console.log(`Commande [${commandName}] inconnue`); break; + } } } else if (interaction.isModalSubmit()) { const pollToCreate = interaction.components; @@ -130,7 +174,6 @@ client.on(Events.InteractionCreate, async interaction => { await interaction.reply({embeds: [introEmbed, pollEmbed], components: [buttons]}); } else if (interaction.isMessageComponent()) { - console.log(interaction) const userVote = await findUserVoteForPoll(interaction.user.id, interaction.customId.split("_")[0]) if (userVote) { await interaction.reply({