mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-02-20 02:21:20 +00:00
Compare commits
2 Commits
d84db949c6
...
2a298a3ee4
Author | SHA1 | Date | |
---|---|---|---|
|
2a298a3ee4 | ||
|
05c6333c5e |
@ -122,6 +122,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
self.tournament = await Tournament.objects.filter(pk=self.tournament_id)\
|
self.tournament = await Tournament.objects.filter(pk=self.tournament_id)\
|
||||||
.prefetch_related('draw__current_round__current_pool__current_team__participation__team').aget()
|
.prefetch_related('draw__current_round__current_pool__current_team__participation__team').aget()
|
||||||
|
|
||||||
|
translation.activate(settings.PREFERRED_LANGUAGE_CODE)
|
||||||
|
|
||||||
match content['type']:
|
match content['type']:
|
||||||
case 'set_language':
|
case 'set_language':
|
||||||
# Update the translation language
|
# Update the translation language
|
||||||
@ -233,8 +235,8 @@ 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': 'Tirage au sort du TFJM²',
|
'title': 'Tirage au sort du TFJM²',
|
||||||
'body': "Le tirage au sort du tournoi de "
|
'body': _("The draw of tournament {tournament} started!")
|
||||||
f"{self.tournament.name} a commencé !"})
|
.format(tournament=self.tournament.name)})
|
||||||
|
|
||||||
async def draw_start(self, content) -> None:
|
async def draw_start(self, content) -> None:
|
||||||
"""
|
"""
|
||||||
@ -403,8 +405,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
await self.channel_layer.group_send(
|
await self.channel_layer.group_send(
|
||||||
f"team-{dup.participation.team.trigram}",
|
f"team-{dup.participation.team.trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify', 'title': 'Tirage au sort du TFJM²',
|
{'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. '
|
'body': _("Your dice score is identical to the one of one or multiple teams. "
|
||||||
'Veuillez le relancer.'}
|
"Please relaunch it.")}
|
||||||
)
|
)
|
||||||
# Alert the tournament
|
# Alert the tournament
|
||||||
await self.channel_layer.group_send(
|
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
|
# 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.
|
# 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.
|
# 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,))
|
tds_copy = sorted(tds, key=lambda td: (td.passage_index, -td.pool.letter,))
|
||||||
jokers = [td for td in tds if td.passage_index == 4]
|
jokers = [td for td in tds if td.passage_index == 4]
|
||||||
round2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
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()
|
await self.tournament.draw.current_round.asave()
|
||||||
|
|
||||||
# Display dice result in the header of the information alert
|
# Display dice result in the header of the information alert
|
||||||
msg = "Les résultats des dés sont les suivants : "
|
trigrams = ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
|
||||||
msg += ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
|
msg = _("The dice results are the following: {trigrams}. "
|
||||||
msg += ". L'ordre de passage et les compositions des différentes poules sont affiché⋅es sur le côté. "
|
"The passage order and the compositions of the different pools are displayed on the side. "
|
||||||
msg += "Les ordres de passage pour le premier tour sont déterminés à partir des scores des dés, "
|
"The passage orders for the first round are determined from the dice scores, in increasing order. "
|
||||||
msg += "dans l'ordre croissant. Pour le deuxième tour, les ordres de passage sont déterminés à partir "
|
"For the second round, the passage orders are determined from the passage orders of the first round.")
|
||||||
msg += "des ordres de passage du premier tour."
|
|
||||||
self.tournament.draw.last_message = msg
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -610,8 +611,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
# Notify the team that it can draw a problem
|
# Notify the team that it can draw a problem
|
||||||
await self.channel_layer.group_send(f"team-{tds[0].participation.team.trigram}",
|
await self.channel_layer.group_send(f"team-{tds[0].participation.team.trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
'body': _("It's your turn to draw a problem!")})
|
||||||
|
|
||||||
async def select_problem(self, **kwargs):
|
async def select_problem(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -631,7 +632,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
.prefetch_related('team').aget()
|
.prefetch_related('team').aget()
|
||||||
# Ensure that the user can draws a problem at this time
|
# Ensure that the user can draws a problem at this time
|
||||||
if participation.id != td.participation_id:
|
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:
|
while True:
|
||||||
# Choose a random problem
|
# Choose a random problem
|
||||||
@ -702,19 +703,20 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
.prefetch_related('team').aget()
|
.prefetch_related('team').aget()
|
||||||
# Ensure that the user can accept a problem at this time
|
# Ensure that the user can accept a problem at this time
|
||||||
if participation.id != td.participation_id:
|
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.accepted = td.purposed
|
||||||
td.purposed = None
|
td.purposed = None
|
||||||
await td.asave()
|
await td.asave()
|
||||||
|
|
||||||
trigram = td.participation.team.trigram
|
trigram = td.participation.team.trigram
|
||||||
msg = f"L'équipe <strong>{trigram}</strong> a accepté le problème <strong>{td.accepted} : " \
|
msg = _("The team <strong>{trigram}</strong> accepted the problem <string>{problem}</strong>: "
|
||||||
f"{settings.PROBLEMS[td.accepted - 1]}</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:
|
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:
|
else:
|
||||||
msg += "Plus personne ne peut l'accepter."
|
msg += _("No team can accept this problem anymore.")
|
||||||
self.tournament.draw.last_message = msg
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -749,8 +751,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
# Notify the team that it can draw a problem
|
# Notify the team that it can draw a problem
|
||||||
await self.channel_layer.group_send(f"team-{new_trigram}",
|
await self.channel_layer.group_send(f"team-{new_trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
'body': _("It's your turn to draw a problem!")})
|
||||||
else:
|
else:
|
||||||
# Pool is ended
|
# Pool is ended
|
||||||
await self.end_pool(pool)
|
await self.end_pool(pool)
|
||||||
@ -808,8 +810,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
'problems': [td.accepted async for td in pool.team_draws],
|
'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é. " \
|
msg += "<br><br>" + _("The draw of the pool {pool} is ended. The summary is below.") \
|
||||||
f"Le tableau récapitulatif est en bas."
|
.format(pool=f"{pool.get_letter_display()}{r.number}")
|
||||||
self.tournament.draw.last_message = msg
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -826,8 +828,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
# Notify the team that it can draw a dice
|
# Notify the team that it can draw a dice
|
||||||
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de lancer le dé !"})
|
'body': _("It's your turn to launch the dice!")})
|
||||||
|
|
||||||
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.dice_visibility',
|
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
|
||||||
@ -843,11 +845,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
"""
|
"""
|
||||||
msg = self.tournament.draw.last_message
|
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
|
||||||
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget()
|
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget()
|
||||||
self.tournament.draw.current_round = next_round
|
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
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -860,8 +862,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
# Notify the team that it can draw a dice
|
# Notify the team that it can draw a dice
|
||||||
await self.channel_layer.group_send(f"team-{participation.team.trigram}",
|
await self.channel_layer.group_send(f"team-{participation.team.trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de lancer le dé !"})
|
'body': _("It's your turn to launch the dice!")})
|
||||||
|
|
||||||
# Reorder dices
|
# Reorder dices
|
||||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
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}",
|
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',
|
||||||
'visible': True})
|
'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.
|
# 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
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -919,7 +921,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
.prefetch_related('team').aget()
|
.prefetch_related('team').aget()
|
||||||
# Ensure that the user can reject a problem at this time
|
# Ensure that the user can reject a problem at this time
|
||||||
if participation.id != td.participation_id:
|
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
|
# Add the problem to the rejected problems list
|
||||||
problem = td.purposed
|
problem = td.purposed
|
||||||
@ -933,15 +935,16 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
|
|
||||||
# Update messages
|
# Update messages
|
||||||
trigram = td.participation.team.trigram
|
trigram = td.participation.team.trigram
|
||||||
msg = f"L'équipe <strong>{trigram}</strong> a refusé le problème <strong>{problem} : " \
|
msg = _("The team <strong>{trigram}</strong> refused the problem <strong>{problem}</strong>: "
|
||||||
f"{settings.PROBLEMS[problem - 1]}</strong>. "
|
"{problem_name}.").format(trigram=trigram, problem=problem,
|
||||||
|
problem_name=settings.PROBLEMS[problem - 1]) + " "
|
||||||
if remaining >= 0:
|
if remaining >= 0:
|
||||||
msg += f"Il lui reste {remaining} refus sans pénalité."
|
msg += _("It remains {remaining} refusals without penalty.").format(remaining=remaining)
|
||||||
else:
|
else:
|
||||||
if already_refused:
|
if already_refused:
|
||||||
msg += "Cela n'ajoute pas de pénalité."
|
msg += _("This problem was already refused by this team.")
|
||||||
else:
|
else:
|
||||||
msg += "Cela ajoute une pénalité de 25 % 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
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
@ -984,8 +987,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
# Notify the team that it can draw a problem
|
# Notify the team that it can draw a problem
|
||||||
await self.channel_layer.group_send(f"team-{new_trigram}",
|
await self.channel_layer.group_send(f"team-{new_trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
'body': _("It's your turn to draw a problem!")})
|
||||||
|
|
||||||
@ensure_orga
|
@ensure_orga
|
||||||
async def export(self, **kwargs):
|
async def export(self, **kwargs):
|
||||||
@ -1022,17 +1025,17 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
|
|
||||||
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
||||||
self.tournament.draw.current_round = r2
|
self.tournament.draw.current_round = r2
|
||||||
msg = "Le tirage au sort pour le tour 2 va commencer. " \
|
msg = _("The draw of the round 2 is starting. "
|
||||||
"L'ordre de passage est déterminé à partir du classement du premier tour, " \
|
"The passage order is determined from the ranking of the first round, "
|
||||||
"de sorte à mélanger les équipes entre les deux jours."
|
"in order to mix the teams between the two days.")
|
||||||
self.tournament.draw.last_message = msg
|
self.tournament.draw.last_message = msg
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
# Send notification to everyone
|
# Send notification to everyone
|
||||||
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': 'Tirage au sort du TFJM²',
|
'title': _("Draw") + " " + settings.APP_NAME,
|
||||||
'body': "Le tirage au sort pour le second tour de la finale a commencé !"})
|
'body': _("The draw of the second round is starting!")})
|
||||||
|
|
||||||
# Set the first pool of the second round as the active pool
|
# 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()
|
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
|
# Notify the team that it can draw a problem
|
||||||
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||||
'title': "À votre tour !",
|
'title': _("Your turn!"),
|
||||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
'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',
|
||||||
|
@ -110,58 +110,61 @@ class Draw(models.Model):
|
|||||||
# Waiting for dices to determine pools and passage order
|
# Waiting for dices to determine pools and passage order
|
||||||
if self.current_round.number == 1:
|
if self.current_round.number == 1:
|
||||||
# Specific information for the first round
|
# Specific information for the first round
|
||||||
s += """Nous allons commencer le tirage des problèmes.<br>
|
s += _("We are going to start the problem draw.<br>"
|
||||||
Vous pouvez à tout moment poser toute question si quelque chose
|
"You can ask any question if something is not clear or wrong.<br><br>"
|
||||||
n'est pas clair ou ne va pas.<br><br>
|
"We are going to first draw the pools and the passage order for the first round "
|
||||||
Nous allons d'abord tirer les poules et l'ordre de passage
|
"with all the teams, then for each pool, we will draw the draw order and the problems.")
|
||||||
pour le premier tour avec toutes les équipes puis pour chaque poule,
|
s += "<br><br>"
|
||||||
nous tirerons l'ordre de tirage pour le tour et les problèmes.<br><br>"""
|
s += _("The captains, you can now all throw a 100-sided dice, by clicking on the big dice button. "
|
||||||
s += """
|
"The pools and the passage order during the first round will be the increasing order "
|
||||||
Les capitaines, vous pouvez désormais toustes lancer un dé 100,
|
"of the dices, ie. the smallest dice will be the first to pass in pool A.")
|
||||||
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."""
|
|
||||||
case 'DICE_ORDER_POULE':
|
case 'DICE_ORDER_POULE':
|
||||||
# Waiting for dices to determine the choice order
|
# Waiting for dices to determine the choice order
|
||||||
s += f"""Nous passons au tirage des problèmes pour la poule
|
s += _("We are going to start the problem draw for the pool <strong>{pool}</strong>, "
|
||||||
<strong>{self.current_round.current_pool}</strong>, entre les équipes
|
"between the teams <strong>{teams}</strong>. "
|
||||||
<strong>{', '.join(td.participation.team.trigram
|
"The captains can throw a 100-sided dice by clicking on the big dice button "
|
||||||
for td in self.current_round.current_pool.teamdraw_set.all())}</strong>.
|
"to determine the order of draw. The team with the highest score will draw first.") \
|
||||||
Les capitaines peuvent lancer un dé 100 en cliquant sur le gros bouton
|
.format(pool=self.current_round.current_pool,
|
||||||
pour déterminer l'ordre de tirage. L'équipe réalisant le plus gros score pourra
|
teams=', '.join(td.participation.team.trigram
|
||||||
tirer en premier."""
|
for td in self.current_round.current_pool.teamdraw_set.all()))
|
||||||
case 'WAITING_DRAW_PROBLEM':
|
case 'WAITING_DRAW_PROBLEM':
|
||||||
# Waiting for a problem draw
|
# Waiting for a problem draw
|
||||||
td = self.current_round.current_pool.current_team
|
td = self.current_round.current_pool.current_team
|
||||||
s += f"""C'est au tour de l'équipe <strong>{td.participation.team.trigram}</strong>
|
s += _("The team <strong>{trigram}</strong> is going to draw a problem. "
|
||||||
de choisir son problème. Cliquez sur l'urne au milieu pour tirer un problème au sort."""
|
"Click on the urn in the middle to draw a problem.") \
|
||||||
|
.format(trigram=td.participation.team.trigram)
|
||||||
case 'WAITING_CHOOSE_PROBLEM':
|
case 'WAITING_CHOOSE_PROBLEM':
|
||||||
# Waiting for the team that can accept or reject the problem
|
# Waiting for the team that can accept or reject the problem
|
||||||
td = self.current_round.current_pool.current_team
|
td = self.current_round.current_pool.current_team
|
||||||
s += f"""L'équipe <strong>{td.participation.team.trigram}</strong> a tiré le problème
|
s += _("The team <strong>{trigram}</strong> drew the problem <strong>{problem}: "
|
||||||
<strong>{td.purposed} : {settings.PROBLEMS[td.purposed - 1]}</strong>. """
|
"{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:
|
if td.purposed in td.rejected:
|
||||||
# The problem was previously 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
|
s += _("It already refused this problem before, so it can refuse it without penalty and "
|
||||||
tirer un nouveau problème immédiatement, ou bien revenir sur son choix."""
|
"draw a new problem immediately, or change its mind.")
|
||||||
else:
|
else:
|
||||||
# The problem can be rejected
|
# 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:
|
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 25% penalty "
|
||||||
|
"on the coefficient of the oral defense.")
|
||||||
else:
|
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':
|
case 'WAITING_FINAL':
|
||||||
# We are between the two rounds of the final tournament
|
# 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':
|
case 'DRAW_ENDED':
|
||||||
# The draw is 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 += "<br><br>" if s else ""
|
||||||
s += """Pour plus de détails sur le déroulement du tirage au sort,
|
rules_link = "https://tfjm.org/reglement" if settings.TFJM_APP == "TFJM" else "https://eteam.tfjm.org/rules/"
|
||||||
le règlement est accessible sur
|
s += _("For more details on the draw, the rules are available on "
|
||||||
<a class="alert-link" href="https://tfjm.org/reglement">https://tfjm.org/reglement</a>."""
|
"<a class=\"alert-link\" href=\"{link}\">{link}</a>.").format(link=rules_link)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
async def ainformation(self) -> str:
|
async def ainformation(self) -> str:
|
||||||
@ -412,7 +415,7 @@ class Pool(models.Model):
|
|||||||
solution_number=tds[line[0]].accepted,
|
solution_number=tds[line[0]].accepted,
|
||||||
defender=tds[line[0]].participation,
|
defender=tds[line[0]].participation,
|
||||||
opponent=tds[line[1]].participation,
|
opponent=tds[line[1]].participation,
|
||||||
reporter=tds[line[2]].participation,
|
reviewer=tds[line[2]].participation,
|
||||||
defender_penalties=tds[line[0]].penalty_int,
|
defender_penalties=tds[line[0]].penalty_int,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -529,37 +529,37 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
opponentTd.classList.add('text-center')
|
opponentTd.classList.add('text-center')
|
||||||
opponentTd.innerText = 'Opp'
|
opponentTd.innerText = 'Opp'
|
||||||
|
|
||||||
let reporterTd = document.createElement('td')
|
let reviewerTd = document.createElement('td')
|
||||||
reporterTd.classList.add('text-center')
|
reviewerTd.classList.add('text-center')
|
||||||
reporterTd.innerText = 'Rap'
|
reviewerTd.innerText = 'Rap'
|
||||||
|
|
||||||
// Put the cells in their right places, according to the pool size and the row number.
|
// Put the cells in their right places, according to the pool size and the row number.
|
||||||
if (poule.teams.length === 3) {
|
if (poule.teams.length === 3) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(defenderTd, reporterTd, opponentTd)
|
teamTr.append(defenderTd, reviewerTd, opponentTd)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(opponentTd, defenderTd, reporterTd)
|
teamTr.append(opponentTd, defenderTd, reviewerTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(reporterTd, opponentTd, defenderTd)
|
teamTr.append(reviewerTd, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (poule.teams.length === 4) {
|
} else if (poule.teams.length === 4) {
|
||||||
let emptyTd = document.createElement('td')
|
let emptyTd = document.createElement('td')
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(defenderTd, emptyTd, reporterTd, opponentTd)
|
teamTr.append(defenderTd, emptyTd, reviewerTd, opponentTd)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(opponentTd, defenderTd, emptyTd, reporterTd)
|
teamTr.append(opponentTd, defenderTd, emptyTd, reviewerTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(reporterTd, opponentTd, defenderTd, emptyTd)
|
teamTr.append(reviewerTd, opponentTd, defenderTd, emptyTd)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
teamTr.append(emptyTd, reporterTd, opponentTd, defenderTd)
|
teamTr.append(emptyTd, reviewerTd, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (poule.teams.length === 5) {
|
} else if (poule.teams.length === 5) {
|
||||||
@ -567,19 +567,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let emptyTd2 = document.createElement('td')
|
let emptyTd2 = document.createElement('td')
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
teamTr.append(defenderTd, emptyTd, opponentTd, reporterTd, emptyTd2)
|
teamTr.append(defenderTd, emptyTd, opponentTd, reviewerTd, emptyTd2)
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
teamTr.append(emptyTd, defenderTd, reporterTd, emptyTd2, opponentTd)
|
teamTr.append(emptyTd, defenderTd, reviewerTd, emptyTd2, opponentTd)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reporterTd)
|
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reviewerTd)
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
teamTr.append(reporterTd, opponentTd, emptyTd, defenderTd, emptyTd2)
|
teamTr.append(reviewerTd, opponentTd, emptyTd, defenderTd, emptyTd2)
|
||||||
break
|
break
|
||||||
case 4:
|
case 4:
|
||||||
teamTr.append(emptyTd, reporterTd, emptyTd2, opponentTd, defenderTd)
|
teamTr.append(emptyTd, reviewerTd, emptyTd2, opponentTd, defenderTd)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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-06-13 10:56+0200\n"
|
"POT-Creation-Date: 2024-07-05 10:48+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"
|
||||||
@ -93,7 +93,7 @@ msgstr ""
|
|||||||
"Pour une permission qui concerne un tournoi, indique quel est le tournoi "
|
"Pour une permission qui concerne un tournoi, indique quel est le tournoi "
|
||||||
"concerné."
|
"concerné."
|
||||||
|
|
||||||
#: chat/models.py:73 draw/models.py:429 draw/models.py:456
|
#: chat/models.py:73 draw/models.py:432 draw/models.py:459
|
||||||
#: participation/admin.py:136 participation/admin.py:155
|
#: participation/admin.py:136 participation/admin.py:155
|
||||||
#: participation/models.py:1515 participation/models.py:1524
|
#: participation/models.py:1515 participation/models.py:1524
|
||||||
#: participation/tables.py:84
|
#: participation/tables.py:84
|
||||||
@ -264,12 +264,12 @@ msgstr "Connexion"
|
|||||||
msgid "teams"
|
msgid "teams"
|
||||||
msgstr "équipes"
|
msgstr "équipes"
|
||||||
|
|
||||||
#: draw/admin.py:92 draw/models.py:234 draw/models.py:448
|
#: draw/admin.py:92 draw/models.py:237 draw/models.py:451
|
||||||
#: participation/models.py:1016
|
#: participation/models.py:1016
|
||||||
msgid "round"
|
msgid "round"
|
||||||
msgstr "tour"
|
msgstr "tour"
|
||||||
|
|
||||||
#: draw/apps.py:10 tfjm/templates/navbar.html:68
|
#: draw/apps.py:10 draw/consumers.py:1037 tfjm/templates/navbar.html:68
|
||||||
msgid "Draw"
|
msgid "Draw"
|
||||||
msgstr "Tirage au sort"
|
msgstr "Tirage au sort"
|
||||||
|
|
||||||
@ -277,67 +277,182 @@ msgstr "Tirage au sort"
|
|||||||
msgid "You are not an organizer."
|
msgid "You are not an organizer."
|
||||||
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice."
|
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice."
|
||||||
|
|
||||||
#: draw/consumers.py:165
|
#: draw/consumers.py:167
|
||||||
msgid "The draw is already started."
|
msgid "The draw is already started."
|
||||||
msgstr "Le tirage a déjà commencé."
|
msgstr "Le tirage a déjà commencé."
|
||||||
|
|
||||||
#: draw/consumers.py:171
|
#: draw/consumers.py:173
|
||||||
msgid "Invalid format"
|
msgid "Invalid format"
|
||||||
msgstr "Format invalide"
|
msgstr "Format invalide"
|
||||||
|
|
||||||
#: draw/consumers.py:176
|
#: draw/consumers.py:178
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The sum must be equal to the number of teams: expected {len}, got {sum}"
|
msgid "The sum must be equal to the number of teams: expected {len}, got {sum}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"La somme doit être égale au nombre d'équipes : attendu {len}, obtenu {sum}"
|
"La somme doit être égale au nombre d'équipes : attendu {len}, obtenu {sum}"
|
||||||
|
|
||||||
#: draw/consumers.py:181
|
#: draw/consumers.py:183
|
||||||
msgid "There can be at most one pool with 5 teams."
|
msgid "There can be at most one pool with 5 teams."
|
||||||
msgstr "Il ne peut y avoir au plus qu'une seule poule de 5 équipes."
|
msgstr "Il ne peut y avoir au plus qu'une seule poule de 5 équipes."
|
||||||
|
|
||||||
#: draw/consumers.py:221
|
#: draw/consumers.py:223
|
||||||
msgid "Draw started!"
|
msgid "Draw started!"
|
||||||
msgstr "Le tirage a commencé !"
|
msgstr "Le tirage a commencé !"
|
||||||
|
|
||||||
#: draw/consumers.py:243
|
#: draw/consumers.py:238
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The draw of tournament {tournament} started!"
|
||||||
|
msgstr "Le tirage au sort du tournoi {tournament} a commencé !"
|
||||||
|
|
||||||
|
#: draw/consumers.py:245
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The draw for the tournament {tournament} will start."
|
msgid "The draw for the tournament {tournament} will start."
|
||||||
msgstr "Le tirage au sort du tournoi {tournament} va commencer."
|
msgstr "Le tirage au sort du tournoi {tournament} va commencer."
|
||||||
|
|
||||||
#: draw/consumers.py:254 draw/consumers.py:280 draw/consumers.py:690
|
#: draw/consumers.py:256 draw/consumers.py:282 draw/consumers.py:691
|
||||||
#: draw/consumers.py:907 draw/consumers.py:996 draw/consumers.py:1018
|
#: draw/consumers.py:909 draw/consumers.py:999 draw/consumers.py:1021
|
||||||
#: draw/consumers.py:1109 draw/templates/draw/tournament_content.html:5
|
#: draw/consumers.py:1112 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é."
|
||||||
|
|
||||||
#: draw/consumers.py:267
|
#: draw/consumers.py:269
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The draw for the tournament {tournament} is aborted."
|
msgid "The draw for the tournament {tournament} is aborted."
|
||||||
msgstr "Le tirage au sort du tournoi {tournament} est annulé."
|
msgstr "Le tirage au sort du tournoi {tournament} est annulé."
|
||||||
|
|
||||||
#: draw/consumers.py:307 draw/consumers.py:328 draw/consumers.py:624
|
#: draw/consumers.py:309 draw/consumers.py:330 draw/consumers.py:625
|
||||||
#: draw/consumers.py:695 draw/consumers.py:912
|
#: draw/consumers.py:696 draw/consumers.py:914
|
||||||
msgid "This is not the time for this."
|
msgid "This is not the time for this."
|
||||||
msgstr "Ce n'est pas le moment pour cela."
|
msgstr "Ce n'est pas le moment pour cela."
|
||||||
|
|
||||||
#: draw/consumers.py:320 draw/consumers.py:323
|
#: draw/consumers.py:322 draw/consumers.py:325
|
||||||
msgid "You've already launched the dice."
|
msgid "You've already launched the dice."
|
||||||
msgstr "Vous avez déjà lancé le dé."
|
msgstr "Vous avez déjà lancé le dé."
|
||||||
|
|
||||||
#: draw/consumers.py:326
|
#: draw/consumers.py:328
|
||||||
msgid "It is not your turn."
|
msgid "It is not your turn."
|
||||||
msgstr "Ce n'est pas votre tour."
|
msgstr "Ce n'est pas votre tour."
|
||||||
|
|
||||||
#: draw/consumers.py:413
|
#: draw/consumers.py:408
|
||||||
|
msgid ""
|
||||||
|
"Your dice score is identical to the one of one or multiple teams. Please "
|
||||||
|
"relaunch it."
|
||||||
|
msgstr ""
|
||||||
|
"Votre score de dé est identique à celui d'une ou plusieurs équipes. Merci de "
|
||||||
|
"le relancer."
|
||||||
|
|
||||||
|
#: draw/consumers.py:415
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Dices from teams {teams} are identical. Please relaunch your dices."
|
msgid "Dices from teams {teams} are identical. Please relaunch your dices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Les dés des équipes {teams} sont identiques. Merci de relancer vos dés."
|
"Les dés des équipes {teams} sont identiques. Merci de relancer vos dés."
|
||||||
|
|
||||||
#: draw/consumers.py:1021
|
#: draw/consumers.py:508
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"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."
|
||||||
|
msgstr ""
|
||||||
|
"Les résultats des dés sont les suivants : {trigrams}. L'ordre de passage et "
|
||||||
|
"les compositions des différentes poules sont affichés sur le côté. Les "
|
||||||
|
"ordres de passage pour le premier tour sont déterminés à partir des scores "
|
||||||
|
"de dés, par ordre croissant. Pour le deuxième tour, les ordres de passage "
|
||||||
|
"sont déterminés à partir des ordres de passage du premier tour."
|
||||||
|
|
||||||
|
#: draw/consumers.py:614 draw/consumers.py:754 draw/consumers.py:831
|
||||||
|
#: draw/consumers.py:865 draw/consumers.py:990 draw/consumers.py:1088
|
||||||
|
msgid "Your turn!"
|
||||||
|
msgstr "À votre tour !"
|
||||||
|
|
||||||
|
#: draw/consumers.py:615 draw/consumers.py:755 draw/consumers.py:991
|
||||||
|
#: draw/consumers.py:1089
|
||||||
|
msgid "It's your turn to draw a problem!"
|
||||||
|
msgstr "C'est à vous de tirer un problème !"
|
||||||
|
|
||||||
|
#: draw/consumers.py:635 draw/consumers.py:706 draw/consumers.py:924
|
||||||
|
msgid "This is not your turn."
|
||||||
|
msgstr "Ce n'est pas votre tour."
|
||||||
|
|
||||||
|
#: draw/consumers.py:713
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"The team <strong>{trigram}</strong> accepted the problem <string>{problem}</"
|
||||||
|
"strong>: {problem_name}. "
|
||||||
|
msgstr ""
|
||||||
|
"L'équipe <strong>{trigram}</strong> a accepté le problème <strong>{problem}</"
|
||||||
|
"strong> : {problem_name}. "
|
||||||
|
|
||||||
|
#: draw/consumers.py:717
|
||||||
|
msgid "One team more can accept this problem."
|
||||||
|
msgstr "Une équipe de plus peut accepter ce problème."
|
||||||
|
|
||||||
|
#: draw/consumers.py:719
|
||||||
|
msgid "No team can accept this problem anymore."
|
||||||
|
msgstr "Aucune autre équipe ne peut accepter ce problème."
|
||||||
|
|
||||||
|
#: draw/consumers.py:813
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The draw of the pool {pool} is ended. The summary is below."
|
||||||
|
msgstr "Le tirage de la poule {pool} est terminé. Le résumé est ci-dessous."
|
||||||
|
|
||||||
|
#: draw/consumers.py:832 draw/consumers.py:866
|
||||||
|
msgid "It's your turn to launch the dice!"
|
||||||
|
msgstr "C'est à vous de lancer le dé !"
|
||||||
|
|
||||||
|
#: draw/consumers.py:852
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "The draw of the round {round} is ended."
|
||||||
|
msgstr "Le tirage au sort du tour {round} est annulé."
|
||||||
|
|
||||||
|
#: draw/consumers.py:895
|
||||||
|
msgid "The draw of the first round is ended."
|
||||||
|
msgstr "Le tirage au sort du premier tour est terminé."
|
||||||
|
|
||||||
|
#: draw/consumers.py:938
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"The team <strong>{trigram}</strong> refused the problem <strong>{problem}</"
|
||||||
|
"strong>: {problem_name}."
|
||||||
|
msgstr ""
|
||||||
|
"L'équipe <strong>{trigram}</strong> a refusé le problème <strong>{problem}</"
|
||||||
|
"strong> : {problem_name}."
|
||||||
|
|
||||||
|
#: draw/consumers.py:942
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "It remains {remaining} refusals without penalty."
|
||||||
|
msgstr "Il reste {remaining} refus sans pénalité."
|
||||||
|
|
||||||
|
#: draw/consumers.py:945
|
||||||
|
msgid "This problem was already refused by this team."
|
||||||
|
msgstr "Ce problème a déjà été refusé par cette équipe."
|
||||||
|
|
||||||
|
#: draw/consumers.py:947
|
||||||
|
msgid "It adds a 25% penalty on the coefficient of the oral defense."
|
||||||
|
msgstr ""
|
||||||
|
"Cela ajoute une pénalité de 25 % sur le coefficient de l'oral de la "
|
||||||
|
"défense."
|
||||||
|
|
||||||
|
#: draw/consumers.py:1024
|
||||||
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:1028
|
||||||
|
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."
|
||||||
|
msgstr ""
|
||||||
|
"Le tirage au sort du tour 2 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:1038
|
||||||
|
msgid "The draw of the second round is starting!"
|
||||||
|
msgstr "Le tirage au sort du deuxième tour commence !"
|
||||||
|
|
||||||
#: draw/models.py:27
|
#: draw/models.py:27
|
||||||
msgid "The associated tournament."
|
msgid "The associated tournament."
|
||||||
msgstr "Le tournoi associé."
|
msgstr "Le tournoi associé."
|
||||||
@ -362,154 +477,261 @@ msgstr "Le dernier message qui est affiché sur l'interface de tirage."
|
|||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "État"
|
msgstr "État"
|
||||||
|
|
||||||
#: draw/models.py:174
|
#: draw/models.py:113
|
||||||
|
msgid ""
|
||||||
|
"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."
|
||||||
|
msgstr ""
|
||||||
|
"Nous allons commencer le tirage des problèmes.<br>Vous pouvez poser des "
|
||||||
|
"questions si quelque chose n'est pas clair ou faux.<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 allons tirer l'ordre de "
|
||||||
|
"tirage et les problèmes."
|
||||||
|
|
||||||
|
#: draw/models.py:118
|
||||||
|
msgid ""
|
||||||
|
"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."
|
||||||
|
msgstr ""
|
||||||
|
"Les capitaines, vous pouvez maintenant tous lancer un dé à 100 faces, en "
|
||||||
|
"cliquant sur le gros bouton de dé. Les poules et l'ordre de passage pendant "
|
||||||
|
"le premier tour seront l'ordre croissant des dés, c'est-à-dire que le plus "
|
||||||
|
"petit dé passera en premier dans la poule A."
|
||||||
|
|
||||||
|
#: draw/models.py:123
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"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."
|
||||||
|
msgstr ""
|
||||||
|
"Nous allons commencer le tirage des problèmes pour la poule <strong>{pool}</"
|
||||||
|
"strong>, entre les équipes <strong>{teams}</strong>. Les capitaines peuvent "
|
||||||
|
"lancer un dé à 100 faces en cliquant sur le gros bouton de dé pour "
|
||||||
|
"déterminer l'ordre de tirage. L'équipe avec le score le plus élevé tirera en "
|
||||||
|
"premier."
|
||||||
|
|
||||||
|
#: draw/models.py:133
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"The team <strong>{trigram}</strong> is going to draw a problem. Click on the "
|
||||||
|
"urn in the middle to draw a problem."
|
||||||
|
msgstr ""
|
||||||
|
"L'équipe <strong>{trigram}</strong> va tirer un problème. Cliquez sur l'urne "
|
||||||
|
"au milieu pour tirer un problème."
|
||||||
|
|
||||||
|
#: draw/models.py:139
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"The team <strong>{trigram}</strong> drew the problem <strong>{problem}: "
|
||||||
|
"{problem_name}</strong>."
|
||||||
|
msgstr ""
|
||||||
|
"L'équipe <strong>{trigram}</strong> a tiré le problème <strong>{problem} : "
|
||||||
|
"{problem_name}</strong>."
|
||||||
|
|
||||||
|
#: draw/models.py:145
|
||||||
|
msgid ""
|
||||||
|
"It already refused this problem before, so it can refuse it without penalty "
|
||||||
|
"and draw a new problem immediately, or change its mind."
|
||||||
|
msgstr ""
|
||||||
|
"Elle a déjà refusé ce problème auparavant, donc elle peut le refuser sans "
|
||||||
|
"pénalité et tirer un nouveau problème immédiatement, ou changer d'avis."
|
||||||
|
|
||||||
|
#: draw/models.py:149
|
||||||
|
msgid "It can decide to accept or refuse this problem."
|
||||||
|
msgstr "Elle peut décider d'accepter ou de refuser ce problème."
|
||||||
|
|
||||||
|
#: draw/models.py:151
|
||||||
|
msgid ""
|
||||||
|
"Refusing this problem will add a new 25% penalty on the coefficient of "
|
||||||
|
"the oral defense."
|
||||||
|
msgstr ""
|
||||||
|
"Refuser ce problème ajoutera une nouvelle pénalité de 25nbsp;% sur le "
|
||||||
|
"coefficient de l'oral de la défense."
|
||||||
|
|
||||||
|
#: draw/models.py:154
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "There are still {remaining} refusals without penalty."
|
||||||
|
msgstr "Il reste {remaining} refus sans pénalité."
|
||||||
|
|
||||||
|
#: draw/models.py:158
|
||||||
|
msgid ""
|
||||||
|
"The draw for the second round will take place at the end of the first round. "
|
||||||
|
"Good luck!"
|
||||||
|
msgstr ""
|
||||||
|
"Le tirage au sort du deuxième tour aura lieu à la fin du premier tour. Bonne "
|
||||||
|
"chance !"
|
||||||
|
|
||||||
|
#: draw/models.py:161
|
||||||
|
msgid ""
|
||||||
|
"The draw is ended. The solutions of the other teams can be found in the tab "
|
||||||
|
"\"My participation\"."
|
||||||
|
msgstr ""
|
||||||
|
"Le tirage est terminé. Les solutions des autres équipes peuvent être "
|
||||||
|
"trouvées dans l'onglet « Ma participation »."
|
||||||
|
|
||||||
|
#: draw/models.py:166
|
||||||
|
#, python-brace-format
|
||||||
|
msgid ""
|
||||||
|
"For more details on the draw, the rules are available on <a class=\"alert-"
|
||||||
|
"link\" href=\"{link}\">{link}</a>."
|
||||||
|
msgstr ""
|
||||||
|
"Pour plus de détails sur le tirage, les règles sont disponibles sur <a "
|
||||||
|
"class=\"alert-link\" href=\"{link}\">{link}</a>."
|
||||||
|
|
||||||
|
#: draw/models.py:177
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Draw of tournament {tournament}"
|
msgid "Draw of tournament {tournament}"
|
||||||
msgstr "Tirage au sort du tournoi {tournament}"
|
msgstr "Tirage au sort du tournoi {tournament}"
|
||||||
|
|
||||||
#: draw/models.py:177 draw/models.py:189
|
#: draw/models.py:180 draw/models.py:192
|
||||||
msgid "draw"
|
msgid "draw"
|
||||||
msgstr "tirage au sort"
|
msgstr "tirage au sort"
|
||||||
|
|
||||||
#: draw/models.py:178
|
#: draw/models.py:181
|
||||||
msgid "draws"
|
msgid "draws"
|
||||||
msgstr "tirages au sort"
|
msgstr "tirages au sort"
|
||||||
|
|
||||||
#: draw/models.py:194
|
#: draw/models.py:197
|
||||||
msgid "Round 1"
|
msgid "Round 1"
|
||||||
msgstr "Tour 1"
|
msgstr "Tour 1"
|
||||||
|
|
||||||
#: draw/models.py:195
|
#: draw/models.py:198
|
||||||
msgid "Round 2"
|
msgid "Round 2"
|
||||||
msgstr "Tour 2"
|
msgstr "Tour 2"
|
||||||
|
|
||||||
#: draw/models.py:196
|
#: draw/models.py:199
|
||||||
msgid "Round 3"
|
msgid "Round 3"
|
||||||
msgstr "Tour 3"
|
msgstr "Tour 3"
|
||||||
|
|
||||||
#: draw/models.py:197
|
#: draw/models.py:200
|
||||||
msgid "number"
|
msgid "number"
|
||||||
msgstr "numéro"
|
msgstr "numéro"
|
||||||
|
|
||||||
#: draw/models.py:198
|
#: draw/models.py:201
|
||||||
msgid "The number of the round, 1 or 2 (or 3 for ETEAM)"
|
msgid "The number of the round, 1 or 2 (or 3 for ETEAM)"
|
||||||
msgstr "Le numéro du tour, 1 ou 2 (ou 3 pour ETEAM)"
|
msgstr "Le numéro du tour, 1 ou 2 (ou 3 pour ETEAM)"
|
||||||
|
|
||||||
#: draw/models.py:208
|
#: draw/models.py:211
|
||||||
msgid "current pool"
|
msgid "current pool"
|
||||||
msgstr "poule actuelle"
|
msgstr "poule actuelle"
|
||||||
|
|
||||||
#: draw/models.py:209
|
#: draw/models.py:212
|
||||||
msgid "The current pool where teams select their problems."
|
msgid "The current pool where teams select their problems."
|
||||||
msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
|
msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
|
||||||
|
|
||||||
#: draw/models.py:235
|
#: draw/models.py:238
|
||||||
msgid "rounds"
|
msgid "rounds"
|
||||||
msgstr "tours"
|
msgstr "tours"
|
||||||
|
|
||||||
#: draw/models.py:257 participation/models.py:1024
|
#: draw/models.py:260 participation/models.py:1024
|
||||||
msgid "letter"
|
msgid "letter"
|
||||||
msgstr "lettre"
|
msgstr "lettre"
|
||||||
|
|
||||||
#: draw/models.py:258
|
#: draw/models.py:261
|
||||||
msgid "The letter of the pool: A, B, C or D."
|
msgid "The letter of the pool: A, B, C or D."
|
||||||
msgstr "La lettre de la poule : A, B, C ou D."
|
msgstr "La lettre de la poule : A, B, C ou D."
|
||||||
|
|
||||||
#: draw/models.py:262
|
#: draw/models.py:265
|
||||||
#: participation/templates/participation/tournament_detail.html:15
|
#: participation/templates/participation/tournament_detail.html:15
|
||||||
msgid "size"
|
msgid "size"
|
||||||
msgstr "taille"
|
msgstr "taille"
|
||||||
|
|
||||||
#: draw/models.py:264
|
#: draw/models.py:267
|
||||||
msgid "The number of teams in this pool, between 3 and 5."
|
msgid "The number of teams in this pool, between 3 and 5."
|
||||||
msgstr "Le nombre d'équipes dans la poule, entre 3 et 5."
|
msgstr "Le nombre d'équipes dans la poule, entre 3 et 5."
|
||||||
|
|
||||||
#: draw/models.py:273
|
#: draw/models.py:276
|
||||||
msgid "current team"
|
msgid "current team"
|
||||||
msgstr "équipe actuelle"
|
msgstr "équipe actuelle"
|
||||||
|
|
||||||
#: draw/models.py:274
|
#: draw/models.py:277
|
||||||
msgid "The current team that is selecting its problem."
|
msgid "The current team that is selecting its problem."
|
||||||
msgstr "L'équipe qui est en train de choisir son problème."
|
msgstr "L'équipe qui est en train de choisir son problème."
|
||||||
|
|
||||||
#: draw/models.py:283
|
#: draw/models.py:286
|
||||||
msgid "associated pool"
|
msgid "associated pool"
|
||||||
msgstr "poule associée"
|
msgstr "poule associée"
|
||||||
|
|
||||||
#: draw/models.py:284
|
#: draw/models.py:287
|
||||||
msgid "The full pool instance."
|
msgid "The full pool instance."
|
||||||
msgstr "L'instance complète de la poule."
|
msgstr "L'instance complète de la poule."
|
||||||
|
|
||||||
#: draw/models.py:426
|
#: draw/models.py:429
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Pool {letter}{number}"
|
msgid "Pool {letter}{number}"
|
||||||
msgstr "Poule {letter}{number}"
|
msgstr "Poule {letter}{number}"
|
||||||
|
|
||||||
#: draw/models.py:430 participation/models.py:1516
|
#: draw/models.py:433 participation/models.py:1516
|
||||||
msgid "pools"
|
msgid "pools"
|
||||||
msgstr "poules"
|
msgstr "poules"
|
||||||
|
|
||||||
#: draw/models.py:442 participation/models.py:1002 participation/models.py:1665
|
#: draw/models.py:445 participation/models.py:1002 participation/models.py:1665
|
||||||
#: participation/models.py:1695 participation/models.py:1737
|
#: participation/models.py:1695 participation/models.py:1737
|
||||||
msgid "participation"
|
msgid "participation"
|
||||||
msgstr "participation"
|
msgstr "participation"
|
||||||
|
|
||||||
#: draw/models.py:463
|
#: draw/models.py:466
|
||||||
msgid "passage index"
|
msgid "passage index"
|
||||||
msgstr "numéro de passage"
|
msgstr "numéro de passage"
|
||||||
|
|
||||||
#: draw/models.py:464
|
#: draw/models.py:467
|
||||||
msgid ""
|
msgid ""
|
||||||
"The passage order in the pool, between 0 and the size of the pool minus 1."
|
"The passage order in the pool, between 0 and the size of the pool minus 1."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"L'ordre de passage dans la poule, de 0 à la taille de la poule moins 1."
|
"L'ordre de passage dans la poule, de 0 à la taille de la poule moins 1."
|
||||||
|
|
||||||
#: draw/models.py:472
|
#: draw/models.py:475
|
||||||
msgid "choose index"
|
msgid "choose index"
|
||||||
msgstr "numéro de choix"
|
msgstr "numéro de choix"
|
||||||
|
|
||||||
#: draw/models.py:473
|
#: draw/models.py:476
|
||||||
msgid ""
|
msgid ""
|
||||||
"The choice order in the pool, between 0 and the size of the pool minus 1."
|
"The choice order in the pool, between 0 and the size of the pool minus 1."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1."
|
"L'ordre de choix dans la poule, entre 0 et la taille de la poule moins 1."
|
||||||
|
|
||||||
#: draw/models.py:479 draw/models.py:502 participation/models.py:1538
|
#: draw/models.py:482 draw/models.py:505 participation/models.py:1538
|
||||||
#: participation/models.py:1702
|
#: participation/models.py:1702
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Problem #{problem}"
|
msgid "Problem #{problem}"
|
||||||
msgstr "Problème n°{problem}"
|
msgstr "Problème n°{problem}"
|
||||||
|
|
||||||
#: draw/models.py:483
|
#: draw/models.py:486
|
||||||
msgid "accepted problem"
|
msgid "accepted problem"
|
||||||
msgstr "problème accepté"
|
msgstr "problème accepté"
|
||||||
|
|
||||||
#: draw/models.py:490
|
#: draw/models.py:493
|
||||||
msgid "passage dice"
|
msgid "passage dice"
|
||||||
msgstr "dé d'ordre de passage"
|
msgstr "dé d'ordre de passage"
|
||||||
|
|
||||||
#: draw/models.py:497
|
#: draw/models.py:500
|
||||||
msgid "choice dice"
|
msgid "choice dice"
|
||||||
msgstr "dé d'ordre de choix"
|
msgstr "dé d'ordre de choix"
|
||||||
|
|
||||||
#: draw/models.py:506
|
#: draw/models.py:509
|
||||||
msgid "purposed problem"
|
msgid "purposed problem"
|
||||||
msgstr "problème proposé"
|
msgstr "problème proposé"
|
||||||
|
|
||||||
#: draw/models.py:511
|
#: draw/models.py:514
|
||||||
msgid "rejected problems"
|
msgid "rejected problems"
|
||||||
msgstr "problèmes rejetés"
|
msgstr "problèmes rejetés"
|
||||||
|
|
||||||
#: draw/models.py:540
|
#: draw/models.py:543
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Draw of the team {trigram} for the pool {letter}{number}"
|
msgid "Draw of the team {trigram} for the pool {letter}{number}"
|
||||||
msgstr "Tirage de l'équipe {trigram} pour la poule {letter}{number}"
|
msgstr "Tirage de l'équipe {trigram} pour la poule {letter}{number}"
|
||||||
|
|
||||||
#: draw/models.py:546
|
#: draw/models.py:549
|
||||||
msgid "team draw"
|
msgid "team draw"
|
||||||
msgstr "tirage d'équipe"
|
msgstr "tirage d'équipe"
|
||||||
|
|
||||||
#: draw/models.py:547
|
#: draw/models.py:550
|
||||||
msgid "team draws"
|
msgid "team draws"
|
||||||
msgstr "tirages d'équipe"
|
msgstr "tirages d'équipe"
|
||||||
|
|
||||||
@ -702,7 +924,7 @@ msgstr "opposant⋅e"
|
|||||||
|
|
||||||
#: participation/admin.py:132 participation/models.py:1559
|
#: participation/admin.py:132 participation/models.py:1559
|
||||||
#: participation/models.py:1750
|
#: participation/models.py:1750
|
||||||
msgid "reporter"
|
msgid "reviewer"
|
||||||
msgstr "rapporteur⋅rice"
|
msgstr "rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/admin.py:187 participation/models.py:1700
|
#: participation/admin.py:187 participation/models.py:1700
|
||||||
@ -794,7 +1016,7 @@ msgid "The following user was not found:"
|
|||||||
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
|
msgstr "L'utilisateur⋅rice suivant n'a pas été trouvé :"
|
||||||
|
|
||||||
#: participation/forms.py:349
|
#: participation/forms.py:349
|
||||||
msgid "The defender, the opponent and the reporter must be different."
|
msgid "The defender, the opponent and the reviewer must be different."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
||||||
|
|
||||||
@ -1175,11 +1397,11 @@ msgstr ""
|
|||||||
#: participation/models.py:966
|
#: participation/models.py:966
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>You will report the solution of the team {reporter} on the <a "
|
"<p>You will report the solution of the team {reviewer} on the <a "
|
||||||
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
|
"href='{solution_url}'>problem {problem}. You can upload your synthesis sheet "
|
||||||
"on <a href='{passage_url}'>this page</a>.</p>"
|
"on <a href='{passage_url}'>this page</a>.</p>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"<p>Vous rapporterez la solution de l'équipe {reporter} sur le <a "
|
"<p>Vous rapporterez la solution de l'équipe {reviewer} sur le <a "
|
||||||
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
|
"href='{solution_url}'>problème {problem}</a>. Vous pouvez envoyer votre note "
|
||||||
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
|
"de synthèse sur <a href='{passage_url}'>cette page</a>.</p>"
|
||||||
|
|
||||||
@ -1409,11 +1631,11 @@ msgid "opponent oral note"
|
|||||||
msgstr "note d'oral opposant⋅e"
|
msgstr "note d'oral opposant⋅e"
|
||||||
|
|
||||||
#: participation/models.py:1815
|
#: participation/models.py:1815
|
||||||
msgid "reporter writing note"
|
msgid "reviewer writing note"
|
||||||
msgstr "note d'écrit rapporteur⋅rice"
|
msgstr "note d'écrit rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/models.py:1821
|
#: participation/models.py:1821
|
||||||
msgid "reporter oral note"
|
msgid "reviewer oral note"
|
||||||
msgstr "note d'oral du rapporteur⋅rice"
|
msgstr "note d'oral du rapporteur⋅rice"
|
||||||
|
|
||||||
#: participation/models.py:1881
|
#: participation/models.py:1881
|
||||||
@ -1592,7 +1814,7 @@ msgid "Opponent:"
|
|||||||
msgstr "Opposant⋅e :"
|
msgstr "Opposant⋅e :"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:34
|
#: participation/templates/participation/passage_detail.html:34
|
||||||
msgid "Reporter:"
|
msgid "reviewer:"
|
||||||
msgstr "Rapporteur⋅rice :"
|
msgstr "Rapporteur⋅rice :"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:37
|
#: participation/templates/participation/passage_detail.html:37
|
||||||
@ -1644,11 +1866,11 @@ msgid "Average points for the opponent oral"
|
|||||||
msgstr "Moyenne de l'oral de l'équipe opposante"
|
msgstr "Moyenne de l'oral de l'équipe opposante"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:101
|
#: participation/templates/participation/passage_detail.html:101
|
||||||
msgid "Average points for the reporter writing"
|
msgid "Average points for the reviewer writing"
|
||||||
msgstr "Moyenne de l'écrit de l'équipe rapportrice"
|
msgstr "Moyenne de l'écrit de l'équipe rapportrice"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:107
|
#: participation/templates/participation/passage_detail.html:107
|
||||||
msgid "Average points for the reporter oral"
|
msgid "Average points for the reviewer oral"
|
||||||
msgstr "Moyenne de l'oral de l'équipe rapportrice"
|
msgstr "Moyenne de l'oral de l'équipe rapportrice"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:117
|
#: participation/templates/participation/passage_detail.html:117
|
||||||
@ -1660,7 +1882,7 @@ msgid "Opponent points"
|
|||||||
msgstr "Points de l'équipe opposante"
|
msgstr "Points de l'équipe opposante"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:129
|
#: participation/templates/participation/passage_detail.html:129
|
||||||
msgid "Reporter points"
|
msgid "reviewer points"
|
||||||
msgstr "Points de l'équipe rapportrice"
|
msgstr "Points de l'équipe rapportrice"
|
||||||
|
|
||||||
#: participation/templates/participation/passage_detail.html:139
|
#: participation/templates/participation/passage_detail.html:139
|
||||||
|
@ -51,7 +51,7 @@ class PassageInline(admin.TabularInline):
|
|||||||
model = Passage
|
model = Passage
|
||||||
extra = 0
|
extra = 0
|
||||||
ordering = ('position',)
|
ordering = ('position',)
|
||||||
autocomplete_fields = ('defender', 'opponent', 'reporter',)
|
autocomplete_fields = ('defender', 'opponent', 'reviewer',)
|
||||||
show_change_link = True
|
show_change_link = True
|
||||||
|
|
||||||
|
|
||||||
@ -113,12 +113,12 @@ class PoolAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(Passage)
|
@admin.register(Passage)
|
||||||
class PassageAdmin(admin.ModelAdmin):
|
class PassageAdmin(admin.ModelAdmin):
|
||||||
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reporter_trigram',
|
list_display = ('__str__', 'defender_trigram', 'solution_number', 'opponent_trigram', 'reviewer_trigram',
|
||||||
'pool_abbr', 'position', 'tournament')
|
'pool_abbr', 'position', 'tournament')
|
||||||
list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',)
|
list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',)
|
||||||
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
|
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
|
||||||
ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',)
|
ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',)
|
||||||
autocomplete_fields = ('pool', 'defender', 'opponent', 'reporter',)
|
autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer',)
|
||||||
inlines = (NoteInline,)
|
inlines = (NoteInline,)
|
||||||
|
|
||||||
@admin.display(description=_("defender"), ordering='defender__team__trigram')
|
@admin.display(description=_("defender"), ordering='defender__team__trigram')
|
||||||
@ -129,9 +129,9 @@ class PassageAdmin(admin.ModelAdmin):
|
|||||||
def opponent_trigram(self, record: Passage):
|
def opponent_trigram(self, record: Passage):
|
||||||
return record.opponent.team.trigram
|
return record.opponent.team.trigram
|
||||||
|
|
||||||
@admin.display(description=_("reporter"), ordering='reporter__team__trigram')
|
@admin.display(description=_("reviewer"), ordering='reviewer__team__trigram')
|
||||||
def reporter_trigram(self, record: Passage):
|
def reviewer_trigram(self, record: Passage):
|
||||||
return record.reporter.team.trigram
|
return record.reviewer.team.trigram
|
||||||
|
|
||||||
@admin.display(description=_("pool"), ordering='pool__letter')
|
@admin.display(description=_("pool"), ordering='pool__letter')
|
||||||
def pool_abbr(self, record):
|
def pool_abbr(self, record):
|
||||||
@ -145,10 +145,10 @@ class PassageAdmin(admin.ModelAdmin):
|
|||||||
@admin.register(Note)
|
@admin.register(Note)
|
||||||
class NoteAdmin(admin.ModelAdmin):
|
class NoteAdmin(admin.ModelAdmin):
|
||||||
list_display = ('passage', 'pool', 'jury', 'defender_writing', 'defender_oral',
|
list_display = ('passage', 'pool', 'jury', 'defender_writing', 'defender_oral',
|
||||||
'opponent_writing', 'opponent_oral', 'reporter_writing', 'reporter_oral',)
|
'opponent_writing', 'opponent_oral', 'reviewer_writing', 'reviewer_oral',)
|
||||||
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
|
list_filter = ('passage__pool__letter', 'passage__solution_number', 'jury',
|
||||||
'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
|
'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
|
||||||
'reporter_writing', 'reporter_oral')
|
'reviewer_writing', 'reviewer_oral')
|
||||||
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',)
|
search_fields = ('jury__user__last_name', 'jury__user__first_name', 'passage__defender__team__trigram',)
|
||||||
autocomplete_fields = ('jury', 'passage',)
|
autocomplete_fields = ('jury', 'passage',)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class NoteViewSet(ModelViewSet):
|
|||||||
serializer_class = NoteSerializer
|
serializer_class = NoteSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['jury', 'passage', 'defender_writing', 'defender_oral', 'opponent_writing',
|
filterset_fields = ['jury', 'passage', 'defender_writing', 'defender_oral', 'opponent_writing',
|
||||||
'opponent_oral', 'reporter_writing', 'reporter_oral', ]
|
'opponent_oral', 'reviewer_writing', 'reviewer_oral', ]
|
||||||
|
|
||||||
|
|
||||||
class ParticipationViewSet(ModelViewSet):
|
class ParticipationViewSet(ModelViewSet):
|
||||||
@ -27,7 +27,7 @@ class PassageViewSet(ModelViewSet):
|
|||||||
queryset = Passage.objects.all()
|
queryset = Passage.objects.all()
|
||||||
serializer_class = PassageSerializer
|
serializer_class = PassageSerializer
|
||||||
filter_backends = [DjangoFilterBackend]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['pool', 'solution_number', 'defender', 'opponent', 'reporter', 'pool_tournament', ]
|
filterset_fields = ['pool', 'solution_number', 'defender', 'opponent', 'reviewer', 'pool_tournament', ]
|
||||||
|
|
||||||
|
|
||||||
class PoolViewSet(ModelViewSet):
|
class PoolViewSet(ModelViewSet):
|
||||||
|
@ -344,9 +344,9 @@ class UploadNotesForm(forms.Form):
|
|||||||
class PassageForm(forms.ModelForm):
|
class PassageForm(forms.ModelForm):
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super().clean()
|
cleaned_data = super().clean()
|
||||||
if "defender" in cleaned_data and "opponent" in cleaned_data and "reporter" in cleaned_data \
|
if "defender" in cleaned_data and "opponent" in cleaned_data and "reviewer" in cleaned_data \
|
||||||
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reporter"]}) < 3:
|
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reviewer"]}) < 3:
|
||||||
self.add_error(None, _("The defender, the opponent and the reporter must be different."))
|
self.add_error(None, _("The defender, the opponent and the reviewer must be different."))
|
||||||
if "defender" in self.cleaned_data and "solution_number" in self.cleaned_data \
|
if "defender" in self.cleaned_data and "solution_number" in self.cleaned_data \
|
||||||
and not Solution.objects.filter(participation=cleaned_data["defender"],
|
and not Solution.objects.filter(participation=cleaned_data["defender"],
|
||||||
problem=cleaned_data["solution_number"]).exists():
|
problem=cleaned_data["solution_number"]).exists():
|
||||||
@ -355,7 +355,7 @@ class PassageForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Passage
|
model = Passage
|
||||||
fields = ('position', 'solution_number', 'defender', 'opponent', 'reporter', 'defender_penalties',)
|
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'defender_penalties',)
|
||||||
|
|
||||||
|
|
||||||
class SynthesisForm(forms.ModelForm):
|
class SynthesisForm(forms.ModelForm):
|
||||||
@ -386,4 +386,4 @@ class NoteForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Note
|
model = Note
|
||||||
fields = ('defender_writing', 'defender_oral', 'opponent_writing',
|
fields = ('defender_writing', 'defender_oral', 'opponent_writing',
|
||||||
'opponent_oral', 'reporter_writing', 'reporter_oral', )
|
'opponent_oral', 'reviewer_writing', 'reviewer_oral', )
|
||||||
|
@ -53,23 +53,23 @@ class Command(BaseCommand):
|
|||||||
pool1 = tournament.pools.filter(round=1, participations=team2).first()
|
pool1 = tournament.pools.filter(round=1, participations=team2).first()
|
||||||
defender_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, defender=team2)
|
defender_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, defender=team2)
|
||||||
opponent_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, opponent=team2)
|
opponent_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, opponent=team2)
|
||||||
reporter_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reporter=team2)
|
reviewer_passage_1 = Passage.objects.get(pool__tournament=tournament, pool__round=1, reviewer=team2)
|
||||||
pool2 = tournament.pools.filter(round=2, participations=team2).first()
|
pool2 = tournament.pools.filter(round=2, participations=team2).first()
|
||||||
defender_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, defender=team2)
|
defender_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, defender=team2)
|
||||||
opponent_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, opponent=team2)
|
opponent_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, opponent=team2)
|
||||||
reporter_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reporter=team2)
|
reviewer_passage_2 = Passage.objects.get(pool__tournament=tournament, pool__round=2, reviewer=team2)
|
||||||
|
|
||||||
line.append(team2.team.trigram)
|
line.append(team2.team.trigram)
|
||||||
line.append(str(pool1.jury_president or ""))
|
line.append(str(pool1.jury_president or ""))
|
||||||
line.append(f"Pb. {defender_passage_1.solution_number}")
|
line.append(f"Pb. {defender_passage_1.solution_number}")
|
||||||
line.extend([defender_passage_1.average_defender_writing, defender_passage_1.average_defender_oral,
|
line.extend([defender_passage_1.average_defender_writing, defender_passage_1.average_defender_oral,
|
||||||
opponent_passage_1.average_opponent_writing, opponent_passage_1.average_opponent_oral,
|
opponent_passage_1.average_opponent_writing, opponent_passage_1.average_opponent_oral,
|
||||||
reporter_passage_1.average_reporter_writing, reporter_passage_1.average_reporter_oral])
|
reviewer_passage_1.average_reviewer_writing, reviewer_passage_1.average_reviewer_oral])
|
||||||
line.append(str(pool2.jury_president or ""))
|
line.append(str(pool2.jury_president or ""))
|
||||||
line.append(f"Pb. {defender_passage_2.solution_number}")
|
line.append(f"Pb. {defender_passage_2.solution_number}")
|
||||||
line.extend([defender_passage_2.average_defender_writing, defender_passage_2.average_defender_oral,
|
line.extend([defender_passage_2.average_defender_writing, defender_passage_2.average_defender_oral,
|
||||||
opponent_passage_2.average_opponent_writing, opponent_passage_2.average_opponent_oral,
|
opponent_passage_2.average_opponent_writing, opponent_passage_2.average_opponent_oral,
|
||||||
reporter_passage_2.average_reporter_writing, reporter_passage_2.average_reporter_oral])
|
reviewer_passage_2.average_reviewer_writing, reviewer_passage_2.average_reviewer_oral])
|
||||||
line.extend([score2, f"{score1:.1f} ({team1.team.trigram})",
|
line.extend([score2, f"{score1:.1f} ({team1.team.trigram})",
|
||||||
f"{score3:.1f} ({team3.team.trigram})"])
|
f"{score3:.1f} ({team3.team.trigram})"])
|
||||||
|
|
||||||
|
91
participation/migrations/0018_rename_reporter_to_reviewer.py
Normal file
91
participation/migrations/0018_rename_reporter_to_reviewer.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-07-05 08:53
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
(
|
||||||
|
"participation",
|
||||||
|
"0017_alter_passage_solution_number_alter_pool_round_and_more",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="note",
|
||||||
|
old_name="reporter_oral",
|
||||||
|
new_name="reviewer_oral",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="note",
|
||||||
|
old_name="reporter_writing",
|
||||||
|
new_name="reviewer_writing",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="passage",
|
||||||
|
old_name="reporter",
|
||||||
|
new_name="reviewer",
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="note",
|
||||||
|
name="reviewer_oral",
|
||||||
|
field=models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, 0),
|
||||||
|
(1, 1),
|
||||||
|
(2, 2),
|
||||||
|
(3, 3),
|
||||||
|
(4, 4),
|
||||||
|
(5, 5),
|
||||||
|
(6, 6),
|
||||||
|
(7, 7),
|
||||||
|
(8, 8),
|
||||||
|
(9, 9),
|
||||||
|
(10, 10),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
verbose_name="reviewer oral note",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="note",
|
||||||
|
name="reviewer_writing",
|
||||||
|
field=models.PositiveSmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, 0),
|
||||||
|
(1, 1),
|
||||||
|
(2, 2),
|
||||||
|
(3, 3),
|
||||||
|
(4, 4),
|
||||||
|
(5, 5),
|
||||||
|
(6, 6),
|
||||||
|
(7, 7),
|
||||||
|
(8, 8),
|
||||||
|
(9, 9),
|
||||||
|
(10, 10),
|
||||||
|
],
|
||||||
|
default=0,
|
||||||
|
verbose_name="reviewer writing note",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="passage",
|
||||||
|
name="reviewer",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
|
related_name="+",
|
||||||
|
to="participation.participation",
|
||||||
|
verbose_name="reviewer",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="synthesis",
|
||||||
|
name="type",
|
||||||
|
field=models.PositiveSmallIntegerField(
|
||||||
|
choices=[(1, "opponent"), (2, "reviewer")]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -858,7 +858,7 @@ class Participation(models.Model):
|
|||||||
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
|
elif timezone.now() <= tournament.syntheses_first_phase_limit + timedelta(hours=2):
|
||||||
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self)
|
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, defender=self)
|
||||||
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self)
|
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, opponent=self)
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reporter=self)
|
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=1, reviewer=self)
|
||||||
|
|
||||||
defender_text = _("<p>The solutions draw is ended. You can check the result on "
|
defender_text = _("<p>The solutions draw is ended. You can check the result on "
|
||||||
"<a href='{draw_url}'>this page</a>.</p>"
|
"<a href='{draw_url}'>this page</a>.</p>"
|
||||||
@ -878,21 +878,21 @@ class Participation(models.Model):
|
|||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}. "
|
"<a href='{solution_url}'>problem {problem}. "
|
||||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reporter_passage.defended_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=reporter_passage.solution_number, passage_url=passage_url)
|
problem=reviewer_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
||||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex", "odt", "docx"])
|
for ext in ["pdf", "tex", "odt", "docx"])
|
||||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
|
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("First round"),
|
'title': _("First round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
@ -902,7 +902,7 @@ class Participation(models.Model):
|
|||||||
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
|
elif timezone.now() <= tournament.syntheses_second_phase_limit + timedelta(hours=2):
|
||||||
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self)
|
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, defender=self)
|
||||||
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self)
|
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, opponent=self)
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reporter=self)
|
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=2, reviewer=self)
|
||||||
|
|
||||||
defender_text = _("<p>For the second round, you will defend "
|
defender_text = _("<p>For the second round, you will defend "
|
||||||
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
||||||
@ -920,21 +920,21 @@ class Participation(models.Model):
|
|||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}. "
|
"<a href='{solution_url}'>problem {problem}. "
|
||||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reporter_passage.defended_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=reporter_passage.solution_number, passage_url=passage_url)
|
problem=reviewer_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
||||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex", "odt", "docx"])
|
for ext in ["pdf", "tex", "odt", "docx"])
|
||||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
|
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("Second round"),
|
'title': _("Second round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
@ -945,7 +945,7 @@ class Participation(models.Model):
|
|||||||
and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2):
|
and timezone.now() <= tournament.syntheses_third_phase_limit + timedelta(hours=2):
|
||||||
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self)
|
defender_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, defender=self)
|
||||||
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self)
|
opponent_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, opponent=self)
|
||||||
reporter_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reporter=self)
|
reviewer_passage = Passage.objects.get(pool__tournament=self.tournament, pool__round=3, reviewer=self)
|
||||||
|
|
||||||
defender_text = _("<p>For the third round, you will defend "
|
defender_text = _("<p>For the third round, you will defend "
|
||||||
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
||||||
@ -963,21 +963,21 @@ class Participation(models.Model):
|
|||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=opponent_passage.solution_number, passage_url=passage_url)
|
problem=opponent_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
reporter_text = _("<p>You will report the solution of the team {reporter} on the "
|
reviewer_text = _("<p>You will report the solution of the team {reviewer} on the "
|
||||||
"<a href='{solution_url}'>problem {problem}. "
|
"<a href='{solution_url}'>problem {problem}. "
|
||||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||||
solution_url = reporter_passage.defended_solution.file.url
|
solution_url = reviewer_passage.defended_solution.file.url
|
||||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||||
solution_url=solution_url,
|
solution_url=solution_url,
|
||||||
problem=reporter_passage.solution_number, passage_url=passage_url)
|
problem=reviewer_passage.solution_number, passage_url=passage_url)
|
||||||
|
|
||||||
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
syntheses_template_begin = f"{settings.STATIC_URL}Fiche_synthèse."
|
||||||
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
syntheses_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||||
for ext in ["pdf", "tex", "odt", "docx"])
|
for ext in ["pdf", "tex", "odt", "docx"])
|
||||||
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
|
||||||
|
|
||||||
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
|
content = defender_content + opponent_content + reviewer_content + syntheses_templates_content
|
||||||
informations.append({
|
informations.append({
|
||||||
'title': _("Second round"),
|
'title': _("Second round"),
|
||||||
'type': "info",
|
'type': "info",
|
||||||
@ -1132,7 +1132,7 @@ class Pool(models.Model):
|
|||||||
for passage in passages), start=["Problème", ""]),
|
for passage in passages), start=["Problème", ""]),
|
||||||
sum(([f"Défenseur⋅se ({passage.defender.team.trigram})", "",
|
sum(([f"Défenseur⋅se ({passage.defender.team.trigram})", "",
|
||||||
f"Opposant⋅e ({passage.opponent.team.trigram})", "",
|
f"Opposant⋅e ({passage.opponent.team.trigram})", "",
|
||||||
f"Rapporteur⋅rice ({passage.reporter.team.trigram})", ""]
|
f"Rapporteur⋅rice ({passage.reviewer.team.trigram})", ""]
|
||||||
for passage in passages), start=["Rôle", ""]),
|
for passage in passages), start=["Rôle", ""]),
|
||||||
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
|
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
|
||||||
for _passage in passages), start=["Juré⋅e", ""]),
|
for _passage in passages), start=["Juré⋅e", ""]),
|
||||||
@ -1144,7 +1144,7 @@ class Pool(models.Model):
|
|||||||
for passage in passages:
|
for passage in passages:
|
||||||
note = passage.notes.filter(jury=jury).first()
|
note = passage.notes.filter(jury=jury).first()
|
||||||
line.extend([note.defender_writing, note.defender_oral, note.opponent_writing, note.opponent_oral,
|
line.extend([note.defender_writing, note.defender_oral, note.opponent_writing, note.opponent_oral,
|
||||||
note.reporter_writing, note.reporter_oral])
|
note.reviewer_writing, note.reviewer_oral])
|
||||||
notes.append(line)
|
notes.append(line)
|
||||||
notes.append([]) # Add empty line to ensure pretty design
|
notes.append([]) # Add empty line to ensure pretty design
|
||||||
|
|
||||||
@ -1204,18 +1204,18 @@ class Pool(models.Model):
|
|||||||
opponent_row = 5 + opponent_passage.pool.juries.count()
|
opponent_row = 5 + opponent_passage.pool.juries.count()
|
||||||
opponent_col = opponent_passage.position - 1
|
opponent_col = opponent_passage.position - 1
|
||||||
|
|
||||||
reporter_passage = Passage.objects.get(reporter=participation,
|
reviewer_passage = Passage.objects.get(reviewer=participation,
|
||||||
pool__tournament=self.tournament, pool__round=self.round)
|
pool__tournament=self.tournament, pool__round=self.round)
|
||||||
reporter_row = 5 + reporter_passage.pool.juries.count()
|
reviewer_row = 5 + reviewer_passage.pool.juries.count()
|
||||||
reporter_col = reporter_passage.position - 1
|
reviewer_col = reviewer_passage.position - 1
|
||||||
|
|
||||||
formula = "="
|
formula = "="
|
||||||
formula += (f"'Poule {defender_passage.pool.short_name}'"
|
formula += (f"'Poule {defender_passage.pool.short_name}'"
|
||||||
f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
|
f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
|
||||||
formula += (f" + 'Poule {opponent_passage.pool.short_name}'"
|
formula += (f" + 'Poule {opponent_passage.pool.short_name}'"
|
||||||
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
|
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
|
||||||
formula += (f" + 'Poule {reporter_passage.pool.short_name}'"
|
formula += (f" + 'Poule {reviewer_passage.pool.short_name}'"
|
||||||
f"!{getcol(min_column + reporter_col * passage_width + 4)}{reporter_row + 3}") # Reporter
|
f"!{getcol(min_column + reviewer_col * passage_width + 4)}{reviewer_row + 3}") # reviewer
|
||||||
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
|
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
|
||||||
f"='Poule {defender_passage.pool.short_name}'"
|
f"='Poule {defender_passage.pool.short_name}'"
|
||||||
f"!${getcol(3 + defender_col * passage_width)}$1",
|
f"!${getcol(3 + defender_col * passage_width)}$1",
|
||||||
@ -1553,10 +1553,10 @@ class Passage(models.Model):
|
|||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter = models.ForeignKey(
|
reviewer = models.ForeignKey(
|
||||||
Participation,
|
Participation,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
verbose_name=_("reporter"),
|
verbose_name=_("reviewer"),
|
||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1603,16 +1603,16 @@ class Passage(models.Model):
|
|||||||
return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral
|
return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter_writing(self) -> float:
|
def average_reviewer_writing(self) -> float:
|
||||||
return self.avg(note.reporter_writing for note in self.notes.all())
|
return self.avg(note.reviewer_writing for note in self.notes.all())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter_oral(self) -> float:
|
def average_reviewer_oral(self) -> float:
|
||||||
return self.avg(note.reporter_oral for note in self.notes.all())
|
return self.avg(note.reviewer_oral for note in self.notes.all())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def average_reporter(self) -> float:
|
def average_reviewer(self) -> float:
|
||||||
return 0.9 * self.average_reporter_writing + self.average_reporter_oral
|
return 0.9 * self.average_reviewer_writing + self.average_reviewer_oral
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def averages(self):
|
def averages(self):
|
||||||
@ -1620,12 +1620,12 @@ class Passage(models.Model):
|
|||||||
yield self.average_defender_oral
|
yield self.average_defender_oral
|
||||||
yield self.average_opponent_writing
|
yield self.average_opponent_writing
|
||||||
yield self.average_opponent_oral
|
yield self.average_opponent_oral
|
||||||
yield self.average_reporter_writing
|
yield self.average_reviewer_writing
|
||||||
yield self.average_reporter_oral
|
yield self.average_reviewer_oral
|
||||||
|
|
||||||
def average(self, participation):
|
def average(self, participation):
|
||||||
return self.average_defender if participation == self.defender else self.average_opponent \
|
return self.average_defender if participation == self.defender else self.average_opponent \
|
||||||
if participation == self.opponent else self.average_reporter if participation == self.reporter else 0
|
if participation == self.opponent else self.average_reviewer if participation == self.reviewer else 0
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse_lazy("participation:passage_detail", args=(self.pk,))
|
return reverse_lazy("participation:passage_detail", args=(self.pk,))
|
||||||
@ -1637,9 +1637,9 @@ class Passage(models.Model):
|
|||||||
if self.opponent not in self.pool.participations.all():
|
if self.opponent not in self.pool.participations.all():
|
||||||
raise ValidationError(_("Team {trigram} is not registered in the pool.")
|
raise ValidationError(_("Team {trigram} is not registered in the pool.")
|
||||||
.format(trigram=self.opponent.team.trigram))
|
.format(trigram=self.opponent.team.trigram))
|
||||||
if self.reporter not in self.pool.participations.all():
|
if self.reviewer not in self.pool.participations.all():
|
||||||
raise ValidationError(_("Team {trigram} is not registered in the pool.")
|
raise ValidationError(_("Team {trigram} is not registered in the pool.")
|
||||||
.format(trigram=self.reporter.team.trigram))
|
.format(trigram=self.reviewer.team.trigram))
|
||||||
return super().clean()
|
return super().clean()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -1747,7 +1747,7 @@ class Synthesis(models.Model):
|
|||||||
type = models.PositiveSmallIntegerField(
|
type = models.PositiveSmallIntegerField(
|
||||||
choices=[
|
choices=[
|
||||||
(1, _("opponent"), ),
|
(1, _("opponent"), ),
|
||||||
(2, _("reporter"), ),
|
(2, _("reviewer"), ),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1811,14 +1811,14 @@ class Note(models.Model):
|
|||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter_writing = models.PositiveSmallIntegerField(
|
reviewer_writing = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("reporter writing note"),
|
verbose_name=_("reviewer writing note"),
|
||||||
choices=[(i, i) for i in range(0, 11)],
|
choices=[(i, i) for i in range(0, 11)],
|
||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
reporter_oral = models.PositiveSmallIntegerField(
|
reviewer_oral = models.PositiveSmallIntegerField(
|
||||||
verbose_name=_("reporter oral note"),
|
verbose_name=_("reviewer oral note"),
|
||||||
choices=[(i, i) for i in range(0, 11)],
|
choices=[(i, i) for i in range(0, 11)],
|
||||||
default=0,
|
default=0,
|
||||||
)
|
)
|
||||||
@ -1828,17 +1828,17 @@ class Note(models.Model):
|
|||||||
yield self.defender_oral
|
yield self.defender_oral
|
||||||
yield self.opponent_writing
|
yield self.opponent_writing
|
||||||
yield self.opponent_oral
|
yield self.opponent_oral
|
||||||
yield self.reporter_writing
|
yield self.reviewer_writing
|
||||||
yield self.reporter_oral
|
yield self.reviewer_oral
|
||||||
|
|
||||||
def set_all(self, defender_writing: int, defender_oral: int, opponent_writing: int, opponent_oral: int,
|
def set_all(self, defender_writing: int, defender_oral: int, opponent_writing: int, opponent_oral: int,
|
||||||
reporter_writing: int, reporter_oral: int):
|
reviewer_writing: int, reviewer_oral: int):
|
||||||
self.defender_writing = defender_writing
|
self.defender_writing = defender_writing
|
||||||
self.defender_oral = defender_oral
|
self.defender_oral = defender_oral
|
||||||
self.opponent_writing = opponent_writing
|
self.opponent_writing = opponent_writing
|
||||||
self.opponent_oral = opponent_oral
|
self.opponent_oral = opponent_oral
|
||||||
self.reporter_writing = reporter_writing
|
self.reviewer_writing = reviewer_writing
|
||||||
self.reporter_oral = reporter_oral
|
self.reviewer_oral = reviewer_oral
|
||||||
|
|
||||||
def update_spreadsheet(self):
|
def update_spreadsheet(self):
|
||||||
if not self.has_any_note():
|
if not self.has_any_note():
|
||||||
|
@ -118,7 +118,7 @@ class PassageTable(tables.Table):
|
|||||||
def render_opponent(self, value):
|
def render_opponent(self, value):
|
||||||
return value.team.trigram
|
return value.team.trigram
|
||||||
|
|
||||||
def render_reporter(self, value):
|
def render_reviewer(self, value):
|
||||||
return value.team.trigram
|
return value.team.trigram
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -126,7 +126,7 @@ class PassageTable(tables.Table):
|
|||||||
'class': 'table table-condensed table-striped text-center',
|
'class': 'table table-condensed table-striped text-center',
|
||||||
}
|
}
|
||||||
model = Passage
|
model = Passage
|
||||||
fields = ('defender', 'opponent', 'reporter', 'solution_number', )
|
fields = ('defender', 'opponent', 'reviewer', 'solution_number', )
|
||||||
|
|
||||||
|
|
||||||
class NoteTable(tables.Table):
|
class NoteTable(tables.Table):
|
||||||
@ -155,4 +155,4 @@ class NoteTable(tables.Table):
|
|||||||
}
|
}
|
||||||
model = Note
|
model = Note
|
||||||
fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
|
fields = ('jury', 'defender_writing', 'defender_oral', 'opponent_writing', 'opponent_oral',
|
||||||
'reporter_writing', 'reporter_oral', 'update',)
|
'reviewer_writing', 'reviewer_oral', 'update',)
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
<dt class="col-sm-3">{% trans "Opponent:" %}</dt>
|
<dt class="col-sm-3">{% trans "Opponent:" %}</dt>
|
||||||
<dd class="col-sm-9"><a href="{{ passage.opponent.get_absolute_url }}">{{ passage.opponent.team }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.opponent.get_absolute_url }}">{{ passage.opponent.team }}</a></dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Reporter:" %}</dt>
|
<dt class="col-sm-3">{% trans "reviewer:" %}</dt>
|
||||||
<dd class="col-sm-9"><a href="{{ passage.reporter.get_absolute_url }}">{{ passage.reporter.team }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.reviewer.get_absolute_url }}">{{ passage.reviewer.team }}</a></dd>
|
||||||
|
|
||||||
<dt class="col-sm-3">{% trans "Defended solution:" %}</dt>
|
<dt class="col-sm-3">{% trans "Defended solution:" %}</dt>
|
||||||
<dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd>
|
<dd class="col-sm-9"><a href="{{ passage.defended_solution.file.url }}">{{ passage.defended_solution }}</a></dd>
|
||||||
@ -98,16 +98,16 @@
|
|||||||
<dd class="col-sm-4">{{ passage.average_opponent_oral|floatformat }}/10</dd>
|
<dd class="col-sm-4">{{ passage.average_opponent_oral|floatformat }}/10</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Average points for the reporter writing" %}
|
{% trans "Average points for the reviewer writing" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.reviewer.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">{{ passage.average_reporter_writing|floatformat }}/10</dd>
|
<dd class="col-sm-4">{{ passage.average_reviewer_writing|floatformat }}/10</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Average points for the reporter oral" %}
|
{% trans "Average points for the reviewer oral" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.reviewer.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">{{ passage.average_reporter_oral|floatformat }}/10</dd>
|
<dd class="col-sm-4">{{ passage.average_reviewer_oral|floatformat }}/10</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
@ -126,10 +126,10 @@
|
|||||||
<dd class="col-sm-4">{{ passage.average_opponent|floatformat }}/29</dd>
|
<dd class="col-sm-4">{{ passage.average_opponent|floatformat }}/29</dd>
|
||||||
|
|
||||||
<dt class="col-sm-8">
|
<dt class="col-sm-8">
|
||||||
{% trans "Reporter points" %}
|
{% trans "reviewer points" %}
|
||||||
({{ passage.reporter.team.trigram }}) :
|
({{ passage.reviewer.team.trigram }}) :
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="col-sm-4">{{ passage.average_reporter|floatformat }}/19</dd>
|
<dd class="col-sm-4">{{ passage.average_reviewer|floatformat }}/19</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%RAPPORTEUR.RICE
|
%%%%%%%%%%%%%%%%%%%%%%RAPPORTEUR.RICE
|
||||||
\begin{tabular}{|c|p{24mm}|p{11cm}|c{% for passage in passages.all %}|p{2cm}{% endfor %}|}\hline
|
\begin{tabular}{|c|p{24mm}|p{11cm}|c{% for passage in passages.all %}|p{2cm}{% endfor %}|}\hline
|
||||||
\multicolumn{4}{|l|}{Læ {\bf Rapporteur\textperiodcentered{}rice} \normalsize \'evalue le d\'ebat entre læ D\'efenseur\textperiodcentered{}se et l'Opposant\textperiodcentered{}e.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.reporter.team.trigram }} {% endfor %}\\ \hline \hline
|
\multicolumn{4}{|l|}{Læ {\bf Rapporteur\textperiodcentered{}rice} \normalsize \'evalue le d\'ebat entre læ D\'efenseur\textperiodcentered{}se et l'Opposant\textperiodcentered{}e.} {% for passage in passages.all %}& P.{{ forloop.counter }} - {{ passage.reviewer.team.trigram }} {% endfor %}\\ \hline \hline
|
||||||
|
|
||||||
%ECRIT
|
%ECRIT
|
||||||
\multirow{4}{3mm}{\centering\bf\'E\\ C\\ R\\ I\\ T} &\multirow{3}{20mm}{Partie scientifique} & Recul et esprit critique par rapport à la solution proposée & [0,3] {{ esp|safe }}\\ \cline{3-{{ passages.count|add:4 }}}
|
\multirow{4}{3mm}{\centering\bf\'E\\ C\\ R\\ I\\ T} &\multirow{3}{20mm}{Partie scientifique} & Recul et esprit critique par rapport à la solution proposée & [0,3] {{ esp|safe }}\\ \cline{3-{{ passages.count|add:4 }}}
|
||||||
|
@ -56,7 +56,7 @@ Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.partici
|
|||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
||||||
{% endfor %} & \hline
|
{% endfor %} & \hline
|
||||||
\multirow{2}{35mm}{\LARGE Rapporteur\textperiodcentered{}rice} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.reporter.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
\multirow{2}{35mm}{\LARGE Rapporteur\textperiodcentered{}rice} {% for passage in passages.all %}& \multicolumn{2}{c|}{\Large {{ passage.reviewer.team.trigram }}}{% endfor %} \\ \cline{2-{{ passages.count|add:passages.count|add:1 }}}
|
||||||
{% for passage in passages.all %}
|
{% for passage in passages.all %}
|
||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
||||||
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
& \phantom{asd asd} \phantom{asd asd} \centering \normalsize$0\leq x\leq 10$
|
||||||
|
@ -1507,11 +1507,11 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
header_role.addElement(opponent_tc)
|
header_role.addElement(opponent_tc)
|
||||||
header_role.addElement(CoveredTableCell())
|
header_role.addElement(CoveredTableCell())
|
||||||
|
|
||||||
reporter_tc = TableCell(valuetype="string",
|
reviewer_tc = TableCell(valuetype="string",
|
||||||
stylename=title_style_right)
|
stylename=title_style_right)
|
||||||
reporter_tc.addElement(P(text="Rapporteur⋅rice"))
|
reviewer_tc.addElement(P(text="Rapporteur⋅rice"))
|
||||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
reviewer_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
header_role.addElement(reporter_tc)
|
header_role.addElement(reviewer_tc)
|
||||||
header_role.addElement(CoveredTableCell())
|
header_role.addElement(CoveredTableCell())
|
||||||
|
|
||||||
# Add maximum notes on the third line
|
# Add maximum notes on the third line
|
||||||
@ -1540,13 +1540,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
opponent_o_tc.addElement(P(text="Oral (/10)"))
|
opponent_o_tc.addElement(P(text="Oral (/10)"))
|
||||||
header_notes.addElement(opponent_o_tc)
|
header_notes.addElement(opponent_o_tc)
|
||||||
|
|
||||||
reporter_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
reviewer_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||||
reporter_w_tc.addElement(P(text="Écrit (/10)"))
|
reviewer_w_tc.addElement(P(text="Écrit (/10)"))
|
||||||
header_notes.addElement(reporter_w_tc)
|
header_notes.addElement(reviewer_w_tc)
|
||||||
|
|
||||||
reporter_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
|
reviewer_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
|
||||||
reporter_o_tc.addElement(P(text="Oral (/10)"))
|
reviewer_o_tc.addElement(P(text="Oral (/10)"))
|
||||||
header_notes.addElement(reporter_o_tc)
|
header_notes.addElement(reviewer_o_tc)
|
||||||
|
|
||||||
# Add a notation line for each jury
|
# Add a notation line for each jury
|
||||||
for jury in self.object.juries.all():
|
for jury in self.object.juries.all():
|
||||||
@ -1617,13 +1617,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
opponent_o_tc.addElement(P(text="2"))
|
opponent_o_tc.addElement(P(text="2"))
|
||||||
coeff_row.addElement(opponent_o_tc)
|
coeff_row.addElement(opponent_o_tc)
|
||||||
|
|
||||||
reporter_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
|
reviewer_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
|
||||||
reporter_w_tc.addElement(P(text="1"))
|
reviewer_w_tc.addElement(P(text="1"))
|
||||||
coeff_row.addElement(reporter_w_tc)
|
coeff_row.addElement(reviewer_w_tc)
|
||||||
|
|
||||||
reporter_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
|
reviewer_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
|
||||||
reporter_o_tc.addElement(P(text="1"))
|
reviewer_o_tc.addElement(P(text="1"))
|
||||||
coeff_row.addElement(reporter_o_tc)
|
coeff_row.addElement(reviewer_o_tc)
|
||||||
|
|
||||||
# Add the subtotal on the next line
|
# Add the subtotal on the next line
|
||||||
subtotal_row = TableRow()
|
subtotal_row = TableRow()
|
||||||
@ -1656,12 +1656,12 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
|
|
||||||
rep_w_col = getcol(min_column + passage_width * i + 4)
|
rep_w_col = getcol(min_column + passage_width * i + 4)
|
||||||
rep_o_col = getcol(min_column + passage_width * i + 5)
|
rep_o_col = getcol(min_column + passage_width * i + 5)
|
||||||
reporter_tc = TableCell(valuetype="float", value=passage.average_reporter, stylename=style_botright)
|
reviewer_tc = TableCell(valuetype="float", value=passage.average_reviewer, stylename=style_botright)
|
||||||
reporter_tc.addElement(P(text=str(passage.average_reporter)))
|
reviewer_tc.addElement(P(text=str(passage.average_reviewer)))
|
||||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
reviewer_tc.setAttribute('numbercolumnsspanned', "2")
|
||||||
reporter_tc.setAttribute("formula", f"of:=[.{rep_w_col}{max_row + 1}] * [.{rep_w_col}{max_row + 2}]"
|
reviewer_tc.setAttribute("formula", f"of:=[.{rep_w_col}{max_row + 1}] * [.{rep_w_col}{max_row + 2}]"
|
||||||
f" + [.{rep_o_col}{max_row + 1}] * [.{rep_o_col}{max_row + 2}]")
|
f" + [.{rep_o_col}{max_row + 1}] * [.{rep_o_col}{max_row + 2}]")
|
||||||
subtotal_row.addElement(reporter_tc)
|
subtotal_row.addElement(reviewer_tc)
|
||||||
subtotal_row.addElement(CoveredTableCell())
|
subtotal_row.addElement(CoveredTableCell())
|
||||||
|
|
||||||
table.addElement(TableRow())
|
table.addElement(TableRow())
|
||||||
@ -1713,7 +1713,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
|
|
||||||
defender_pos = passage.position - 1
|
defender_pos = passage.position - 1
|
||||||
opponent_pos = self.object.passages.get(opponent=passage.defender).position - 1
|
opponent_pos = self.object.passages.get(opponent=passage.defender).position - 1
|
||||||
reporter_pos = self.object.passages.get(reporter=passage.defender).position - 1
|
reviewer_pos = self.object.passages.get(reviewer=passage.defender).position - 1
|
||||||
|
|
||||||
score_tc = TableCell(valuetype="float", value=self.object.average(passage.defender),
|
score_tc = TableCell(valuetype="float", value=self.object.average(passage.defender),
|
||||||
stylename=style_bot if passage.position == pool_size else style)
|
stylename=style_bot if passage.position == pool_size else style)
|
||||||
@ -1721,7 +1721,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
|||||||
formula = "of:="
|
formula = "of:="
|
||||||
formula += getcol(min_column + defender_pos * passage_width) + str(max_row + 3) # Defender
|
formula += getcol(min_column + defender_pos * passage_width) + str(max_row + 3) # Defender
|
||||||
formula += " + " + getcol(min_column + opponent_pos * passage_width + 2) + str(max_row + 3) # Opponent
|
formula += " + " + getcol(min_column + opponent_pos * passage_width + 2) + str(max_row + 3) # Opponent
|
||||||
formula += " + " + getcol(min_column + reporter_pos * passage_width + 4) + str(max_row + 3) # Reporter
|
formula += " + " + getcol(min_column + reviewer_pos * passage_width + 4) + str(max_row + 3) # reviewer
|
||||||
score_tc.setAttribute("formula", formula)
|
score_tc.setAttribute("formula", formula)
|
||||||
team_row.addElement(score_tc)
|
team_row.addElement(score_tc)
|
||||||
|
|
||||||
@ -1931,7 +1931,7 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
|||||||
or reg in passage.pool.juries.all()
|
or reg in passage.pool.juries.all()
|
||||||
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
||||||
or reg.participates and reg.team \
|
or reg.participates and reg.team \
|
||||||
and reg.team.participation in [passage.defender, passage.opponent, passage.reporter]:
|
and reg.team.participation in [passage.defender, passage.opponent, passage.reviewer]:
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
return self.handle_no_permission()
|
return self.handle_no_permission()
|
||||||
|
|
||||||
@ -1956,8 +1956,8 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
|||||||
context['notes'].columns['defender_oral'].column.verbose_name += f" ({passage.defender.team.trigram})"
|
context['notes'].columns['defender_oral'].column.verbose_name += f" ({passage.defender.team.trigram})"
|
||||||
context['notes'].columns['opponent_writing'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
context['notes'].columns['opponent_writing'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
||||||
context['notes'].columns['opponent_oral'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
context['notes'].columns['opponent_oral'].column.verbose_name += f" ({passage.opponent.team.trigram})"
|
||||||
context['notes'].columns['reporter_writing'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
context['notes'].columns['reviewer_writing'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
||||||
context['notes'].columns['reporter_oral'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
context['notes'].columns['reviewer_oral'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@ -1992,7 +1992,7 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
|
|||||||
self.participation = self.request.user.registration.team.participation
|
self.participation = self.request.user.registration.team.participation
|
||||||
self.passage = qs.get()
|
self.passage = qs.get()
|
||||||
|
|
||||||
if self.participation not in [self.passage.opponent, self.passage.reporter]:
|
if self.participation not in [self.passage.opponent, self.passage.reviewer]:
|
||||||
return self.handle_no_permission()
|
return self.handle_no_permission()
|
||||||
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
@ -2050,8 +2050,8 @@ class NoteUpdateView(VolunteerMixin, UpdateView):
|
|||||||
form.fields['defender_oral'].label += f" ({self.object.passage.defender.team.trigram})"
|
form.fields['defender_oral'].label += f" ({self.object.passage.defender.team.trigram})"
|
||||||
form.fields['opponent_writing'].label += f" ({self.object.passage.opponent.team.trigram})"
|
form.fields['opponent_writing'].label += f" ({self.object.passage.opponent.team.trigram})"
|
||||||
form.fields['opponent_oral'].label += f" ({self.object.passage.opponent.team.trigram})"
|
form.fields['opponent_oral'].label += f" ({self.object.passage.opponent.team.trigram})"
|
||||||
form.fields['reporter_writing'].label += f" ({self.object.passage.reporter.team.trigram})"
|
form.fields['reviewer_writing'].label += f" ({self.object.passage.reviewer.team.trigram})"
|
||||||
form.fields['reporter_oral'].label += f" ({self.object.passage.reporter.team.trigram})"
|
form.fields['reviewer_oral'].label += f" ({self.object.passage.reviewer.team.trigram})"
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -839,7 +839,7 @@ class SolutionView(LoginRequiredMixin, View):
|
|||||||
if user.registration.participates:
|
if user.registration.participates:
|
||||||
passage_participant_qs = Passage.objects.filter(Q(defender=user.registration.team.participation)
|
passage_participant_qs = Passage.objects.filter(Q(defender=user.registration.team.participation)
|
||||||
| Q(opponent=user.registration.team.participation)
|
| Q(opponent=user.registration.team.participation)
|
||||||
| Q(reporter=user.registration.team.participation),
|
| Q(reviewer=user.registration.team.participation),
|
||||||
defender=solution.participation,
|
defender=solution.participation,
|
||||||
solution_number=solution.problem)
|
solution_number=solution.problem)
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user