mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-02-17 05:41: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)\
|
||||
.prefetch_related('draw__current_round__current_pool__current_team__participation__team').aget()
|
||||
|
||||
translation.activate(settings.PREFERRED_LANGUAGE_CODE)
|
||||
|
||||
match content['type']:
|
||||
case 'set_language':
|
||||
# Update the translation language
|
||||
@ -233,8 +235,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': 'Tirage au sort du TFJM²',
|
||||
'body': "Le tirage au sort du tournoi de "
|
||||
f"{self.tournament.name} a commencé !"})
|
||||
'body': _("The draw of tournament {tournament} started!")
|
||||
.format(tournament=self.tournament.name)})
|
||||
|
||||
async def draw_start(self, content) -> None:
|
||||
"""
|
||||
@ -403,8 +405,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
await self.channel_layer.group_send(
|
||||
f"team-{dup.participation.team.trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify', 'title': 'Tirage au sort du TFJM²',
|
||||
'body': 'Votre score de dé est identique à celui de une ou plusieurs équipes. '
|
||||
'Veuillez le relancer.'}
|
||||
'body': _("Your dice score is identical to the one of one or multiple teams. "
|
||||
"Please relaunch it.")}
|
||||
)
|
||||
# Alert the tournament
|
||||
await self.channel_layer.group_send(
|
||||
@ -448,7 +450,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# We can add a joker team if there is not already a team in the pool that was in the same pool
|
||||
# in the first round, and such that the number of such jokers is exactly the free space of the current pool.
|
||||
# Exception: if there is one only pool with 5 teams, we exchange the first and the last teams of the pool.
|
||||
if not self.tournament.final:
|
||||
if not self.tournament.final and settings.TFJM_APP == "TFJM":
|
||||
tds_copy = sorted(tds, key=lambda td: (td.passage_index, -td.pool.letter,))
|
||||
jokers = [td for td in tds if td.passage_index == 4]
|
||||
round2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
||||
@ -502,12 +504,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
await self.tournament.draw.current_round.asave()
|
||||
|
||||
# Display dice result in the header of the information alert
|
||||
msg = "Les résultats des dés sont les suivants : "
|
||||
msg += ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
|
||||
msg += ". L'ordre de passage et les compositions des différentes poules sont affiché⋅es sur le côté. "
|
||||
msg += "Les ordres de passage pour le premier tour sont déterminés à partir des scores des dés, "
|
||||
msg += "dans l'ordre croissant. Pour le deuxième tour, les ordres de passage sont déterminés à partir "
|
||||
msg += "des ordres de passage du premier tour."
|
||||
trigrams = ", ".join(f"<strong>{td.participation.team.trigram}</strong> ({td.passage_dice})" for td in tds)
|
||||
msg = _("The dice results are the following: {trigrams}. "
|
||||
"The passage order and the compositions of the different pools are displayed on the side. "
|
||||
"The passage orders for the first round are determined from the dice scores, in increasing order. "
|
||||
"For the second round, the passage orders are determined from the passage orders of the first round.")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -610,8 +611,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a problem
|
||||
await self.channel_layer.group_send(f"team-{tds[0].participation.team.trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to draw a problem!")})
|
||||
|
||||
async def select_problem(self, **kwargs):
|
||||
"""
|
||||
@ -631,7 +632,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
.prefetch_related('team').aget()
|
||||
# Ensure that the user can draws a problem at this time
|
||||
if participation.id != td.participation_id:
|
||||
return await self.alert("This is not your turn.", 'danger')
|
||||
return await self.alert(_("This is not your turn."), 'danger')
|
||||
|
||||
while True:
|
||||
# Choose a random problem
|
||||
@ -702,19 +703,20 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
.prefetch_related('team').aget()
|
||||
# Ensure that the user can accept a problem at this time
|
||||
if participation.id != td.participation_id:
|
||||
return await self.alert("This is not your turn.", 'danger')
|
||||
return await self.alert(_("This is not your turn."), 'danger')
|
||||
|
||||
td.accepted = td.purposed
|
||||
td.purposed = None
|
||||
await td.asave()
|
||||
|
||||
trigram = td.participation.team.trigram
|
||||
msg = f"L'équipe <strong>{trigram}</strong> a accepté le problème <strong>{td.accepted} : " \
|
||||
f"{settings.PROBLEMS[td.accepted - 1]}</strong>. "
|
||||
msg = _("The team <strong>{trigram}</strong> accepted the problem <string>{problem}</strong>: "
|
||||
"{problem_name}. ").format(trigram=trigram, problem=td.accepted,
|
||||
problem_name=settings.PROBLEMS[td.accepted - 1])
|
||||
if pool.size == 5 and await pool.teamdraw_set.filter(accepted=td.accepted).acount() < 2:
|
||||
msg += "Une équipe peut encore l'accepter."
|
||||
msg += _("One team more can accept this problem.")
|
||||
else:
|
||||
msg += "Plus personne ne peut l'accepter."
|
||||
msg += _("No team can accept this problem anymore.")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -749,8 +751,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a problem
|
||||
await self.channel_layer.group_send(f"team-{new_trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to draw a problem!")})
|
||||
else:
|
||||
# Pool is ended
|
||||
await self.end_pool(pool)
|
||||
@ -808,8 +810,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
'problems': [td.accepted async for td in pool.team_draws],
|
||||
})
|
||||
|
||||
msg += f"<br><br>Le tirage de la poule {pool.get_letter_display()}{r.number} est terminé. " \
|
||||
f"Le tableau récapitulatif est en bas."
|
||||
msg += "<br><br>" + _("The draw of the pool {pool} is ended. The summary is below.") \
|
||||
.format(pool=f"{pool.get_letter_display()}{r.number}")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -826,8 +828,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a dice
|
||||
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de lancer le dé !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to launch the dice!")})
|
||||
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
|
||||
@ -843,11 +845,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
"""
|
||||
msg = self.tournament.draw.last_message
|
||||
|
||||
if r.number < settings.NB_ROUNDS and not self.tournament.final:
|
||||
if r.number < settings.NB_ROUNDS and not self.tournament.final and settings.TFJM_APP == "TFJM":
|
||||
# Next round
|
||||
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget()
|
||||
self.tournament.draw.current_round = next_round
|
||||
msg += f"<br><br>Le tirage au sort du tour {r.number} est terminé."
|
||||
msg += "<br><br>" + _("The draw of the round {round} is ended.").format(round=r.number)
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -860,8 +862,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a dice
|
||||
await self.channel_layer.group_send(f"team-{participation.team.trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de lancer le dé !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to launch the dice!")})
|
||||
|
||||
# Reorder dices
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
@ -888,9 +890,9 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
|
||||
'visible': True})
|
||||
elif r.number == 1 and self.tournament.final:
|
||||
elif r.number == 1 and (self.tournament.final or settings.TFJM_APP == "ETEAM"):
|
||||
# For the final tournament, we wait for a manual update between the two rounds.
|
||||
msg += "<br><br>Le tirage au sort du tour 1 est terminé."
|
||||
msg += "<br><br>" + _("The draw of the first round is ended.")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -919,7 +921,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
.prefetch_related('team').aget()
|
||||
# Ensure that the user can reject a problem at this time
|
||||
if participation.id != td.participation_id:
|
||||
return await self.alert("This is not your turn.", 'danger')
|
||||
return await self.alert(_("This is not your turn."), 'danger')
|
||||
|
||||
# Add the problem to the rejected problems list
|
||||
problem = td.purposed
|
||||
@ -933,15 +935,16 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
|
||||
# Update messages
|
||||
trigram = td.participation.team.trigram
|
||||
msg = f"L'équipe <strong>{trigram}</strong> a refusé le problème <strong>{problem} : " \
|
||||
f"{settings.PROBLEMS[problem - 1]}</strong>. "
|
||||
msg = _("The team <strong>{trigram}</strong> refused the problem <strong>{problem}</strong>: "
|
||||
"{problem_name}.").format(trigram=trigram, problem=problem,
|
||||
problem_name=settings.PROBLEMS[problem - 1]) + " "
|
||||
if remaining >= 0:
|
||||
msg += f"Il lui reste {remaining} refus sans pénalité."
|
||||
msg += _("It remains {remaining} refusals without penalty.").format(remaining=remaining)
|
||||
else:
|
||||
if already_refused:
|
||||
msg += "Cela n'ajoute pas de pénalité."
|
||||
msg += _("This problem was already refused by this team.")
|
||||
else:
|
||||
msg += "Cela ajoute une pénalité de 25 % sur le coefficient de l'oral de la défense."
|
||||
msg += _("It adds a 25% penalty on the coefficient of the oral defense.")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
@ -984,8 +987,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a problem
|
||||
await self.channel_layer.group_send(f"team-{new_trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to draw a problem!")})
|
||||
|
||||
@ensure_orga
|
||||
async def export(self, **kwargs):
|
||||
@ -1022,17 +1025,17 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
|
||||
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
||||
self.tournament.draw.current_round = r2
|
||||
msg = "Le tirage au sort pour le tour 2 va commencer. " \
|
||||
"L'ordre de passage est déterminé à partir du classement du premier tour, " \
|
||||
"de sorte à mélanger les équipes entre les deux jours."
|
||||
msg = _("The draw of the round 2 is starting. "
|
||||
"The passage order is determined from the ranking of the first round, "
|
||||
"in order to mix the teams between the two days.")
|
||||
self.tournament.draw.last_message = msg
|
||||
await self.tournament.draw.asave()
|
||||
|
||||
# Send notification to everyone
|
||||
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': 'Tirage au sort du TFJM²',
|
||||
'body': "Le tirage au sort pour le second tour de la finale a commencé !"})
|
||||
'title': _("Draw") + " " + settings.APP_NAME,
|
||||
'body': _("The draw of the second round is starting!")})
|
||||
|
||||
# Set the first pool of the second round as the active pool
|
||||
pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget()
|
||||
@ -1082,8 +1085,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||
# Notify the team that it can draw a problem
|
||||
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.notify',
|
||||
'title': "À votre tour !",
|
||||
'body': "C'est à vous de tirer un nouveau problème !"})
|
||||
'title': _("Your turn!"),
|
||||
'body': _("It's your turn to draw a problem!")})
|
||||
|
||||
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||
{'tid': self.tournament_id, 'type': 'draw.dice_visibility',
|
||||
|
@ -110,58 +110,61 @@ class Draw(models.Model):
|
||||
# Waiting for dices to determine pools and passage order
|
||||
if self.current_round.number == 1:
|
||||
# Specific information for the first round
|
||||
s += """Nous allons commencer le tirage des problèmes.<br>
|
||||
Vous pouvez à tout moment poser toute question si quelque chose
|
||||
n'est pas clair ou ne va pas.<br><br>
|
||||
Nous allons d'abord tirer les poules et l'ordre de passage
|
||||
pour le premier tour avec toutes les équipes puis pour chaque poule,
|
||||
nous tirerons l'ordre de tirage pour le tour et les problèmes.<br><br>"""
|
||||
s += """
|
||||
Les capitaines, vous pouvez désormais toustes lancer un dé 100,
|
||||
en cliquant sur le gros bouton. Les poules et l'ordre de passage
|
||||
lors du premier tour sera l'ordre croissant des dés, c'est-à-dire
|
||||
que le plus petit lancer sera le premier à passer dans la poule A."""
|
||||
s += _("We are going to start the problem draw.<br>"
|
||||
"You can ask any question if something is not clear or wrong.<br><br>"
|
||||
"We are going to first draw the pools and the passage order for the first round "
|
||||
"with all the teams, then for each pool, we will draw the draw order and the problems.")
|
||||
s += "<br><br>"
|
||||
s += _("The captains, you can now all throw a 100-sided dice, by clicking on the big dice button. "
|
||||
"The pools and the passage order during the first round will be the increasing order "
|
||||
"of the dices, ie. the smallest dice will be the first to pass in pool A.")
|
||||
case 'DICE_ORDER_POULE':
|
||||
# Waiting for dices to determine the choice order
|
||||
s += f"""Nous passons au tirage des problèmes pour la poule
|
||||
<strong>{self.current_round.current_pool}</strong>, entre les équipes
|
||||
<strong>{', '.join(td.participation.team.trigram
|
||||
for td in self.current_round.current_pool.teamdraw_set.all())}</strong>.
|
||||
Les capitaines peuvent lancer un dé 100 en cliquant sur le gros bouton
|
||||
pour déterminer l'ordre de tirage. L'équipe réalisant le plus gros score pourra
|
||||
tirer en premier."""
|
||||
s += _("We are going to start the problem draw for the pool <strong>{pool}</strong>, "
|
||||
"between the teams <strong>{teams}</strong>. "
|
||||
"The captains can throw a 100-sided dice by clicking on the big dice button "
|
||||
"to determine the order of draw. The team with the highest score will draw first.") \
|
||||
.format(pool=self.current_round.current_pool,
|
||||
teams=', '.join(td.participation.team.trigram
|
||||
for td in self.current_round.current_pool.teamdraw_set.all()))
|
||||
case 'WAITING_DRAW_PROBLEM':
|
||||
# Waiting for a problem draw
|
||||
td = self.current_round.current_pool.current_team
|
||||
s += f"""C'est au tour de l'équipe <strong>{td.participation.team.trigram}</strong>
|
||||
de choisir son problème. Cliquez sur l'urne au milieu pour tirer un problème au sort."""
|
||||
s += _("The team <strong>{trigram}</strong> is going to draw a problem. "
|
||||
"Click on the urn in the middle to draw a problem.") \
|
||||
.format(trigram=td.participation.team.trigram)
|
||||
case 'WAITING_CHOOSE_PROBLEM':
|
||||
# Waiting for the team that can accept or reject the problem
|
||||
td = self.current_round.current_pool.current_team
|
||||
s += f"""L'équipe <strong>{td.participation.team.trigram}</strong> a tiré le problème
|
||||
<strong>{td.purposed} : {settings.PROBLEMS[td.purposed - 1]}</strong>. """
|
||||
s += _("The team <strong>{trigram}</strong> drew the problem <strong>{problem}: "
|
||||
"{problem_name}</strong>.") \
|
||||
.format(trigram=td.participation.team.trigram,
|
||||
problem=td.purposed, problem_name=settings.PROBLEMS[td.purposed - 1]) + " "
|
||||
if td.purposed in td.rejected:
|
||||
# The problem was previously rejected
|
||||
s += """Elle a déjà refusé ce problème auparavant, elle peut donc le refuser sans pénalité et
|
||||
tirer un nouveau problème immédiatement, ou bien revenir sur son choix."""
|
||||
s += _("It already refused this problem before, so it can refuse it without penalty and "
|
||||
"draw a new problem immediately, or change its mind.")
|
||||
else:
|
||||
# The problem can be rejected
|
||||
s += "Elle peut décider d'accepter ou de refuser ce problème. "
|
||||
s += _("It can decide to accept or refuse this problem.") + " "
|
||||
if len(td.rejected) >= len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT:
|
||||
s += "Refuser ce problème ajoutera une nouvelle pénalité de 25 % sur le coefficient de l'oral de la défense."
|
||||
s += _("Refusing this problem will add a new 25% penalty "
|
||||
"on the coefficient of the oral defense.")
|
||||
else:
|
||||
s += f"Il reste {len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT - len(td.rejected)} refus sans pénalité."
|
||||
s += _("There are still {remaining} refusals without penalty.").format(
|
||||
remaining=len(settings.PROBLEMS) - settings.RECOMMENDED_SOLUTIONS_COUNT - len(td.rejected))
|
||||
case 'WAITING_FINAL':
|
||||
# We are between the two rounds of the final tournament
|
||||
s += "Le tirage au sort pour le tour 2 aura lieu à la fin du premier tour. Bon courage !"
|
||||
s += _("The draw for the second round will take place at the end of the first round. Good luck!")
|
||||
case 'DRAW_ENDED':
|
||||
# The draw is ended
|
||||
s += "Le tirage au sort est terminé. Les solutions des autres équipes peuvent être trouvées dans l'onglet « Ma participation »."
|
||||
s += _("The draw is ended. The solutions of the other teams can be found in the tab "
|
||||
"\"My participation\".")
|
||||
|
||||
s += "<br><br>" if s else ""
|
||||
s += """Pour plus de détails sur le déroulement du tirage au sort,
|
||||
le règlement est accessible sur
|
||||
<a class="alert-link" href="https://tfjm.org/reglement">https://tfjm.org/reglement</a>."""
|
||||
rules_link = "https://tfjm.org/reglement" if settings.TFJM_APP == "TFJM" else "https://eteam.tfjm.org/rules/"
|
||||
s += _("For more details on the draw, the rules are available on "
|
||||
"<a class=\"alert-link\" href=\"{link}\">{link}</a>.").format(link=rules_link)
|
||||
return s
|
||||
|
||||
async def ainformation(self) -> str:
|
||||
@ -412,7 +415,7 @@ class Pool(models.Model):
|
||||
solution_number=tds[line[0]].accepted,
|
||||
defender=tds[line[0]].participation,
|
||||
opponent=tds[line[1]].participation,
|
||||
reporter=tds[line[2]].participation,
|
||||
reviewer=tds[line[2]].participation,
|
||||
defender_penalties=tds[line[0]].penalty_int,
|
||||
)
|
||||
|
||||
|
@ -529,37 +529,37 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
opponentTd.classList.add('text-center')
|
||||
opponentTd.innerText = 'Opp'
|
||||
|
||||
let reporterTd = document.createElement('td')
|
||||
reporterTd.classList.add('text-center')
|
||||
reporterTd.innerText = 'Rap'
|
||||
let reviewerTd = document.createElement('td')
|
||||
reviewerTd.classList.add('text-center')
|
||||
reviewerTd.innerText = 'Rap'
|
||||
|
||||
// Put the cells in their right places, according to the pool size and the row number.
|
||||
if (poule.teams.length === 3) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
teamTr.append(defenderTd, reporterTd, opponentTd)
|
||||
teamTr.append(defenderTd, reviewerTd, opponentTd)
|
||||
break
|
||||
case 1:
|
||||
teamTr.append(opponentTd, defenderTd, reporterTd)
|
||||
teamTr.append(opponentTd, defenderTd, reviewerTd)
|
||||
break
|
||||
case 2:
|
||||
teamTr.append(reporterTd, opponentTd, defenderTd)
|
||||
teamTr.append(reviewerTd, opponentTd, defenderTd)
|
||||
break
|
||||
}
|
||||
} else if (poule.teams.length === 4) {
|
||||
let emptyTd = document.createElement('td')
|
||||
switch (i) {
|
||||
case 0:
|
||||
teamTr.append(defenderTd, emptyTd, reporterTd, opponentTd)
|
||||
teamTr.append(defenderTd, emptyTd, reviewerTd, opponentTd)
|
||||
break
|
||||
case 1:
|
||||
teamTr.append(opponentTd, defenderTd, emptyTd, reporterTd)
|
||||
teamTr.append(opponentTd, defenderTd, emptyTd, reviewerTd)
|
||||
break
|
||||
case 2:
|
||||
teamTr.append(reporterTd, opponentTd, defenderTd, emptyTd)
|
||||
teamTr.append(reviewerTd, opponentTd, defenderTd, emptyTd)
|
||||
break
|
||||
case 3:
|
||||
teamTr.append(emptyTd, reporterTd, opponentTd, defenderTd)
|
||||
teamTr.append(emptyTd, reviewerTd, opponentTd, defenderTd)
|
||||
break
|
||||
}
|
||||
} else if (poule.teams.length === 5) {
|
||||
@ -567,19 +567,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
let emptyTd2 = document.createElement('td')
|
||||
switch (i) {
|
||||
case 0:
|
||||
teamTr.append(defenderTd, emptyTd, opponentTd, reporterTd, emptyTd2)
|
||||
teamTr.append(defenderTd, emptyTd, opponentTd, reviewerTd, emptyTd2)
|
||||
break
|
||||
case 1:
|
||||
teamTr.append(emptyTd, defenderTd, reporterTd, emptyTd2, opponentTd)
|
||||
teamTr.append(emptyTd, defenderTd, reviewerTd, emptyTd2, opponentTd)
|
||||
break
|
||||
case 2:
|
||||
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reporterTd)
|
||||
teamTr.append(opponentTd, emptyTd, defenderTd, emptyTd2, reviewerTd)
|
||||
break
|
||||
case 3:
|
||||
teamTr.append(reporterTd, opponentTd, emptyTd, defenderTd, emptyTd2)
|
||||
teamTr.append(reviewerTd, opponentTd, emptyTd, defenderTd, emptyTd2)
|
||||
break
|
||||
case 4:
|
||||
teamTr.append(emptyTd, reporterTd, emptyTd2, opponentTd, defenderTd)
|
||||
teamTr.append(emptyTd, reviewerTd, emptyTd2, opponentTd, defenderTd)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: TFJM\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"
|
||||
"Last-Translator: Emmy D'Anello <emmy.danello@animath.fr>\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 "
|
||||
"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/models.py:1515 participation/models.py:1524
|
||||
#: participation/tables.py:84
|
||||
@ -264,12 +264,12 @@ msgstr "Connexion"
|
||||
msgid "teams"
|
||||
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
|
||||
msgid "round"
|
||||
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"
|
||||
msgstr "Tirage au sort"
|
||||
|
||||
@ -277,67 +277,182 @@ msgstr "Tirage au sort"
|
||||
msgid "You are not an organizer."
|
||||
msgstr "Vous n'êtes pas un⋅e organisateur⋅rice."
|
||||
|
||||
#: draw/consumers.py:165
|
||||
#: draw/consumers.py:167
|
||||
msgid "The draw is already started."
|
||||
msgstr "Le tirage a déjà commencé."
|
||||
|
||||
#: draw/consumers.py:171
|
||||
#: draw/consumers.py:173
|
||||
msgid "Invalid format"
|
||||
msgstr "Format invalide"
|
||||
|
||||
#: draw/consumers.py:176
|
||||
#: draw/consumers.py:178
|
||||
#, python-brace-format
|
||||
msgid "The sum must be equal to the number of teams: expected {len}, got {sum}"
|
||||
msgstr ""
|
||||
"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."
|
||||
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!"
|
||||
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
|
||||
msgid "The draw for the tournament {tournament} will start."
|
||||
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:907 draw/consumers.py:996 draw/consumers.py:1018
|
||||
#: draw/consumers.py:1109 draw/templates/draw/tournament_content.html:5
|
||||
#: draw/consumers.py:256 draw/consumers.py:282 draw/consumers.py:691
|
||||
#: draw/consumers.py:909 draw/consumers.py:999 draw/consumers.py:1021
|
||||
#: draw/consumers.py:1112 draw/templates/draw/tournament_content.html:5
|
||||
msgid "The draw has not started yet."
|
||||
msgstr "Le tirage au sort n'a pas encore commencé."
|
||||
|
||||
#: draw/consumers.py:267
|
||||
#: draw/consumers.py:269
|
||||
#, python-brace-format
|
||||
msgid "The draw for the tournament {tournament} is aborted."
|
||||
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:695 draw/consumers.py:912
|
||||
#: draw/consumers.py:309 draw/consumers.py:330 draw/consumers.py:625
|
||||
#: draw/consumers.py:696 draw/consumers.py:914
|
||||
msgid "This is not the time for this."
|
||||
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."
|
||||
msgstr "Vous avez déjà lancé le dé."
|
||||
|
||||
#: draw/consumers.py:326
|
||||
#: draw/consumers.py:328
|
||||
msgid "It is not your turn."
|
||||
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
|
||||
msgid "Dices from teams {teams} are identical. Please relaunch your dices."
|
||||
msgstr ""
|
||||
"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."
|
||||
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
|
||||
msgid "The associated tournament."
|
||||
msgstr "Le tournoi associé."
|
||||
@ -362,154 +477,261 @@ msgstr "Le dernier message qui est affiché sur l'interface de tirage."
|
||||
msgid "State"
|
||||
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
|
||||
msgid "Draw of tournament {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"
|
||||
msgstr "tirage au sort"
|
||||
|
||||
#: draw/models.py:178
|
||||
#: draw/models.py:181
|
||||
msgid "draws"
|
||||
msgstr "tirages au sort"
|
||||
|
||||
#: draw/models.py:194
|
||||
#: draw/models.py:197
|
||||
msgid "Round 1"
|
||||
msgstr "Tour 1"
|
||||
|
||||
#: draw/models.py:195
|
||||
#: draw/models.py:198
|
||||
msgid "Round 2"
|
||||
msgstr "Tour 2"
|
||||
|
||||
#: draw/models.py:196
|
||||
#: draw/models.py:199
|
||||
msgid "Round 3"
|
||||
msgstr "Tour 3"
|
||||
|
||||
#: draw/models.py:197
|
||||
#: draw/models.py:200
|
||||
msgid "number"
|
||||
msgstr "numéro"
|
||||
|
||||
#: draw/models.py:198
|
||||
#: draw/models.py:201
|
||||
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)"
|
||||
|
||||
#: draw/models.py:208
|
||||
#: draw/models.py:211
|
||||
msgid "current pool"
|
||||
msgstr "poule actuelle"
|
||||
|
||||
#: draw/models.py:209
|
||||
#: draw/models.py:212
|
||||
msgid "The current pool where teams select their problems."
|
||||
msgstr "La poule en cours, où les équipes choisissent leurs problèmes"
|
||||
|
||||
#: draw/models.py:235
|
||||
#: draw/models.py:238
|
||||
msgid "rounds"
|
||||
msgstr "tours"
|
||||
|
||||
#: draw/models.py:257 participation/models.py:1024
|
||||
#: draw/models.py:260 participation/models.py:1024
|
||||
msgid "letter"
|
||||
msgstr "lettre"
|
||||
|
||||
#: draw/models.py:258
|
||||
#: draw/models.py:261
|
||||
msgid "The letter of the pool: A, B, C or 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
|
||||
msgid "size"
|
||||
msgstr "taille"
|
||||
|
||||
#: draw/models.py:264
|
||||
#: draw/models.py:267
|
||||
msgid "The number of teams in this pool, between 3 and 5."
|
||||
msgstr "Le nombre d'équipes dans la poule, entre 3 et 5."
|
||||
|
||||
#: draw/models.py:273
|
||||
#: draw/models.py:276
|
||||
msgid "current team"
|
||||
msgstr "équipe actuelle"
|
||||
|
||||
#: draw/models.py:274
|
||||
#: draw/models.py:277
|
||||
msgid "The current team that is selecting its problem."
|
||||
msgstr "L'équipe qui est en train de choisir son problème."
|
||||
|
||||
#: draw/models.py:283
|
||||
#: draw/models.py:286
|
||||
msgid "associated pool"
|
||||
msgstr "poule associée"
|
||||
|
||||
#: draw/models.py:284
|
||||
#: draw/models.py:287
|
||||
msgid "The full pool instance."
|
||||
msgstr "L'instance complète de la poule."
|
||||
|
||||
#: draw/models.py:426
|
||||
#: draw/models.py:429
|
||||
#, python-brace-format
|
||||
msgid "Pool {letter}{number}"
|
||||
msgstr "Poule {letter}{number}"
|
||||
|
||||
#: draw/models.py:430 participation/models.py:1516
|
||||
#: draw/models.py:433 participation/models.py:1516
|
||||
msgid "pools"
|
||||
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
|
||||
msgid "participation"
|
||||
msgstr "participation"
|
||||
|
||||
#: draw/models.py:463
|
||||
#: draw/models.py:466
|
||||
msgid "passage index"
|
||||
msgstr "numéro de passage"
|
||||
|
||||
#: draw/models.py:464
|
||||
#: draw/models.py:467
|
||||
msgid ""
|
||||
"The passage order in the pool, between 0 and the size of the pool minus 1."
|
||||
msgstr ""
|
||||
"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"
|
||||
msgstr "numéro de choix"
|
||||
|
||||
#: draw/models.py:473
|
||||
#: draw/models.py:476
|
||||
msgid ""
|
||||
"The choice order in the pool, between 0 and the size of the pool minus 1."
|
||||
msgstr ""
|
||||
"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
|
||||
#, python-brace-format
|
||||
msgid "Problem #{problem}"
|
||||
msgstr "Problème n°{problem}"
|
||||
|
||||
#: draw/models.py:483
|
||||
#: draw/models.py:486
|
||||
msgid "accepted problem"
|
||||
msgstr "problème accepté"
|
||||
|
||||
#: draw/models.py:490
|
||||
#: draw/models.py:493
|
||||
msgid "passage dice"
|
||||
msgstr "dé d'ordre de passage"
|
||||
|
||||
#: draw/models.py:497
|
||||
#: draw/models.py:500
|
||||
msgid "choice dice"
|
||||
msgstr "dé d'ordre de choix"
|
||||
|
||||
#: draw/models.py:506
|
||||
#: draw/models.py:509
|
||||
msgid "purposed problem"
|
||||
msgstr "problème proposé"
|
||||
|
||||
#: draw/models.py:511
|
||||
#: draw/models.py:514
|
||||
msgid "rejected problems"
|
||||
msgstr "problèmes rejetés"
|
||||
|
||||
#: draw/models.py:540
|
||||
#: draw/models.py:543
|
||||
#, python-brace-format
|
||||
msgid "Draw of the team {trigram} for the pool {letter}{number}"
|
||||
msgstr "Tirage de l'équipe {trigram} pour la poule {letter}{number}"
|
||||
|
||||
#: draw/models.py:546
|
||||
#: draw/models.py:549
|
||||
msgid "team draw"
|
||||
msgstr "tirage d'équipe"
|
||||
|
||||
#: draw/models.py:547
|
||||
#: draw/models.py:550
|
||||
msgid "team draws"
|
||||
msgstr "tirages d'équipe"
|
||||
|
||||
@ -702,7 +924,7 @@ msgstr "opposant⋅e"
|
||||
|
||||
#: participation/admin.py:132 participation/models.py:1559
|
||||
#: participation/models.py:1750
|
||||
msgid "reporter"
|
||||
msgid "reviewer"
|
||||
msgstr "rapporteur⋅rice"
|
||||
|
||||
#: 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é :"
|
||||
|
||||
#: 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 ""
|
||||
"Les équipes défenseuse, opposante et rapportrice doivent être différent⋅es."
|
||||
|
||||
@ -1175,11 +1397,11 @@ msgstr ""
|
||||
#: participation/models.py:966
|
||||
#, python-brace-format
|
||||
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 "
|
||||
"on <a href='{passage_url}'>this page</a>.</p>"
|
||||
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 "
|
||||
"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"
|
||||
|
||||
#: participation/models.py:1815
|
||||
msgid "reporter writing note"
|
||||
msgid "reviewer writing note"
|
||||
msgstr "note d'écrit rapporteur⋅rice"
|
||||
|
||||
#: participation/models.py:1821
|
||||
msgid "reporter oral note"
|
||||
msgid "reviewer oral note"
|
||||
msgstr "note d'oral du rapporteur⋅rice"
|
||||
|
||||
#: participation/models.py:1881
|
||||
@ -1592,7 +1814,7 @@ msgid "Opponent:"
|
||||
msgstr "Opposant⋅e :"
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:34
|
||||
msgid "Reporter:"
|
||||
msgid "reviewer:"
|
||||
msgstr "Rapporteur⋅rice :"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: 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"
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:117
|
||||
@ -1660,7 +1882,7 @@ msgid "Opponent points"
|
||||
msgstr "Points de l'équipe opposante"
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:129
|
||||
msgid "Reporter points"
|
||||
msgid "reviewer points"
|
||||
msgstr "Points de l'équipe rapportrice"
|
||||
|
||||
#: participation/templates/participation/passage_detail.html:139
|
||||
|
@ -51,7 +51,7 @@ class PassageInline(admin.TabularInline):
|
||||
model = Passage
|
||||
extra = 0
|
||||
ordering = ('position',)
|
||||
autocomplete_fields = ('defender', 'opponent', 'reporter',)
|
||||
autocomplete_fields = ('defender', 'opponent', 'reviewer',)
|
||||
show_change_link = True
|
||||
|
||||
|
||||
@ -113,12 +113,12 @@ class PoolAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(Passage)
|
||||
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')
|
||||
list_filter = ('pool__tournament', 'pool__round', 'pool__letter', 'solution_number',)
|
||||
search_fields = ('pool__participations__team__name', 'pool__participations__team__trigram',)
|
||||
ordering = ('pool__tournament', 'pool__round', 'pool__letter', 'position',)
|
||||
autocomplete_fields = ('pool', 'defender', 'opponent', 'reporter',)
|
||||
autocomplete_fields = ('pool', 'defender', 'opponent', 'reviewer',)
|
||||
inlines = (NoteInline,)
|
||||
|
||||
@admin.display(description=_("defender"), ordering='defender__team__trigram')
|
||||
@ -129,9 +129,9 @@ class PassageAdmin(admin.ModelAdmin):
|
||||
def opponent_trigram(self, record: Passage):
|
||||
return record.opponent.team.trigram
|
||||
|
||||
@admin.display(description=_("reporter"), ordering='reporter__team__trigram')
|
||||
def reporter_trigram(self, record: Passage):
|
||||
return record.reporter.team.trigram
|
||||
@admin.display(description=_("reviewer"), ordering='reviewer__team__trigram')
|
||||
def reviewer_trigram(self, record: Passage):
|
||||
return record.reviewer.team.trigram
|
||||
|
||||
@admin.display(description=_("pool"), ordering='pool__letter')
|
||||
def pool_abbr(self, record):
|
||||
@ -145,10 +145,10 @@ class PassageAdmin(admin.ModelAdmin):
|
||||
@admin.register(Note)
|
||||
class NoteAdmin(admin.ModelAdmin):
|
||||
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',
|
||||
'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',)
|
||||
autocomplete_fields = ('jury', 'passage',)
|
||||
|
||||
|
@ -13,7 +13,7 @@ class NoteViewSet(ModelViewSet):
|
||||
serializer_class = NoteSerializer
|
||||
filter_backends = [DjangoFilterBackend]
|
||||
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):
|
||||
@ -27,7 +27,7 @@ class PassageViewSet(ModelViewSet):
|
||||
queryset = Passage.objects.all()
|
||||
serializer_class = PassageSerializer
|
||||
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):
|
||||
|
@ -344,9 +344,9 @@ class UploadNotesForm(forms.Form):
|
||||
class PassageForm(forms.ModelForm):
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if "defender" in cleaned_data and "opponent" in cleaned_data and "reporter" in cleaned_data \
|
||||
and len({cleaned_data["defender"], cleaned_data["opponent"], cleaned_data["reporter"]}) < 3:
|
||||
self.add_error(None, _("The defender, the opponent and the reporter must be different."))
|
||||
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["reviewer"]}) < 3:
|
||||
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 \
|
||||
and not Solution.objects.filter(participation=cleaned_data["defender"],
|
||||
problem=cleaned_data["solution_number"]).exists():
|
||||
@ -355,7 +355,7 @@ class PassageForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Passage
|
||||
fields = ('position', 'solution_number', 'defender', 'opponent', 'reporter', 'defender_penalties',)
|
||||
fields = ('position', 'solution_number', 'defender', 'opponent', 'reviewer', 'defender_penalties',)
|
||||
|
||||
|
||||
class SynthesisForm(forms.ModelForm):
|
||||
@ -386,4 +386,4 @@ class NoteForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Note
|
||||
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()
|
||||
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)
|
||||
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()
|
||||
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)
|
||||
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(str(pool1.jury_president or ""))
|
||||
line.append(f"Pb. {defender_passage_1.solution_number}")
|
||||
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,
|
||||
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(f"Pb. {defender_passage_2.solution_number}")
|
||||
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,
|
||||
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})",
|
||||
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):
|
||||
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)
|
||||
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 "
|
||||
"<a href='{draw_url}'>this page</a>.</p>"
|
||||
@ -878,21 +878,21 @@ class Participation(models.Model):
|
||||
solution_url=solution_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}. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reporter_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
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_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
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({
|
||||
'title': _("First round"),
|
||||
'type': "info",
|
||||
@ -902,7 +902,7 @@ class Participation(models.Model):
|
||||
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)
|
||||
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 "
|
||||
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
||||
@ -920,21 +920,21 @@ class Participation(models.Model):
|
||||
solution_url=solution_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}. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reporter_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
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_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
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({
|
||||
'title': _("Second round"),
|
||||
'type': "info",
|
||||
@ -945,7 +945,7 @@ class Participation(models.Model):
|
||||
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)
|
||||
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 "
|
||||
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
|
||||
@ -963,21 +963,21 @@ class Participation(models.Model):
|
||||
solution_url=solution_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}. "
|
||||
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
|
||||
solution_url = reporter_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reporter_passage.pk,))
|
||||
reporter_content = format_lazy(reporter_text, reporter=reporter_passage.defender.team.trigram,
|
||||
solution_url = reviewer_passage.defended_solution.file.url
|
||||
passage_url = reverse_lazy("participation:passage_detail", args=(reviewer_passage.pk,))
|
||||
reviewer_content = format_lazy(reviewer_text, reviewer=reviewer_passage.defender.team.trigram,
|
||||
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_templates = " — ".join(f"<a href='{syntheses_template_begin}{ext}'>{ext.upper()}</a>"
|
||||
for ext in ["pdf", "tex", "odt", "docx"])
|
||||
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({
|
||||
'title': _("Second round"),
|
||||
'type': "info",
|
||||
@ -1132,7 +1132,7 @@ class Pool(models.Model):
|
||||
for passage in passages), start=["Problème", ""]),
|
||||
sum(([f"Défenseur⋅se ({passage.defender.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", ""]),
|
||||
sum((["Écrit (/20)", "Oral (/20)", "Écrit (/10)", "Oral (/10)", "Écrit (/10)", "Oral (/10)"]
|
||||
for _passage in passages), start=["Juré⋅e", ""]),
|
||||
@ -1144,7 +1144,7 @@ class Pool(models.Model):
|
||||
for passage in passages:
|
||||
note = passage.notes.filter(jury=jury).first()
|
||||
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([]) # Add empty line to ensure pretty design
|
||||
|
||||
@ -1204,18 +1204,18 @@ class Pool(models.Model):
|
||||
opponent_row = 5 + opponent_passage.pool.juries.count()
|
||||
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)
|
||||
reporter_row = 5 + reporter_passage.pool.juries.count()
|
||||
reporter_col = reporter_passage.position - 1
|
||||
reviewer_row = 5 + reviewer_passage.pool.juries.count()
|
||||
reviewer_col = reviewer_passage.position - 1
|
||||
|
||||
formula = "="
|
||||
formula += (f"'Poule {defender_passage.pool.short_name}'"
|
||||
f"!{getcol(min_column + defender_col * passage_width)}{defender_row + 3}") # Defender
|
||||
formula += (f" + 'Poule {opponent_passage.pool.short_name}'"
|
||||
f"!{getcol(min_column + opponent_col * passage_width + 2)}{opponent_row + 3}") # Opponent
|
||||
formula += (f" + 'Poule {reporter_passage.pool.short_name}'"
|
||||
f"!{getcol(min_column + reporter_col * passage_width + 4)}{reporter_row + 3}") # Reporter
|
||||
formula += (f" + 'Poule {reviewer_passage.pool.short_name}'"
|
||||
f"!{getcol(min_column + reviewer_col * passage_width + 4)}{reviewer_row + 3}") # reviewer
|
||||
ranking.append([f"{participation.team.name} ({participation.team.trigram})", "",
|
||||
f"='Poule {defender_passage.pool.short_name}'"
|
||||
f"!${getcol(3 + defender_col * passage_width)}$1",
|
||||
@ -1553,10 +1553,10 @@ class Passage(models.Model):
|
||||
related_name="+",
|
||||
)
|
||||
|
||||
reporter = models.ForeignKey(
|
||||
reviewer = models.ForeignKey(
|
||||
Participation,
|
||||
on_delete=models.PROTECT,
|
||||
verbose_name=_("reporter"),
|
||||
verbose_name=_("reviewer"),
|
||||
related_name="+",
|
||||
)
|
||||
|
||||
@ -1603,16 +1603,16 @@ class Passage(models.Model):
|
||||
return 0.9 * self.average_opponent_writing + 2 * self.average_opponent_oral
|
||||
|
||||
@property
|
||||
def average_reporter_writing(self) -> float:
|
||||
return self.avg(note.reporter_writing for note in self.notes.all())
|
||||
def average_reviewer_writing(self) -> float:
|
||||
return self.avg(note.reviewer_writing for note in self.notes.all())
|
||||
|
||||
@property
|
||||
def average_reporter_oral(self) -> float:
|
||||
return self.avg(note.reporter_oral for note in self.notes.all())
|
||||
def average_reviewer_oral(self) -> float:
|
||||
return self.avg(note.reviewer_oral for note in self.notes.all())
|
||||
|
||||
@property
|
||||
def average_reporter(self) -> float:
|
||||
return 0.9 * self.average_reporter_writing + self.average_reporter_oral
|
||||
def average_reviewer(self) -> float:
|
||||
return 0.9 * self.average_reviewer_writing + self.average_reviewer_oral
|
||||
|
||||
@property
|
||||
def averages(self):
|
||||
@ -1620,12 +1620,12 @@ class Passage(models.Model):
|
||||
yield self.average_defender_oral
|
||||
yield self.average_opponent_writing
|
||||
yield self.average_opponent_oral
|
||||
yield self.average_reporter_writing
|
||||
yield self.average_reporter_oral
|
||||
yield self.average_reviewer_writing
|
||||
yield self.average_reviewer_oral
|
||||
|
||||
def average(self, participation):
|
||||
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):
|
||||
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():
|
||||
raise ValidationError(_("Team {trigram} is not registered in the pool.")
|
||||
.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.")
|
||||
.format(trigram=self.reporter.team.trigram))
|
||||
.format(trigram=self.reviewer.team.trigram))
|
||||
return super().clean()
|
||||
|
||||
def __str__(self):
|
||||
@ -1747,7 +1747,7 @@ class Synthesis(models.Model):
|
||||
type = models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(1, _("opponent"), ),
|
||||
(2, _("reporter"), ),
|
||||
(2, _("reviewer"), ),
|
||||
]
|
||||
)
|
||||
|
||||
@ -1811,14 +1811,14 @@ class Note(models.Model):
|
||||
default=0,
|
||||
)
|
||||
|
||||
reporter_writing = models.PositiveSmallIntegerField(
|
||||
verbose_name=_("reporter writing note"),
|
||||
reviewer_writing = models.PositiveSmallIntegerField(
|
||||
verbose_name=_("reviewer writing note"),
|
||||
choices=[(i, i) for i in range(0, 11)],
|
||||
default=0,
|
||||
)
|
||||
|
||||
reporter_oral = models.PositiveSmallIntegerField(
|
||||
verbose_name=_("reporter oral note"),
|
||||
reviewer_oral = models.PositiveSmallIntegerField(
|
||||
verbose_name=_("reviewer oral note"),
|
||||
choices=[(i, i) for i in range(0, 11)],
|
||||
default=0,
|
||||
)
|
||||
@ -1828,17 +1828,17 @@ class Note(models.Model):
|
||||
yield self.defender_oral
|
||||
yield self.opponent_writing
|
||||
yield self.opponent_oral
|
||||
yield self.reporter_writing
|
||||
yield self.reporter_oral
|
||||
yield self.reviewer_writing
|
||||
yield self.reviewer_oral
|
||||
|
||||
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_oral = defender_oral
|
||||
self.opponent_writing = opponent_writing
|
||||
self.opponent_oral = opponent_oral
|
||||
self.reporter_writing = reporter_writing
|
||||
self.reporter_oral = reporter_oral
|
||||
self.reviewer_writing = reviewer_writing
|
||||
self.reviewer_oral = reviewer_oral
|
||||
|
||||
def update_spreadsheet(self):
|
||||
if not self.has_any_note():
|
||||
|
@ -118,7 +118,7 @@ class PassageTable(tables.Table):
|
||||
def render_opponent(self, value):
|
||||
return value.team.trigram
|
||||
|
||||
def render_reporter(self, value):
|
||||
def render_reviewer(self, value):
|
||||
return value.team.trigram
|
||||
|
||||
class Meta:
|
||||
@ -126,7 +126,7 @@ class PassageTable(tables.Table):
|
||||
'class': 'table table-condensed table-striped text-center',
|
||||
}
|
||||
model = Passage
|
||||
fields = ('defender', 'opponent', 'reporter', 'solution_number', )
|
||||
fields = ('defender', 'opponent', 'reviewer', 'solution_number', )
|
||||
|
||||
|
||||
class NoteTable(tables.Table):
|
||||
@ -155,4 +155,4 @@ class NoteTable(tables.Table):
|
||||
}
|
||||
model = Note
|
||||
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>
|
||||
<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>
|
||||
<dd class="col-sm-9"><a href="{{ passage.reporter.get_absolute_url }}">{{ passage.reporter.team }}</a></dd>
|
||||
<dt class="col-sm-3">{% trans "reviewer:" %}</dt>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<dt class="col-sm-8">
|
||||
{% trans "Average points for the reporter writing" %}
|
||||
({{ passage.reporter.team.trigram }}) :
|
||||
{% trans "Average points for the reviewer writing" %}
|
||||
({{ passage.reviewer.team.trigram }}) :
|
||||
</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">
|
||||
{% trans "Average points for the reporter oral" %}
|
||||
({{ passage.reporter.team.trigram }}) :
|
||||
{% trans "Average points for the reviewer oral" %}
|
||||
({{ passage.reviewer.team.trigram }}) :
|
||||
</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>
|
||||
|
||||
<hr>
|
||||
@ -126,10 +126,10 @@
|
||||
<dd class="col-sm-4">{{ passage.average_opponent|floatformat }}/29</dd>
|
||||
|
||||
<dt class="col-sm-8">
|
||||
{% trans "Reporter points" %}
|
||||
({{ passage.reporter.team.trigram }}) :
|
||||
{% trans "reviewer points" %}
|
||||
({{ passage.reviewer.team.trigram }}) :
|
||||
</dt>
|
||||
<dd class="col-sm-4">{{ passage.average_reporter|floatformat }}/19</dd>
|
||||
<dd class="col-sm-4">{{ passage.average_reviewer|floatformat }}/19</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -100,7 +100,7 @@
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%RAPPORTEUR.RICE
|
||||
\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
|
||||
\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$
|
||||
{% 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 %}
|
||||
& \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(CoveredTableCell())
|
||||
|
||||
reporter_tc = TableCell(valuetype="string",
|
||||
reviewer_tc = TableCell(valuetype="string",
|
||||
stylename=title_style_right)
|
||||
reporter_tc.addElement(P(text="Rapporteur⋅rice"))
|
||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
||||
header_role.addElement(reporter_tc)
|
||||
reviewer_tc.addElement(P(text="Rapporteur⋅rice"))
|
||||
reviewer_tc.setAttribute('numbercolumnsspanned', "2")
|
||||
header_role.addElement(reviewer_tc)
|
||||
header_role.addElement(CoveredTableCell())
|
||||
|
||||
# Add maximum notes on the third line
|
||||
@ -1540,13 +1540,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
opponent_o_tc.addElement(P(text="Oral (/10)"))
|
||||
header_notes.addElement(opponent_o_tc)
|
||||
|
||||
reporter_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||
reporter_w_tc.addElement(P(text="Écrit (/10)"))
|
||||
header_notes.addElement(reporter_w_tc)
|
||||
reviewer_w_tc = TableCell(valuetype="string", stylename=title_style_bot)
|
||||
reviewer_w_tc.addElement(P(text="Écrit (/10)"))
|
||||
header_notes.addElement(reviewer_w_tc)
|
||||
|
||||
reporter_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
|
||||
reporter_o_tc.addElement(P(text="Oral (/10)"))
|
||||
header_notes.addElement(reporter_o_tc)
|
||||
reviewer_o_tc = TableCell(valuetype="string", stylename=title_style_botright)
|
||||
reviewer_o_tc.addElement(P(text="Oral (/10)"))
|
||||
header_notes.addElement(reviewer_o_tc)
|
||||
|
||||
# Add a notation line for each jury
|
||||
for jury in self.object.juries.all():
|
||||
@ -1617,13 +1617,13 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
opponent_o_tc.addElement(P(text="2"))
|
||||
coeff_row.addElement(opponent_o_tc)
|
||||
|
||||
reporter_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
|
||||
reporter_w_tc.addElement(P(text="1"))
|
||||
coeff_row.addElement(reporter_w_tc)
|
||||
reviewer_w_tc = TableCell(valuetype="float", value=0.9, stylename=style)
|
||||
reviewer_w_tc.addElement(P(text="1"))
|
||||
coeff_row.addElement(reviewer_w_tc)
|
||||
|
||||
reporter_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
|
||||
reporter_o_tc.addElement(P(text="1"))
|
||||
coeff_row.addElement(reporter_o_tc)
|
||||
reviewer_o_tc = TableCell(valuetype="float", value=1, stylename=style_right)
|
||||
reviewer_o_tc.addElement(P(text="1"))
|
||||
coeff_row.addElement(reviewer_o_tc)
|
||||
|
||||
# Add the subtotal on the next line
|
||||
subtotal_row = TableRow()
|
||||
@ -1656,12 +1656,12 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
|
||||
rep_w_col = getcol(min_column + passage_width * i + 4)
|
||||
rep_o_col = getcol(min_column + passage_width * i + 5)
|
||||
reporter_tc = TableCell(valuetype="float", value=passage.average_reporter, stylename=style_botright)
|
||||
reporter_tc.addElement(P(text=str(passage.average_reporter)))
|
||||
reporter_tc.setAttribute('numbercolumnsspanned', "2")
|
||||
reporter_tc.setAttribute("formula", f"of:=[.{rep_w_col}{max_row + 1}] * [.{rep_w_col}{max_row + 2}]"
|
||||
reviewer_tc = TableCell(valuetype="float", value=passage.average_reviewer, stylename=style_botright)
|
||||
reviewer_tc.addElement(P(text=str(passage.average_reviewer)))
|
||||
reviewer_tc.setAttribute('numbercolumnsspanned', "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}]")
|
||||
subtotal_row.addElement(reporter_tc)
|
||||
subtotal_row.addElement(reviewer_tc)
|
||||
subtotal_row.addElement(CoveredTableCell())
|
||||
|
||||
table.addElement(TableRow())
|
||||
@ -1713,7 +1713,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
|
||||
defender_pos = passage.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),
|
||||
stylename=style_bot if passage.position == pool_size else style)
|
||||
@ -1721,7 +1721,7 @@ class PoolNotesTemplateView(VolunteerMixin, DetailView):
|
||||
formula = "of:="
|
||||
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 + 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)
|
||||
team_row.addElement(score_tc)
|
||||
|
||||
@ -1931,7 +1931,7 @@ class PassageDetailView(LoginRequiredMixin, DetailView):
|
||||
or reg in passage.pool.juries.all()
|
||||
or reg.pools_presided.filter(tournament=passage.pool.tournament).exists()) \
|
||||
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 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['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['reporter_writing'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
||||
context['notes'].columns['reporter_oral'].column.verbose_name += f" ({passage.reporter.team.trigram})"
|
||||
context['notes'].columns['reviewer_writing'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
||||
context['notes'].columns['reviewer_oral'].column.verbose_name += f" ({passage.reviewer.team.trigram})"
|
||||
|
||||
return context
|
||||
|
||||
@ -1992,7 +1992,7 @@ class SynthesisUploadView(LoginRequiredMixin, FormView):
|
||||
self.participation = self.request.user.registration.team.participation
|
||||
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 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['opponent_writing'].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['reporter_oral'].label += f" ({self.object.passage.reporter.team.trigram})"
|
||||
form.fields['reviewer_writing'].label += f" ({self.object.passage.reviewer.team.trigram})"
|
||||
form.fields['reviewer_oral'].label += f" ({self.object.passage.reviewer.team.trigram})"
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
|
@ -839,7 +839,7 @@ class SolutionView(LoginRequiredMixin, View):
|
||||
if user.registration.participates:
|
||||
passage_participant_qs = Passage.objects.filter(Q(defender=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,
|
||||
solution_number=solution.problem)
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user