🚧 new tirages working without save

This commit is contained in:
ddorn 2020-05-06 17:38:47 +02:00
parent 5ed508be10
commit a51f2130ec
4 changed files with 227 additions and 232 deletions

View File

@ -1,5 +1,8 @@
import asyncio import asyncio
import random import random
import sys
import traceback
from functools import wraps
from pprint import pprint from pprint import pprint
from io import StringIO 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 "\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)} # return f""" - Accepté: {self.accepted_problems[round]}
- Ordre au tirage: {self.tirage_order[round]} # - Refusés: {", ".join(p[0] for p in self.rejected[round]) if self.rejected[round] else "aucun"}
- Ordre de passage: {self.passage_order[round]} # - Coefficient: {self.coeff(round)}
""" # - Ordre au tirage: {self.tirage_order[round]}
# - Ordre de passage: {self.passage_order[round]}
# """
class Poule: class Poule:
@ -110,6 +115,9 @@ class BaseTirage:
] ]
return await self.event(Event(trigram, random.choice(available))) 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): async def next(self, typ, team=None):
while True: while True:
event = await self.queue.get() event = await self.queue.get()
@ -148,6 +156,7 @@ class BaseTirage:
# TODO: avoid KeyError # TODO: avoid KeyError
if dices[event.team] is None: if dices[event.team] is None:
dices[event.team] = event.value dices[event.team] = event.value
await self.info_dice(event.team, event.value)
else: else:
await self.warn_twice(int) await self.warn_twice(int)
@ -173,6 +182,9 @@ class BaseTirage:
return poules return poules
async def draw_poule(self, poule): async def draw_poule(self, poule):
await self.start_draw_poule(poule)
# Trigrams in draw order # Trigrams in draw order
trigrams = await self.draw_order(poule) trigrams = await self.draw_order(poule)
@ -184,25 +196,27 @@ class BaseTirage:
if team.accepted_problems[poule.rnd] is not None: if team.accepted_problems[poule.rnd] is not None:
# The team already accepted a problem # The team already accepted a problem
current += 1 current += 1
current %= len(teams)
continue continue
# Choose problem # Choose problem
await self.start_select_pb(team) 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 # TODO: Add check for already selected / taken by someone else
# This is not a bug for now, since it cannot happen yet # 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 it
accept = await self.next(bool, team.name) accept = await self.next(bool, team.name)
if accept: if accept.value:
team.accepted_problems[poule.rnd] = event.value team.accepted_problems[poule.rnd] = pevent.value
await self.info_accepted(team, event.value) await self.info_accepted(team, pevent.value)
else: else:
await self.info_rejected(team, event.value, rnd=poule.rnd) await self.info_rejected(team, pevent.value, rnd=poule.rnd)
team.rejected[poule.rnd].add(event.value) team.rejected[poule.rnd].add(pevent.value)
current += 1 current += 1
current %= len(teams)
await self.annonce_poule(poule) await self.annonce_poule(poule)
@ -212,7 +226,7 @@ class BaseTirage:
teams = self.poules[poule] teams = self.poules[poule]
dices = await self.get_dices(teams) 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) await self.annonce_draw_order(order)
return order return order
@ -232,6 +246,9 @@ class BaseTirage:
async def start_make_poule(self, rnd): async def start_make_poule(self, rnd):
"""Called when it starts drawing the poules for round `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): async def start_draw_order(self, poule):
"""Called when we start to draw the order.""" """Called when we start to draw the order."""
@ -253,6 +270,9 @@ class BaseTirage:
async def info_finish(self): async def info_finish(self):
"""Called when the tirage has ended.""" """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): async def info_draw_pb(self, team, pb, rnd):
"""Called when a team draws a problem.""" """Called when a team draws a problem."""
@ -262,3 +282,7 @@ class BaseTirage:
async def info_rejected(self, team, pb, rnd): async def info_rejected(self, team, pb, rnd):
"""Called when a team rejects a problem, """Called when a team rejects a problem,
before it is added to the rejected set.""" before it is added to the rejected set."""
def setup(_):
pass

View File

@ -18,6 +18,7 @@ from src.constants import *
from src.core import CustomBot from src.core import CustomBot
COGS_SHORTCUTS = { COGS_SHORTCUTS = {
"bt": "src.base_tirage",
"c": "src.constants", "c": "src.constants",
"d": "tirages", "d": "tirages",
"e": "errors", "e": "errors",

View File

@ -2,6 +2,8 @@
import asyncio import asyncio
import random import random
import sys
import traceback
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from dataclasses import dataclass from dataclasses import dataclass
from functools import wraps from functools import wraps
@ -15,7 +17,7 @@ from discord.ext import commands
from discord.ext.commands import group, Cog, Context from discord.ext.commands import group, Cog, Context
from discord.utils import get from discord.utils import get
from src.base_tirage import BaseTirage from src.base_tirage import BaseTirage, Event
from src.constants import * from src.constants import *
from src.core import CustomBot from src.core import CustomBot
from src.errors import TfjmError, UnwantedCommand from src.errors import TfjmError, UnwantedCommand
@ -34,7 +36,7 @@ Record = namedtuple("Record", ["name", "pb", "penalite"])
def delete_and_pm(f): def delete_and_pm(f):
@wraps(f) @wraps(f)
def wrapper(self, *args, **kwargs): async def wrapper(self, *args, **kwargs):
await self.ctx.message.delete() await self.ctx.message.delete()
await self.ctx.author.send( await self.ctx.author.send(
"J'ai supprimé ton message:\n> " "J'ai supprimé ton message:\n> "
@ -47,6 +49,8 @@ def delete_and_pm(f):
if msg: if msg:
await self.ctx.author.send(f"Raison: {msg}") await self.ctx.author.send(f"Raison: {msg}")
return wrapper
def send_all(f): def send_all(f):
@wraps(f) @wraps(f)
@ -57,12 +61,33 @@ def send_all(f):
return wrapper 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): class DiscordTirage(BaseTirage):
def __init__(self, ctx, *teams, fmt): def __init__(self, ctx, *teams, fmt):
super(DiscordTirage, self).__init__(*teams, fmt=fmt) super(DiscordTirage, self).__init__(*teams, fmt=fmt)
self.ctx = ctx self.ctx = ctx
self.captain_mention = get(ctx.guild.roles, name=Role.CAPTAIN).mention 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): def records(self, teams, rnd):
"""Get the strings needed for show the tirage in a list of Records""" """Get the strings needed for show the tirage in a list of Records"""
@ -75,6 +100,36 @@ class DiscordTirage(BaseTirage):
for team in teams 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 @delete_and_pm
async def warn_unwanted(self, wanted: Type, got: Type): 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... " else "Halte là ! Ce serait bien de tirer un problème d'abord... "
"et peut-être qu'il te plaira :) ", "et peut-être qu'il te plaira :) ",
(bool, int): "Il tirer un dé avec `!dice 100` d'abord.", (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)) reason = texts.get((type(got), wanted))
@ -100,10 +157,12 @@ class DiscordTirage(BaseTirage):
reason = "Je sais pas, le code ne devrait pas venir ici..." reason = "Je sais pas, le code ne devrait pas venir ici..."
return reason return reason
@safe
@delete_and_pm @delete_and_pm
async def warn_wrong_team(self, expected, got): async def warn_wrong_team(self, expected, got):
return "ce n'était pas à ton tour." return "ce n'était pas à ton tour."
@safe
async def warn_colisions(self, collisions: List[str]): async def warn_colisions(self, collisions: List[str]):
await self.ctx.send( await self.ctx.send(
f"Les equipes {french_join(collisions)} ont fait le même résultat " 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." "Le nouveau lancer effacera l'ancien."
) )
@safe
@delete_and_pm @delete_and_pm
async def warn_twice(self, typ: Type): async def warn_twice(self, typ: Type):
@ -120,6 +180,7 @@ class DiscordTirage(BaseTirage):
print("Weird, DiscordTirage.warn_twice was called with", typ) print("Weird, DiscordTirage.warn_twice was called with", typ)
return "Je sais pas, le code ne devrait pas venir ici..." return "Je sais pas, le code ne devrait pas venir ici..."
@safe
@send_all @send_all
async def start_make_poule(self, rnd): async def start_make_poule(self, rnd):
if rnd == 0: if rnd == 0:
@ -135,50 +196,82 @@ class DiscordTirage(BaseTirage):
f"afin de déterminer les poules du second tour." f"afin de déterminer les poules du second tour."
) )
async def start_draw_order(self, poule): @safe
print(poule) @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): async def start_select_pb(self, team):
await self.ctx.send(f"C'est au tour de {team.mention} de choisir un problème.") 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): 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 @send_all
async def annonce_draw_order(self, order): async def annonce_draw_order(self, order):
order_str = "\n ".join(f"{i}) {tri}" for i, tri in enumerate(order)) order_str = "\n".join(f"{i+1}) {tri}" for i, tri in enumerate(order))
yield "L'ordre de tirage des problèmes pour ce tour est donc: \n" + order_str yield f"L'ordre de tirage des problèmes pour ce tour est donc: ```{order_str}```"
@safe
async def annonce_poule(self, poule): async def annonce_poule(self, poule):
teams = [self.teams[tri] for tri in self.poules[poule]] teams = [self.teams[tri] for tri in self.poules[poule]]
if len(teams) == 3: if len(teams) == 3:
table = """``` table = """```
+-----+---------+---------+---------+ +-----+---------+---------+---------+
| | Phase 1 | Phase 2 | Phase 3 | | | Phase 1 | Phase 2 | Phase 3 |
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | | | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} |
+-----+---------+---------+---------+ +-----+---------+---------+---------+
| {0.name} | Déf | Rap | Opp | | {0.name} | Déf | Rap | Opp |
+-----+---------+---------+---------+ +-----+---------+---------+---------+
| {1.name} | Opp | Déf | Rap | | {1.name} | Opp | Déf | Rap |
+-----+---------+---------+---------+ +-----+---------+---------+---------+
| {2.name} | Rap | Opp | Déf | | {2.name} | Rap | Opp | Déf |
+-----+---------+---------+---------+ +-----+---------+---------+---------+
```""" ```"""
else: else:
table = """``` table = """```
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
| | Phase 1 | Phase 2 | Phase 3 | Phase 4 | | | Phase 1 | Phase 2 | Phase 3 | Phase 4 |
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} | | | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
| {0.name} | Déf | | Rap | Opp | | {0.name} | Déf | | Rap | Opp |
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
| {1.name} | Opp | Déf | | Rap | | {1.name} | Opp | Déf | | Rap |
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
| {2.name} | Rap | Opp | Déf | | | {2.name} | Rap | Opp | Déf | |
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
| {3.name} | | Rap | Opp | Déf | | {3.name} | | Rap | Opp | Déf |
+-----+---------+---------+---------+---------+ +-----+---------+---------+---------+---------+
```""" ```"""
embed = discord.Embed( embed = discord.Embed(
@ -205,6 +298,7 @@ class DiscordTirage(BaseTirage):
await self.ctx.send(embed=embed) await self.ctx.send(embed=embed)
@safe
@send_all @send_all
async def info_start(self): async def info_start(self):
yield ( yield (
@ -225,6 +319,7 @@ class DiscordTirage(BaseTirage):
"l'ordre de tirage pour le tour et les problèmes." "l'ordre de tirage pour le tour et les problèmes."
) )
@safe
@send_all @send_all
async def info_finish(self): async def info_finish(self):
yield "Le tirage est fini, merci à tout le monde !" yield "Le tirage est fini, merci à tout le monde !"
@ -235,9 +330,19 @@ class DiscordTirage(BaseTirage):
# TODO: Save it # TODO: Save it
# TODO: make them available with the api # 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): 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]: if pb in team.rejected[rnd]:
await self.ctx.send( yield (
f"Vous avez déjà refusé **{pb}**, " f"Vous avez déjà refusé **{pb}**, "
f"vous pouvez le refuser à nouveau (`!non`) et " f"vous pouvez le refuser à nouveau (`!non`) et "
f"tirer immédiatement un nouveau problème " f"tirer immédiatement un nouveau problème "
@ -245,19 +350,20 @@ class DiscordTirage(BaseTirage):
) )
else: else:
if len(team.rejected[rnd]) >= MAX_REFUSE: if len(team.rejected[rnd]) >= MAX_REFUSE:
await self.ctx.send( yield (
f"Vous pouvez accepter ou refuser **{pb}** " f"Vous pouvez accepter ou refuser **{pb}** "
f"mais si vous choisissez de le refuser, il y " f"mais si vous choisissez de le refuser, il y "
f"aura une pénalité de 0.5 sur le multiplicateur du " f"aura une pénalité de 0.5 sur le multiplicateur du "
f"défenseur." f"défenseur."
) )
else: else:
await self.ctx.send( yield (
f"Vous pouvez accepter (`!oui`) ou refuser (`!non`) **{pb}**. " f"Vous pouvez l'accepter (`!oui`) ou le refuser (`!non`). "
f"Il reste {MAX_REFUSE - len(team.rejected[rnd])} refus sans pénalité " f"Il reste {MAX_REFUSE - len(team.rejected[rnd])} refus sans pénalité "
f"pour {team.mention}." f"pour {team.mention}."
) )
@safe
async def info_accepted(self, team, pb): async def info_accepted(self, team, pb):
await self.ctx.send( await self.ctx.send(
f"L'équipe {team.mention} a accepté " f"L'équipe {team.mention} a accepté "
@ -265,6 +371,7 @@ class DiscordTirage(BaseTirage):
f"ne peuvent plus l'accepter." f"ne peuvent plus l'accepter."
) )
@safe
async def info_rejected(self, team, pb, rnd): async def info_rejected(self, team, pb, rnd):
msg = f"{team.mention} a refusé **{pb}** " msg = f"{team.mention} a refusé **{pb}** "
if pb in team.rejected[rnd]: if pb in team.rejected[rnd]:
@ -274,152 +381,7 @@ class DiscordTirage(BaseTirage):
await self.ctx.send(msg) await self.ctx.send(msg)
class Tirage(yaml.YAMLObject): class TiragePhase:
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):
"""The phase where captains accept or refuse random problems.""" """The phase where captains accept or refuse random problems."""
def __init__(self, tirage, round=0): def __init__(self, tirage, round=0):
@ -654,6 +616,15 @@ class TirageCog(Cog, name="Tirages"):
dice = random.randint(1, n) dice = random.randint(1, n)
return f"{ctx.author.mention} : {Emoji.DICE} {dice}" 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( @commands.command(
name="random-problem", name="random-problem",
aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"], aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"],
@ -663,7 +634,7 @@ class TirageCog(Cog, name="Tirages"):
channel = ctx.channel.id channel = ctx.channel.id
if channel in self.tirages: if channel in self.tirages:
await self.tirages[channel].choose_problem(ctx) await self.tirages[channel].rproblem(ctx)
else: else:
problem = random.choice(PROBLEMS) problem = random.choice(PROBLEMS)
await ctx.send(f"Le problème tiré est... **{problem}**") 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)", name="start", usage="équipe1 équipe2 équipe3 (équipe4)",
) )
@commands.has_any_role(*Role.ORGAS) @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. (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." "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( raise TfjmError(
"Il faut 3 ou 4 équipes pour un tirage. " "Le premier argument doit être le format du tournoi, "
"Exemple: `!draw start @AAA @BBB @CCC`" "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 # Here all data should be valid
# Prevent everyone from writing except Capitaines, Orga, CNO, Benevole self.tirages[channel_id] = DiscordTirage(ctx, *teams, fmt=fmt)
if False: await self.tirages[channel_id].run()
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] = Tirage(ctx, channel_id, teams) if self.tirages[channel_id]:
await self.tirages[channel_id].phase.start(ctx) # Check if aborted in an other way
del self.tirages[channel_id]
@draw_group.command(name="abort") @draw_group.command(name="abort")
@commands.has_any_role(*Role.ORGAS) @commands.has_any_role(*Role.ORGAS)
@ -768,32 +736,32 @@ class TirageCog(Cog, name="Tirages"):
if channel_id in self.tirages: if channel_id in self.tirages:
print(self.tirages, channel_id) print(self.tirages, channel_id)
print(self.tirages[channel_id]) print(self.tirages[channel_id])
del self.tirages[channel_id]
await self.tirages[channel_id].end(ctx)
await ctx.send("Le tirage est annulé.") await ctx.send("Le tirage est annulé.")
else: else:
await ctx.send("Il n'y a pas de tirage en cours.") await ctx.send("Il n'y a pas de tirage en cours.")
@draw_group.command(name="skip", aliases=["s"]) #
@commands.has_role(Role.DEV) # @draw_group.command(name="skip", aliases=["s"])
async def draw_skip(self, ctx, *teams: discord.Role): # @commands.has_role(Role.DEV)
"""(dev) Passe certaines phases du tirage.""" # async def draw_skip(self, ctx, *teams: discord.Role):
channel = ctx.channel.id # """(dev) Passe certaines phases du tirage."""
self.tirages[channel] = tirage = Tirage(ctx, channel, teams) # 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) def get_tirages(self) -> Dict[int, BaseTirage]:
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]:
if not File.TIRAGES.exists(): if not File.TIRAGES.exists():
return {} return {}
@ -812,6 +780,7 @@ class TirageCog(Cog, name="Tirages"):
`!draw show 42` - Affiche le tirage n°42 `!draw show 42` - Affiche le tirage n°42
""" """
return
tirages = self.get_tirages() tirages = self.get_tirages()
if not tirages: if not tirages:

View File

@ -5,6 +5,7 @@ from discord.ext.commands import Bot
def french_join(l): def french_join(l):
l = list(l)
start = ", ".join(l[:-1]) start = ", ".join(l[:-1])
return f"{start} et {l[-1]}" return f"{start} et {l[-1]}"