1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2024-12-03 20:06:54 +00:00

Compare commits

..

No commits in common. "cf92c78d0343b0c92d37952d9ce78281acbbf6b7" and "ec2fa43e20bb10479a15e7e11950d3d8f90c35fc" have entirely different histories.

11 changed files with 306 additions and 510 deletions

View File

@ -183,7 +183,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Create the draw # Create the draw
draw = await Draw.objects.acreate(tournament=self.tournament) draw = await Draw.objects.acreate(tournament=self.tournament)
r1 = None r1 = None
for i in range(1, settings.NB_ROUNDS + 1): for i in [1, 2]:
# Create the round # Create the round
r = await Round.objects.acreate(draw=draw, number=i) r = await Round.objects.acreate(draw=draw, number=i)
if i == 1: if i == 1:
@ -532,17 +532,17 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
'visible': True}) 'visible': True})
# First send the second pool to have the good team order # First send the second pool to have the good team order
for r in self.tournament.draw.round_set.filter(number__gte=2).all(): r2 = await self.tournament.draw.round_set.filter(number=2).aget()
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.send_poules', {'tid': self.tournament_id, 'type': 'draw.send_poules',
'round': r.number, 'round': r2.number,
'poules': [ 'poules': [
{ {
'letter': pool.get_letter_display(), 'letter': pool.get_letter_display(),
'teams': await pool.atrigrams(), 'teams': await pool.atrigrams(),
} }
async for pool in r.pool_set.order_by('letter').all() async for pool in r2.pool_set.order_by('letter').all()
]}) ]})
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.send_poules', {'tid': self.tournament_id, 'type': 'draw.send_poules',
'round': r.number, 'round': r.number,
@ -843,11 +843,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
""" """
msg = self.tournament.draw.last_message msg = self.tournament.draw.last_message
if r.number < settings.NB_ROUNDS and not self.tournament.final: if r.number == 1 and not self.tournament.final:
# Next round # Next round
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget() r2 = await self.tournament.draw.round_set.filter(number=2).aget()
self.tournament.draw.current_round = next_round self.tournament.draw.current_round = r2
msg += f"<br><br>Le tirage au sort du tour {r.number} est terminé." msg += "<br><br>Le tirage au sort du tour 1 est terminé."
self.tournament.draw.last_message = msg self.tournament.draw.last_message = msg
await self.tournament.draw.asave() await self.tournament.draw.asave()
@ -866,20 +866,20 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
# Reorder dices # Reorder dices
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.send_poules', {'tid': self.tournament_id, 'type': 'draw.send_poules',
'round': next_round.number, 'round': r2.number,
'poules': [ 'poules': [
{ {
'letter': pool.get_letter_display(), 'letter': pool.get_letter_display(),
'teams': await pool.atrigrams(), 'teams': await pool.atrigrams(),
} }
async for pool in next_round.pool_set.order_by('letter').all() async for pool in r2.pool_set.order_by('letter').all()
]}) ]})
# The passage order for the second round is already determined by the first round # The passage order for the second round is already determined by the first round
# Start the first pool of the second round # Start the first pool of the second round
p1: Pool = await next_round.pool_set.filter(letter=1).aget() p1: Pool = await r2.pool_set.filter(letter=1).aget()
next_round.current_pool = p1 r2.current_pool = p1
await next_round.asave() await r2.asave()
async for td in p1.teamdraw_set.prefetch_related('participation__team').all(): async for td in p1.teamdraw_set.prefetch_related('participation__team').all():
await self.channel_layer.group_send(f"team-{td.participation.team.trigram}", await self.channel_layer.group_send(f"team-{td.participation.team.trigram}",
@ -1372,36 +1372,32 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
'round': r.number, 'round': r.number,
'team': td.participation.team.trigram, 'team': td.participation.team.trigram,
'problem': td.accepted}) 'problem': td.accepted})
elif r.number >= 2: elif r.number == 2:
if not self.tournament.final: if not self.tournament.final:
# Go to the previous round # Go to the previous round
previous_round = await self.tournament.draw.round_set \ r1 = await self.tournament.draw.round_set \
.prefetch_related('current_pool__current_team__participation__team').aget(number=r.number - 1) .prefetch_related('current_pool__current_team__participation__team').aget(number=1)
self.tournament.draw.current_round = previous_round self.tournament.draw.current_round = r1
await self.tournament.draw.asave() await self.tournament.draw.asave()
async for td in previous_round.team_draws.prefetch_related('participation__team').all(): async for td in r1.team_draws.prefetch_related('participation__team').all():
await self.channel_layer.group_send( await self.channel_layer.group_send(
f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice', f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice',
'team': td.participation.team.trigram, 'team': td.participation.team.trigram,
'result': td.choice_dice}) 'result': td.choice_dice})
await self.channel_layer.group_send( await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.send_poules',
{ 'round': r1.number,
'tid': self.tournament_id, 'poules': [
'type': 'draw.send_poules', {
'round': previous_round.number, 'letter': pool.get_letter_display(),
'poules': [ 'teams': await pool.atrigrams(),
{ }
'letter': pool.get_letter_display(), async for pool in r1.pool_set.order_by('letter').all()
'teams': await pool.atrigrams(), ]})
}
async for pool in previous_round.pool_set.order_by('letter').all()
]
})
previous_pool = previous_round.current_pool previous_pool = r1.current_pool
td = previous_pool.current_team td = previous_pool.current_team
td.purposed = td.accepted td.purposed = td.accepted
@ -1421,14 +1417,14 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"tournament-{self.tournament.id}", await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'tid': self.tournament_id, 'type': 'draw.set_problem', {'tid': self.tournament_id, 'type': 'draw.set_problem',
'round': previous_round.number, 'round': r1.number,
'team': td.participation.team.trigram, 'team': td.participation.team.trigram,
'problem': td.accepted}) 'problem': td.accepted})
else: else:
# Don't continue the final tournament # Don't continue the final tournament
previous_round = await self.tournament.draw.round_set \ r1 = await self.tournament.draw.round_set \
.prefetch_related('current_pool__current_team__participation__team').aget(number=1) .prefetch_related('current_pool__current_team__participation__team').aget(number=1)
self.tournament.draw.current_round = previous_round self.tournament.draw.current_round = r1
await self.tournament.draw.asave() await self.tournament.draw.asave()
async for td in r.teamdraw_set.all(): async for td in r.teamdraw_set.all():
@ -1450,7 +1446,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
] ]
}) })
async for td in previous_round.team_draws.prefetch_related('participation__team').all(): async for td in r1.team_draws.prefetch_related('participation__team').all():
await self.channel_layer.group_send( await self.channel_layer.group_send(
f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice', f"tournament-{self.tournament.id}", {'tid': self.tournament_id, 'type': 'draw.dice',
'team': td.participation.team.trigram, 'team': td.participation.team.trigram,

View File

@ -311,7 +311,7 @@ document.addEventListener('DOMContentLoaded', () => {
/** /**
* Set the different pools for the given round, and update the interface. * Set the different pools for the given round, and update the interface.
* @param tid The tournament id * @param tid The tournament id
* @param round The round number, as integer (1 or 2, or 3 for ETEAM) * @param round The round number, as integer (1 or 2)
* @param poules The list of poules, which are represented with their letters and trigrams, * @param poules The list of poules, which are represented with their letters and trigrams,
* [{'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']}] * [{'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']}]
*/ */
@ -433,7 +433,7 @@ document.addEventListener('DOMContentLoaded', () => {
/** /**
* Update the table for the given round and the given pool, where there will be the chosen problems. * Update the table for the given round and the given pool, where there will be the chosen problems.
* @param tid The tournament id * @param tid The tournament id
* @param round The round number, as integer (1 or 2, or 3 for ETEAM) * @param round The round number, as integer (1 or 2)
* @param poule The current pool, which id represented with its letter and trigrams, * @param poule The current pool, which id represented with its letter and trigrams,
* {'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']} * {'letter': 'A', 'teams': ['ABC', 'DEF', 'GHI']}
*/ */
@ -590,7 +590,7 @@ document.addEventListener('DOMContentLoaded', () => {
/** /**
* Highlight the team that is currently choosing its problem. * Highlight the team that is currently choosing its problem.
* @param tid The tournament id * @param tid The tournament id
* @param round The current round number, as integer (1 or 2, or 3 for ETEAM) * @param round The current round number, as integer (1 or 2)
* @param pool The current pool letter (A, B, C or D) (null if non-relevant) * @param pool The current pool letter (A, B, C or D) (null if non-relevant)
* @param team The current team trigram (null if non-relevant) * @param team The current team trigram (null if non-relevant)
*/ */
@ -627,7 +627,7 @@ document.addEventListener('DOMContentLoaded', () => {
/** /**
* Update the recap and the table when a team accepts a problem. * Update the recap and the table when a team accepts a problem.
* @param tid The tournament id * @param tid The tournament id
* @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param round The current round, as integer (1 or 2)
* @param team The current team trigram * @param team The current team trigram
* @param problem The accepted problem, as integer * @param problem The accepted problem, as integer
*/ */
@ -651,7 +651,7 @@ document.addEventListener('DOMContentLoaded', () => {
/** /**
* Update the recap when a team rejects a problem. * Update the recap when a team rejects a problem.
* @param tid The tournament id * @param tid The tournament id
* @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param round The current round, as integer (1 or 2)
* @param team The current team trigram * @param team The current team trigram
* @param rejected The full list of rejected problems * @param rejected The full list of rejected problems
*/ */
@ -682,7 +682,7 @@ document.addEventListener('DOMContentLoaded', () => {
* For a 5-teams pool, we may reorder the pool if two teams select the same problem. * For a 5-teams pool, we may reorder the pool if two teams select the same problem.
* Then, we redraw the table and set the accepted problems. * Then, we redraw the table and set the accepted problems.
* @param tid The tournament id * @param tid The tournament id
* @param round The current round, as integer (1 or 2, or 3 for ETEAM) * @param round The current round, as integer (1 or 2)
* @param poule The pool represented by its letter * @param poule The pool represented by its letter
* @param teams The teams list represented by their trigrams, ["ABC", "DEF", "GHI", "JKL", "MNO"] * @param teams The teams list represented by their trigrams, ["ABC", "DEF", "GHI", "JKL", "MNO"]
* @param problems The accepted problems in the same order than the teams, [1, 1, 2, 2, 3] * @param problems The accepted problems in the same order than the teams, [1, 1, 2, 2, 3]

File diff suppressed because it is too large Load Diff

View File

@ -60,7 +60,6 @@ class TournamentSerializer(serializers.ModelSerializer):
fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote', fields = ('id', 'pk', 'name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit', 'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
'solutions_available_second_phase', 'syntheses_second_phase_limit', 'solutions_available_second_phase', 'syntheses_second_phase_limit',
'solutions_available_third_phase', 'syntheses_third_phase_limit',
'description', 'organizers', 'final', 'participations',) 'description', 'organizers', 'final', 'participations',)

View File

@ -66,7 +66,6 @@ class TournamentViewSet(ModelViewSet):
filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote', filterset_fields = ['name', 'date_start', 'date_end', 'place', 'max_teams', 'price', 'remote',
'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit', 'inscription_limit', 'solution_limit', 'solutions_draw', 'syntheses_first_phase_limit',
'solutions_available_second_phase', 'syntheses_second_phase_limit', 'solutions_available_second_phase', 'syntheses_second_phase_limit',
'solutions_available_third_phase', 'syntheses_third_phase_limit',
'description', 'organizers', 'final', ] 'description', 'organizers', 'final', ]

View File

@ -14,7 +14,6 @@ from django.utils.translation import gettext_lazy as _
import pandas import pandas
from pypdf import PdfReader from pypdf import PdfReader
from registration.models import VolunteerRegistration from registration.models import VolunteerRegistration
from tfjm import settings
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
@ -126,13 +125,6 @@ class ValidateParticipationForm(forms.Form):
class TournamentForm(forms.ModelForm): class TournamentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if settings.TFJM_APP != "ETEAM":
del self.fields['date_third_phase']
del self.fields['solutions_available_third_phase']
del self.fields['syntheses_third_phase_limit']
class Meta: class Meta:
model = Tournament model = Tournament
exclude = ('notes_sheet_id', ) exclude = ('notes_sheet_id', )
@ -144,10 +136,10 @@ class TournamentForm(forms.ModelForm):
'solutions_draw': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'), 'solutions_draw': forms.DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%d %H:%M'),
'syntheses_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, 'syntheses_first_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
format='%Y-%m-%d %H:%M'), format='%Y-%m-%d %H:%M'),
'solutions_available_second_phase': forms.DateTimeInput(attrs={'type': 'datetime-local'},
format='%Y-%m-%d %H:%M'),
'syntheses_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'}, 'syntheses_second_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
format='%Y-%m-%d %H:%M'), format='%Y-%m-%d %H:%M'),
'syntheses_third_phase_limit': forms.DateTimeInput(attrs={'type': 'datetime-local'},
format='%Y-%m-%d %H:%M'),
'organizers': forms.SelectMultiple(attrs={ 'organizers': forms.SelectMultiple(attrs={
'class': 'selectpicker', 'class': 'selectpicker',
'data-live-search': 'true', 'data-live-search': 'true',

View File

@ -1,42 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-07 13:51
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("participation", "0014_alter_team_trigram"),
]
operations = [
migrations.RemoveField(
model_name="tournament",
name="solutions_available_second_phase",
),
migrations.AddField(
model_name="tournament",
name="solutions_available_second_phase",
field=models.BooleanField(
default=False,
verbose_name="check this case when solutions for the second round become available",
),
),
migrations.AddField(
model_name="tournament",
name="solutions_available_third_phase",
field=models.BooleanField(
default=False,
verbose_name="check this case when solutions for the third round become available",
),
),
migrations.AddField(
model_name="tournament",
name="syntheses_third_phase_limit",
field=models.DateTimeField(
default=django.utils.timezone.now,
verbose_name="limit date to upload the syntheses for the third phase",
),
)
]

View File

@ -1,35 +0,0 @@
# Generated by Django 5.0.6 on 2024-06-07 14:01
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("participation", "0015_tournament_solutions_available_third_phase_and_more"),
]
operations = [
migrations.AddField(
model_name="tournament",
name="date_first_phase",
field=models.DateField(
default=datetime.date.today, verbose_name="first phase date"
),
),
migrations.AddField(
model_name="tournament",
name="date_second_phase",
field=models.DateField(
default=datetime.date.today, verbose_name="first second date"
),
),
migrations.AddField(
model_name="tournament",
name="date_third_phase",
field=models.DateField(
default=datetime.date.today, verbose_name="third phase date"
),
),
]

View File

@ -310,24 +310,14 @@ class Tournament(models.Model):
default=timezone.now, default=timezone.now,
) )
date_first_phase = models.DateField(
verbose_name=_("first phase date"),
default=date.today,
)
syntheses_first_phase_limit = models.DateTimeField( syntheses_first_phase_limit = models.DateTimeField(
verbose_name=_("limit date to upload the syntheses for the first phase"), verbose_name=_("limit date to upload the syntheses for the first phase"),
default=timezone.now, default=timezone.now,
) )
date_second_phase = models.DateField( solutions_available_second_phase = models.DateTimeField(
verbose_name=_("first second date"), verbose_name=_("date when the solutions for the second round become available"),
default=date.today, default=timezone.now,
)
solutions_available_second_phase = models.BooleanField(
verbose_name=_("check this case when solutions for the second round become available"),
default=False,
) )
syntheses_second_phase_limit = models.DateTimeField( syntheses_second_phase_limit = models.DateTimeField(
@ -335,21 +325,6 @@ class Tournament(models.Model):
default=timezone.now, default=timezone.now,
) )
date_third_phase = models.DateField(
verbose_name=_("third phase date"),
default=date.today,
)
solutions_available_third_phase = models.BooleanField(
verbose_name=_("check this case when solutions for the third round become available"),
default=False,
)
syntheses_third_phase_limit = models.DateTimeField(
verbose_name=_("limit date to upload the syntheses for the third phase"),
default=timezone.now,
)
description = models.TextField( description = models.TextField(
verbose_name=_("description"), verbose_name=_("description"),
blank=True, blank=True,
@ -926,49 +901,6 @@ class Participation(models.Model):
for ext in ["pdf", "tex", "odt", "docx"]) for ext in ["pdf", "tex", "odt", "docx"])
syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>" syntheses_templates_content = f"<p>{_('Templates:')} {syntheses_templates}</p>"
content = defender_content + opponent_content + reporter_content + syntheses_templates_content
informations.append({
'title': _("Second round"),
'type': "info",
'priority': 1,
'content': content,
})
elif settings.TFJM_APP == "ETEAM" \
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)
defender_text = _("<p>For the third round, you will defend "
"<a href='{solution_url}'>your solution of the problem {problem}</a>.</p>")
draw_url = reverse_lazy("draw:index")
solution_url = defender_passage.defended_solution.file.url
defender_content = format_lazy(defender_text, draw_url=draw_url,
solution_url=solution_url, problem=defender_passage.solution_number)
opponent_text = _("<p>You will oppose the solution of the team {opponent} on the "
"<a href='{solution_url}'>problem {problem}</a>. "
"You can upload your synthesis sheet on <a href='{passage_url}'>this page</a>.</p>")
solution_url = opponent_passage.defended_solution.file.url
passage_url = reverse_lazy("participation:passage_detail", args=(opponent_passage.pk,))
opponent_content = format_lazy(opponent_text, opponent=opponent_passage.defender.team.trigram,
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 "
"<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=solution_url,
problem=reporter_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 + reporter_content + syntheses_templates_content
informations.append({ informations.append({
'title': _("Second round"), 'title': _("Second round"),

View File

@ -37,7 +37,7 @@
\Large {\bf \tfjmedition$^{e}$ Tournoi Fran\c cais des Jeunes Math\'ematiciennes et Math\'ematiciens \tfjm}\\ \Large {\bf \tfjmedition$^{e}$ Tournoi Fran\c cais des Jeunes Math\'ematiciennes et Math\'ematiciens \tfjm}\\
\vspace{3mm} \vspace{3mm}
Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.participations.count == 5 %} \;-- {{ pool.get_room_display }}{% endif %} \;-- {% if pool.round == 1 %}{{ pool.tournament.date_first_phase }}{% elif pool.round == 2 %}{{ pool.tournament.date_second_phase }}{% else %}{{ pool.tournament.date_third_phase }}{% endif %} Tour {{ pool.round }} \;-- Poule {{ pool.get_letter_display }}{% if pool.participations.count == 5 %} \;-- {{ pool.get_room_display }}{% endif %} \;-- {% if pool.round == 1 %}{{ pool.tournament.date_start }}{% else %}{{ pool.tournament.date_end }}{% endif %}
\vspace{15mm} \vspace{15mm}

View File

@ -39,14 +39,12 @@
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the first round'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the first round'|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.syntheses_first_phase_limit }}</dd> <dd class="col-sm-6">{{ tournament.syntheses_first_phase_limit }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date when solutions of round 2 are available'|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.solutions_available_second_phase }}</dd>
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the second round'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the second round'|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.syntheses_second_phase_limit }}</dd> <dd class="col-sm-6">{{ tournament.syntheses_second_phase_limit }}</dd>
{% if TFJM_APP == "ETEAM" %}
<dt class="col-sm-6 text-sm-end">{% trans 'date of maximal syntheses submission for the third round'|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.syntheses_third_phase_limit }}</dd>
{% endif %}
<dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt> <dt class="col-sm-6 text-sm-end">{% trans 'description'|capfirst %}</dt>
<dd class="col-sm-6">{{ tournament.description }}</dd> <dd class="col-sm-6">{{ tournament.description }}</dd>