mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-07-04 08:12:17 +02:00
Compare commits
6 Commits
7e212d011e
...
ae62e3daf7
Author | SHA1 | Date | |
---|---|---|---|
ae62e3daf7
|
|||
8778f58fe4
|
|||
751e35ac62
|
|||
f41b2e16ab
|
|||
1f6ce072bf
|
|||
746aae464a
|
@ -2,13 +2,16 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
import json
|
||||||
from random import randint, shuffle
|
from random import randint, shuffle
|
||||||
|
|
||||||
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
from channels.generic.websocket import AsyncJsonWebsocketConsumer
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from draw.models import Draw, Pool, Round, TeamDraw
|
from draw.models import Draw, Pool, Round, TeamDraw
|
||||||
|
from logs.models import Changelog
|
||||||
from participation.models import Participation, Tournament
|
from participation.models import Participation, Tournament
|
||||||
from registration.models import Registration
|
from registration.models import Registration
|
||||||
|
|
||||||
@ -115,6 +118,9 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
case 'abort':
|
case 'abort':
|
||||||
# Abort the current draw
|
# Abort the current draw
|
||||||
await self.abort(**content)
|
await self.abort(**content)
|
||||||
|
case 'cancel':
|
||||||
|
# Cancel the last step
|
||||||
|
await self.cancel_last_step(**content)
|
||||||
case 'dice':
|
case 'dice':
|
||||||
# Launch a dice
|
# Launch a dice
|
||||||
await self.process_dice(**content)
|
await self.process_dice(**content)
|
||||||
@ -345,11 +351,14 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
if values.count(v) > 1:
|
if values.count(v) > 1:
|
||||||
# v is a duplicate value
|
# v is a duplicate value
|
||||||
# Get all teams that have the same result
|
# Get all teams that have the same result
|
||||||
dups = [td for td in tds if td.passage_dice == v]
|
dups = [td for td in tds if (td.passage_dice if state == 'DICE_SELECT_POULES' else td.choice_dice) == v]
|
||||||
|
|
||||||
for dup in dups:
|
for dup in dups:
|
||||||
# Reset the dice
|
# Reset the dice
|
||||||
|
if state == 'DICE_SELECT_POULES':
|
||||||
dup.passage_dice = None
|
dup.passage_dice = None
|
||||||
|
else:
|
||||||
|
dup.choice_dice = None
|
||||||
await dup.asave()
|
await dup.asave()
|
||||||
await self.channel_layer.group_send(
|
await self.channel_layer.group_send(
|
||||||
f"tournament-{self.tournament.id}",
|
f"tournament-{self.tournament.id}",
|
||||||
@ -647,7 +656,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
|||||||
:param pool: The pool to end.
|
:param pool: The pool to end.
|
||||||
"""
|
"""
|
||||||
msg = self.tournament.draw.last_message
|
msg = self.tournament.draw.last_message
|
||||||
r = pool.round
|
r = self.tournament.draw.current_round
|
||||||
|
|
||||||
if pool.size == 5:
|
if pool.size == 5:
|
||||||
# Maybe reorder teams if the same problem is presented twice
|
# Maybe reorder teams if the same problem is presented twice
|
||||||
@ -925,6 +934,402 @@ 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}",
|
||||||
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||||
|
|
||||||
|
@ensure_orga
|
||||||
|
async def cancel_last_step(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Cancel the last step of the draw.
|
||||||
|
"""
|
||||||
|
if not await Draw.objects.filter(tournament=self.tournament).aexists():
|
||||||
|
return await self.alert(_("The draw has not started yet."), 'danger')
|
||||||
|
|
||||||
|
state = self.tournament.draw.get_state()
|
||||||
|
|
||||||
|
self.tournament.draw.last_message = ""
|
||||||
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
|
if state == 'DRAW_ENDED' or state == 'WAITING_FINAL':
|
||||||
|
await self.undo_end_draw()
|
||||||
|
elif state == 'WAITING_CHOOSE_PROBLEM':
|
||||||
|
await self.undo_draw_problem()
|
||||||
|
elif state == 'WAITING_DRAW_PROBLEM':
|
||||||
|
await self.undo_process_problem()
|
||||||
|
elif state == 'DICE_ORDER_POULE':
|
||||||
|
await self.undo_pool_dice()
|
||||||
|
elif state == 'DICE_SELECT_POULES':
|
||||||
|
await self.undo_order_dice()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_info', 'draw': self.tournament.draw})
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_active', 'draw': self.tournament.draw})
|
||||||
|
|
||||||
|
async def undo_end_draw(self) -> None:
|
||||||
|
"""
|
||||||
|
If the draw is ended, or if we are between the two rounds of the final,
|
||||||
|
then we cancel the last problem that was accepted.
|
||||||
|
"""
|
||||||
|
r = self.tournament.draw.current_round
|
||||||
|
td = r.current_pool.current_team
|
||||||
|
td.purposed = td.accepted
|
||||||
|
td.accepted = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.continue_visibility', 'visible': False})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_problem',
|
||||||
|
'round': r.number,
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'problem': td.accepted})
|
||||||
|
|
||||||
|
async def undo_draw_problem(self):
|
||||||
|
"""
|
||||||
|
A problem was drawn and we wait for the current team to accept or reject the problem.
|
||||||
|
Then, we just reset the problem draw.
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
td = self.tournament.draw.current_round.current_pool.current_team
|
||||||
|
td.purposed = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': False})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': False})
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.box_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.box_visibility', 'visible': True})
|
||||||
|
|
||||||
|
async def undo_process_problem(self):
|
||||||
|
"""
|
||||||
|
Now, a team must draw a new problem. Multiple cases are possible:
|
||||||
|
* In the same pool, a previous team accepted a problem ;
|
||||||
|
* In the same pool, a previous team rejected a problem ;
|
||||||
|
* The current team rejected a problem that was previously rejected ;
|
||||||
|
* The last team drawn its dice to choose the draw order.
|
||||||
|
|
||||||
|
In the two first cases, we explore the database history to fetch what team accepted or rejected
|
||||||
|
its problem at last.
|
||||||
|
The third case is ignored, because too hard and too useless to manage.
|
||||||
|
For the last case, we cancel the last dice.
|
||||||
|
"""
|
||||||
|
content_type = await ContentType.objects.aget(app_label=TeamDraw._meta.app_label,
|
||||||
|
model=TeamDraw._meta.model_name)
|
||||||
|
|
||||||
|
r = self.tournament.draw.current_round
|
||||||
|
p = r.current_pool
|
||||||
|
accepted_tds = {td.id: td async for td in p.team_draws.filter(accepted__isnull=False)
|
||||||
|
.prefetch_related('participation__team')}
|
||||||
|
has_rejected_one_tds = {td.id: td async for td in p.team_draws.exclude(rejected=[])
|
||||||
|
.prefetch_related('participation__team')}
|
||||||
|
|
||||||
|
last_td = None
|
||||||
|
|
||||||
|
if accepted_tds or has_rejected_one_tds:
|
||||||
|
# One team of the already accepted or its problem, we fetch the last one
|
||||||
|
changelogs = Changelog.objects.filter(
|
||||||
|
model=content_type,
|
||||||
|
action='edit',
|
||||||
|
instance_pk__in=set(accepted_tds.keys()).union(set(has_rejected_one_tds.keys()))
|
||||||
|
).order_by('-timestamp')
|
||||||
|
|
||||||
|
async for changelog in changelogs:
|
||||||
|
previous = json.loads(changelog.previous)
|
||||||
|
data = json.loads(changelog.data)
|
||||||
|
pk = int(changelog.instance_pk)
|
||||||
|
|
||||||
|
if 'accepted' in data and data['accepted'] and pk in accepted_tds:
|
||||||
|
# Undo the last acceptance
|
||||||
|
last_td = accepted_tds[pk]
|
||||||
|
last_td.purposed = last_td.accepted
|
||||||
|
last_td.accepted = None
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_problem',
|
||||||
|
'round': r.number,
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'problem': last_td.accepted})
|
||||||
|
break
|
||||||
|
if 'rejected' in data and len(data['rejected']) > len(previous['rejected']) \
|
||||||
|
and pk in has_rejected_one_tds:
|
||||||
|
# Undo the last reject
|
||||||
|
last_td = has_rejected_one_tds[pk]
|
||||||
|
rejected_problem = set(data['rejected']).difference(previous['rejected']).pop()
|
||||||
|
if rejected_problem not in last_td.rejected:
|
||||||
|
# This is an old diff
|
||||||
|
continue
|
||||||
|
last_td.rejected.remove(rejected_problem)
|
||||||
|
last_td.purposed = rejected_problem
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.reject_problem',
|
||||||
|
'round': r.number,
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'rejected': last_td.rejected})
|
||||||
|
break
|
||||||
|
|
||||||
|
r.current_pool.current_team = last_td
|
||||||
|
await r.current_pool.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"team-{last_td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
else:
|
||||||
|
# Return to the dice choice
|
||||||
|
pool_tds = {td.id: td async for td in p.team_draws.prefetch_related('participation__team')}
|
||||||
|
changelogs = Changelog.objects.filter(
|
||||||
|
model=content_type,
|
||||||
|
action='edit',
|
||||||
|
instance_pk__in=set(pool_tds.keys())
|
||||||
|
).order_by('-timestamp')
|
||||||
|
|
||||||
|
# Find the last dice that was launched
|
||||||
|
async for changelog in changelogs:
|
||||||
|
data = json.loads(changelog.data)
|
||||||
|
if 'choice_dice' in data and data['choice_dice']:
|
||||||
|
last_td = pool_tds[int(changelog.instance_pk)]
|
||||||
|
# Reset the dice
|
||||||
|
last_td.choice_dice = None
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
# Reset the dice on the interface
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'result': None})
|
||||||
|
break
|
||||||
|
|
||||||
|
p.current_team = None
|
||||||
|
await p.asave()
|
||||||
|
|
||||||
|
# Make dice box visible
|
||||||
|
for td in pool_tds.values():
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': True})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.box_visibility', 'visible': False})
|
||||||
|
|
||||||
|
async def undo_pool_dice(self):
|
||||||
|
"""
|
||||||
|
Teams of a pool are launching their dices to define the draw order.
|
||||||
|
We reset the last dice if possible, or we go to the last pool, or the last round,
|
||||||
|
or the passage dices.
|
||||||
|
"""
|
||||||
|
content_type = await ContentType.objects.aget(app_label=TeamDraw._meta.app_label,
|
||||||
|
model=TeamDraw._meta.model_name)
|
||||||
|
|
||||||
|
r = self.tournament.draw.current_round
|
||||||
|
p = r.current_pool
|
||||||
|
already_launched_tds = {td.id: td async for td in p.team_draws.filter(choice_dice__isnull=False)
|
||||||
|
.prefetch_related('participation__team')}
|
||||||
|
|
||||||
|
if already_launched_tds:
|
||||||
|
# Reset the last dice
|
||||||
|
changelogs = Changelog.objects.filter(
|
||||||
|
model=content_type,
|
||||||
|
action='edit',
|
||||||
|
instance_pk__in=set(already_launched_tds.keys())
|
||||||
|
).order_by('-timestamp')
|
||||||
|
|
||||||
|
# Find the last dice that was launched
|
||||||
|
async for changelog in changelogs:
|
||||||
|
data = json.loads(changelog.data)
|
||||||
|
if 'choice_dice' in data and data['choice_dice']:
|
||||||
|
last_td = already_launched_tds[int(changelog.instance_pk)]
|
||||||
|
# Reset the dice
|
||||||
|
last_td.choice_dice = None
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
# Reset the dice on the interface
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'result': None})
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Go to the previous pool if possible
|
||||||
|
if p.letter > 1:
|
||||||
|
# Go to the previous pool
|
||||||
|
previous_pool = await r.pool_set.prefetch_related('current_team__participation__team') \
|
||||||
|
.aget(letter=p.letter - 1)
|
||||||
|
r.current_pool = previous_pool
|
||||||
|
await r.asave()
|
||||||
|
|
||||||
|
td = previous_pool.current_team
|
||||||
|
td.purposed = td.accepted
|
||||||
|
td.accepted = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': False})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_problem',
|
||||||
|
'round': r.number,
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'problem': td.accepted})
|
||||||
|
elif r.number == 2:
|
||||||
|
if not self.tournament.final:
|
||||||
|
# Go to the previous round
|
||||||
|
r1 = await self.tournament.draw.round_set \
|
||||||
|
.prefetch_related('current_pool__current_team__participation__team').aget(number=1)
|
||||||
|
self.tournament.draw.current_round = r1
|
||||||
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
|
async for td in r1.team_draws.prefetch_related('participation__team').all():
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'result': td.choice_dice})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.send_poules', 'round': r1})
|
||||||
|
|
||||||
|
previous_pool = r1.current_pool
|
||||||
|
|
||||||
|
td = previous_pool.current_team
|
||||||
|
td.purposed = td.accepted
|
||||||
|
td.accepted = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': False})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.buttons_visibility', 'visible': True})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.set_problem',
|
||||||
|
'round': r1.number,
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'problem': td.accepted})
|
||||||
|
else:
|
||||||
|
# Don't continue the final tournament
|
||||||
|
r1 = await self.tournament.draw.round_set \
|
||||||
|
.prefetch_related('current_pool__current__team__participation__team').aget(number=1)
|
||||||
|
self.tournament.draw.current_round = r1
|
||||||
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
|
async for td in r.teamdraw_set.all():
|
||||||
|
td.pool = None
|
||||||
|
td.choose_index = None
|
||||||
|
td.choice_dice = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
async for td in r1.team_draws.prefetch_related('participation__team').all():
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'result': td.choice_dice})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': False})
|
||||||
|
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
|
||||||
|
{'type': 'draw.continue_visibility', 'visible': True})
|
||||||
|
else:
|
||||||
|
# Go to the dice order
|
||||||
|
async for r0 in self.tournament.draw.round_set.all():
|
||||||
|
async for td in r0.teamdraw_set.all():
|
||||||
|
td.pool = None
|
||||||
|
td.passage_index = None
|
||||||
|
td.choose_index = None
|
||||||
|
td.choice_dice = None
|
||||||
|
await td.asave()
|
||||||
|
|
||||||
|
r.current_pool = None
|
||||||
|
await r.asave()
|
||||||
|
|
||||||
|
round_tds = {td.id: td async for td in r.team_draws.prefetch_related('participation__team')}
|
||||||
|
|
||||||
|
# Reset the last dice
|
||||||
|
changelogs = Changelog.objects.filter(
|
||||||
|
model=content_type,
|
||||||
|
action='edit',
|
||||||
|
instance_pk__in=set(round_tds.keys())
|
||||||
|
).order_by('-timestamp')
|
||||||
|
|
||||||
|
# Find the last dice that was launched
|
||||||
|
async for changelog in changelogs:
|
||||||
|
data = json.loads(changelog.data)
|
||||||
|
if 'passage_dice' in data and data['passage_dice']:
|
||||||
|
last_td = round_tds[int(changelog.instance_pk)]
|
||||||
|
# Reset the dice
|
||||||
|
last_td.passage_dice = None
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
# Reset the dice on the interface
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'result': None})
|
||||||
|
break
|
||||||
|
|
||||||
|
async for td in r.team_draws.prefetch_related('participation__team').all():
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': td.participation.team.trigram,
|
||||||
|
'result': td.passage_dice})
|
||||||
|
|
||||||
|
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
|
||||||
|
{'type': 'draw.dice_visibility', 'visible': True})
|
||||||
|
|
||||||
|
async def undo_order_dice(self):
|
||||||
|
"""
|
||||||
|
Undo the last dice for the passage order, or abort the draw if we are at the beginning.
|
||||||
|
"""
|
||||||
|
content_type = await ContentType.objects.aget(app_label=TeamDraw._meta.app_label,
|
||||||
|
model=TeamDraw._meta.model_name)
|
||||||
|
|
||||||
|
r = self.tournament.draw.current_round
|
||||||
|
already_launched_tds = {td.id: td async for td in r.team_draws.filter(passage_dice__isnull=False)
|
||||||
|
.prefetch_related('participation__team')}
|
||||||
|
|
||||||
|
if already_launched_tds:
|
||||||
|
# Reset the last dice
|
||||||
|
changelogs = Changelog.objects.filter(
|
||||||
|
model=content_type,
|
||||||
|
action='edit',
|
||||||
|
instance_pk__in=set(already_launched_tds.keys())
|
||||||
|
).order_by('-timestamp')
|
||||||
|
|
||||||
|
# Find the last dice that was launched
|
||||||
|
async for changelog in changelogs:
|
||||||
|
data = json.loads(changelog.data)
|
||||||
|
if 'passage_dice' in data and data['passage_dice']:
|
||||||
|
last_td = already_launched_tds[int(changelog.instance_pk)]
|
||||||
|
# Reset the dice
|
||||||
|
last_td.passage_dice = None
|
||||||
|
await last_td.asave()
|
||||||
|
|
||||||
|
# Reset the dice on the interface
|
||||||
|
await self.channel_layer.group_send(
|
||||||
|
f"tournament-{self.tournament.id}", {'type': 'draw.dice',
|
||||||
|
'team': last_td.participation.team.trigram,
|
||||||
|
'result': None})
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
await self.abort()
|
||||||
|
|
||||||
async def draw_alert(self, content):
|
async def draw_alert(self, content):
|
||||||
"""
|
"""
|
||||||
Send alert to the current user.
|
Send alert to the current user.
|
||||||
|
@ -20,6 +20,15 @@ function abortDraw(tid) {
|
|||||||
sockets[tid].send(JSON.stringify({'type': 'abort'}))
|
sockets[tid].send(JSON.stringify({'type': 'abort'}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to cancel the last step.
|
||||||
|
* Only volunteers are allowed to do this.
|
||||||
|
* @param tid The tournament id
|
||||||
|
*/
|
||||||
|
function cancelLastStep(tid) {
|
||||||
|
sockets[tid].send(JSON.stringify({'type': 'cancel'}))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request to launch a dice between 1 and 100, for the two first steps.
|
* Request to launch a dice between 1 and 100, for the two first steps.
|
||||||
* The parameter `trigram` can be specified (by volunteers) to launch a dice for a specific team.
|
* The parameter `trigram` can be specified (by volunteers) to launch a dice for a specific team.
|
||||||
@ -583,13 +592,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
function setProblemAccepted(round, team, problem) {
|
function setProblemAccepted(round, team, problem) {
|
||||||
// Update recap
|
// Update recap
|
||||||
let recapDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-accepted`)
|
let recapDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-accepted`)
|
||||||
|
if (problem !== null) {
|
||||||
recapDiv.classList.remove('text-bg-warning')
|
recapDiv.classList.remove('text-bg-warning')
|
||||||
recapDiv.classList.add('text-bg-success')
|
recapDiv.classList.add('text-bg-success')
|
||||||
recapDiv.textContent = `${team} 📃 ${problem}`
|
}
|
||||||
|
else {
|
||||||
|
recapDiv.classList.add('text-bg-warning')
|
||||||
|
recapDiv.classList.remove('text-bg-success')
|
||||||
|
}
|
||||||
|
recapDiv.textContent = `${team} 📃 ${problem ? problem : '?'}`
|
||||||
|
|
||||||
// Update table
|
// Update table
|
||||||
let tableSpan = document.getElementById(`table-${tournament.id}-round-${round}-problem-${team}`)
|
let tableSpan = document.getElementById(`table-${tournament.id}-round-${round}-problem-${team}`)
|
||||||
tableSpan.textContent = problem
|
tableSpan.textContent = problem ? problem : '?'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -603,9 +618,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let recapDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-rejected`)
|
let recapDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-rejected`)
|
||||||
recapDiv.textContent = `🗑️ ${rejected.join(', ')}`
|
recapDiv.textContent = `🗑️ ${rejected.join(', ')}`
|
||||||
|
|
||||||
|
let penaltyDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-penalty`)
|
||||||
if (rejected.length > problems_count - 5) {
|
if (rejected.length > problems_count - 5) {
|
||||||
// If more than P - 5 problems were rejected, add a penalty of 0.5 of the coefficient of the oral defender
|
// If more than P - 5 problems were rejected, add a penalty of 0.5 of the coefficient of the oral defender
|
||||||
let penaltyDiv = document.getElementById(`recap-${tournament.id}-round-${round}-team-${team}-penalty`)
|
|
||||||
if (penaltyDiv === null) {
|
if (penaltyDiv === null) {
|
||||||
penaltyDiv = document.createElement('div')
|
penaltyDiv = document.createElement('div')
|
||||||
penaltyDiv.id = `recap-${tournament.id}-round-${round}-team-${team}-penalty`
|
penaltyDiv.id = `recap-${tournament.id}-round-${round}-team-${team}-penalty`
|
||||||
@ -614,6 +629,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
penaltyDiv.textContent = `❌ ${0.5 * (rejected.length - (problems_count - 5))}`
|
penaltyDiv.textContent = `❌ ${0.5 * (rejected.length - (problems_count - 5))}`
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Eventually remove this div
|
||||||
|
if (penaltyDiv !== null)
|
||||||
|
penaltyDiv.remove()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,9 +55,10 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
Recap
|
Recap
|
||||||
{% if user.registration.is_volunteer %}
|
{% if user.registration.is_volunteer %}
|
||||||
{# Volunteers can click on this button to abort the draw #}
|
<button id="cancel-last-step-{{ tournament.id }}"
|
||||||
<button id="abort-{{ tournament.id }}" class="badge rounded-pill text-bg-danger" onclick="abortDraw({{ tournament.id }})">
|
class="badge rounded-pill text-bg-warning"
|
||||||
{% trans "Abort" %}
|
onclick="cancelLastStep({{ tournament.id }})">
|
||||||
|
🔙 {% trans "Cancel last step" %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -326,4 +327,33 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if user.registration.is_volunteer %}
|
||||||
|
{# Volunteers can click on this button to abort the draw #}
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<button id="abort-{{ tournament.id }}" class="badge rounded-pill text-bg-danger" data-bs-toggle="modal" data-bs-target="#abort{{ tournament.id }}Modal">
|
||||||
|
{% trans "Abort" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="abort{{ tournament.id }}Modal" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">{% trans "Are you sure?" %}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
{% trans "This will reset the draw from the beginning." %}
|
||||||
|
{% trans "This operation is irreversible." %}
|
||||||
|
{% trans "Are you sure you want to abort this draw?" %}
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-danger" onclick="abortDraw({{ tournament.id }})">{% trans "Abort" %}</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Close" %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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: 2023-04-05 16:46+0200\n"
|
"POT-Creation-Date: 2023-04-05 18:54+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"
|
||||||
@ -26,15 +26,15 @@ msgstr "API"
|
|||||||
msgid "teams"
|
msgid "teams"
|
||||||
msgstr "équipes"
|
msgstr "équipes"
|
||||||
|
|
||||||
#: draw/admin.py:40 draw/admin.py:56 draw/models.py:25
|
#: draw/admin.py:40 draw/admin.py:56 draw/models.py:24
|
||||||
#: participation/admin.py:16 participation/admin.py:73
|
#: participation/admin.py:16 participation/admin.py:73
|
||||||
#: participation/admin.py:104 participation/models.py:296
|
#: participation/admin.py:104 participation/models.py:295
|
||||||
#: participation/models.py:320 participation/models.py:352
|
#: participation/models.py:319 participation/models.py:351
|
||||||
msgid "tournament"
|
msgid "tournament"
|
||||||
msgstr "tournoi"
|
msgstr "tournoi"
|
||||||
|
|
||||||
#: draw/admin.py:60 draw/models.py:229 draw/models.py:415
|
#: draw/admin.py:60 draw/models.py:228 draw/models.py:414
|
||||||
#: participation/models.py:356
|
#: participation/models.py:355
|
||||||
msgid "round"
|
msgid "round"
|
||||||
msgstr "tour"
|
msgstr "tour"
|
||||||
|
|
||||||
@ -42,237 +42,237 @@ msgstr "tour"
|
|||||||
msgid "Draw"
|
msgid "Draw"
|
||||||
msgstr "Tirage au sort"
|
msgstr "Tirage au sort"
|
||||||
|
|
||||||
#: draw/consumers.py:26
|
#: draw/consumers.py:25
|
||||||
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:146
|
#: draw/consumers.py:148
|
||||||
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:152
|
#: draw/consumers.py:154
|
||||||
msgid "Invalid format"
|
msgid "Invalid format"
|
||||||
msgstr "Format invalide"
|
msgstr "Format invalide"
|
||||||
|
|
||||||
#: draw/consumers.py:157
|
#: draw/consumers.py:159
|
||||||
#, 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:162
|
#: draw/consumers.py:164
|
||||||
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:190
|
#: draw/consumers.py:192
|
||||||
msgid "Draw started!"
|
msgid "Draw started!"
|
||||||
msgstr "Le tirage a commencé !"
|
msgstr "Le tirage a commencé !"
|
||||||
|
|
||||||
#: draw/consumers.py:210
|
#: draw/consumers.py:212
|
||||||
#, 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:221 draw/consumers.py:247 draw/consumers.py:578
|
#: draw/consumers.py:223 draw/consumers.py:248 draw/consumers.py:579
|
||||||
#: draw/consumers.py:749 draw/consumers.py:832 draw/consumers.py:849
|
#: draw/consumers.py:768 draw/consumers.py:850 draw/consumers.py:867
|
||||||
#: draw/templates/draw/tournament_content.html:5
|
#: draw/consumers.py:937 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:233
|
#: draw/consumers.py:235
|
||||||
#, 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:274 draw/consumers.py:295 draw/consumers.py:524
|
#: draw/consumers.py:275 draw/consumers.py:296 draw/consumers.py:525
|
||||||
#: draw/consumers.py:583 draw/consumers.py:754
|
#: draw/consumers.py:584 draw/consumers.py:773
|
||||||
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:287 draw/consumers.py:290
|
#: draw/consumers.py:288 draw/consumers.py:291
|
||||||
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:293
|
#: draw/consumers.py:294
|
||||||
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:371
|
#: draw/consumers.py:372
|
||||||
#, 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:852
|
#: draw/consumers.py:870
|
||||||
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/models.py:26
|
#: draw/models.py:25
|
||||||
msgid "The associated tournament."
|
msgid "The associated tournament."
|
||||||
msgstr "Le tournoi associé."
|
msgstr "Le tournoi associé."
|
||||||
|
|
||||||
#: draw/models.py:35
|
#: draw/models.py:34
|
||||||
msgid "current round"
|
msgid "current round"
|
||||||
msgstr "tour actuel"
|
msgstr "tour actuel"
|
||||||
|
|
||||||
#: draw/models.py:36
|
#: draw/models.py:35
|
||||||
msgid "The current round where teams select their problems."
|
msgid "The current round where teams select their problems."
|
||||||
msgstr "Le tour en cours où les équipes choisissent leurs problèmes."
|
msgstr "Le tour en cours où les équipes choisissent leurs problèmes."
|
||||||
|
|
||||||
#: draw/models.py:42
|
#: draw/models.py:41
|
||||||
msgid "last message"
|
msgid "last message"
|
||||||
msgstr "dernier message"
|
msgstr "dernier message"
|
||||||
|
|
||||||
#: draw/models.py:43
|
#: draw/models.py:42
|
||||||
msgid "The last message that is displayed on the drawing interface."
|
msgid "The last message that is displayed on the drawing interface."
|
||||||
msgstr "Le dernier message qui est affiché sur l'interface de tirage."
|
msgstr "Le dernier message qui est affiché sur l'interface de tirage."
|
||||||
|
|
||||||
#: draw/models.py:172
|
#: draw/models.py:171
|
||||||
#, 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:175 draw/models.py:187
|
#: draw/models.py:174 draw/models.py:186
|
||||||
msgid "draw"
|
msgid "draw"
|
||||||
msgstr "tirage au sort"
|
msgstr "tirage au sort"
|
||||||
|
|
||||||
#: draw/models.py:176
|
#: draw/models.py:175
|
||||||
msgid "draws"
|
msgid "draws"
|
||||||
msgstr "tirages au sort"
|
msgstr "tirages au sort"
|
||||||
|
|
||||||
#: draw/models.py:192
|
#: draw/models.py:191
|
||||||
msgid "Round 1"
|
msgid "Round 1"
|
||||||
msgstr "Tour 1"
|
msgstr "Tour 1"
|
||||||
|
|
||||||
#: draw/models.py:193
|
#: draw/models.py:192
|
||||||
msgid "Round 2"
|
msgid "Round 2"
|
||||||
msgstr "Tour 2"
|
msgstr "Tour 2"
|
||||||
|
|
||||||
#: draw/models.py:195
|
#: draw/models.py:194
|
||||||
msgid "number"
|
msgid "number"
|
||||||
msgstr "numéro"
|
msgstr "numéro"
|
||||||
|
|
||||||
#: draw/models.py:196
|
#: draw/models.py:195
|
||||||
msgid "The number of the round, 1 or 2"
|
msgid "The number of the round, 1 or 2"
|
||||||
msgstr "Le numéro du tour, 1 ou 2"
|
msgstr "Le numéro du tour, 1 ou 2"
|
||||||
|
|
||||||
#: draw/models.py:206
|
#: draw/models.py:205
|
||||||
msgid "current pool"
|
msgid "current pool"
|
||||||
msgstr "poule actuelle"
|
msgstr "poule actuelle"
|
||||||
|
|
||||||
#: draw/models.py:207
|
#: draw/models.py:206
|
||||||
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:230
|
#: draw/models.py:229
|
||||||
msgid "rounds"
|
msgid "rounds"
|
||||||
msgstr "tours"
|
msgstr "tours"
|
||||||
|
|
||||||
#: draw/models.py:252 participation/models.py:370
|
#: draw/models.py:251 participation/models.py:369
|
||||||
msgid "letter"
|
msgid "letter"
|
||||||
msgstr "lettre"
|
msgstr "lettre"
|
||||||
|
|
||||||
#: draw/models.py:253
|
#: draw/models.py:252
|
||||||
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:257
|
#: draw/models.py:256
|
||||||
#: 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:259
|
#: draw/models.py:258
|
||||||
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:268
|
#: draw/models.py:267
|
||||||
msgid "current team"
|
msgid "current team"
|
||||||
msgstr "équipe actuelle"
|
msgstr "équipe actuelle"
|
||||||
|
|
||||||
#: draw/models.py:269
|
#: draw/models.py:268
|
||||||
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:278
|
#: draw/models.py:277
|
||||||
msgid "associated pool"
|
msgid "associated pool"
|
||||||
msgstr "poule associée"
|
msgstr "poule associée"
|
||||||
|
|
||||||
#: draw/models.py:279
|
#: draw/models.py:278
|
||||||
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:393
|
#: draw/models.py:392
|
||||||
#, 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:396 draw/models.py:423 participation/admin.py:69
|
#: draw/models.py:395 draw/models.py:422 participation/admin.py:69
|
||||||
#: participation/admin.py:88 participation/models.py:422
|
#: participation/admin.py:88 participation/models.py:421
|
||||||
#: participation/models.py:431 participation/tables.py:82
|
#: participation/models.py:430 participation/tables.py:82
|
||||||
msgid "pool"
|
msgid "pool"
|
||||||
msgstr "poule"
|
msgstr "poule"
|
||||||
|
|
||||||
#: draw/models.py:397 participation/models.py:423
|
#: draw/models.py:396 participation/models.py:422
|
||||||
msgid "pools"
|
msgid "pools"
|
||||||
msgstr "poules"
|
msgstr "poules"
|
||||||
|
|
||||||
#: draw/models.py:409 participation/models.py:343 participation/models.py:555
|
#: draw/models.py:408 participation/models.py:342 participation/models.py:554
|
||||||
#: participation/models.py:585 participation/models.py:623
|
#: participation/models.py:584 participation/models.py:622
|
||||||
msgid "participation"
|
msgid "participation"
|
||||||
msgstr "participation"
|
msgstr "participation"
|
||||||
|
|
||||||
#: draw/models.py:430
|
#: draw/models.py:429
|
||||||
msgid "passage index"
|
msgid "passage index"
|
||||||
msgstr "numéro de passage"
|
msgstr "numéro de passage"
|
||||||
|
|
||||||
#: draw/models.py:431
|
#: draw/models.py:430
|
||||||
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:439
|
#: draw/models.py:438
|
||||||
msgid "choose index"
|
msgid "choose index"
|
||||||
msgstr "numéro de choix"
|
msgstr "numéro de choix"
|
||||||
|
|
||||||
#: draw/models.py:440
|
#: draw/models.py:439
|
||||||
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:446 draw/models.py:469 participation/models.py:438
|
#: draw/models.py:445 draw/models.py:468 participation/models.py:437
|
||||||
#: participation/models.py:592
|
#: participation/models.py:591
|
||||||
#, 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:450 draw/models.py:473
|
#: draw/models.py:449 draw/models.py:472
|
||||||
msgid "accepted problem"
|
msgid "accepted problem"
|
||||||
msgstr "problème accepté"
|
msgstr "problème accepté"
|
||||||
|
|
||||||
#: draw/models.py:457
|
#: draw/models.py:456
|
||||||
msgid "passage dice"
|
msgid "passage dice"
|
||||||
msgstr "dé d'ordre de passage"
|
msgstr "dé d'ordre de passage"
|
||||||
|
|
||||||
#: draw/models.py:464
|
#: draw/models.py:463
|
||||||
msgid "choice dice"
|
msgid "choice dice"
|
||||||
msgstr "dé d'ordre de choix"
|
msgstr "dé d'ordre de choix"
|
||||||
|
|
||||||
#: draw/models.py:478
|
#: draw/models.py:477
|
||||||
msgid "rejected problems"
|
msgid "rejected problems"
|
||||||
msgstr "problèmes rejetés"
|
msgstr "problèmes rejetés"
|
||||||
|
|
||||||
#: draw/models.py:504
|
#: draw/models.py:503
|
||||||
#, 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:510
|
#: draw/models.py:509
|
||||||
msgid "team draw"
|
msgid "team draw"
|
||||||
msgstr "tirage d'équipe"
|
msgstr "tirage d'équipe"
|
||||||
|
|
||||||
#: draw/models.py:511
|
#: draw/models.py:510
|
||||||
msgid "team draws"
|
msgid "team draws"
|
||||||
msgstr "tirages d'équipe"
|
msgstr "tirages d'équipe"
|
||||||
|
|
||||||
@ -288,36 +288,36 @@ msgstr "Démarrer !"
|
|||||||
msgid "Last dices"
|
msgid "Last dices"
|
||||||
msgstr "Derniers jets de dés"
|
msgstr "Derniers jets de dés"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:60
|
#: draw/templates/draw/tournament_content.html:129
|
||||||
msgid "Abort"
|
|
||||||
msgstr "Annuler"
|
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:135
|
|
||||||
msgid "Launch dice"
|
msgid "Launch dice"
|
||||||
msgstr "Lancer le dé"
|
msgstr "Lancer le dé"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:149
|
#: draw/templates/draw/tournament_content.html:143
|
||||||
msgid "Draw a problem"
|
msgid "Draw a problem"
|
||||||
msgstr "Tirer un problème"
|
msgstr "Tirer un problème"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:160
|
#: draw/templates/draw/tournament_content.html:154
|
||||||
msgid "Accept"
|
msgid "Accept"
|
||||||
msgstr "Accepter"
|
msgstr "Accepter"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:163
|
#: draw/templates/draw/tournament_content.html:157
|
||||||
msgid "Decline"
|
msgid "Decline"
|
||||||
msgstr "Refuser"
|
msgstr "Refuser"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:174
|
#: draw/templates/draw/tournament_content.html:168
|
||||||
msgid "Export"
|
msgid "Export"
|
||||||
msgstr "Exporter"
|
msgstr "Exporter"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:182
|
#: draw/templates/draw/tournament_content.html:176
|
||||||
msgid "Continue draw"
|
msgid "Continue draw"
|
||||||
msgstr "Continuer le tirage"
|
msgstr "Continuer le tirage"
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:183
|
||||||
|
msgid "Cancel last step"
|
||||||
|
msgstr "Annuler la dernière étape"
|
||||||
|
|
||||||
#: draw/templates/draw/tournament_content.html:215 participation/admin.py:100
|
#: draw/templates/draw/tournament_content.html:215 participation/admin.py:100
|
||||||
#: participation/models.py:125 participation/models.py:311
|
#: participation/models.py:125 participation/models.py:310
|
||||||
#: registration/models.py:127
|
#: registration/models.py:127
|
||||||
msgid "team"
|
msgid "team"
|
||||||
msgstr "équipe"
|
msgstr "équipe"
|
||||||
@ -330,6 +330,32 @@ msgstr "équipe"
|
|||||||
msgid "Room"
|
msgid "Room"
|
||||||
msgstr "Salle"
|
msgstr "Salle"
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:335
|
||||||
|
#: draw/templates/draw/tournament_content.html:353
|
||||||
|
msgid "Abort"
|
||||||
|
msgstr "Annuler"
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:344
|
||||||
|
msgid "Are you sure?"
|
||||||
|
msgstr "Êtes-vous sûr⋅e ?"
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:348
|
||||||
|
msgid "This will reset the draw from the beginning."
|
||||||
|
msgstr "Cela va réinitialiser le tirage au sort depuis le début."
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:349
|
||||||
|
msgid "This operation is irreversible."
|
||||||
|
msgstr "Cette opération est irréversible."
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:350
|
||||||
|
msgid "Are you sure you want to abort this draw?"
|
||||||
|
msgstr "Êtes-vous sûr·e de vouloir annuler le tirage au sort ?"
|
||||||
|
|
||||||
|
#: draw/templates/draw/tournament_content.html:354
|
||||||
|
#: tfjm/templates/base_modal.html:17
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Fermer"
|
||||||
|
|
||||||
#: logs/apps.py:11
|
#: logs/apps.py:11
|
||||||
msgid "Logs"
|
msgid "Logs"
|
||||||
msgstr "Logs"
|
msgstr "Logs"
|
||||||
@ -399,26 +425,26 @@ msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}"
|
|||||||
msgid "valid"
|
msgid "valid"
|
||||||
msgstr "valide"
|
msgstr "valide"
|
||||||
|
|
||||||
#: participation/admin.py:24 participation/models.py:332
|
#: participation/admin.py:24 participation/models.py:331
|
||||||
msgid "selected for final"
|
msgid "selected for final"
|
||||||
msgstr "sélectionnée pour la finale"
|
msgstr "sélectionnée pour la finale"
|
||||||
|
|
||||||
#: participation/admin.py:57 participation/admin.py:116
|
#: participation/admin.py:57 participation/admin.py:116
|
||||||
#: participation/models.py:445 participation/tables.py:109
|
#: participation/models.py:444 participation/tables.py:109
|
||||||
msgid "defender"
|
msgid "defender"
|
||||||
msgstr "défenseur⋅se"
|
msgstr "défenseur⋅se"
|
||||||
|
|
||||||
#: participation/admin.py:61 participation/models.py:452
|
#: participation/admin.py:61 participation/models.py:451
|
||||||
#: participation/models.py:635
|
#: participation/models.py:634
|
||||||
msgid "opponent"
|
msgid "opponent"
|
||||||
msgstr "opposant⋅e"
|
msgstr "opposant⋅e"
|
||||||
|
|
||||||
#: participation/admin.py:65 participation/models.py:459
|
#: participation/admin.py:65 participation/models.py:458
|
||||||
#: participation/models.py:636
|
#: participation/models.py:635
|
||||||
msgid "reporter"
|
msgid "reporter"
|
||||||
msgstr "rapporteur⋅e"
|
msgstr "rapporteur⋅e"
|
||||||
|
|
||||||
#: participation/admin.py:120 participation/models.py:590
|
#: participation/admin.py:120 participation/models.py:589
|
||||||
msgid "problem"
|
msgid "problem"
|
||||||
msgstr "numéro de problème"
|
msgstr "numéro de problème"
|
||||||
|
|
||||||
@ -471,17 +497,17 @@ msgstr "Le fichier envoyé doit être au format PDF."
|
|||||||
msgid "The PDF file must not have more than 30 pages."
|
msgid "The PDF file must not have more than 30 pages."
|
||||||
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
|
msgstr "Le fichier PDF ne doit pas avoir plus de 30 pages."
|
||||||
|
|
||||||
#: participation/forms.py:209
|
#: participation/forms.py:210
|
||||||
msgid "Add new jury"
|
msgid "Add new jury"
|
||||||
msgstr "Ajouter un⋅e nouvelleau juré⋅e"
|
msgstr "Ajouter un⋅e nouvelleau juré⋅e"
|
||||||
|
|
||||||
#: participation/forms.py:224
|
#: participation/forms.py:225
|
||||||
#: participation/templates/participation/pool_detail.html:77
|
#: participation/templates/participation/pool_detail.html:77
|
||||||
#: participation/templates/participation/tournament_detail.html:111
|
#: participation/templates/participation/tournament_detail.html:111
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr "Ajouter"
|
msgstr "Ajouter"
|
||||||
|
|
||||||
#: participation/forms.py:237 registration/forms.py:35 registration/forms.py:60
|
#: participation/forms.py:238 registration/forms.py:35 registration/forms.py:60
|
||||||
msgid "This email address is already used."
|
msgid "This email address is already used."
|
||||||
msgstr "Cette adresse e-mail est déjà utilisée."
|
msgstr "Cette adresse e-mail est déjà utilisée."
|
||||||
|
|
||||||
@ -608,53 +634,53 @@ msgstr "organisateur⋅rices"
|
|||||||
msgid "final"
|
msgid "final"
|
||||||
msgstr "finale"
|
msgstr "finale"
|
||||||
|
|
||||||
#: participation/models.py:297 registration/admin.py:92
|
#: participation/models.py:296 registration/admin.py:93
|
||||||
msgid "tournaments"
|
msgid "tournaments"
|
||||||
msgstr "tournois"
|
msgstr "tournois"
|
||||||
|
|
||||||
#: participation/models.py:326
|
#: participation/models.py:325
|
||||||
msgid "valid team"
|
msgid "valid team"
|
||||||
msgstr "équipe valide"
|
msgstr "équipe valide"
|
||||||
|
|
||||||
#: participation/models.py:327
|
#: participation/models.py:326
|
||||||
msgid "The participation got the validation of the organizers."
|
msgid "The participation got the validation of the organizers."
|
||||||
msgstr "La participation a été validée par les organisateur⋅rices."
|
msgstr "La participation a été validée par les organisateur⋅rices."
|
||||||
|
|
||||||
#: participation/models.py:333
|
#: participation/models.py:332
|
||||||
msgid "The team is selected for the final tournament."
|
msgid "The team is selected for the final tournament."
|
||||||
msgstr "L'équipe est sélectionnée pour la finale."
|
msgstr "L'équipe est sélectionnée pour la finale."
|
||||||
|
|
||||||
#: participation/models.py:340
|
#: participation/models.py:339
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Participation of the team {name} ({trigram})"
|
msgid "Participation of the team {name} ({trigram})"
|
||||||
msgstr "Participation de l'équipe {name} ({trigram})"
|
msgstr "Participation de l'équipe {name} ({trigram})"
|
||||||
|
|
||||||
#: participation/models.py:344 participation/models.py:376
|
#: participation/models.py:343 participation/models.py:375
|
||||||
msgid "participations"
|
msgid "participations"
|
||||||
msgstr "participations"
|
msgstr "participations"
|
||||||
|
|
||||||
#: participation/models.py:358 participation/models.py:359
|
#: participation/models.py:357 participation/models.py:358
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Round {round}"
|
msgid "Round {round}"
|
||||||
msgstr "Tour {round}"
|
msgstr "Tour {round}"
|
||||||
|
|
||||||
#: participation/models.py:382
|
#: participation/models.py:381
|
||||||
msgid "juries"
|
msgid "juries"
|
||||||
msgstr "jurys"
|
msgstr "jurys"
|
||||||
|
|
||||||
#: participation/models.py:389
|
#: participation/models.py:388
|
||||||
msgid "BigBlueButton URL"
|
msgid "BigBlueButton URL"
|
||||||
msgstr "Lien BigBlueButton"
|
msgstr "Lien BigBlueButton"
|
||||||
|
|
||||||
#: participation/models.py:390
|
#: participation/models.py:389
|
||||||
msgid "The link of the BBB visio for this pool."
|
msgid "The link of the BBB visio for this pool."
|
||||||
msgstr "Le lien du salon BBB pour cette poule."
|
msgstr "Le lien du salon BBB pour cette poule."
|
||||||
|
|
||||||
#: participation/models.py:395
|
#: participation/models.py:394
|
||||||
msgid "results available"
|
msgid "results available"
|
||||||
msgstr "résultats disponibles"
|
msgstr "résultats disponibles"
|
||||||
|
|
||||||
#: participation/models.py:396
|
#: participation/models.py:395
|
||||||
msgid ""
|
msgid ""
|
||||||
"Check this case when results become accessible to teams. They stay "
|
"Check this case when results become accessible to teams. They stay "
|
||||||
"accessible to you. Only averages are given."
|
"accessible to you. Only averages are given."
|
||||||
@ -663,20 +689,20 @@ msgstr ""
|
|||||||
"Ils restent toujours accessibles pour vous. Seules les moyennes sont "
|
"Ils restent toujours accessibles pour vous. Seules les moyennes sont "
|
||||||
"communiquées."
|
"communiquées."
|
||||||
|
|
||||||
#: participation/models.py:416
|
#: participation/models.py:415
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Pool of day {round} for tournament {tournament} with teams {teams}"
|
msgid "Pool of day {round} for tournament {tournament} with teams {teams}"
|
||||||
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}"
|
msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}"
|
||||||
|
|
||||||
#: participation/models.py:436
|
#: participation/models.py:435
|
||||||
msgid "defended solution"
|
msgid "defended solution"
|
||||||
msgstr "solution défendue"
|
msgstr "solution défendue"
|
||||||
|
|
||||||
#: participation/models.py:464
|
#: participation/models.py:463
|
||||||
msgid "penalties"
|
msgid "penalties"
|
||||||
msgstr "pénalités"
|
msgstr "pénalités"
|
||||||
|
|
||||||
#: participation/models.py:466
|
#: participation/models.py:465
|
||||||
msgid ""
|
msgid ""
|
||||||
"Number of penalties for the defender. The defender will loose a 0.5 "
|
"Number of penalties for the defender. The defender will loose a 0.5 "
|
||||||
"coefficient per penalty."
|
"coefficient per penalty."
|
||||||
@ -684,120 +710,120 @@ msgstr ""
|
|||||||
"Nombre de pénalités pour læ défenseur⋅se. Læ défenseur⋅se perd un "
|
"Nombre de pénalités pour læ défenseur⋅se. Læ défenseur⋅se perd un "
|
||||||
"coefficient 0.5 sur sa présentation orale par pénalité."
|
"coefficient 0.5 sur sa présentation orale par pénalité."
|
||||||
|
|
||||||
#: participation/models.py:526 participation/models.py:529
|
#: participation/models.py:525 participation/models.py:528
|
||||||
#: participation/models.py:532
|
#: participation/models.py:531
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Team {trigram} is not registered in the pool."
|
msgid "Team {trigram} is not registered in the pool."
|
||||||
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
|
msgstr "L'équipe {trigram} n'est pas inscrite dans la poule."
|
||||||
|
|
||||||
#: participation/models.py:537
|
#: participation/models.py:536
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Passage of {defender} for problem {problem}"
|
msgid "Passage of {defender} for problem {problem}"
|
||||||
msgstr "Passage de {defender} pour le problème {problem}"
|
msgstr "Passage de {defender} pour le problème {problem}"
|
||||||
|
|
||||||
#: participation/models.py:541 participation/models.py:549
|
#: participation/models.py:540 participation/models.py:548
|
||||||
#: participation/models.py:630 participation/models.py:672
|
#: participation/models.py:629 participation/models.py:671
|
||||||
msgid "passage"
|
msgid "passage"
|
||||||
msgstr "passage"
|
msgstr "passage"
|
||||||
|
|
||||||
#: participation/models.py:542
|
#: participation/models.py:541
|
||||||
msgid "passages"
|
msgid "passages"
|
||||||
msgstr "passages"
|
msgstr "passages"
|
||||||
|
|
||||||
#: participation/models.py:560
|
#: participation/models.py:559
|
||||||
msgid "difference"
|
msgid "difference"
|
||||||
msgstr "différence"
|
msgstr "différence"
|
||||||
|
|
||||||
#: participation/models.py:561
|
#: participation/models.py:560
|
||||||
msgid "Score to add/remove on the final score"
|
msgid "Score to add/remove on the final score"
|
||||||
msgstr "Score à ajouter/retrancher au score final"
|
msgstr "Score à ajouter/retrancher au score final"
|
||||||
|
|
||||||
#: participation/models.py:568
|
#: participation/models.py:567
|
||||||
msgid "tweak"
|
msgid "tweak"
|
||||||
msgstr "harmonisation"
|
msgstr "harmonisation"
|
||||||
|
|
||||||
#: participation/models.py:569
|
#: participation/models.py:568
|
||||||
msgid "tweaks"
|
msgid "tweaks"
|
||||||
msgstr "harmonisations"
|
msgstr "harmonisations"
|
||||||
|
|
||||||
#: participation/models.py:597
|
#: participation/models.py:596
|
||||||
msgid "solution for the final tournament"
|
msgid "solution for the final tournament"
|
||||||
msgstr "solution pour la finale"
|
msgstr "solution pour la finale"
|
||||||
|
|
||||||
#: participation/models.py:602 participation/models.py:641
|
#: participation/models.py:601 participation/models.py:640
|
||||||
msgid "file"
|
msgid "file"
|
||||||
msgstr "fichier"
|
msgstr "fichier"
|
||||||
|
|
||||||
#: participation/models.py:608
|
#: participation/models.py:607
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Solution of team {team} for problem {problem}"
|
msgid "Solution of team {team} for problem {problem}"
|
||||||
msgstr "Solution de l'équipe {team} pour le problème {problem}"
|
msgstr "Solution de l'équipe {team} pour le problème {problem}"
|
||||||
|
|
||||||
#: participation/models.py:610
|
#: participation/models.py:609
|
||||||
msgid "for final"
|
msgid "for final"
|
||||||
msgstr "pour la finale"
|
msgstr "pour la finale"
|
||||||
|
|
||||||
#: participation/models.py:613
|
#: participation/models.py:612
|
||||||
msgid "solution"
|
msgid "solution"
|
||||||
msgstr "solution"
|
msgstr "solution"
|
||||||
|
|
||||||
#: participation/models.py:614
|
#: participation/models.py:613
|
||||||
msgid "solutions"
|
msgid "solutions"
|
||||||
msgstr "solutions"
|
msgstr "solutions"
|
||||||
|
|
||||||
#: participation/models.py:647
|
#: participation/models.py:646
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
|
msgid "Synthesis of {team} as {type} for problem {problem} of {defender}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
|
"Note de synthèse de l'équipe {team} en tant que {type} pour le problème "
|
||||||
"{problem} de {defender}"
|
"{problem} de {defender}"
|
||||||
|
|
||||||
#: participation/models.py:655
|
#: participation/models.py:654
|
||||||
msgid "synthesis"
|
msgid "synthesis"
|
||||||
msgstr "note de synthèse"
|
msgstr "note de synthèse"
|
||||||
|
|
||||||
#: participation/models.py:656
|
#: participation/models.py:655
|
||||||
msgid "syntheses"
|
msgid "syntheses"
|
||||||
msgstr "notes de synthèse"
|
msgstr "notes de synthèse"
|
||||||
|
|
||||||
#: participation/models.py:665
|
#: participation/models.py:664
|
||||||
msgid "jury"
|
msgid "jury"
|
||||||
msgstr "jury"
|
msgstr "jury"
|
||||||
|
|
||||||
#: participation/models.py:677
|
#: participation/models.py:676
|
||||||
msgid "defender writing note"
|
msgid "defender writing note"
|
||||||
msgstr "note d'écrit de læ défenseur⋅se"
|
msgstr "note d'écrit de læ défenseur⋅se"
|
||||||
|
|
||||||
#: participation/models.py:683
|
#: participation/models.py:682
|
||||||
msgid "defender oral note"
|
msgid "defender oral note"
|
||||||
msgstr "note d'oral de læ défenseur⋅se"
|
msgstr "note d'oral de læ défenseur⋅se"
|
||||||
|
|
||||||
#: participation/models.py:689
|
#: participation/models.py:688
|
||||||
msgid "opponent writing note"
|
msgid "opponent writing note"
|
||||||
msgstr "note d'écrit de l'opposant⋅e"
|
msgstr "note d'écrit de l'opposant⋅e"
|
||||||
|
|
||||||
#: participation/models.py:695
|
#: participation/models.py:694
|
||||||
msgid "opponent oral note"
|
msgid "opponent oral note"
|
||||||
msgstr "note d'oral de l'opposant⋅e"
|
msgstr "note d'oral de l'opposant⋅e"
|
||||||
|
|
||||||
#: participation/models.py:701
|
#: participation/models.py:700
|
||||||
msgid "reporter writing note"
|
msgid "reporter writing note"
|
||||||
msgstr "note d'écrit de læ rapporteur⋅e"
|
msgstr "note d'écrit de læ rapporteur⋅e"
|
||||||
|
|
||||||
#: participation/models.py:707
|
#: participation/models.py:706
|
||||||
msgid "reporter oral note"
|
msgid "reporter oral note"
|
||||||
msgstr "note d'oral de læ rapporteur⋅e"
|
msgstr "note d'oral de læ rapporteur⋅e"
|
||||||
|
|
||||||
#: participation/models.py:725
|
#: participation/models.py:724
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Notes of {jury} for {passage}"
|
msgid "Notes of {jury} for {passage}"
|
||||||
msgstr "Notes de {jury} pour le {passage}"
|
msgstr "Notes de {jury} pour le {passage}"
|
||||||
|
|
||||||
#: participation/models.py:732
|
#: participation/models.py:731
|
||||||
msgid "note"
|
msgid "note"
|
||||||
msgstr "note"
|
msgstr "note"
|
||||||
|
|
||||||
#: participation/models.py:733
|
#: participation/models.py:732
|
||||||
msgid "notes"
|
msgid "notes"
|
||||||
msgstr "notes"
|
msgstr "notes"
|
||||||
|
|
||||||
@ -1061,8 +1087,8 @@ msgid ""
|
|||||||
"Be careful: this form register new users. To add existing users into the "
|
"Be careful: this form register new users. To add existing users into the "
|
||||||
"jury, please use this form:"
|
"jury, please use this form:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Attention : ce formulaire inscrit des nouvelleaux utilisateur⋅rices. "
|
"Attention : ce formulaire inscrit des nouvelleaux utilisateur⋅rices. Pour "
|
||||||
"Pour ajouter des utilisateur⋅rices au jury, utilisez ce formulaire :"
|
"ajouter des utilisateur⋅rices au jury, utilisez ce formulaire :"
|
||||||
|
|
||||||
#: participation/templates/participation/pool_add_jurys.html:11
|
#: participation/templates/participation/pool_add_jurys.html:11
|
||||||
#: participation/templates/participation/pool_add_jurys.html:34
|
#: participation/templates/participation/pool_add_jurys.html:34
|
||||||
@ -1504,43 +1530,43 @@ msgstr "Participation de l'équipe {trigram}"
|
|||||||
msgid "You can't upload a solution after the deadline."
|
msgid "You can't upload a solution after the deadline."
|
||||||
msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
|
msgstr "Vous ne pouvez pas envoyer de solution après la date limite."
|
||||||
|
|
||||||
#: participation/views.py:727
|
#: participation/views.py:730
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Jurys of {pool}"
|
msgid "Jurys of {pool}"
|
||||||
msgstr "Juré⋅es de la {pool}"
|
msgstr "Juré⋅es de la {pool}"
|
||||||
|
|
||||||
#: participation/views.py:749
|
#: participation/views.py:757
|
||||||
msgid "New TFJM² jury account"
|
msgid "New TFJM² jury account"
|
||||||
msgstr "Nouveau compte de juré⋅e pour le TFJM²"
|
msgstr "Nouveau compte de juré⋅e pour le TFJM²"
|
||||||
|
|
||||||
#: participation/views.py:761
|
#: participation/views.py:770
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "The jury {name} has been successfully added!"
|
msgid "The jury {name} has been successfully added!"
|
||||||
msgstr "Læ juré⋅e {name} a été ajouté⋅e avec succès !"
|
msgstr "Læ juré⋅e {name} a été ajouté⋅e avec succès !"
|
||||||
|
|
||||||
#: participation/views.py:796
|
#: participation/views.py:806
|
||||||
msgid "The following user is not registered as a jury:"
|
msgid "The following user is not registered as a jury:"
|
||||||
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
|
msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :"
|
||||||
|
|
||||||
#: participation/views.py:804
|
#: participation/views.py:814
|
||||||
msgid "Notes were successfully uploaded."
|
msgid "Notes were successfully uploaded."
|
||||||
msgstr "Les notes ont bien été envoyées."
|
msgstr "Les notes ont bien été envoyées."
|
||||||
|
|
||||||
#: participation/views.py:916
|
#: participation/views.py:926
|
||||||
msgid "You can't upload a synthesis after the deadline."
|
msgid "You can't upload a synthesis after the deadline."
|
||||||
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
|
msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite."
|
||||||
|
|
||||||
#: registration/admin.py:21 registration/admin.py:36 registration/admin.py:52
|
#: registration/admin.py:21 registration/admin.py:37 registration/admin.py:53
|
||||||
#: registration/admin.py:68 registration/admin.py:84
|
#: registration/admin.py:69 registration/admin.py:85
|
||||||
msgid "first name"
|
msgid "first name"
|
||||||
msgstr "prénom"
|
msgstr "prénom"
|
||||||
|
|
||||||
#: registration/admin.py:25 registration/admin.py:40 registration/admin.py:56
|
#: registration/admin.py:25 registration/admin.py:41 registration/admin.py:57
|
||||||
#: registration/admin.py:72 registration/admin.py:88 registration/tables.py:17
|
#: registration/admin.py:73 registration/admin.py:89 registration/tables.py:17
|
||||||
msgid "last name"
|
msgid "last name"
|
||||||
msgstr "nom de famille"
|
msgstr "nom de famille"
|
||||||
|
|
||||||
#: registration/admin.py:104
|
#: registration/admin.py:105
|
||||||
msgid "registration type"
|
msgid "registration type"
|
||||||
msgstr "type d'inscription"
|
msgstr "type d'inscription"
|
||||||
|
|
||||||
@ -1552,7 +1578,7 @@ msgstr "rôle"
|
|||||||
msgid "participant"
|
msgid "participant"
|
||||||
msgstr "participant⋅e"
|
msgstr "participant⋅e"
|
||||||
|
|
||||||
#: registration/forms.py:25 registration/models.py:286
|
#: registration/forms.py:25 registration/models.py:285
|
||||||
msgid "coach"
|
msgid "coach"
|
||||||
msgstr "encadrant⋅e"
|
msgstr "encadrant⋅e"
|
||||||
|
|
||||||
@ -1577,7 +1603,7 @@ msgstr "email confirmé"
|
|||||||
msgid "Activate your TFJM² account"
|
msgid "Activate your TFJM² account"
|
||||||
msgstr "Activez votre compte du TFJM²"
|
msgstr "Activez votre compte du TFJM²"
|
||||||
|
|
||||||
#: registration/models.py:99 registration/models.py:339
|
#: registration/models.py:99 registration/models.py:338
|
||||||
msgid "registration"
|
msgid "registration"
|
||||||
msgstr "inscription"
|
msgstr "inscription"
|
||||||
|
|
||||||
@ -1633,91 +1659,91 @@ msgstr ""
|
|||||||
msgid "photo authorization"
|
msgid "photo authorization"
|
||||||
msgstr "autorisation de droit à l'image"
|
msgstr "autorisation de droit à l'image"
|
||||||
|
|
||||||
#: registration/models.py:196
|
#: registration/models.py:195
|
||||||
msgid "participant registration"
|
msgid "participant registration"
|
||||||
msgstr "inscription de participant⋅e"
|
msgstr "inscription de participant⋅e"
|
||||||
|
|
||||||
#: registration/models.py:197
|
#: registration/models.py:196
|
||||||
msgid "participant registrations"
|
msgid "participant registrations"
|
||||||
msgstr "inscriptions de participant⋅es"
|
msgstr "inscriptions de participant⋅es"
|
||||||
|
|
||||||
#: registration/models.py:206
|
#: registration/models.py:205
|
||||||
msgid "birth date"
|
msgid "birth date"
|
||||||
msgstr "date de naissance"
|
msgstr "date de naissance"
|
||||||
|
|
||||||
#: registration/models.py:212
|
#: registration/models.py:211
|
||||||
msgid "12th grade"
|
msgid "12th grade"
|
||||||
msgstr "Terminale"
|
msgstr "Terminale"
|
||||||
|
|
||||||
#: registration/models.py:213
|
#: registration/models.py:212
|
||||||
msgid "11th grade"
|
msgid "11th grade"
|
||||||
msgstr "Première"
|
msgstr "Première"
|
||||||
|
|
||||||
#: registration/models.py:214
|
#: registration/models.py:213
|
||||||
msgid "10th grade or lower"
|
msgid "10th grade or lower"
|
||||||
msgstr "Seconde ou inférieur"
|
msgstr "Seconde ou inférieur"
|
||||||
|
|
||||||
#: registration/models.py:216
|
#: registration/models.py:215
|
||||||
msgid "student class"
|
msgid "student class"
|
||||||
msgstr "classe"
|
msgstr "classe"
|
||||||
|
|
||||||
#: registration/models.py:221
|
#: registration/models.py:220
|
||||||
msgid "school"
|
msgid "school"
|
||||||
msgstr "école"
|
msgstr "école"
|
||||||
|
|
||||||
#: registration/models.py:226
|
#: registration/models.py:225
|
||||||
msgid "responsible name"
|
msgid "responsible name"
|
||||||
msgstr "nom de læ responsable légal⋅e"
|
msgstr "nom de læ responsable légal⋅e"
|
||||||
|
|
||||||
#: registration/models.py:231
|
#: registration/models.py:230
|
||||||
msgid "responsible phone number"
|
msgid "responsible phone number"
|
||||||
msgstr "numéro de téléphone de læ responsable légal⋅e"
|
msgstr "numéro de téléphone de læ responsable légal⋅e"
|
||||||
|
|
||||||
#: registration/models.py:236
|
#: registration/models.py:235
|
||||||
msgid "responsible email address"
|
msgid "responsible email address"
|
||||||
msgstr "adresse e-mail de læ responsable légal⋅e"
|
msgstr "adresse e-mail de læ responsable légal⋅e"
|
||||||
|
|
||||||
#: registration/models.py:241
|
#: registration/models.py:240
|
||||||
msgid "parental authorization"
|
msgid "parental authorization"
|
||||||
msgstr "autorisation parentale"
|
msgstr "autorisation parentale"
|
||||||
|
|
||||||
#: registration/models.py:248
|
#: registration/models.py:247
|
||||||
msgid "health sheet"
|
msgid "health sheet"
|
||||||
msgstr "fiche sanitaire"
|
msgstr "fiche sanitaire"
|
||||||
|
|
||||||
#: registration/models.py:255
|
#: registration/models.py:254
|
||||||
msgid "vaccine sheet"
|
msgid "vaccine sheet"
|
||||||
msgstr "carnet de vaccination"
|
msgstr "carnet de vaccination"
|
||||||
|
|
||||||
#: registration/models.py:263
|
#: registration/models.py:262
|
||||||
msgid "student"
|
msgid "student"
|
||||||
msgstr "étudiant⋅e"
|
msgstr "étudiant⋅e"
|
||||||
|
|
||||||
#: registration/models.py:271
|
#: registration/models.py:270
|
||||||
msgid "student registration"
|
msgid "student registration"
|
||||||
msgstr "inscription d'élève"
|
msgstr "inscription d'élève"
|
||||||
|
|
||||||
#: registration/models.py:272
|
#: registration/models.py:271
|
||||||
msgid "student registrations"
|
msgid "student registrations"
|
||||||
msgstr "inscriptions d'élève"
|
msgstr "inscriptions d'élève"
|
||||||
|
|
||||||
#: registration/models.py:281 registration/models.py:303
|
#: registration/models.py:280 registration/models.py:302
|
||||||
msgid "professional activity"
|
msgid "professional activity"
|
||||||
msgstr "activité professionnelle"
|
msgstr "activité professionnelle"
|
||||||
|
|
||||||
#: registration/models.py:294
|
#: registration/models.py:293
|
||||||
msgid "coach registration"
|
msgid "coach registration"
|
||||||
msgstr "inscription d'encadrant⋅e"
|
msgstr "inscription d'encadrant⋅e"
|
||||||
|
|
||||||
#: registration/models.py:295
|
#: registration/models.py:294
|
||||||
msgid "coach registrations"
|
msgid "coach registrations"
|
||||||
msgstr "inscriptions d'encadrant⋅es"
|
msgstr "inscriptions d'encadrant⋅es"
|
||||||
|
|
||||||
#: registration/models.py:307
|
#: registration/models.py:306
|
||||||
msgid "administrator"
|
msgid "administrator"
|
||||||
msgstr "administrateur⋅rice"
|
msgstr "administrateur⋅rice"
|
||||||
|
|
||||||
#: registration/models.py:308
|
#: registration/models.py:307
|
||||||
msgid ""
|
msgid ""
|
||||||
"An administrator has all rights. Please don't give this right to all juries "
|
"An administrator has all rights. Please don't give this right to all juries "
|
||||||
"and volunteers."
|
"and volunteers."
|
||||||
@ -1725,76 +1751,76 @@ msgstr ""
|
|||||||
"Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit "
|
"Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit "
|
||||||
"à toustes les juré⋅es et bénévoles."
|
"à toustes les juré⋅es et bénévoles."
|
||||||
|
|
||||||
#: registration/models.py:318
|
#: registration/models.py:317
|
||||||
msgid "admin"
|
msgid "admin"
|
||||||
msgstr "admin"
|
msgstr "admin"
|
||||||
|
|
||||||
#: registration/models.py:318
|
#: registration/models.py:317
|
||||||
msgid "volunteer"
|
msgid "volunteer"
|
||||||
msgstr "bénévole"
|
msgstr "bénévole"
|
||||||
|
|
||||||
#: registration/models.py:326
|
#: registration/models.py:325
|
||||||
msgid "volunteer registration"
|
msgid "volunteer registration"
|
||||||
msgstr "inscription de bénévole"
|
msgstr "inscription de bénévole"
|
||||||
|
|
||||||
#: registration/models.py:327
|
#: registration/models.py:326
|
||||||
msgid "volunteer registrations"
|
msgid "volunteer registrations"
|
||||||
msgstr "inscriptions de bénévoles"
|
msgstr "inscriptions de bénévoles"
|
||||||
|
|
||||||
#: registration/models.py:343
|
#: registration/models.py:342
|
||||||
msgid "type"
|
msgid "type"
|
||||||
msgstr "type"
|
msgstr "type"
|
||||||
|
|
||||||
#: registration/models.py:346
|
#: registration/models.py:345
|
||||||
msgid "No payment"
|
msgid "No payment"
|
||||||
msgstr "Pas de paiement"
|
msgstr "Pas de paiement"
|
||||||
|
|
||||||
#: registration/models.py:348
|
#: registration/models.py:347
|
||||||
msgid "Scholarship"
|
msgid "Scholarship"
|
||||||
msgstr "Notification de bourse"
|
msgstr "Notification de bourse"
|
||||||
|
|
||||||
#: registration/models.py:349
|
#: registration/models.py:348
|
||||||
msgid "Bank transfer"
|
msgid "Bank transfer"
|
||||||
msgstr "Virement bancaire"
|
msgstr "Virement bancaire"
|
||||||
|
|
||||||
#: registration/models.py:350
|
#: registration/models.py:349
|
||||||
msgid "Other (please indicate)"
|
msgid "Other (please indicate)"
|
||||||
msgstr "Autre (veuillez spécifier)"
|
msgstr "Autre (veuillez spécifier)"
|
||||||
|
|
||||||
#: registration/models.py:351
|
#: registration/models.py:350
|
||||||
msgid "The tournament is free"
|
msgid "The tournament is free"
|
||||||
msgstr "Le tournoi est gratuit"
|
msgstr "Le tournoi est gratuit"
|
||||||
|
|
||||||
#: registration/models.py:358
|
#: registration/models.py:357
|
||||||
msgid "scholarship file"
|
msgid "scholarship file"
|
||||||
msgstr "Notification de bourse"
|
msgstr "Notification de bourse"
|
||||||
|
|
||||||
#: registration/models.py:359
|
#: registration/models.py:358
|
||||||
msgid "only if you have a scholarship."
|
msgid "only if you have a scholarship."
|
||||||
msgstr "Nécessaire seulement si vous déclarez être boursier."
|
msgstr "Nécessaire seulement si vous déclarez être boursier."
|
||||||
|
|
||||||
#: registration/models.py:366
|
#: registration/models.py:365
|
||||||
msgid "additional information"
|
msgid "additional information"
|
||||||
msgstr "informations additionnelles"
|
msgstr "informations additionnelles"
|
||||||
|
|
||||||
#: registration/models.py:367
|
#: registration/models.py:366
|
||||||
msgid "To help us to find your payment."
|
msgid "To help us to find your payment."
|
||||||
msgstr "Pour nous aider à retrouver votre paiement, si nécessaire."
|
msgstr "Pour nous aider à retrouver votre paiement, si nécessaire."
|
||||||
|
|
||||||
#: registration/models.py:373
|
#: registration/models.py:372
|
||||||
msgid "payment valid"
|
msgid "payment valid"
|
||||||
msgstr "paiement valide"
|
msgstr "paiement valide"
|
||||||
|
|
||||||
#: registration/models.py:382
|
#: registration/models.py:381
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Payment of {registration}"
|
msgid "Payment of {registration}"
|
||||||
msgstr "Paiement de {registration}"
|
msgstr "Paiement de {registration}"
|
||||||
|
|
||||||
#: registration/models.py:385
|
#: registration/models.py:384
|
||||||
msgid "payment"
|
msgid "payment"
|
||||||
msgstr "paiement"
|
msgstr "paiement"
|
||||||
|
|
||||||
#: registration/models.py:386
|
#: registration/models.py:385
|
||||||
msgid "payments"
|
msgid "payments"
|
||||||
msgstr "paiements"
|
msgstr "paiements"
|
||||||
|
|
||||||
@ -2367,10 +2393,6 @@ msgstr "À propos"
|
|||||||
msgid "Search results"
|
msgid "Search results"
|
||||||
msgstr "Résultats de la recherche"
|
msgstr "Résultats de la recherche"
|
||||||
|
|
||||||
#: tfjm/templates/base_modal.html:17
|
|
||||||
msgid "Close"
|
|
||||||
msgstr "Fermer"
|
|
||||||
|
|
||||||
#: tfjm/templates/registration/logged_out.html:8
|
#: tfjm/templates/registration/logged_out.html:8
|
||||||
msgid "Thanks for spending some quality time with the Web site today."
|
msgid "Thanks for spending some quality time with the Web site today."
|
||||||
msgstr "Merci d'avoir utilisé la plateforme du TFJM²."
|
msgstr "Merci d'avoir utilisé la plateforme du TFJM²."
|
||||||
|
Reference in New Issue
Block a user