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():
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')
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
msg = _("The draw of the round 2 is starting. "
"The passage order is determined from the ranking of the first round, "
"in order to mix the teams between the two days.")
if settings.TFJM_APP == "TFJM":
msg = str(_("The draw of the round {round} is starting. "
"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
await self.tournament.draw.asave()
@ -1036,29 +1040,30 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'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
pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget()
r2.current_pool = pool
await r2.asave()
if settings.TFJM_APP == "TFJM":
# Set the first pool of the second round as the active pool
pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget()
r2.current_pool = pool
await r2.asave()
# Fetch notes from the first round
notes = dict()
async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team').all():
notes[participation] = sum([await pool.aaverage(participation)
async for pool in self.tournament.pools.filter(participations=participation)
.prefetch_related('passages')])
# Sort notes in a decreasing order
ordered_participations = sorted(notes.keys(), key=lambda x: -notes[x])
# Define pools and passage orders from the ranking of the first round
async for pool in r2.pool_set.order_by('letter').all():
for i in range(pool.size):
participation = ordered_participations.pop(0)
td = await TeamDraw.objects.aget(round=r2, participation=participation)
td.pool = pool
td.passage_index = i
await td.asave()
# Fetch notes from the first round
notes = dict()
async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team').all():
notes[participation] = sum([await pool.aaverage(participation)
async for pool in self.tournament.pools.filter(participations=participation)
.prefetch_related('passages')])
# Sort notes in a decreasing order
ordered_participations = sorted(notes.keys(), key=lambda x: -notes[x])
# Define pools and passage orders from the ranking of the first round
async for pool in r2.pool_set.order_by('letter').all():
for i in range(pool.size):
participation = ordered_participations.pop(0)
td = await TeamDraw.objects.aget(round=r2, participation=participation)
td.pool = pool
td.passage_index = i
await td.asave()
# Send pools to users
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
@ -1078,16 +1083,23 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
f"tournament-{self.tournament.id}",
{'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'):
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
'visible': True})
if settings.TFJM_APP == "TFJM":
async for td in r2.current_pool.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!")})
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}",
{'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}",
{'tid': self.tournament_id, 'type': 'draw.set_active',
'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
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:
return 'DICE_ORDER_POULE'
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
# only for the final between the two rounds
return 'WAITING_FINAL'
@ -205,7 +205,7 @@ class Round(models.Model):
current_pool = models.ForeignKey(
'Pool',
on_delete=models.CASCADE,
on_delete=models.SET_NULL,
null=True,
default=None,
related_name='+',

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: TFJM\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"
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -269,7 +269,7 @@ msgstr "équipes"
msgid "round"
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"
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: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."
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."
#: 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!"
msgstr "À votre tour !"
#: 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!"
msgstr "C'est à vous de tirer un problème !"
@ -439,17 +439,27 @@ msgstr ""
msgid "This is only available for the final tournament."
msgstr "Cela n'est possible que pour la finale."
#: draw/consumers.py:1029
#: draw/consumers.py:1030
#, python-brace-format
msgid ""
"The draw of the round 2 is starting. The passage order is determined from "
"the ranking of the first round, in order to mix the teams between the two "
"days."
"The draw of the round {round} is starting. The passage order is determined "
"from the ranking of the first round, in order to mix the teams between the "
"two days."
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 "
"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!"
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:337
#: draw/templates/draw/tournament_content.html:339
#: draw/templates/draw/tournament_content.html:350
#: draw/templates/draw/tournament_content.html:352
#: draw/templates/draw/tournament_content.html:359
#: draw/templates/draw/tournament_content.html:366
#: draw/templates/draw/tournament_content.html:373
#: draw/templates/draw/tournament_content.html:347
#: draw/templates/draw/tournament_content.html:354
#: draw/templates/draw/tournament_content.html:361
#: draw/templates/draw/tournament_content.html:368
#: draw/templates/draw/tournament_content.html:370
msgctxt "Role abbreviation"
msgid "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."
msgstr "Les notes ont bien été envoyées."
#: participation/views.py:1902
#: participation/views.py:1904
#, python-brace-format
msgid "Notation sheets of pool {pool} of {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
msgid "Notation sheets of {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."
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."