2020-04-25 14:42:06 +00:00
|
|
|
#!/bin/python
|
2020-04-28 13:33:40 +00:00
|
|
|
|
|
|
|
import asyncio
|
2020-04-25 23:50:06 +00:00
|
|
|
import random
|
2020-05-20 00:52:42 +00:00
|
|
|
import re
|
2020-05-06 15:38:47 +00:00
|
|
|
import sys
|
|
|
|
import traceback
|
2020-04-28 13:33:40 +00:00
|
|
|
from collections import defaultdict, namedtuple
|
2020-05-06 00:27:09 +00:00
|
|
|
from dataclasses import dataclass
|
|
|
|
from functools import wraps
|
2020-04-28 13:33:40 +00:00
|
|
|
from io import StringIO
|
|
|
|
from pprint import pprint
|
2020-05-06 00:27:09 +00:00
|
|
|
from typing import Type, Dict, Union, Optional, List
|
2020-04-25 14:42:06 +00:00
|
|
|
|
2020-05-16 10:50:35 +00:00
|
|
|
import aiohttp
|
2020-04-25 14:42:06 +00:00
|
|
|
import discord
|
2020-04-27 08:05:17 +00:00
|
|
|
import yaml
|
2020-04-27 09:43:16 +00:00
|
|
|
from discord.ext import commands
|
2020-05-13 14:36:46 +00:00
|
|
|
from discord.ext.commands import group, Cog, Context, RoleConverter
|
2020-04-25 16:58:35 +00:00
|
|
|
from discord.utils import get
|
2020-04-25 14:42:06 +00:00
|
|
|
|
2020-05-06 17:04:36 +00:00
|
|
|
from src.base_tirage import BaseTirage, Event, Poule
|
2020-04-27 08:05:17 +00:00
|
|
|
from src.constants import *
|
2020-04-30 15:26:33 +00:00
|
|
|
from src.core import CustomBot
|
2020-04-28 13:33:40 +00:00
|
|
|
from src.errors import TfjmError, UnwantedCommand
|
|
|
|
|
2020-05-06 17:04:36 +00:00
|
|
|
__all__ = ["TirageCog"]
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
from src.utils import send_and_bin, french_join, pprint_send, confirm
|
2020-05-05 11:23:07 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
RE_DRAW_START = re.compile(
|
|
|
|
r"^((?P<fmt>\d(\+\d)*) )?(?P<teams>[A-Z]{3}(\s[A-Z]{3})+)((?P<finale>\s--finale)|(\s--continue[= ](?P<continue>\d+)))$"
|
|
|
|
)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
|
|
|
Record = namedtuple("Record", ["name", "pb", "penalite"])
|
|
|
|
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
def delete_and_pm(f):
|
|
|
|
@wraps(f)
|
2020-05-06 15:38:47 +00:00
|
|
|
async def wrapper(self, *args, **kwargs):
|
2020-05-06 00:27:09 +00:00
|
|
|
await self.ctx.message.delete()
|
|
|
|
await self.ctx.author.send(
|
|
|
|
"J'ai supprimé ton message:\n> "
|
|
|
|
+ self.ctx.message.clean_content
|
|
|
|
+ "\nC'est pas grave, c'est juste pour ne pas encombrer "
|
|
|
|
"le chat lors du tirage."
|
|
|
|
)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
msg = await f(self, *args, **kwargs)
|
|
|
|
if msg:
|
|
|
|
await self.ctx.author.send(f"Raison: {msg}")
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
return wrapper
|
|
|
|
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
def send_all(f):
|
|
|
|
@wraps(f)
|
|
|
|
async def wrapper(self, *args, **kwargs):
|
|
|
|
async for msg in f(self, *args, **kwargs):
|
|
|
|
await self.ctx.send(msg)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
return wrapper
|
2020-04-28 13:33:40 +00:00
|
|
|
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
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
|
|
|
|
|
2020-05-06 17:04:36 +00:00
|
|
|
ts = self.load_all()
|
|
|
|
self.id = 1 + (max(ts) if ts else 0)
|
|
|
|
self.save()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def load_all():
|
|
|
|
if not File.TIRAGES.exists():
|
|
|
|
return {}
|
|
|
|
|
|
|
|
with open(File.TIRAGES) as f:
|
|
|
|
tirages = yaml.load(f)
|
|
|
|
|
|
|
|
return tirages
|
|
|
|
|
|
|
|
def save(self):
|
|
|
|
ts = self.load_all()
|
|
|
|
|
|
|
|
ctx = self.ctx
|
|
|
|
queue = self.queue
|
|
|
|
self.ctx = None
|
|
|
|
self.queue = None
|
|
|
|
ts[self.id] = self
|
|
|
|
|
|
|
|
File.TIRAGES.touch()
|
|
|
|
with open(File.TIRAGES, "w") as f:
|
|
|
|
yaml.dump(ts, f)
|
|
|
|
|
|
|
|
self.ctx = ctx
|
|
|
|
self.queue = queue
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
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
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
def records(self, teams, rnd):
|
|
|
|
"""Get the strings needed for show the tirage in a list of Records"""
|
|
|
|
|
|
|
|
return [
|
|
|
|
Record(
|
|
|
|
team.name,
|
|
|
|
(team.accepted_problems[rnd] or "- None")[0],
|
|
|
|
f"k = {team.coeff(rnd)} ",
|
|
|
|
)
|
|
|
|
for team in teams
|
|
|
|
]
|
2020-04-29 22:53:34 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
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
|
2020-05-06 00:27:09 +00:00
|
|
|
@delete_and_pm
|
|
|
|
async def warn_unwanted(self, wanted: Type, got: Type):
|
|
|
|
|
|
|
|
texts = {
|
|
|
|
(int, str): "Il faut tirer un problème avec `!rp` et pas un dé.",
|
|
|
|
(int, bool): "Il faut accepter `!oui` ou refuser `!non` "
|
|
|
|
"le problème d'abord.",
|
|
|
|
(str, int): "Tu dois lancer un dé (`!dice 100`), pas choisir un problème.",
|
|
|
|
(str, bool): "Il faut accepter `!oui` ou refuser `!non` le "
|
|
|
|
"problème avant d'en choisir un autre",
|
|
|
|
(bool, str): "Tu es bien optimiste pour vouloir accepter un problème "
|
|
|
|
"avant de l'avoir tiré !"
|
|
|
|
if got
|
|
|
|
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.",
|
2020-05-06 15:38:47 +00:00
|
|
|
(int, int): "Il faut lancer un dé à 100 faces.",
|
|
|
|
(str, str): f"'{got}' n'est pas un problème valide.",
|
2020-04-29 22:53:34 +00:00
|
|
|
}
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
reason = texts.get((type(got), wanted))
|
2020-04-29 22:53:34 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
if reason is None:
|
|
|
|
print(f"Weird, arguments for warn_unwanted were {wanted} and {got}")
|
|
|
|
reason = "Je sais pas, le code ne devrait pas venir ici..."
|
|
|
|
return reason
|
2020-04-29 22:53:34 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@delete_and_pm
|
|
|
|
async def warn_wrong_team(self, expected, got):
|
|
|
|
return "ce n'était pas à ton tour."
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
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 "
|
|
|
|
"et doivent relancer un dé. "
|
|
|
|
"Le nouveau lancer effacera l'ancien."
|
|
|
|
)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@delete_and_pm
|
|
|
|
async def warn_twice(self, typ: Type):
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
if typ == int:
|
|
|
|
return "Tu as déjà lancé un dé, pas besoin de le refaire ;)"
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
print("Weird, DiscordTirage.warn_twice was called with", typ)
|
|
|
|
return "Je sais pas, le code ne devrait pas venir ici..."
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@send_all
|
|
|
|
async def start_make_poule(self, rnd):
|
|
|
|
if rnd == 0:
|
|
|
|
yield (
|
|
|
|
f"Les {self.captain_mention}s, vous pouvez désormais tous lancer un dé 100 "
|
|
|
|
"comme ceci : `!dice 100`. "
|
|
|
|
"Les poules et l'ordre de passage lors du premier tour sera l'ordre croissant des dés, "
|
|
|
|
"c'est-à-dire que le plus petit lancer sera le premier à passer dans la poule A."
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
yield (
|
|
|
|
f"Les {self.captain_mention}s, vous pouvez à nouveau tous lancer un dé 100, "
|
|
|
|
f"afin de déterminer les poules du second tour."
|
|
|
|
)
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@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
|
2020-05-06 00:27:09 +00:00
|
|
|
async def start_draw_order(self, poule):
|
2020-05-06 15:38:47 +00:00
|
|
|
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."
|
|
|
|
)
|
2020-05-06 00:27:09 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
async def start_select_pb(self, team):
|
2020-05-20 00:52:42 +00:00
|
|
|
await self.ctx.send(
|
|
|
|
f"C'est au tour de {team.mention} de choisir un problème (`!rp`)."
|
|
|
|
)
|
2020-05-06 00:27:09 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
|
|
|
@send_all
|
2020-05-06 00:27:09 +00:00
|
|
|
async def annonce_poules(self, poules):
|
2020-05-06 15:38:47 +00:00
|
|
|
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
|
|
|
|
)
|
2020-05-20 00:52:42 +00:00
|
|
|
if first:
|
|
|
|
yield (f"Les poules sont donc, pour le premier tour :" f"```{first}```\n")
|
|
|
|
if second:
|
|
|
|
yield (f"Pour le second tour les poules sont :" f"```{second}```")
|
2020-05-06 00:27:09 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@send_all
|
|
|
|
async def annonce_draw_order(self, order):
|
2020-05-06 15:38:47 +00:00
|
|
|
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}```"
|
2020-05-06 00:27:09 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
async def annonce_poule(self, poule):
|
|
|
|
teams = [self.teams[tri] for tri in self.poules[poule]]
|
|
|
|
|
|
|
|
if len(teams) == 3:
|
|
|
|
table = """```
|
2020-05-13 13:49:00 +00:00
|
|
|
╔═════╦═════════╦═════════╦═════════╗
|
2020-05-20 10:54:46 +00:00
|
|
|
║ T F ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
|
2020-05-23 18:18:21 +00:00
|
|
|
║ J M ║ Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb} ║
|
2020-05-13 13:49:00 +00:00
|
|
|
╠═════╬═════════╬═════════╬═════════╣
|
|
|
|
║ {0.name} ║ Def ║ Rap ║ Opp ║
|
|
|
|
╠═════╬═════════╬═════════╬═════════╣
|
|
|
|
║ {1.name} ║ Opp ║ Def ║ Rap ║
|
|
|
|
╠═════╬═════════╬═════════╬═════════╣
|
|
|
|
║ {2.name} ║ Rap ║ Opp ║ Def ║
|
|
|
|
╚═════╩═════════╩═════════╩═════════╝```"""
|
|
|
|
elif len(teams) == 4:
|
2020-05-06 00:27:09 +00:00
|
|
|
table = """```
|
2020-05-06 15:38:47 +00:00
|
|
|
+-----+---------+---------+---------+---------+
|
|
|
|
| | Phase 1 | Phase 2 | Phase 3 | Phase 4 |
|
2020-05-20 10:54:46 +00:00
|
|
|
| | Pb {0.pb} | Pb {1.pb} | Pb {2.pb} | Pb {3.pb} |
|
2020-05-06 15:38:47 +00:00
|
|
|
+-----+---------+---------+---------+---------+
|
|
|
|
| {0.name} | Déf | | Rap | Opp |
|
|
|
|
+-----+---------+---------+---------+---------+
|
|
|
|
| {1.name} | Opp | Déf | | Rap |
|
|
|
|
+-----+---------+---------+---------+---------+
|
|
|
|
| {2.name} | Rap | Opp | Déf | |
|
|
|
|
+-----+---------+---------+---------+---------+
|
|
|
|
| {3.name} | | Rap | Opp | Déf |
|
2020-05-06 17:04:36 +00:00
|
|
|
+-----+---------+---------+---------+---------+```"""
|
2020-05-13 13:49:00 +00:00
|
|
|
elif len(teams) == 5:
|
|
|
|
table = """```
|
2020-05-20 10:54:46 +00:00
|
|
|
╔═══╦═══════════════════╦═══════════════════╦═════════╗
|
|
|
|
║ ║ Phase 1 ║ Phase 2 ║ Phase 3 ║
|
|
|
|
╠═══╬═════════╦═════════╬═════════╦═════════╬═════════╣
|
|
|
|
║ ║ Salle 1 ║ Salle 2 ║ Salle 1 ║ Salle 2 ║ Salle 1 ║
|
|
|
|
║ ║ Pb. {0.pb} ║ Pb. {1.pb} ║ Pb. {2.pb} ║ Pb. {3.pb} ║ Pb. {4.pb} ║
|
|
|
|
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
|
|
|
|
║{0.name}║ Def ║ ║ Opp ║ Rap ║ ║
|
|
|
|
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
|
|
|
|
║{1.name}║ ║ Def ║ Rap ║ ║ Opp ║
|
|
|
|
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
|
|
|
|
║{2.name}║ Opp ║ ║ Def ║ ║ Rap ║
|
|
|
|
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
|
|
|
|
║{3.name}║ Rap ║ Opp ║ ║ Def ║ ║
|
|
|
|
╠═══╬═════════╬═════════╬═════════╬═════════╬═════════╣
|
|
|
|
║{4.name}║ ║ Rap ║ ║ Opp ║ Def ║
|
|
|
|
╚═══╩═════════╩═════════╩═════════╩═════════╩═════════╝```"""
|
2020-05-13 13:49:00 +00:00
|
|
|
else:
|
|
|
|
table = "WTF il n'y a pas 3,4 ou 5 equipes ici."
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
embed = discord.Embed(
|
|
|
|
title=f"Résumé du tirage entre {french_join([t.name for t in teams])}",
|
|
|
|
color=EMBED_COLOR,
|
|
|
|
)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
embed.add_field(
|
|
|
|
name=ROUND_NAMES[poule.rnd].capitalize(),
|
|
|
|
value=table.format(*self.records(teams, poule.rnd)),
|
|
|
|
inline=False,
|
2020-04-28 13:33:40 +00:00
|
|
|
)
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
for team in teams:
|
|
|
|
embed.add_field(
|
|
|
|
name=team.name + " - " + team.accepted_problems[poule.rnd],
|
|
|
|
value=team.details(poule.rnd),
|
|
|
|
inline=True,
|
2020-04-28 13:33:40 +00:00
|
|
|
)
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
embed.set_footer(
|
2020-05-06 17:04:36 +00:00
|
|
|
text=f"Ce tirage peut être affiché à tout moment avec `!draw show {self.id}`"
|
2020-05-06 00:27:09 +00:00
|
|
|
)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
await self.ctx.send(embed=embed)
|
|
|
|
|
2020-05-06 17:04:36 +00:00
|
|
|
self.save()
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@send_all
|
|
|
|
async def info_start(self):
|
|
|
|
yield (
|
|
|
|
"Nous allons commencer le tirage des problèmes. "
|
|
|
|
"Seuls les capitaines de chaque équipe peuvent désormais écrire ici. "
|
|
|
|
"Merci de d'envoyer seulement ce que est nécessaire et suffisant au "
|
|
|
|
"bon déroulement du tirage. Vous pouvez à tout moment poser toute question "
|
|
|
|
"si quelque chose n'est pas clair ou ne va pas."
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"Pour plus de détails sur le déroulement du tirgae au sort, le règlement "
|
|
|
|
"est accessible sur https://tfjm.org/reglement."
|
|
|
|
)
|
|
|
|
|
|
|
|
yield (
|
|
|
|
"Nous allons d'abord tirer les poules et l'ordre de passage dans chaque tour "
|
|
|
|
"avec toutes les équipes puis pour chaque poule de chaque tour, nous tirerons "
|
|
|
|
"l'ordre de tirage pour le tour et les problèmes."
|
|
|
|
)
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
@send_all
|
|
|
|
async def info_finish(self):
|
|
|
|
yield "Le tirage est fini, merci à tout le monde !"
|
|
|
|
yield (
|
|
|
|
"Vous pouvez désormais trouver les problèmes que vous devrez opposer ou rapporter "
|
|
|
|
"sur la page de votre équipe."
|
|
|
|
)
|
|
|
|
# TODO: make them available with the api
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
|
|
|
@send_all
|
|
|
|
async def info_dice(self, team, dice):
|
|
|
|
yield f"L'équipe {team} a lancé un... {dice} :game_die:"
|
|
|
|
|
|
|
|
@safe
|
|
|
|
@send_all
|
2020-05-06 00:27:09 +00:00
|
|
|
async def info_draw_pb(self, team, pb, rnd):
|
2020-05-06 15:38:47 +00:00
|
|
|
|
|
|
|
yield (f"L'équipe {self.mention(team.name)} a tiré... **{pb}**")
|
|
|
|
|
2020-05-06 00:27:09 +00:00
|
|
|
if pb in team.rejected[rnd]:
|
2020-05-06 15:38:47 +00:00
|
|
|
yield (
|
2020-05-06 00:27:09 +00:00
|
|
|
f"Vous avez déjà refusé **{pb}**, "
|
|
|
|
f"vous pouvez le refuser à nouveau (`!non`) et "
|
|
|
|
f"tirer immédiatement un nouveau problème "
|
|
|
|
f"ou changer d'avis et l'accepter (`!oui`)."
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
if len(team.rejected[rnd]) >= MAX_REFUSE:
|
2020-05-06 15:38:47 +00:00
|
|
|
yield (
|
2020-05-06 00:27:09 +00:00
|
|
|
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:
|
2020-05-06 15:38:47 +00:00
|
|
|
yield (
|
|
|
|
f"Vous pouvez l'accepter (`!oui`) ou le refuser (`!non`). "
|
2020-05-06 00:27:09 +00:00
|
|
|
f"Il reste {MAX_REFUSE - len(team.rejected[rnd])} refus sans pénalité "
|
|
|
|
f"pour {team.mention}."
|
|
|
|
)
|
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-13 13:49:00 +00:00
|
|
|
async def info_accepted(self, team, pb, still_available):
|
|
|
|
if still_available:
|
|
|
|
await self.ctx.send(
|
|
|
|
f"L'équipe {team.mention} a accepté "
|
|
|
|
f"**{pb}** ! Une autre équipe peut encore l'accepter."
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
await self.ctx.send(
|
|
|
|
f"L'équipe {team.mention} a accepté "
|
|
|
|
f"**{pb}** ! Les autres équipes "
|
|
|
|
f"ne peuvent plus l'accepter."
|
|
|
|
)
|
2020-05-06 00:27:09 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
@safe
|
2020-05-06 00:27:09 +00:00
|
|
|
async def info_rejected(self, team, pb, rnd):
|
|
|
|
msg = f"{team.mention} a refusé **{pb}** "
|
|
|
|
if pb in team.rejected[rnd]:
|
|
|
|
msg += "sans pénalité."
|
|
|
|
else:
|
|
|
|
msg += "!"
|
|
|
|
await self.ctx.send(msg)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
2020-05-06 17:04:36 +00:00
|
|
|
async def show(self, ctx):
|
|
|
|
self.ctx = ctx
|
|
|
|
for poule in self.poules:
|
|
|
|
await self.annonce_poule(poule)
|
2020-04-28 13:33:40 +00:00
|
|
|
|
|
|
|
|
2020-04-27 09:43:16 +00:00
|
|
|
class TirageCog(Cog, name="Tirages"):
|
|
|
|
def __init__(self, bot):
|
2020-04-30 15:26:33 +00:00
|
|
|
self.bot: CustomBot = bot
|
2020-04-27 09:43:16 +00:00
|
|
|
|
|
|
|
# We retrieve the global variable.
|
2020-05-06 00:27:09 +00:00
|
|
|
# We don't want tirages to be just an attribute
|
2020-04-27 09:43:16 +00:00
|
|
|
# as we want them to outlive the Cog, for instance
|
|
|
|
# if the cog is reloaded turing a tirage.
|
|
|
|
from src.tfjm_discord_bot import tirages
|
|
|
|
|
|
|
|
self.tirages = tirages
|
|
|
|
|
2020-04-27 10:28:30 +00:00
|
|
|
# ---------- Commandes hors du groupe draw ----------- #
|
|
|
|
|
|
|
|
@commands.command(
|
|
|
|
name="dice", aliases=["de", "dé", "roll"], usage="n",
|
|
|
|
)
|
2020-05-05 11:23:07 +00:00
|
|
|
@send_and_bin
|
|
|
|
async def dice(self, ctx: Context, n):
|
2020-04-27 10:28:30 +00:00
|
|
|
"""Lance un dé à `n` faces."""
|
2020-05-05 11:23:07 +00:00
|
|
|
|
|
|
|
if not n:
|
|
|
|
raise TfjmError("Tu dois préciser un nombre de faces :wink:")
|
|
|
|
|
|
|
|
bases = {"0x": 16, "0b": 2, "0o": 8}
|
|
|
|
|
|
|
|
base = bases.get(n[:2], 10)
|
|
|
|
try:
|
|
|
|
n = int(n, base)
|
|
|
|
except ValueError:
|
|
|
|
try:
|
|
|
|
n = float(n)
|
|
|
|
|
|
|
|
if abs(n) == float("inf"):
|
|
|
|
raise TfjmError("Alors là tu vises vraiment gros toi !")
|
|
|
|
if n != n: # NaN
|
|
|
|
raise TfjmError("Nan, ça je peux pas faire !")
|
|
|
|
if not n.is_integer():
|
|
|
|
raise TfjmError(
|
|
|
|
"Un dé avec des fractions de faces ? "
|
|
|
|
"Si tu me donnes un patron, je le lancerai !"
|
|
|
|
)
|
|
|
|
|
|
|
|
n = int(n)
|
|
|
|
except ValueError:
|
|
|
|
raise TfjmError(
|
|
|
|
"Ton argument ne ressemble pas trop à un entier :thinking:"
|
|
|
|
)
|
|
|
|
|
2020-04-27 10:28:30 +00:00
|
|
|
channel = ctx.channel.id
|
|
|
|
if channel in self.tirages:
|
|
|
|
await self.tirages[channel].dice(ctx, n)
|
|
|
|
else:
|
2020-04-30 15:26:33 +00:00
|
|
|
if n == 0:
|
|
|
|
raise TfjmError(f"Un dé sans faces ? Le concept m'intéresse...")
|
2020-04-27 10:28:30 +00:00
|
|
|
if n < 1:
|
2020-04-30 15:26:33 +00:00
|
|
|
raise TfjmError(
|
2020-05-05 11:23:07 +00:00
|
|
|
"Je n'ai pas encore de dés en antimatière, "
|
|
|
|
"désolé :man_shrugging:"
|
2020-04-30 15:26:33 +00:00
|
|
|
)
|
|
|
|
if len(str(n)) > 1900:
|
|
|
|
raise TfjmError(
|
|
|
|
"Oulà... Je sais que la taille ça ne compte pas, "
|
|
|
|
"mais là il est vraiment gros ton dé !"
|
|
|
|
)
|
2020-04-27 10:28:30 +00:00
|
|
|
|
|
|
|
dice = random.randint(1, n)
|
2020-05-05 11:23:07 +00:00
|
|
|
return f"{ctx.author.mention} : {Emoji.DICE} {dice}"
|
2020-04-27 10:28:30 +00:00
|
|
|
|
2020-05-13 14:36:46 +00:00
|
|
|
@commands.command(name="dice-all", aliases=["da"])
|
2020-05-06 15:38:47 +00:00
|
|
|
@commands.has_role(Role.DEV)
|
|
|
|
async def dice_all_cmd(self, ctx, *teams):
|
2020-05-19 15:11:35 +00:00
|
|
|
"""(dev) Lance un dé pour chaque equipe en entrée."""
|
2020-05-06 15:38:47 +00:00
|
|
|
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))
|
|
|
|
|
2020-04-27 10:28:30 +00:00
|
|
|
@commands.command(
|
|
|
|
name="random-problem",
|
|
|
|
aliases=["rp", "problème-aléatoire", "probleme-aleatoire", "pa"],
|
|
|
|
)
|
|
|
|
async def random_problem(self, ctx: Context):
|
|
|
|
"""Choisit un problème parmi ceux de cette année."""
|
|
|
|
|
|
|
|
channel = ctx.channel.id
|
|
|
|
if channel in self.tirages:
|
2020-05-06 15:38:47 +00:00
|
|
|
await self.tirages[channel].rproblem(ctx)
|
2020-04-27 10:28:30 +00:00
|
|
|
else:
|
|
|
|
problem = random.choice(PROBLEMS)
|
|
|
|
await ctx.send(f"Le problème tiré est... **{problem}**")
|
|
|
|
|
|
|
|
@commands.command(
|
2020-05-20 10:54:46 +00:00
|
|
|
name="oui",
|
|
|
|
aliases=["accept", "yes", "o", "oh-yeaaah", "accepte", "ouiiiiiii", "owi"],
|
2020-04-27 10:28:30 +00:00
|
|
|
)
|
|
|
|
async def accept_cmd(self, ctx):
|
|
|
|
"""
|
|
|
|
Accepte le problème qui vient d'être tiré.
|
|
|
|
|
|
|
|
Sans effet si il n'y a pas de tirage en cours.
|
|
|
|
"""
|
|
|
|
|
|
|
|
channel = ctx.channel.id
|
|
|
|
if channel in self.tirages:
|
|
|
|
await self.tirages[channel].accept(ctx, True)
|
|
|
|
else:
|
|
|
|
await ctx.send(f"{ctx.author.mention} approuve avec vigeur !")
|
|
|
|
|
|
|
|
@commands.command(
|
|
|
|
name="non", aliases=["refuse", "no", "n", "nope", "jaaamais"],
|
|
|
|
)
|
|
|
|
async def refuse_cmd(self, ctx):
|
|
|
|
"""
|
|
|
|
Refuse le problème qui vient d'être tiré.
|
|
|
|
|
|
|
|
Sans effet si il n'y a pas de tirage en cours.
|
|
|
|
"""
|
|
|
|
|
|
|
|
channel = ctx.channel.id
|
|
|
|
if channel in self.tirages:
|
|
|
|
await self.tirages[channel].accept(ctx, False)
|
|
|
|
else:
|
2020-04-27 18:03:51 +00:00
|
|
|
await ctx.send(f"{ctx.author.mention} nie tout en bloc !")
|
2020-04-27 10:28:30 +00:00
|
|
|
|
|
|
|
# ---------- Commandes du groupe draw ----------- #
|
|
|
|
|
2020-05-18 14:51:23 +00:00
|
|
|
@group(
|
|
|
|
name="draw",
|
|
|
|
aliases=["d", "tirage"],
|
|
|
|
invoke_without_command=True,
|
|
|
|
case_insensitive=True,
|
|
|
|
hidden=True,
|
|
|
|
)
|
2020-04-27 09:43:16 +00:00
|
|
|
async def draw_group(self, ctx: Context) -> None:
|
2020-04-29 11:42:49 +00:00
|
|
|
"""Groupe de commandes pour les tirages."""
|
|
|
|
|
|
|
|
await ctx.invoke(self.bot.get_command("help"), "draw")
|
2020-04-27 09:43:16 +00:00
|
|
|
|
|
|
|
@draw_group.command(
|
2020-05-20 00:52:42 +00:00
|
|
|
name="start", usage="FMT TRI1 TRI2... [--finale] [--continue=ID]",
|
2020-04-27 09:43:16 +00:00
|
|
|
)
|
2020-04-28 16:34:46 +00:00
|
|
|
@commands.has_any_role(*Role.ORGAS)
|
2020-05-20 00:52:42 +00:00
|
|
|
async def start(self, ctx: Context, *args):
|
2020-04-27 09:43:16 +00:00
|
|
|
"""
|
2020-04-27 20:07:20 +00:00
|
|
|
(orga) Commence un tirage avec 3 ou 4 équipes.
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-04-27 14:35:29 +00:00
|
|
|
Cette commande attend des trigrames d'équipes.
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-04-27 14:35:29 +00:00
|
|
|
Exemple:
|
2020-05-20 00:52:42 +00:00
|
|
|
`!draw start 5 AAA BBB CCC DDD EEE` - Tirage à une poule de 5 équipes
|
|
|
|
`!draw start 3+3 AAA BBB CCC DDD EEE FFF` - Deux poules de 3 équipes
|
|
|
|
`!draw start 3 AAA BBB CCC --finale` - Tirage seulement du premier tour
|
|
|
|
`!draw start AAA BBB CCC --continue=7` - Continue un tirage commencé avec `--finale`
|
2020-04-27 09:43:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
channel: discord.TextChannel = ctx.channel
|
|
|
|
channel_id = channel.id
|
|
|
|
if channel_id in self.tirages:
|
2020-04-27 20:07:20 +00:00
|
|
|
raise TfjmError(
|
|
|
|
"Il y a déjà un tirage en cours sur cette channel, "
|
|
|
|
"il est possible d'en commencer un autre sur une autre channel."
|
|
|
|
)
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
query = " ".join(args)
|
|
|
|
match = re.match(RE_DRAW_START, query)
|
|
|
|
|
|
|
|
if match is None:
|
|
|
|
await ctx.send("La commande est mal formée.")
|
|
|
|
return await ctx.invoke(self.bot.get_command("help"), "draw start")
|
|
|
|
|
|
|
|
teams = match["teams"].split()
|
|
|
|
finale = bool(match["finale"])
|
|
|
|
continue_id = int(match["continue"]) if match["continue"] else None
|
|
|
|
|
|
|
|
if match["fmt"]:
|
|
|
|
fmt = list(map(int, match["fmt"].split()))
|
|
|
|
else:
|
|
|
|
l = len(teams)
|
|
|
|
if l <= 5:
|
|
|
|
fmt = [l]
|
|
|
|
else:
|
|
|
|
fmt = [3] * (l // 3 - 1) + [3 + l % 3]
|
|
|
|
|
|
|
|
yes = await confirm(
|
|
|
|
ctx,
|
|
|
|
self.bot,
|
|
|
|
f"Le format déterminé est {'+'.join(map(str, fmt))}, "
|
|
|
|
f"cela est-il correct ?",
|
2020-04-27 20:07:20 +00:00
|
|
|
)
|
2020-05-20 00:52:42 +00:00
|
|
|
if not yes:
|
|
|
|
raise TfjmError(
|
|
|
|
"Le tirage est annulé, vous pouvez le recommencer en précisant le format."
|
|
|
|
)
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-05-13 13:49:00 +00:00
|
|
|
if not set(fmt).issubset({3, 4, 5}):
|
|
|
|
raise TfjmError("Seuls les poules à 3, 4 ou 5 équipes sont suportées.")
|
2020-05-06 15:38:47 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
teams_roles = [get(ctx.guild.roles, name=tri) for tri in teams]
|
|
|
|
if not all(teams_roles):
|
|
|
|
raise TfjmError("Toutes les équipes ne sont pas sur le discord.")
|
|
|
|
|
2020-04-27 09:43:16 +00:00
|
|
|
# Here all data should be valid
|
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
if continue_id is None:
|
|
|
|
# New tirage
|
|
|
|
tirage = DiscordTirage(ctx, *teams_roles, fmt=fmt)
|
|
|
|
if finale:
|
|
|
|
rounds = (0,)
|
|
|
|
else:
|
|
|
|
rounds = 0, 1
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
tirage = self.get_tirages()[continue_id]
|
|
|
|
except KeyError:
|
|
|
|
raise TfjmError(
|
|
|
|
f"Il n'y pas de tirage {continue_id}. ID possibles {french_join(self.get_tirages())}"
|
|
|
|
)
|
|
|
|
|
|
|
|
rounds = (1,)
|
2020-05-06 17:04:36 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
tirage.ctx = ctx
|
|
|
|
tirage.queue = asyncio.Queue()
|
|
|
|
for i, t in enumerate(teams_roles):
|
|
|
|
await tirage.event(Event(t.name, i + 1))
|
|
|
|
|
|
|
|
self.tirages[channel_id] = tirage
|
|
|
|
await self.tirages[channel_id].run(rounds)
|
2020-05-06 15:38:47 +00:00
|
|
|
|
|
|
|
if self.tirages[channel_id]:
|
|
|
|
# Check if aborted in an other way
|
|
|
|
del self.tirages[channel_id]
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-04-27 20:07:20 +00:00
|
|
|
@draw_group.command(name="abort")
|
2020-04-28 16:34:46 +00:00
|
|
|
@commands.has_any_role(*Role.ORGAS)
|
2020-05-20 00:52:42 +00:00
|
|
|
async def abort_draw_cmd(self, ctx, force: bool = False):
|
2020-04-27 10:28:30 +00:00
|
|
|
"""
|
2020-04-27 20:07:20 +00:00
|
|
|
(orga) Annule le tirage en cours.
|
2020-04-27 10:28:30 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
Si oui est passé en paramettre, le tirage sera supprímé en même temps.
|
|
|
|
|
2020-04-27 10:28:30 +00:00
|
|
|
Le tirage ne pourra pas être continué. Si besoin,
|
|
|
|
n'hésitez pas à appeller un @dev : il peut réparer
|
|
|
|
plus de choses qu'on imagine (mais moins qu'on voudrait).
|
|
|
|
"""
|
2020-04-27 09:43:16 +00:00
|
|
|
channel_id = ctx.channel.id
|
2020-04-29 18:45:20 +00:00
|
|
|
|
2020-04-27 09:43:16 +00:00
|
|
|
if channel_id in self.tirages:
|
2020-05-20 00:52:42 +00:00
|
|
|
id = self.tirages[channel_id].id
|
|
|
|
await ctx.send(f"Le tirage {id} est annulé.")
|
2020-05-13 14:36:46 +00:00
|
|
|
self.tirages[channel_id].save()
|
2020-05-06 15:38:47 +00:00
|
|
|
del self.tirages[channel_id]
|
2020-05-20 00:52:42 +00:00
|
|
|
|
|
|
|
if force:
|
|
|
|
tirages = self.get_tirages()
|
|
|
|
del tirages[id]
|
|
|
|
|
|
|
|
File.TIRAGES.touch()
|
|
|
|
with open(File.TIRAGES, "w") as f:
|
|
|
|
yaml.dump(tirages, f)
|
2020-04-29 18:45:20 +00:00
|
|
|
else:
|
|
|
|
await ctx.send("Il n'y a pas de tirage en cours.")
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-05-06 15:38:47 +00:00
|
|
|
def get_tirages(self) -> Dict[int, BaseTirage]:
|
2020-05-06 17:04:36 +00:00
|
|
|
return DiscordTirage.load_all()
|
2020-04-29 18:45:20 +00:00
|
|
|
|
2020-04-27 09:43:16 +00:00
|
|
|
@draw_group.command(name="show")
|
2020-04-27 14:37:27 +00:00
|
|
|
async def show_cmd(self, ctx: Context, tirage_id: str = "all"):
|
2020-04-27 10:28:30 +00:00
|
|
|
"""
|
2020-04-27 14:35:29 +00:00
|
|
|
Affiche le résumé d'un tirage.
|
2020-04-27 10:28:30 +00:00
|
|
|
|
2020-04-27 14:35:29 +00:00
|
|
|
Exemples:
|
2020-05-13 14:36:46 +00:00
|
|
|
`!draw show all` - Liste les ID possibles
|
|
|
|
`!draw show TRI` - Affiche les tirages avec l'équipe TRI
|
2020-04-27 14:35:29 +00:00
|
|
|
`!draw show 42` - Affiche le tirage n°42
|
2020-04-27 10:28:30 +00:00
|
|
|
"""
|
|
|
|
|
2020-04-29 18:45:20 +00:00
|
|
|
tirages = self.get_tirages()
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-04-29 18:45:20 +00:00
|
|
|
if not tirages:
|
|
|
|
return await ctx.send("Il n'y a pas encore eu de tirages.")
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-04-27 10:28:30 +00:00
|
|
|
if tirage_id.lower() == "all":
|
2020-04-27 16:44:39 +00:00
|
|
|
await ctx.send(
|
|
|
|
"Voici in liste de tous les tirages qui ont été faits et "
|
|
|
|
"quelles équipes y on participé."
|
|
|
|
"Vous pouvez en consulter un en particulier avec `!draw show ID`."
|
|
|
|
)
|
2020-04-27 09:43:16 +00:00
|
|
|
msg = "\n".join(
|
2020-05-06 17:04:36 +00:00
|
|
|
f"`{key}`: {', '.join(tirage.teams)}" for key, tirage in tirages.items()
|
2020-04-27 09:43:16 +00:00
|
|
|
)
|
|
|
|
await ctx.send(msg)
|
2020-05-13 14:36:46 +00:00
|
|
|
elif len(tirage_id) == 3 and tirage_id.isupper():
|
|
|
|
for t in tirages.values():
|
|
|
|
for p, teams in t.poules.items():
|
|
|
|
if tirage_id in teams:
|
|
|
|
t.ctx = ctx
|
|
|
|
await t.annonce_poule(p)
|
2020-04-27 09:43:16 +00:00
|
|
|
else:
|
|
|
|
try:
|
2020-04-27 10:28:30 +00:00
|
|
|
n = int(tirage_id)
|
2020-04-27 09:43:16 +00:00
|
|
|
if n < 0:
|
|
|
|
raise ValueError
|
|
|
|
tirage = tirages[n]
|
2020-04-29 19:25:36 +00:00
|
|
|
except (ValueError, KeyError):
|
2020-04-27 09:43:16 +00:00
|
|
|
await ctx.send(
|
2020-04-27 10:28:30 +00:00
|
|
|
f"`{tirage_id}` n'est pas un identifiant valide. "
|
2020-04-27 16:44:39 +00:00
|
|
|
f"Les identifiants valides sont visibles avec `!draw show all`"
|
2020-04-27 09:43:16 +00:00
|
|
|
)
|
|
|
|
else:
|
2020-04-29 19:25:36 +00:00
|
|
|
await tirage.show(ctx)
|
2020-04-27 09:43:16 +00:00
|
|
|
|
2020-05-16 10:50:35 +00:00
|
|
|
@draw_group.command(name="send")
|
2020-04-29 18:45:20 +00:00
|
|
|
@commands.has_role(Role.DEV)
|
2020-05-16 10:50:35 +00:00
|
|
|
async def send_cmd(self, ctx, tirage_id: int, poule="A", round: int = 1):
|
|
|
|
"""
|
2020-05-18 14:51:23 +00:00
|
|
|
(dev) Envoie les poules sur tfjm.org
|
2020-05-16 10:50:35 +00:00
|
|
|
|
|
|
|
Exemple:
|
|
|
|
`!draw send 42 B 1` - Envoie la poule B1 du tirage n°42.
|
|
|
|
"""
|
|
|
|
|
2020-04-29 18:45:20 +00:00
|
|
|
tirages = self.get_tirages()
|
|
|
|
|
|
|
|
try:
|
|
|
|
n = int(tirage_id)
|
|
|
|
if n < 0:
|
|
|
|
raise ValueError
|
|
|
|
tirage = tirages[n]
|
2020-04-29 19:25:36 +00:00
|
|
|
except (ValueError, KeyError):
|
2020-04-29 18:45:20 +00:00
|
|
|
await ctx.send(
|
|
|
|
f"`{tirage_id}` n'est pas un identifiant valide. "
|
|
|
|
f"Les identifiants valides sont visibles avec `!draw show all`"
|
|
|
|
)
|
|
|
|
else:
|
2020-05-06 23:02:35 +00:00
|
|
|
poule = get(tirage.poules, poule=poule, rnd=round - 1)
|
2020-05-16 10:50:35 +00:00
|
|
|
if poule is None:
|
|
|
|
raise TfjmError("Il n'y a pas de telle poule dans ce tirage")
|
|
|
|
|
|
|
|
data = f"{round};" + ";".join(
|
2020-05-06 23:02:35 +00:00
|
|
|
x
|
|
|
|
for t in tirage.poules[poule]
|
|
|
|
for x in (
|
|
|
|
tirage.teams[t].name,
|
|
|
|
tirage.teams[t].accepted_problems[round - 1][0],
|
|
|
|
)
|
2020-04-29 18:45:20 +00:00
|
|
|
)
|
2020-05-16 10:50:35 +00:00
|
|
|
data = f'"{data}"'
|
|
|
|
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
|
|
async with session.post(
|
|
|
|
"https://inscription.tfjm.org/api/pool/",
|
|
|
|
headers={
|
|
|
|
"Authorization": f"Token {TFJM_TOKEN}",
|
|
|
|
"Content-type": "application/json",
|
|
|
|
},
|
|
|
|
data=data,
|
|
|
|
) as resp:
|
|
|
|
await ctx.send(str(resp))
|
|
|
|
await ctx.send(str(resp.status))
|
|
|
|
await ctx.send(str(resp.reason))
|
|
|
|
await ctx.send(await resp.content.read())
|
2020-04-29 18:45:20 +00:00
|
|
|
|
2020-05-20 00:52:42 +00:00
|
|
|
@draw_group.command(name="order")
|
|
|
|
@commands.has_role(Role.DEV)
|
|
|
|
async def set_order(self, ctx, *teams: discord.Role):
|
|
|
|
"""(dev) L'ordre des équipes sera celui du message."""
|
|
|
|
|
|
|
|
channel = ctx.channel.id
|
|
|
|
if channel in self.tirages:
|
|
|
|
for i, t in enumerate(teams):
|
|
|
|
await self.tirages[channel].event(Event(t.name, i + 1))
|
|
|
|
|
2020-04-27 09:43:16 +00:00
|
|
|
|
|
|
|
def setup(bot):
|
|
|
|
bot.add_cog(TirageCog(bot))
|