Implement votes
This commit is contained in:
parent
caa4bcfa92
commit
8f939e288b
104
orochi/bot.py
104
orochi/bot.py
|
@ -5,7 +5,7 @@ import logging
|
|||
|
||||
from orochi import http
|
||||
from orochi.config import Config
|
||||
from orochi.models import Game
|
||||
from orochi.models import Game, GameState, Player, RoundVote, Vote
|
||||
|
||||
bot = commands.Bot(command_prefix='!')
|
||||
|
||||
|
@ -182,6 +182,20 @@ async def on_ready():
|
|||
config.save()
|
||||
|
||||
|
||||
@bot.command(help="Sauvegarde la partie")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def save(ctx: commands.Context):
|
||||
Game.INSTANCE.save('game.save')
|
||||
await ctx.reply("La partie a été sauvegardée.")
|
||||
|
||||
|
||||
@bot.command(help="Recharger la partie")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def load(ctx: commands.Context):
|
||||
Game.load('game.save')
|
||||
await ctx.reply("La partie a été rechargée.")
|
||||
|
||||
|
||||
@bot.command(help="Envoyer un message en tant qu'Orochi.")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def send(ctx: commands.Context, *, message: str):
|
||||
|
@ -197,26 +211,88 @@ async def brother(ctx: commands.Context, *, message: str):
|
|||
await ctx.message.reply("Message envoyé.")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def vote(ctx: commands.Context):
|
||||
view = Confirm()
|
||||
await ctx.message.reply("plop", view=view)
|
||||
await view.wait()
|
||||
@bot.command(help="Ouvrir les votes")
|
||||
async def open(ctx: commands.Context):
|
||||
game: Game = Game.INSTANCE
|
||||
current_round = game.rounds[-1]
|
||||
|
||||
if game.state == GameState.VOTING:
|
||||
await ctx.reply("Les votes sont déjà ouverts.")
|
||||
return
|
||||
elif game.state == GameState.RESULTS:
|
||||
await ctx.reply("Les votes viennent d'être fermés, merci de démarrer un nouveau tour avec !prepare.")
|
||||
return
|
||||
|
||||
# Ensure that each room is configured
|
||||
for room in current_round.rooms:
|
||||
if room is None:
|
||||
await ctx.reply("Les salles ne sont pas configurées.")
|
||||
if len(list(room.players)) != 3:
|
||||
await ctx.reply(f"La salle {room.room.value} ne contient pas trois joueurs, merci de la reconfigurer.")
|
||||
|
||||
# Send messages to players
|
||||
for room in current_round.rooms:
|
||||
votes = list(room.votes)
|
||||
for i, vote in enumerate(votes):
|
||||
players = list(vote.players)
|
||||
other_vote = votes[1 - i]
|
||||
for j, player in enumerate(players):
|
||||
other_player = players[1 - j] if len(players) == 2 else None
|
||||
view = VoteView(timeout=3600)
|
||||
channel_id = player.private_channel_id
|
||||
channel = bot.get_channel(channel_id)
|
||||
message = "Les votes sont ouverts.\n"
|
||||
message += f"Vous devez aller voter en salle **{room.room.value}**.\n"
|
||||
if other_player:
|
||||
message += f"Vous êtes allié⋅e avec **{other_player.name}**.\n"
|
||||
message += f"Vous affrontez {' et '.join(f'**{adv.name}**' for adv in other_vote.players)}.\n"
|
||||
message += "Bonne chance !"
|
||||
await channel.send(message)
|
||||
|
||||
await channel.send("Pour voter, utilisez l'un des boutons ci-dessous. Vous pouvez appuyer "
|
||||
"sur le bouton plusieurs fois, mais seul le premier vote sera enregistré.",
|
||||
view=view)
|
||||
|
||||
game.state = GameState.VOTING
|
||||
|
||||
await ctx.reply("Les salles de vote sont ouvertes, les joueur⋅se⋅s peuvent désormais voter.")
|
||||
|
||||
|
||||
# Define a simple View that gives us a confirmation menu
|
||||
class Confirm(disnake.ui.View):
|
||||
class VoteView(disnake.ui.View):
|
||||
@disnake.ui.button(label="S'allier", style=disnake.ButtonStyle.green)
|
||||
async def confirm(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction):
|
||||
self.clear_items()
|
||||
await interaction.response.edit_message(content="Vous vous êtes allié.", view=self)
|
||||
self.stop()
|
||||
await interaction.response.send_message("Votre vote a bien été pris en compte.", ephemeral=True)
|
||||
|
||||
self.vote(interaction, Vote.ALLY)
|
||||
|
||||
@disnake.ui.button(label="Trahir", style=disnake.ButtonStyle.red)
|
||||
async def cancel(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction):
|
||||
self.clear_items()
|
||||
await interaction.response.edit_message(content="Vous avez trahi.", view=self)
|
||||
self.stop()
|
||||
await interaction.response.send_message("Votre vote a bien été pris en compte.", ephemeral=True)
|
||||
|
||||
self.vote(interaction, Vote.BETRAY)
|
||||
|
||||
def vote(self, interaction: disnake.MessageInteraction, vote: Vote) -> None:
|
||||
game = Game.INSTANCE
|
||||
current_round = game.rounds[-1]
|
||||
current_player: Player | None = None
|
||||
for player in game.players.values():
|
||||
if player.private_channel_id == interaction.channel_id:
|
||||
current_player = player
|
||||
break
|
||||
|
||||
current_vote: RoundVote | None = None
|
||||
for room in current_round.rooms:
|
||||
for v in room.votes:
|
||||
if current_player in v.players:
|
||||
current_vote = v
|
||||
break
|
||||
else:
|
||||
continue
|
||||
break
|
||||
|
||||
if current_vote.vote is None:
|
||||
current_vote.vote = vote
|
||||
game.save('game.save')
|
||||
|
||||
|
||||
def run():
|
||||
|
|
|
@ -2,7 +2,7 @@ import pickle
|
|||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import ClassVar
|
||||
from typing import ClassVar, Iterable, Generator
|
||||
|
||||
|
||||
class Room(Enum):
|
||||
|
@ -28,7 +28,7 @@ class Player:
|
|||
private_channel_id: int = field(hash=False)
|
||||
|
||||
@property
|
||||
def round_votes(self):
|
||||
def round_votes(self) -> Generator["RoundVote", None, None]:
|
||||
for r in Game.INSTANCE.rounds:
|
||||
for room in r.rooms:
|
||||
for vote in room.votes:
|
||||
|
@ -36,7 +36,7 @@ class Player:
|
|||
yield vote
|
||||
|
||||
@property
|
||||
def score(self):
|
||||
def score(self) -> int:
|
||||
s = 3
|
||||
|
||||
for vote in self.round_votes:
|
||||
|
@ -63,11 +63,13 @@ class RoundVote:
|
|||
timestamp: datetime | None = None
|
||||
|
||||
@property
|
||||
def players(self):
|
||||
def players(self) -> Iterable[Player]:
|
||||
if self.player2 is None:
|
||||
return self.player1,
|
||||
return self.player1, self.player2
|
||||
|
||||
@property
|
||||
def room(self):
|
||||
def room(self) -> "RoundRoom":
|
||||
for r in Game.INSTANCE.rounds:
|
||||
for room in r.rooms:
|
||||
if self in room.votes:
|
||||
|
@ -84,6 +86,11 @@ class RoundRoom:
|
|||
def votes(self):
|
||||
return self.vote1, self.vote2
|
||||
|
||||
@property
|
||||
def players(self) -> Generator[Player, None, None]:
|
||||
for vote in self.votes:
|
||||
yield from vote.players
|
||||
|
||||
@property
|
||||
def round(self):
|
||||
for r in Game.INSTANCE.rounds:
|
||||
|
@ -99,7 +106,7 @@ class Round:
|
|||
room_c: RoundRoom
|
||||
|
||||
@property
|
||||
def rooms(self):
|
||||
def rooms(self) -> tuple[RoundRoom, RoundRoom, RoundRoom]:
|
||||
return self.room_a, self.room_b, self.room_c
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
{% endif %}
|
||||
<td>{{ vote.player1.name }}{% if vote.player2 %}, {{ vote.player2.name }}{% endif %}</td>
|
||||
{% if round.round != game.rounds|length or admin %}
|
||||
<td>{{ room.vote1.vote.value|default('Pas de vote') }}</td>
|
||||
<td>{{ vote.vote.value|default('Pas de vote') }}</td>
|
||||
{% else %}
|
||||
<td><em>Vote en cours ...</em></td>
|
||||
{% endif %}
|
||||
|
|
Loading…
Reference in New Issue