1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-21 15:18:26 +02:00

Translate draw messages

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello
2024-07-05 10:41:48 +02:00
parent d84db949c6
commit 05c6333c5e
3 changed files with 360 additions and 133 deletions

View File

@ -122,6 +122,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
self.tournament = await Tournament.objects.filter(pk=self.tournament_id)\
.prefetch_related('draw__current_round__current_pool__current_team__participation__team').aget()
translation.activate(settings.PREFERRED_LANGUAGE_CODE)
match content['type']:
case 'set_language':
# Update the translation language
@ -233,8 +235,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': 'Tirage au sort du TFJM²',
'body': "Le tirage au sort du tournoi de "
f"{self.tournament.name} a commencé !"})
'body': _("The draw of tournament {tournament} started!")
.format(tournament=self.tournament.name)})
async def draw_start(self, content) -> None:
"""
@ -403,8 +405,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(
f"team-{dup.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify', 'title': 'Tirage au sort du TFJM²',
'body': 'Votre score de dé est identique à celui de une ou plusieurs équipes. '
'Veuillez le relancer.'}
'body': _("Your dice score is identical to the one of one or multiple teams. "
"Please relaunch it.")}
)
# Alert the tournament
await self.channel_layer.group_send(
@ -448,7 +450,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# We can add a joker team if there is not already a team in the pool that was in the same pool
# in the first round, and such that the number of such jokers is exactly the free space of the current pool.
# Exception: if there is one only pool with 5 teams, we exchange the first and the last teams of the pool.
if not self.tournament.final:
if not self.tournament.final and settings.TFJM_APP == "TFJM":
tds_copy = sorted(tds, key=lambda td: (td.passage_index, -td.pool.letter,))
jokers = [td for td in tds if td.passage_index == 4]
round2 = await self.tournament.draw.round_set.filter(number=2).aget()
@ -502,12 +504,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.tournament.draw.current_round.asave()
# Display dice result in the header of the information alert
msg = "Les résultats des dés sont les suivants : "
msg += ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
msg += ". L'ordre de passage et les compositions des différentes poules sont affiché⋅es sur le côté. "
msg += "Les ordres de passage pour le premier tour sont déterminés à partir des scores des dés, "
msg += "dans l'ordre croissant. Pour le deuxième tour, les ordres de passage sont déterminés à partir "
msg += "des ordres de passage du premier tour."
trigrams = ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
msg = _("The dice results are the following: {trigrams}. "
"The passage order and the compositions of the different pools are displayed on the side. "
"The passage orders for the first round are determined from the dice scores, in increasing order. "
"For the second round, the passage orders are determined from the passage orders of the first round.")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -610,8 +611,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Notify the team that it can draw a problem
await self.channel_layer.group_send(f"team-{tds[0].participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': "À votre tour !",
'body': "C'est à vous de tirer un nouveau problème !"})
'title': _("Your turn!"),
'body': _("It's your turn to draw a problem!")})
async def select_problem(self, **kwargs):
"""
@ -631,7 +632,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
.prefetch_related('team').aget()
# Ensure that the user can draws a problem at this time
if participation.id != td.participation_id:
return await self.alert("This is not your turn.", 'danger')
return await self.alert(_("This is not your turn."), 'danger')
while True:
# Choose a random problem
@ -702,19 +703,20 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
.prefetch_related('team').aget()
# Ensure that the user can accept a problem at this time
if participation.id != td.participation_id:
return await self.alert("This is not your turn.", 'danger')
return await self.alert(_("This is not your turn."), 'danger')
td.accepted = td.purposed
td.purposed = None
await td.asave()
trigram = td.participation.team.trigram
msg = f"L'équipe <strong>{trigram}</strong> a accepté le problème <strong>{td.accepted} : " \
f"{settings.PROBLEMS[td.accepted - 1]}</strong>. "
msg = _("The team <strong>{trigram}</strong> accepted the problem <string>{problem}</strong>: "
"{problem_name}. ").format(trigram=trigram, problem=td.accepted,
problem_name=settings.PROBLEMS[td.accepted - 1])
if pool.size == 5 and await pool.teamdraw_set.filter(accepted=td.accepted).acount() < 2:
msg += "Une équipe peut encore l'accepter."
msg += _("One team more can accept this problem.")
else:
msg += "Plus personne ne peut l'accepter."
msg += _("No team can accept this problem anymore.")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -749,8 +751,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Notify the team that it can draw a problem
await self.channel_layer.group_send(f"team-{new_trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': "À votre tour !",
'body': "C'est à vous de tirer un nouveau problème !"})
'title': _("Your turn!"),
'body': _("It's your turn to draw a problem!")})
else:
# Pool is ended
await self.end_pool(pool)
@ -808,8 +810,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
'problems': [td.accepted async for td in pool.team_draws],
})
msg += f"<br><br>Le tirage de la poule {pool.get_letter_display()}{r.number} est terminé. " \
f"Le tableau récapitulatif est en bas."
msg += "<br><br>" + _("The draw of the pool {pool} is ended. The summary is below.") \
.format(pool=f"{pool.get_letter_display()}{r.number}")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -826,8 +828,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Notify the team that it can draw a dice
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': "À votre tour !",
'body': "C'est à vous de lancer le dé !"})
'title': _("Your turn!"),
'body': _("It's your turn to launch the dice!")})
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
@ -843,11 +845,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
"""
msg = self.tournament.draw.last_message
if r.number < settings.NB_ROUNDS and not self.tournament.final:
if r.number < settings.NB_ROUNDS and not self.tournament.final and settings.TFJM_APP == "TFJM":
# Next round
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget()
self.tournament.draw.current_round = next_round
msg += f"<br><br>Le tirage au sort du tour {r.number} est terminé."
msg += "<br><br>" + _("The draw of the round {round} is ended.").format(round=r.number)
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -860,8 +862,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Notify the team that it can draw a dice
await self.channel_layer.group_send(f"team-{participation.team.trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': "À votre tour !",
'body': "C'est à vous de lancer le dé !"})
'title': _("Your turn!"),
'body': _("It's your turn to launch the dice!")})
# Reorder dices
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
@ -888,9 +890,9 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
'visible': True})
elif r.number == 1 and self.tournament.final:
elif r.number == 1 and (self.tournament.final or settings.TFJM_APP == "ETEAM"):
# For the final tournament, we wait for a manual update between the two rounds.
msg += "<br><br>Le tirage au sort du tour 1 est terminé."
msg += "<br><br>" + _("The draw of the first round is ended.")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -919,7 +921,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
.prefetch_related('team').aget()
# Ensure that the user can reject a problem at this time
if participation.id != td.participation_id:
return await self.alert("This is not your turn.", 'danger')
return await self.alert(_("This is not your turn."), 'danger')
# Add the problem to the rejected problems list
problem = td.purposed
@ -933,15 +935,16 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Update messages
trigram = td.participation.team.trigram
msg = f"L'équipe <strong>{trigram}</strong> a refusé le problème <strong>{problem} : " \
f"{settings.PROBLEMS[problem - 1]}</strong>. "
msg = _("The team <strong>{trigram}</strong> refused the problem <strong>{problem}</strong>: "
"{problem_name}.").format(trigram=trigram, problem=problem,
problem_name=settings.PROBLEMS[problem - 1]) + " "
if remaining >= 0:
msg += f"Il lui reste {remaining} refus sans pénalité."
msg += _("It remains {remaining} refusals without penalty.").format(remaining=remaining)
else:
if already_refused:
msg += "Cela n'ajoute pas de pénalité."
msg += _("This problem was already refused by this team.")
else:
msg += "Cela ajoute une pénalité de 25&nbsp;% sur le coefficient de l'oral de la défense."
msg += _("It adds a 25% penalty on the coefficient of the oral defense.")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
@ -984,8 +987,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Notify the team that it can draw a problem
await self.channel_layer.group_send(f"team-{new_trigram}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': "À votre tour !",
'body': "C'est à vous de tirer un nouveau problème !"})
'title': _("Your turn!"),
'body': _("It's your turn to draw a problem!")})
@ensure_orga
async def export(self, **kwargs):
@ -1022,17 +1025,17 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
self.tournament.draw.current_round = r2
msg = "Le tirage au sort pour le tour 2 va commencer. " \
"L'ordre de passage est déterminé à partir du classement du premier tour, " \
"de sorte à mélanger les équipes entre les deux jours."
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.")
self.tournament.draw.last_message = msg
await self.tournament.draw.asave()
# Send notification to everyone
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.notify',
'title': 'Tirage au sort du TFJM²',
'body': "Le tirage au sort pour le second tour de la finale a commencé !"})
'title': _("Draw") + " " + settings.APP_NAME,
'body': _("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()
@ -1082,8 +1085,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# 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': "À votre tour !",
'body': "C'est à vous de tirer un nouveau problème !"})
'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',

View File

@ -110,58 +110,61 @@ class Draw(models.Model):
# Waiting for dices to determine pools and passage order
if self.current_round.number == 1:
# Specific information for the first round
s += """Nous allons commencer le tirage des problèmes.<br>
Vous pouvez à tout moment poser toute question si quelque chose
n'est pas clair ou ne va pas.<br><br>
Nous allons d'abord tirer les poules et l'ordre de passage
pour le premier tour avec toutes les équipes puis pour chaque poule,
nous tirerons l'ordre de tirage pour le tour et les problèmes.<br><br>"""
s += """
Les capitaines, vous pouvez désormais toustes lancer un dé 100,
en cliquant sur le gros bouton. 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."""
s += _("We are going to start the problem draw.<br>"
"You can ask any question if something is not clear or wrong.<br><br>"
"We are going to first draw the pools and the passage order for the first round "
"with all the teams, then for each pool, we will draw the draw order and the problems.")
s += "<br><br>"
s += _("The captains, you can now all throw a 100-sided dice, by clicking on the big dice button. "
"The pools and the passage order during the first round will be the increasing order "
"of the dices, ie. the smallest dice will be the first to pass in pool A.")
case 'DICE_ORDER_POULE':
# Waiting for dices to determine the choice order
s += f"""Nous passons au tirage des problèmes pour la poule
<strong>{self.current_round.current_pool}</strong>, entre les équipes
<strong>{', '.join(td.participation.team.trigram
for td in self.current_round.current_pool.teamdraw_set.all())}</strong>.
Les capitaines peuvent lancer un dé 100 en cliquant sur le gros bouton
pour déterminer l'ordre de tirage. L'équipe réalisant le plus gros score pourra
tirer en premier."""
s += _("We are going to start the problem draw for the pool <strong>{pool}</strong>, "
"between the teams <strong>{teams}</strong>. "
"The captains can throw a 100-sided dice by clicking on the big dice button "
"to determine the order of draw. The team with the highest score will draw first.") \
.format(pool=self.current_round.current_pool,
teams=', '.join(td.participation.team.trigram
for td in self.current_round.current_pool.teamdraw_set.all()))
case 'WAITING_DRAW_PROBLEM':
# Waiting for a problem draw
td = self.current_round.current_pool.current_team
s += f"""C'est au tour de l'équipe <strong>{td.participation.team.trigram}</strong>
de choisir son problème. Cliquez sur l'urne au milieu pour tirer un problème au sort."""
s += _("The team <strong>{trigram}</strong> is going to draw a problem. "
"Click on the urn in the middle to draw a problem.") \
.format(trigram=td.participation.team.trigram)
case 'WAITING_CHOOSE_PROBLEM':
# Waiting for the team that can accept or reject the problem
td = self.current_round.current_pool.current_team
s += f"""L'équipe <strong>{td.participation.team.trigram}</strong> a tiré le problème
<strong>{td.purposed} : {settings.PROBLEMS[td.purposed - 1]}</strong>. """
s += _("The team <strong>{trigram}</strong> drew the problem <strong>{problem}: "
"{problem_name}</strong>.") \
.format(trigram=td.participation.team.trigram,
problem=td.purposed, problem_name=settings.PROBLEMS[td.purposed - 1]) + " "
if td.purposed in td.rejected:
# The problem was previously rejected
s += """Elle a déjà refusé ce problème auparavant, elle peut donc le refuser sans pénalité et
tirer un nouveau problème immédiatement, ou bien revenir sur son choix."""
s += _("It already refused this problem before, so it can refuse it without penalty and "
"draw a new problem immediately, or change its mind.")
else:
# The problem can be rejected
s += "Elle peut décider d'accepter ou de refuser ce problème. "
s += _("It can decide to accept or refuse this problem.") + " "
if len(td.rejected) >= len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT:
s += "Refuser ce problème ajoutera une nouvelle pénalité de 25 % sur le coefficient de l'oral de la défense."
s += _("Refusing this problem will add a new penalty of 25% "
"on the coefficient of the oral defense.")
else:
s += f"Il reste {len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT - len(td.rejected)} refus sans pénalité."
s += _("There are still {remaining} refusals without penalty.").format(
remaining=len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT - len(td.rejected))
case 'WAITING_FINAL':
# We are between the two rounds of the final tournament
s += "Le tirage au sort pour le tour 2 aura lieu à la fin du premier tour. Bon courage !"
s += _("The draw for the second round will take place at the end of the first round. Good luck!")
case 'DRAW_ENDED':
# The draw is ended
s += "Le tirage au sort est terminé. Les solutions des autres équipes peuvent être trouvées dans l'onglet « Ma participation »."
s += _("The draw is ended. The solutions of the other teams can be found in the tab "
"\"My participation\".")
s += "<br><br>" if s else ""
s += """Pour plus de détails sur le déroulement du tirage au sort,
le règlement est accessible sur
<a class="alert-link" href="https://tfjm.org/reglement">https://tfjm.org/reglement</a>."""
rules_link = "https://tfjm.org/reglement" if settings.TFJM_APP == "TFJM" else "https://eteam.tfjm.org/rules/"
s += _("For more details on the draw, the rules are available on "
"<a class=\"alert-link\" href=\"{link}\">{link}</a>.").format(link=rules_link)
return s
async def ainformation(self) -> str: