From bc9ee30bc0bf0af7979884c1a62eed08aa653c38 Mon Sep 17 00:00:00 2001 From: Nico Hagelberg Date: Mon, 17 Jun 2024 21:08:58 +0300 Subject: [PATCH] Infoboard vote improvements Correctly show results for tied votes. Show infoboard entry about a vote receiving no votes for just 10 minutes. --- src/routes/vote.js | 2 +- src/rules/social/votes.js | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/routes/vote.js b/src/routes/vote.js index c91b57f..236b638 100644 --- a/src/routes/vote.js +++ b/src/routes/vote.js @@ -72,7 +72,7 @@ async function createVoteCreatedInfoboardEntry(vote) { const title = `Vote: ${vote.get('title')}`; const votingAllowedFor = voteFilterToTextMap[vote.get('allowed_voters')] || vote.get('allowed_voters'); - const body = `${votingAllowedFor} can now cast their vote in EOC Datahub.

Voting ends at ${voteActiveUntilFormatted}.`; + const body = `${votingAllowedFor} can now cast their vote in EOC Datahub.

Voting ends at ${voteActiveUntilFormatted}`; await InfoEntry.forge().save({ priority: 1, enabled: true, diff --git a/src/rules/social/votes.js b/src/rules/social/votes.js index 732c7f4..f02ea6c 100644 --- a/src/rules/social/votes.js +++ b/src/rules/social/votes.js @@ -19,8 +19,7 @@ async function createVoteResultsInfoEntry(vote) { const voteOptions = await new VoteOption().where('vote_id', vote.get('id')).fetchAll(); const infoEntry = new InfoEntry(); - const activeMinutes = 60; - const activeUntil = moment().add(activeMinutes, 'minutes').toDate(); + const activeUntil = moment().add(60, 'minutes').toDate(); const postData = { priority: 1, enabled: true, @@ -33,7 +32,11 @@ async function createVoteResultsInfoEntry(vote) { if (totalVotes === 0) { const body = 'No votes were cast.'; const metadata = { vote_results: [] }; - await infoEntry.save({ ...postData, body, metadata }, { method: 'insert' }); + + // No one cared about the vote so no one will care about the results, only show for 10min + const shortActiveTime = moment().add(10, 'minutes').toDate(); + + await infoEntry.save({ ...postData, body, metadata, active_until: shortActiveTime }, { method: 'insert' }); return; } @@ -44,8 +47,17 @@ async function createVoteResultsInfoEntry(vote) { } results.sort((a, b) => b.votes - a.votes); results.forEach(result => result.votesPercentage = Math.round((result.votes / results[0].votes) * 100)); + + const tiedResults = results.filter(result => result.votes === results[0].votes); const votesWord = voteEntries.length === 1 ? 'vote' : 'votes'; - const body = `Vote results are in! ${totalVotes} ${votesWord} were cast. The winning option is ${results[0].option} with ${results[0].votes} ${votesWord}.`; + let body = ""; + if (tiedResults.length === 2) { + body = `Vote results are in! ${totalVotes} ${votesWord} were cast. There was a tie between ${tiedResults[0].option} and ${tiedResults[1].option} with ${tiedResults[0].votes} ${tiedResults[0].votes === 1 ? "vote" : "votes"} each.`; + } else if (tiedResults.length > 2) { + body = `Vote results are in! ${totalVotes} ${votesWord} were cast. There was a tie between multiple options with ${tiedResults[0].votes} ${tiedResults[0].votes === 1 ? "vote" : "votes"} each.`; + } else { + body = `Vote results are in! ${totalVotes} ${votesWord} ${totalVotes === 1 ? "was" : "were"} cast. The winning option is ${results[0].option} with ${results[0].votes} ${votesWord}.`; + } await infoEntry.save({ ...postData,