mirror of
https://gitlab.com/ddorn/tfjm-discord-bot.git
synced 2024-12-26 05:02:22 +00:00
🚧 new tirages working without save
This commit is contained in:
parent
5ed508be10
commit
a51f2130ec
@ -1,5 +1,8 @@
|
||||
import asyncio
|
||||
import random
|
||||
import sys
|
||||
import traceback
|
||||
from functools import wraps
|
||||
from pprint import pprint
|
||||
|
||||
from io import StringIO
|
||||
@ -57,12 +60,14 @@ class Team:
|
||||
|
||||
return "\n".join(f"`{n.rjust(width)}`: {v}" for n, v in info.items())
|
||||
|
||||
return f""" - Accepté: {self.accepted_problems[round]}
|
||||
- Refusés: {", ".join(p[0] for p in self.rejected[round]) if self.rejected[round] else "aucun"}
|
||||
- Coefficient: {self.coeff(round)}
|
||||
- Ordre au tirage: {self.tirage_order[round]}
|
||||
- Ordre de passage: {self.passage_order[round]}
|
||||
"""
|
||||
|
||||
#
|
||||
# return f""" - Accepté: {self.accepted_problems[round]}
|
||||
# - Refusés: {", ".join(p[0] for p in self.rejected[round]) if self.rejected[round] else "aucun"}
|
||||
# - Coefficient: {self.coeff(round)}
|
||||
# - Ordre au tirage: {self.tirage_order[round]}
|
||||
# - Ordre de passage: {self.passage_order[round]}
|
||||
# """
|
||||
|
||||
|
||||
class Poule:
|
||||
@ -110,6 +115,9 @@ class BaseTirage:
|
||||
]
|
||||
return await self.event(Event(trigram, random.choice(available)))
|
||||
|
||||
async def accept(self, trigram, yes: bool):
|
||||
return await self.event(Event(trigram, yes))
|
||||
|
||||
async def next(self, typ, team=None):
|
||||
while True:
|
||||
event = await self.queue.get()
|
||||
@ -148,6 +156,7 @@ class BaseTirage:
|
||||
# TODO: avoid KeyError
|
||||
if dices[event.team] is None:
|
||||
dices[event.team] = event.value
|
||||
await self.info_dice(event.team, event.value)
|
||||
else:
|
||||
await self.warn_twice(int)
|
||||
|
||||
@ -173,6 +182,9 @@ class BaseTirage:
|
||||
return poules
|
||||
|
||||
async def draw_poule(self, poule):
|
||||
|
||||
await self.start_draw_poule(poule)
|
||||
|
||||
# Trigrams in draw order
|
||||
trigrams = await self.draw_order(poule)
|
||||
|
||||
@ -184,25 +196,27 @@ class BaseTirage:
|
||||
if team.accepted_problems[poule.rnd] is not None:
|
||||
# The team already accepted a problem
|
||||
current += 1
|
||||
current %= len(teams)
|
||||
continue
|
||||
|
||||
# Choose problem
|
||||
await self.start_select_pb(team)
|
||||
event = await self.next(str, team.name)
|
||||
pevent = await self.next(str, team.name)
|
||||
# TODO: Add check for already selected / taken by someone else
|
||||
# This is not a bug for now, since it cannot happen yet
|
||||
await self.info_draw_pb(team, event.value, rnd)
|
||||
await self.info_draw_pb(team, pevent.value, poule.rnd)
|
||||
|
||||
# Accept it
|
||||
accept = await self.next(bool, team.name)
|
||||
if accept:
|
||||
team.accepted_problems[poule.rnd] = event.value
|
||||
await self.info_accepted(team, event.value)
|
||||
if accept.value:
|
||||
team.accepted_problems[poule.rnd] = pevent.value
|
||||
await self.info_accepted(team, pevent.value)
|
||||
else:
|
||||
await self.info_rejected(team, event.value, rnd=poule.rnd)
|
||||
team.rejected[poule.rnd].add(event.value)
|
||||
await self.info_rejected(team, pevent.value, rnd=poule.rnd)
|
||||
team.rejected[poule.rnd].add(pevent.value)
|
||||
|
||||
current += 1
|
||||
current %= len(teams)
|
||||
|
||||
await self.annonce_poule(poule)
|
||||
|
||||
@ -212,7 +226,7 @@ class BaseTirage:
|
||||
teams = self.poules[poule]
|
||||
dices = await self.get_dices(teams)
|
||||
|
||||
order = sorted(self.teams, key=lambda t: dices[t], reverse=True)
|
||||
order = sorted(teams, key=lambda t: dices[t], reverse=True)
|
||||
|
||||
await self.annonce_draw_order(order)
|
||||
return order
|
||||
@ -232,6 +246,9 @@ class BaseTirage:
|
||||
async def start_make_poule(self, rnd):
|
||||
"""Called when it starts drawing the poules for round `rnd`"""
|
||||
|
||||
async def start_draw_poule(self, poule):
|
||||
"""Called when we start a poule."""
|
||||
|
||||
async def start_draw_order(self, poule):
|
||||
"""Called when we start to draw the order."""
|
||||
|
||||
@ -253,6 +270,9 @@ class BaseTirage:
|
||||
async def info_finish(self):
|
||||
"""Called when the tirage has ended."""
|
||||
|
||||
async def info_dice(self, team, dice):
|
||||
"""Called on a dice roll."""
|
||||
|
||||
async def info_draw_pb(self, team, pb, rnd):
|
||||
"""Called when a team draws a problem."""
|
||||
|
||||
@ -262,3 +282,7 @@ class BaseTirage:
|
||||
async def info_rejected(self, team, pb, rnd):
|
||||
"""Called when a team rejects a problem,
|
||||
before it is added to the rejected set."""
|
||||
|
||||
|
||||
def setup(_):
|
||||
pass
|
||||
|
@ -18,6 +18,7 @@ from src.constants import *
|
||||
from src.core import CustomBot
|
||||
|
||||
COGS_SHORTCUTS = {
|
||||
"bt": "src.base_tirage",
|
||||
"c": "src.constants",
|
||||
"d": "tirages",
|
||||
"e": "errors",
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
import asyncio
|
||||
import random
|
||||
import sys
|
||||
import traceback
|
||||
from collections import defaultdict, namedtuple
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
@ -15,7 +17,7 @@ from discord.ext import commands
|
||||
from discord.ext.commands import group, Cog, Context
|
||||
from discord.utils import get
|
||||
|
||||
from src.base_tirage import BaseTirage
|
||||
from src.base_tirage import BaseTirage, Event
|
||||
from src.constants import *
|
||||
from src.core import CustomBot
|
||||
from src.errors import TfjmError, UnwantedCommand
|
||||
@ -34,7 +36,7 @@ Record = namedtuple("Record", ["name", "pb", "penalite"])
|
||||
|
||||
def delete_and_pm(f):
|
||||
@wraps(f)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
async def wrapper(self, *args, **kwargs):
|
||||
await self.ctx.message.delete()
|
||||
await self.ctx.author.send(
|
||||
"J'ai supprimé ton message:\n> "
|
||||
@ -47,6 +49,8 @@ def delete_and_pm(f):
|
||||
if msg:
|
||||
await self.ctx.author.send(f"Raison: {msg}")
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def send_all(f):
|
||||
@wraps(f)
|
||||
@ -57,12 +61,33 @@ def send_all(f):
|
||||
return wrapper
|
||||
|
||||
|
||||
def safe(f):
|
||||
@wraps(f)
|
||||
async def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return await f(*args, **kwargs)
|
||||
except Exception as e:
|
||||
traceback.print_tb(e.__traceback__, file=sys.stderr)
|
||||
print(e)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class DiscordTirage(BaseTirage):
|
||||
def __init__(self, ctx, *teams, fmt):
|
||||
super(DiscordTirage, self).__init__(*teams, fmt=fmt)
|
||||
self.ctx = ctx
|
||||
self.captain_mention = get(ctx.guild.roles, name=Role.CAPTAIN).mention
|
||||
|
||||
def team_for(self, author):
|
||||
for team in self.teams:
|
||||
if get(author.roles, name=team):
|
||||
return team
|
||||
return None
|
||||
|
||||
def mention(self, trigram):
|
||||
return get(self.ctx.guild.roles, name=trigram).mention
|
||||
|
||||
def records(self, teams, rnd):
|
||||
"""Get the strings needed for show the tirage in a list of Records"""
|
||||
|
||||
@ -75,6 +100,36 @@ class DiscordTirage(BaseTirage):
|
||||
for team in teams
|
||||
]
|
||||
|
||||
async def dice(self, ctx, n):
|
||||
self.ctx = ctx
|
||||
trigram = self.team_for(ctx.author)
|
||||
|
||||
if trigram is None:
|
||||
await self.warn_wrong_team(None, None)
|
||||
elif n == 100:
|
||||
await super().dice(trigram)
|
||||
else:
|
||||
await self.warn_unwanted(int, int)
|
||||
|
||||
async def rproblem(self, ctx):
|
||||
self.ctx = ctx
|
||||
trigram = self.team_for(ctx.author)
|
||||
|
||||
if trigram is None:
|
||||
await self.warn_wrong_team(None, None)
|
||||
else:
|
||||
await super().rproblem(trigram)
|
||||
|
||||
async def accept(self, ctx, yes):
|
||||
self.ctx = ctx
|
||||
trigram = self.team_for(ctx.author)
|
||||
|
||||
if trigram is None:
|
||||
await self.warn_wrong_team(None, None)
|
||||
else:
|
||||
await super().accept(trigram, yes)
|
||||
|
||||
@safe
|
||||
@delete_and_pm
|
||||
async def warn_unwanted(self, wanted: Type, got: Type):
|
||||
|
||||
@ -91,6 +146,8 @@ class DiscordTirage(BaseTirage):
|
||||
else "Halte là ! Ce serait bien de tirer un problème d'abord... "
|
||||
"et peut-être qu'il te plaira :) ",
|
||||
(bool, int): "Il tirer un dé avec `!dice 100` d'abord.",
|
||||
(int, int): "Il faut lancer un dé à 100 faces.",
|
||||
(str, str): f"'{got}' n'est pas un problème valide.",
|
||||
}
|
||||
|
||||
reason = texts.get((type(got), wanted))
|
||||
@ -100,10 +157,12 @@ class DiscordTirage(BaseTirage):
|
||||
reason = "Je sais pas, le code ne devrait pas venir ici..."
|
||||
return reason
|
||||
|
||||
@safe
|
||||
@delete_and_pm
|
||||
async def warn_wrong_team(self, expected, got):
|
||||
return "ce n'était pas à ton tour."
|
||||
|
||||
@safe
|
||||
async def warn_colisions(self, collisions: List[str]):
|
||||
await self.ctx.send(
|
||||
f"Les equipes {french_join(collisions)} ont fait le même résultat "
|
||||
@ -111,6 +170,7 @@ class DiscordTirage(BaseTirage):
|
||||
"Le nouveau lancer effacera l'ancien."
|
||||
)
|
||||
|
||||
@safe
|
||||
@delete_and_pm
|
||||
async def warn_twice(self, typ: Type):
|
||||
|
||||
@ -120,6 +180,7 @@ class DiscordTirage(BaseTirage):
|
||||
print("Weird, DiscordTirage.warn_twice was called with", typ)
|
||||
return "Je sais pas, le code ne devrait pas venir ici..."
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def start_make_poule(self, rnd):
|
||||
if rnd == 0:
|
||||
@ -135,50 +196,82 @@ class DiscordTirage(BaseTirage):
|
||||
f"afin de déterminer les poules du second tour."
|
||||
)
|
||||
|
||||
async def start_draw_order(self, poule):
|
||||
print(poule)
|
||||
@safe
|
||||
@send_all
|
||||
async def start_draw_poule(self, poule):
|
||||
yield (
|
||||
f"Nous allons commencer le tirage pour la poule **{poule}** entre les "
|
||||
f"équipes {french_join('**%s**' %p for p in self.poules[poule])}. Les autres équipes peuvent "
|
||||
f"quitter le salon si elles le souhaitent et revenir quand elles seront mentionnées."
|
||||
)
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def start_draw_order(self, poule):
|
||||
mentions = [self.mention(tri) for tri in self.poules[poule]]
|
||||
yield (
|
||||
f"Les capitaines de {french_join(mentions)}, vous pouvez à nouveau lancer un dé 100, "
|
||||
f"qui déterminera l'ordre de tirage des problèmes. Le plus grand lancer tirera en premier "
|
||||
f"les problèmes."
|
||||
)
|
||||
|
||||
@safe
|
||||
async def start_select_pb(self, team):
|
||||
await self.ctx.send(f"C'est au tour de {team.mention} de choisir un problème.")
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def annonce_poules(self, poules):
|
||||
print(poules)
|
||||
first = "\n".join(
|
||||
f"{p}: {french_join(t)}" for p, t in poules.items() if p.rnd == 0
|
||||
)
|
||||
second = "\n".join(
|
||||
f"{p}: {french_join(t)}" for p, t in poules.items() if p.rnd == 1
|
||||
)
|
||||
yield (
|
||||
f"Les poules sont donc, pour le premier tour :"
|
||||
f"```{first}```\n"
|
||||
f"Et pour le second tour :"
|
||||
f"```{second}```"
|
||||
)
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def annonce_draw_order(self, order):
|
||||
order_str = "\n ".join(f"{i}) {tri}" for i, tri in enumerate(order))
|
||||
yield "L'ordre de tirage des problèmes pour ce tour est donc: \n" + order_str
|
||||
order_str = "\n".join(f"{i+1}) {tri}" for i, tri in enumerate(order))
|
||||
yield f"L'ordre de tirage des problèmes pour ce tour est donc: ```{order_str}```"
|
||||
|
||||
@safe
|
||||
async def annonce_poule(self, poule):
|
||||
teams = [self.teams[tri] for tri in self.poules[poule]]
|
||||
|
||||
if len(teams) == 3:
|
||||
table = """```
|
||||
+-----+---------+---------+---------+
|
||||
| | Phase 1 | Phase 2 | Phase 3 |
|
||||
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} |
|
||||
+-----+---------+---------+---------+
|
||||
| {0.name} | Déf | Rap | Opp |
|
||||
+-----+---------+---------+---------+
|
||||
| {1.name} | Opp | Déf | Rap |
|
||||
+-----+---------+---------+---------+
|
||||
| {2.name} | Rap | Opp | Déf |
|
||||
+-----+---------+---------+---------+
|
||||
+-----+---------+---------+---------+
|
||||
| | Phase 1 | Phase 2 | Phase 3 |
|
||||
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} |
|
||||
+-----+---------+---------+---------+
|
||||
| {0.name} | Déf | Rap | Opp |
|
||||
+-----+---------+---------+---------+
|
||||
| {1.name} | Opp | Déf | Rap |
|
||||
+-----+---------+---------+---------+
|
||||
| {2.name} | Rap | Opp | Déf |
|
||||
+-----+---------+---------+---------+
|
||||
```"""
|
||||
else:
|
||||
table = """```
|
||||
+-----+---------+---------+---------+---------+
|
||||
| | Phase 1 | Phase 2 | Phase 3 | Phase 4 |
|
||||
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {0.name} | Déf | | Rap | Opp |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {1.name} | Opp | Déf | | Rap |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {2.name} | Rap | Opp | Déf | |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {3.name} | | Rap | Opp | Déf |
|
||||
+-----+---------+---------+---------+---------+
|
||||
+-----+---------+---------+---------+---------+
|
||||
| | Phase 1 | Phase 2 | Phase 3 | Phase 4 |
|
||||
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {0.name} | Déf | | Rap | Opp |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {1.name} | Opp | Déf | | Rap |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {2.name} | Rap | Opp | Déf | |
|
||||
+-----+---------+---------+---------+---------+
|
||||
| {3.name} | | Rap | Opp | Déf |
|
||||
+-----+---------+---------+---------+---------+
|
||||
```"""
|
||||
|
||||
embed = discord.Embed(
|
||||
@ -205,6 +298,7 @@ class DiscordTirage(BaseTirage):
|
||||
|
||||
await self.ctx.send(embed=embed)
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def info_start(self):
|
||||
yield (
|
||||
@ -225,6 +319,7 @@ class DiscordTirage(BaseTirage):
|
||||
"l'ordre de tirage pour le tour et les problèmes."
|
||||
)
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def info_finish(self):
|
||||
yield "Le tirage est fini, merci à tout le monde !"
|
||||
@ -235,9 +330,19 @@ class DiscordTirage(BaseTirage):
|
||||
# TODO: Save it
|
||||
# TODO: make them available with the api
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def info_dice(self, team, dice):
|
||||
yield f"L'équipe {team} a lancé un... {dice} :game_die:"
|
||||
|
||||
@safe
|
||||
@send_all
|
||||
async def info_draw_pb(self, team, pb, rnd):
|
||||
|
||||
yield (f"L'équipe {self.mention(team.name)} a tiré... **{pb}**")
|
||||
|
||||
if pb in team.rejected[rnd]:
|
||||
await self.ctx.send(
|
||||
yield (
|
||||
f"Vous avez déjà refusé **{pb}**, "
|
||||
f"vous pouvez le refuser à nouveau (`!non`) et "
|
||||
f"tirer immédiatement un nouveau problème "
|
||||
@ -245,19 +350,20 @@ class DiscordTirage(BaseTirage):
|
||||
)
|
||||
else:
|
||||
if len(team.rejected[rnd]) >= MAX_REFUSE:
|
||||
await self.ctx.send(
|
||||
yield (
|
||||
f"Vous pouvez accepter ou refuser **{pb}** "
|
||||
f"mais si vous choisissez de le refuser, il y "
|
||||
f"aura une pénalité de 0.5 sur le multiplicateur du "
|
||||
f"défenseur."
|
||||
)
|
||||
else:
|
||||
await self.ctx.send(
|
||||
f"Vous pouvez accepter (`!oui`) ou refuser (`!non`) **{pb}**. "
|
||||
yield (
|
||||
f"Vous pouvez l'accepter (`!oui`) ou le refuser (`!non`). "
|
||||
f"Il reste {MAX_REFUSE - len(team.rejected[rnd])} refus sans pénalité "
|
||||
f"pour {team.mention}."
|
||||
)
|
||||
|
||||
@safe
|
||||
async def info_accepted(self, team, pb):
|
||||
await self.ctx.send(
|
||||
f"L'équipe {team.mention} a accepté "
|
||||
@ -265,6 +371,7 @@ class DiscordTirage(BaseTirage):
|
||||
f"ne peuvent plus l'accepter."
|
||||
)
|
||||
|
||||
@safe
|
||||
async def info_rejected(self, team, pb, rnd):
|
||||
msg = f"{team.mention} a refusé **{pb}** "
|
||||
if pb in team.rejected[rnd]:
|
||||
@ -274,152 +381,7 @@ class DiscordTirage(BaseTirage):
|
||||
await self.ctx.send(msg)
|
||||
|
||||
|
||||
class Tirage(yaml.YAMLObject):
|
||||
yaml_tag = "Tirage"
|
||||
|
||||
def __init__(self, ctx, channel, teams):
|
||||
assert len(teams) in (3, 4)
|
||||
|
||||
self.channel: int = channel
|
||||
self.teams = [Team(team) for team in teams]
|
||||
self.phase = TirageOrderPhase(self, round=0)
|
||||
|
||||
async def update_phase(self, ctx):
|
||||
if self.phase.finished():
|
||||
next_class = await self.phase.next(ctx)
|
||||
|
||||
if next_class is None:
|
||||
await self.end(ctx)
|
||||
else:
|
||||
# Continue on the same round.
|
||||
# If a Phase wants to change the round
|
||||
# it needs to change its own round.
|
||||
self.phase = next_class(self, self.phase.round)
|
||||
await self.phase.start(ctx)
|
||||
|
||||
async def end(self, ctx):
|
||||
self.phase = None
|
||||
if False:
|
||||
# Allow everyone to send messages again
|
||||
send = discord.PermissionOverwrite() # reset
|
||||
await ctx.channel.edit(overwrites={ctx.guild.default_role: send})
|
||||
|
||||
tl = {}
|
||||
if File.TIRAGES.exists():
|
||||
with open(File.TIRAGES) as f:
|
||||
tl = yaml.load(f)
|
||||
else:
|
||||
File.TIRAGES.touch()
|
||||
|
||||
key = max(0, *tl.keys()) + 1
|
||||
tl[key] = self
|
||||
with open(File.TIRAGES, "w") as f:
|
||||
yaml.dump(tl, f)
|
||||
|
||||
await ctx.send(
|
||||
f"A tout moment, ce rapport peut " f"être envoyé avec `!draw show {key}`"
|
||||
)
|
||||
|
||||
from src.tfjm_discord_bot import tirages
|
||||
|
||||
if self.channel in tirages:
|
||||
del tirages[self.channel]
|
||||
|
||||
async def show_tex(self, ctx):
|
||||
if len(self.teams) == 3:
|
||||
table = r"""
|
||||
\begin{{table}}[]
|
||||
\begin{{tabular}}{{|c|c|c|c|}}
|
||||
\hline
|
||||
& Phase 1 - {0.pb} & Phase 2 - {1.pb} & Phase {2.pb} \\\\ \hline
|
||||
{0.name} & Déf & Rap & Opp \\ \hline
|
||||
{1.name} & Opp & Déf & Rap \\ \hline
|
||||
{2.name} & Rap & Opp & Déf \\ \hline
|
||||
\end{{tabular}}
|
||||
\end{{table}}
|
||||
"""
|
||||
else:
|
||||
table = r"""
|
||||
\begin{{table}}[]
|
||||
\begin{{tabular}}{{|c|c|c|c|c|}}
|
||||
\hline
|
||||
& Phase 1 - {0.pb} & Phase 2 - {1.pb} & Phase 3 - {2.pb} & Phase 4 - {3.pb} \\\\ \hline
|
||||
{0.name} & Déf & & Rap & Opp \\ \hline
|
||||
{1.name} & Opp & Déf & & Rap \\ \hline
|
||||
{2.name} & Rap & Opp & Déf & \\ \hline
|
||||
{3.name} & & Rap & Opp & Déf \\ \hline
|
||||
\end{{tabular}}
|
||||
\end{{table}}
|
||||
"""
|
||||
msg = ",tex "
|
||||
for i in (0, 1):
|
||||
msg += rf"\section{{ {ROUND_NAMES[i].capitalize()} }}"
|
||||
msg += table.format(*self.records(i))
|
||||
await ctx.send(msg)
|
||||
|
||||
|
||||
class Phase:
|
||||
...
|
||||
|
||||
|
||||
class OrderPhase(Phase):
|
||||
def __init__(self, tirage, round, name, order_name, reverse=False):
|
||||
super().__init__(tirage, round)
|
||||
self.name = name
|
||||
self.reverse = reverse
|
||||
self.order_name = order_name
|
||||
|
||||
def order_for(self, team):
|
||||
return getattr(team, self.order_name)[self.round]
|
||||
|
||||
def set_order_for(self, team, order):
|
||||
getattr(team, self.order_name)[self.round] = order
|
||||
|
||||
async def dice(self, ctx, author, dice):
|
||||
team = self.team_for(author)
|
||||
|
||||
if self.order_for(team) is None:
|
||||
self.set_order_for(team, dice)
|
||||
await ctx.send(f"L'équipe {team.mention} a obtenu... **{dice}**")
|
||||
else:
|
||||
raise UnwantedCommand("tu as déjà lancé un dé !")
|
||||
|
||||
def finished(self) -> bool:
|
||||
return all(self.order_for(team) is not None for team in self.teams)
|
||||
|
||||
async def next(self, ctx) -> "Type[Phase]":
|
||||
orders = [self.order_for(team) for team in self.teams]
|
||||
if len(set(orders)) == len(orders):
|
||||
# All dice are different: good
|
||||
self.teams.sort(key=self.order_for, reverse=self.reverse)
|
||||
await ctx.send(
|
||||
f"L'ordre {self.name} pour ce tour est donc :\n"
|
||||
" - "
|
||||
+ "\n - ".join(
|
||||
f"{team.mention} ({self.order_for(team)})" for team in self.teams
|
||||
)
|
||||
)
|
||||
return self.NEXT
|
||||
else:
|
||||
# Find dice that are the same
|
||||
count = defaultdict(list)
|
||||
for team in self.teams:
|
||||
count[self.order_for(team)].append(team)
|
||||
|
||||
re_do = []
|
||||
for teams in count.values():
|
||||
if len(teams) > 1:
|
||||
re_do.extend(teams)
|
||||
|
||||
teams_str = ", ".join(team.mention for team in re_do)
|
||||
|
||||
for team in re_do:
|
||||
self.set_order_for(team, None)
|
||||
# We need to do this phase again.
|
||||
return self.__class__
|
||||
|
||||
|
||||
class TiragePhase(Phase):
|
||||
class TiragePhase:
|
||||
"""The phase where captains accept or refuse random problems."""
|
||||
|
||||
def __init__(self, tirage, round=0):
|
||||
@ -654,6 +616,15 @@ class TirageCog(Cog, name="Tirages"):
|
||||
dice = random.randint(1, n)
|
||||
return f"{ctx.author.mention} : {Emoji.DICE} {dice}"
|
||||
|
||||
@commands.command(name="dice-all", aliases=["da"], hidden=True)
|
||||
@commands.has_role(Role.DEV)
|
||||
async def dice_all_cmd(self, ctx, *teams):
|
||||
channel = ctx.channel.id
|
||||
if channel in self.tirages:
|
||||
for t in teams:
|
||||
d = random.randint(1, 100)
|
||||
await self.tirages[channel].event(Event(t, d))
|
||||
|
||||
@commands.command(
|
||||
name="random-problem",
|
||||
aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"],
|
||||
@ -663,7 +634,7 @@ class TirageCog(Cog, name="Tirages"):
|
||||
|
||||
channel = ctx.channel.id
|
||||
if channel in self.tirages:
|
||||
await self.tirages[channel].choose_problem(ctx)
|
||||
await self.tirages[channel].rproblem(ctx)
|
||||
else:
|
||||
problem = random.choice(PROBLEMS)
|
||||
await ctx.send(f"Le problème tiré est... **{problem}**")
|
||||
@ -712,7 +683,7 @@ class TirageCog(Cog, name="Tirages"):
|
||||
name="start", usage="équipe1 équipe2 équipe3 (équipe4)",
|
||||
)
|
||||
@commands.has_any_role(*Role.ORGAS)
|
||||
async def start(self, ctx: Context, *teams: discord.Role):
|
||||
async def start(self, ctx: Context, fmt, *teams: discord.Role):
|
||||
"""
|
||||
(orga) Commence un tirage avec 3 ou 4 équipes.
|
||||
|
||||
@ -730,28 +701,25 @@ class TirageCog(Cog, name="Tirages"):
|
||||
"il est possible d'en commencer un autre sur une autre channel."
|
||||
)
|
||||
|
||||
if len(teams) not in (3, 4):
|
||||
try:
|
||||
fmt = list(map(int, fmt.split("+")))
|
||||
except ValueError:
|
||||
raise TfjmError(
|
||||
"Il faut 3 ou 4 équipes pour un tirage. "
|
||||
"Exemple: `!draw start @AAA @BBB @CCC`"
|
||||
"Le premier argument doit être le format du tournoi, "
|
||||
"par exemple `3+3` pour deux poules à trois équipes"
|
||||
)
|
||||
|
||||
if not set(fmt).issubset({3, 4}):
|
||||
raise TfjmError("Seuls les poules à 3 ou 4 équipes sont suportées.")
|
||||
|
||||
# Here all data should be valid
|
||||
|
||||
# Prevent everyone from writing except Capitaines, Orga, CNO, Benevole
|
||||
if False:
|
||||
read = discord.PermissionOverwrite(send_messages=False)
|
||||
send = discord.PermissionOverwrite(send_messages=True)
|
||||
r = lambda role_name: get(ctx.guild.roles, name=role_name)
|
||||
overwrites = {
|
||||
ctx.guild.default_role: read,
|
||||
r(Role.CAPTAIN): send,
|
||||
r(Role.BENEVOLE): send,
|
||||
}
|
||||
await channel.edit(overwrites=overwrites)
|
||||
self.tirages[channel_id] = DiscordTirage(ctx, *teams, fmt=fmt)
|
||||
await self.tirages[channel_id].run()
|
||||
|
||||
self.tirages[channel_id] = Tirage(ctx, channel_id, teams)
|
||||
await self.tirages[channel_id].phase.start(ctx)
|
||||
if self.tirages[channel_id]:
|
||||
# Check if aborted in an other way
|
||||
del self.tirages[channel_id]
|
||||
|
||||
@draw_group.command(name="abort")
|
||||
@commands.has_any_role(*Role.ORGAS)
|
||||
@ -768,32 +736,32 @@ class TirageCog(Cog, name="Tirages"):
|
||||
if channel_id in self.tirages:
|
||||
print(self.tirages, channel_id)
|
||||
print(self.tirages[channel_id])
|
||||
|
||||
await self.tirages[channel_id].end(ctx)
|
||||
del self.tirages[channel_id]
|
||||
await ctx.send("Le tirage est annulé.")
|
||||
else:
|
||||
await ctx.send("Il n'y a pas de tirage en cours.")
|
||||
|
||||
@draw_group.command(name="skip", aliases=["s"])
|
||||
@commands.has_role(Role.DEV)
|
||||
async def draw_skip(self, ctx, *teams: discord.Role):
|
||||
"""(dev) Passe certaines phases du tirage."""
|
||||
channel = ctx.channel.id
|
||||
self.tirages[channel] = tirage = Tirage(ctx, channel, teams)
|
||||
#
|
||||
# @draw_group.command(name="skip", aliases=["s"])
|
||||
# @commands.has_role(Role.DEV)
|
||||
# async def draw_skip(self, ctx, *teams: discord.Role):
|
||||
# """(dev) Passe certaines phases du tirage."""
|
||||
# channel = ctx.channel.id
|
||||
# self.tirages[channel] = tirage = Tirage(ctx, channel, teams)
|
||||
#
|
||||
# tirage.phase = TiragePhase(tirage, round=1)
|
||||
# for i, team in enumerate(tirage.teams):
|
||||
# team.tirage_order = [i + 1, i + 1]
|
||||
# team.passage_order = [i + 1, i + 1]
|
||||
# team.accepted_problems = [PROBLEMS[i], PROBLEMS[-i - 1]]
|
||||
# tirage.teams[0].rejected = [{PROBLEMS[3]}, set(PROBLEMS[4:8])]
|
||||
# tirage.teams[1].rejected = [{PROBLEMS[7]}, set()]
|
||||
#
|
||||
# await ctx.send(f"Skipping to {tirage.phase.__class__.__name__}.")
|
||||
# await tirage.phase.start(ctx)
|
||||
# await tirage.update_phase(ctx)
|
||||
|
||||
tirage.phase = TiragePhase(tirage, round=1)
|
||||
for i, team in enumerate(tirage.teams):
|
||||
team.tirage_order = [i + 1, i + 1]
|
||||
team.passage_order = [i + 1, i + 1]
|
||||
team.accepted_problems = [PROBLEMS[i], PROBLEMS[-i - 1]]
|
||||
tirage.teams[0].rejected = [{PROBLEMS[3]}, set(PROBLEMS[4:8])]
|
||||
tirage.teams[1].rejected = [{PROBLEMS[7]}, set()]
|
||||
|
||||
await ctx.send(f"Skipping to {tirage.phase.__class__.__name__}.")
|
||||
await tirage.phase.start(ctx)
|
||||
await tirage.update_phase(ctx)
|
||||
|
||||
def get_tirages(self) -> Dict[int, Tirage]:
|
||||
def get_tirages(self) -> Dict[int, BaseTirage]:
|
||||
if not File.TIRAGES.exists():
|
||||
return {}
|
||||
|
||||
@ -812,6 +780,7 @@ class TirageCog(Cog, name="Tirages"):
|
||||
`!draw show 42` - Affiche le tirage n°42
|
||||
"""
|
||||
|
||||
return
|
||||
tirages = self.get_tirages()
|
||||
|
||||
if not tirages:
|
||||
|
@ -5,6 +5,7 @@ from discord.ext.commands import Bot
|
||||
|
||||
|
||||
def french_join(l):
|
||||
l = list(l)
|
||||
start = ", ".join(l[:-1])
|
||||
return f"{start} et {l[-1]}"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user