Adapt the random draw for the next rounds of ETEAM

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-07-09 13:26:39 +02:00
parent 6b7d52c79b
commit 2c4de8cec3
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
4 changed files with 106 additions and 57 deletions

View File

@ -1021,14 +1021,18 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
if not await Draw.objects.filter(tournament=self.tournament).aexists(): if not await Draw.objects.filter(tournament=self.tournament).aexists():
return await self.alert(_("The draw has not started yet."), 'danger') return await self.alert(_("The draw has not started yet."), 'danger')
if not self.tournament.final: if not self.tournament.final and settings.TFJM_APP == "TFJM":
return await self.alert(_("This is only available for the final tournament."), 'danger') return await self.alert(_("This is only available for the final tournament."), 'danger')
r2 = await self.tournament.draw.round_set.filter(number=2).aget() r2 = await self.tournament.draw.round_set.filter(number=self.tournament.draw.current_round.number + 1).aget()
self.tournament.draw.current_round = r2 self.tournament.draw.current_round = r2
msg = _("The draw of the round 2 is starting. " if settings.TFJM_APP == "TFJM":
"The passage order is determined from the ranking of the first round, " msg = str(_("The draw of the round {round} is starting. "
"in order to mix the teams between the two days.") "The passage order is determined from the ranking of the first round, "
"in order to mix the teams between the two days.").format(round=r2.number))
else:
msg = str(_("The draw of the round {round} is starting. "
"The passage order is another time randomly drawn.").format(round=r2.number))
self.tournament.draw.last_message = msg self.tournament.draw.last_message = msg
await self.tournament.draw.asave() await self.tournament.draw.asave()
@ -1036,29 +1040,30 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.notify', {'tid': self.tournament_id, 'type': 'draw.notify',
'title': _("Draw") + " " + settings.APP_NAME, 'title': _("Draw") + " " + settings.APP_NAME,
'body': _("The draw of the second round is starting!")}) 'body': str(_("The draw of the second round is starting!"))})
# Set the first pool of the second round as the active pool if settings.TFJM_APP == "TFJM":
pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget() # Set the first pool of the second round as the active pool
r2.current_pool = pool pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget()
await r2.asave() r2.current_pool = pool
await r2.asave()
# Fetch notes from the first round # Fetch notes from the first round
notes = dict() notes = dict()
async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team').all(): async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team').all():
notes[participation] = sum([await pool.aaverage(participation) notes[participation] = sum([await pool.aaverage(participation)
async for pool in self.tournament.pools.filter(participations=participation) async for pool in self.tournament.pools.filter(participations=participation)
.prefetch_related('passages')]) .prefetch_related('passages')])
# Sort notes in a decreasing order # Sort notes in a decreasing order
ordered_participations = sorted(notes.keys(), key=lambda x: -notes[x]) ordered_participations = sorted(notes.keys(), key=lambda x: -notes[x])
# Define pools and passage orders from the ranking of the first round # Define pools and passage orders from the ranking of the first round
async for pool in r2.pool_set.order_by('letter').all(): async for pool in r2.pool_set.order_by('letter').all():
for i in range(pool.size): for i in range(pool.size):
participation = ordered_participations.pop(0) participation = ordered_participations.pop(0)
td = await TeamDraw.objects.aget(round=r2, participation=participation) td = await TeamDraw.objects.aget(round=r2, participation=participation)
td.pool = pool td.pool = pool
td.passage_index = i td.passage_index = i
await td.asave() await td.asave()
# Send pools to users # Send pools to users
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
@ -1078,16 +1083,23 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
f"tournament-{self.tournament.id}", f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.dice', 'team': participation.team.trigram, 'result': None}) {'tid': self.tournament_id, 'type': 'draw.dice', 'team': participation.team.trigram, 'result': None})
async for td in r2.current_pool.team_draws.prefetch_related('participation__team'): if settings.TFJM_APP == "TFJM":
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}", async for td in r2.current_pool.team_draws.prefetch_related('participation__team'):
{'tid': self.tournament_id, 'type': 'draw.dice_visibility', await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
'visible': True}) {'tid': self.tournament_id, 'type': 'draw.dice_visibility',
'visible': True})
# Notify the team that it can draw a problem
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': _("Your turn!"),
'body': _("It's your turn to draw a problem!")})
else:
async for td in r2.team_draws.prefetch_related('participation__team'):
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
'visible': True})
# Notify the team that it can draw a problem
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': _("Your turn!"),
'body': _("It's your turn to draw a problem!")})
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}", await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.dice_visibility', {'tid': self.tournament_id, 'type': 'draw.dice_visibility',
@ -1102,7 +1114,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.set_active', {'tid': self.tournament_id, 'type': 'draw.set_active',
'round': r2.number, 'round': r2.number,
'pool': r2.current_pool.get_letter_display()}) 'pool': r2.current_pool.get_letter_display() if r2.current_pool else None})
@ensure_orga @ensure_orga
async def cancel_last_step(self, **kwargs): async def cancel_last_step(self, **kwargs):

View File

@ -0,0 +1,27 @@
# Generated by Django 5.0.6 on 2024-07-09 11:07
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("draw", "0005_alter_round_number_alter_teamdraw_accepted_and_more"),
]
operations = [
migrations.AlterField(
model_name="round",
name="current_pool",
field=models.ForeignKey(
default=None,
help_text="The current pool where teams select their problems.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to="draw.pool",
verbose_name="current pool",
),
),
]

View File

@ -82,7 +82,7 @@ class Draw(models.Model):
elif self.current_round.current_pool.current_team is None: elif self.current_round.current_pool.current_team is None:
return 'DICE_ORDER_POULE' return 'DICE_ORDER_POULE'
elif self.current_round.current_pool.current_team.accepted is not None: elif self.current_round.current_pool.current_team.accepted is not None:
if self.current_round.number == 1: if self.current_round.number < settings.NB_ROUNDS:
# The last step can be the last problem acceptation after the first round # The last step can be the last problem acceptation after the first round
# only for the final between the two rounds # only for the final between the two rounds
return 'WAITING_FINAL' return 'WAITING_FINAL'
@ -205,7 +205,7 @@ class Round(models.Model):
current_pool = models.ForeignKey( current_pool = models.ForeignKey(
'Pool', 'Pool',
on_delete=models.CASCADE, on_delete=models.SET_NULL,
null=True, null=True,
default=None, default=None,
related_name='+', related_name='+',

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM\n" "Project-Id-Version: TFJM\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-06 22:34+0200\n" "POT-Creation-Date: 2024-07-09 13:22+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n" "Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -269,7 +269,7 @@ msgstr "équipes"
msgid "round" msgid "round"
msgstr "tour" msgstr "tour"
#: draw/apps.py:10 draw/consumers.py:1038 tfjm/templates/navbar.html:68 #: draw/apps.py:10 draw/consumers.py:1042 tfjm/templates/navbar.html:68
msgid "Draw" msgid "Draw"
msgstr "Tirage au sort" msgstr "Tirage au sort"
@ -311,7 +311,7 @@ msgstr "Le tirage au sort du tournoi {tournament} va commencer."
#: draw/consumers.py:256 draw/consumers.py:282 draw/consumers.py:692 #: draw/consumers.py:256 draw/consumers.py:282 draw/consumers.py:692
#: draw/consumers.py:910 draw/consumers.py:1000 draw/consumers.py:1022 #: draw/consumers.py:910 draw/consumers.py:1000 draw/consumers.py:1022
#: draw/consumers.py:1113 draw/templates/draw/tournament_content.html:5 #: draw/consumers.py:1125 draw/templates/draw/tournament_content.html:5
msgid "The draw has not started yet." msgid "The draw has not started yet."
msgstr "Le tirage au sort n'a pas encore commencé." msgstr "Le tirage au sort n'a pas encore commencé."
@ -363,12 +363,12 @@ msgstr ""
"sont déterminés à partir des ordres de passage du premier tour." "sont déterminés à partir des ordres de passage du premier tour."
#: draw/consumers.py:615 draw/consumers.py:755 draw/consumers.py:832 #: draw/consumers.py:615 draw/consumers.py:755 draw/consumers.py:832
#: draw/consumers.py:866 draw/consumers.py:991 draw/consumers.py:1089 #: draw/consumers.py:866 draw/consumers.py:991 draw/consumers.py:1095
msgid "Your turn!" msgid "Your turn!"
msgstr "À votre tour !" msgstr "À votre tour !"
#: draw/consumers.py:616 draw/consumers.py:756 draw/consumers.py:992 #: draw/consumers.py:616 draw/consumers.py:756 draw/consumers.py:992
#: draw/consumers.py:1090 #: draw/consumers.py:1096
msgid "It's your turn to draw a problem!" msgid "It's your turn to draw a problem!"
msgstr "C'est à vous de tirer un problème !" msgstr "C'est à vous de tirer un problème !"
@ -439,17 +439,27 @@ msgstr ""
msgid "This is only available for the final tournament." msgid "This is only available for the final tournament."
msgstr "Cela n'est possible que pour la finale." msgstr "Cela n'est possible que pour la finale."
#: draw/consumers.py:1029 #: draw/consumers.py:1030
#, python-brace-format
msgid "" msgid ""
"The draw of the round 2 is starting. The passage order is determined from " "The draw of the round {round} is starting. The passage order is determined "
"the ranking of the first round, in order to mix the teams between the two " "from the ranking of the first round, in order to mix the teams between the "
"days." "two days."
msgstr "" msgstr ""
"Le tirage au sort du tour 2 commence. L'ordre de passage est déterminé à " "Le tirage au sort du tour {round} commence. L'ordre de passage est déterminé à "
"partir du classement du premier tour, afin de mélanger les équipes entre les " "partir du classement du premier tour, afin de mélanger les équipes entre les "
"deux jours." "deux jours."
#: draw/consumers.py:1039 #: draw/consumers.py:1034
#, python-brace-format
msgid ""
"The draw of the round {round} is starting. The passage order is another time "
"randomly drawn."
msgstr ""
"Le tirage au sort du tour {round} commence. L'ordre de passage est à nouveau tiré "
"au hasard."
#: draw/consumers.py:1043
msgid "The draw of the second round is starting!" msgid "The draw of the second round is starting!"
msgstr "Le tirage au sort du deuxième tour commence !" msgstr "Le tirage au sort du deuxième tour commence !"
@ -866,11 +876,11 @@ msgstr "Opp"
#: draw/templates/draw/tournament_content.html:331 #: draw/templates/draw/tournament_content.html:331
#: draw/templates/draw/tournament_content.html:337 #: draw/templates/draw/tournament_content.html:337
#: draw/templates/draw/tournament_content.html:339 #: draw/templates/draw/tournament_content.html:339
#: draw/templates/draw/tournament_content.html:350 #: draw/templates/draw/tournament_content.html:347
#: draw/templates/draw/tournament_content.html:352 #: draw/templates/draw/tournament_content.html:354
#: draw/templates/draw/tournament_content.html:359 #: draw/templates/draw/tournament_content.html:361
#: draw/templates/draw/tournament_content.html:366 #: draw/templates/draw/tournament_content.html:368
#: draw/templates/draw/tournament_content.html:373 #: draw/templates/draw/tournament_content.html:370
msgctxt "Role abbreviation" msgctxt "Role abbreviation"
msgid "Obs" msgid "Obs"
msgstr "Obs" msgstr "Obs"
@ -2847,17 +2857,17 @@ msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e
msgid "Notes were successfully uploaded." msgid "Notes were successfully uploaded."
msgstr "Les notes ont bien été envoyées." msgstr "Les notes ont bien été envoyées."
#: participation/views.py:1902 #: participation/views.py:1904
#, python-brace-format #, python-brace-format
msgid "Notation sheets of pool {pool} of {tournament}.zip" msgid "Notation sheets of pool {pool} of {tournament}.zip"
msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip" msgstr "Feuilles de notations pour la poule {pool} du tournoi {tournament}.zip"
#: participation/views.py:1907 #: participation/views.py:1909
#, python-brace-format #, python-brace-format
msgid "Notation sheets of {tournament}.zip" msgid "Notation sheets of {tournament}.zip"
msgstr "Feuilles de notation de {tournament}.zip" msgstr "Feuilles de notation de {tournament}.zip"
#: participation/views.py:2074 #: participation/views.py:2076
msgid "You can't upload a written review after the deadline." msgid "You can't upload a written review after the deadline."
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."