[Trivia] Add support for payout to multiple trivia winners (#4649)

* Add payout splitting for trivia game tie instances

* Add check for non-human players

* Apply suggestions from code review

* `pay_winner()` -> `pay_winners()`

* style

Co-authored-by: jack1142 <6032823+jack1142@users.noreply.github.com>
This commit is contained in:
Grant LeBlanc 2021-01-17 17:32:04 -05:00 committed by GitHub
parent e4d24578b5
commit 2b5d72c7a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -261,7 +261,7 @@ class TriviaSession:
await self.send_table() await self.send_table()
multiplier = self.settings["payout_multiplier"] multiplier = self.settings["payout_multiplier"]
if multiplier > 0: if multiplier > 0:
await self.pay_winner(multiplier) await self.pay_winners(multiplier)
self.stop() self.stop()
async def send_table(self): async def send_table(self):
@ -281,42 +281,57 @@ class TriviaSession:
channel = self.ctx.channel channel = self.ctx.channel
LOG.debug("Force stopping trivia session; #%s in %s", channel, channel.guild.id) LOG.debug("Force stopping trivia session; #%s in %s", channel, channel.guild.id)
async def pay_winner(self, multiplier: float): async def pay_winners(self, multiplier: float):
"""Pay the winner of this trivia session. """Pay the winner(s) of this trivia session.
The winner is only payed if there are at least 3 human contestants. Payout only occurs if there are at least 3 human contestants.
If a tie occurs the payout is split evenly among the winners.
Parameters Parameters
---------- ----------
multiplier : float multiplier : float
The coefficient of the winner's score, used to determine the amount The coefficient of the winning score, used to determine the amount
paid. paid.
""" """
(winner, score) = next((tup for tup in self.scores.most_common(1)), (None, None)) if not self.scores:
me_ = self.ctx.guild.me return
if winner is not None and winner != me_ and score > 0: top_score = self.scores.most_common(1)[0][1]
contestants = list(self.scores.keys()) winners = []
if me_ in contestants: num_humans = 0
contestants.remove(me_) for (player, score) in self.scores.items():
if len(contestants) >= 3: if not player.bot:
amount = int(multiplier * score) if score == top_score:
if amount > 0: winners.append(player)
LOG.debug("Paying trivia winner: %d credits --> %s", amount, str(winner)) num_humans += 1
try: if not winners or num_humans < 3:
await bank.deposit_credits(winner, int(multiplier * score)) return
except errors.BalanceTooHigh as e: payout = int(top_score * multiplier / len(winners))
await bank.set_balance(winner, e.max_balance) if payout <= 0:
await self.ctx.send( return
_( for winner in winners:
"Congratulations, {user}, you have received {num} {currency}" LOG.debug("Paying trivia winner: %d credits --> %s", payout, winner.name)
" for coming first." try:
).format( await bank.deposit_credits(winner, payout)
user=winner.display_name, except errors.BalanceTooHigh as e:
num=humanize_number(amount), await bank.set_balance(winner, e.max_balance)
currency=await bank.get_currency_name(self.ctx.guild), if len(winners) > 1:
) msg = _(
) "Congratulations {users}! You have each received {num} {currency} for winning!"
).format(
users=humanize_list([bold(winner.display_name) for winner in winners]),
num=payout,
currency=await bank.get_currency_name(self.ctx.guild),
)
else:
msg = _(
"Congratulations {user}! You have received {num} {currency} for winning!"
).format(
user=bold(winners[0].display_name),
num=payout,
currency=await bank.get_currency_name(self.ctx.guild),
)
await self.ctx.send(msg)
def _parse_answers(answers): def _parse_answers(answers):