Adapt platform to have 3 rounds (untested)
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
parent
ec2fa43e20
commit
38ceef7a54
|
@ -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 [1, 2]:
|
for i in range(1, settings.NB_ROUNDS + 1):
|
||||||
# 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
|
||||||
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
for r in self.tournament.draw.round_set.filter(number__gte=2).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': r2.number,
|
'round': r.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 r2.pool_set.order_by('letter').all()
|
async for pool in r.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 == 1 and not self.tournament.final:
|
if r.number < settings.NB_ROUNDS and not self.tournament.final:
|
||||||
# Next round
|
# Next round
|
||||||
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
|
next_round = await self.tournament.draw.round_set.filter(number=r.number + 1).aget()
|
||||||
self.tournament.draw.current_round = r2
|
self.tournament.draw.current_round = next_round
|
||||||
msg += "<br><br>Le tirage au sort du tour 1 est terminé."
|
msg += f"<br><br>Le tirage au sort du tour {r.number} 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': r2.number,
|
'round': next_round.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 r2.pool_set.order_by('letter').all()
|
async for pool in next_round.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 r2.pool_set.filter(letter=1).aget()
|
p1: Pool = await next_round.pool_set.filter(letter=1).aget()
|
||||||
r2.current_pool = p1
|
next_round.current_pool = p1
|
||||||
await r2.asave()
|
await next_round.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,32 +1372,36 @@ 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
|
||||||
r1 = await self.tournament.draw.round_set \
|
previous_round = 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=r.number - 1)
|
||||||
self.tournament.draw.current_round = r1
|
self.tournament.draw.current_round = previous_round
|
||||||
await self.tournament.draw.asave()
|
await self.tournament.draw.asave()
|
||||||
|
|
||||||
async for td in r1.team_draws.prefetch_related('participation__team').all():
|
async for td in previous_round.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(f"tournament-{self.tournament.id}",
|
await self.channel_layer.group_send(
|
||||||
{'tid': self.tournament_id, 'type': 'draw.send_poules',
|
f"tournament-{self.tournament.id}",
|
||||||
'round': r1.number,
|
{
|
||||||
'poules': [
|
'tid': self.tournament_id,
|
||||||
{
|
'type': 'draw.send_poules',
|
||||||
'letter': pool.get_letter_display(),
|
'round': previous_round.number,
|
||||||
'teams': await pool.atrigrams(),
|
'poules': [
|
||||||
}
|
{
|
||||||
async for pool in r1.pool_set.order_by('letter').all()
|
'letter': pool.get_letter_display(),
|
||||||
]})
|
'teams': await pool.atrigrams(),
|
||||||
|
}
|
||||||
|
async for pool in previous_round.pool_set.order_by('letter').all()
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
previous_pool = r1.current_pool
|
previous_pool = previous_round.current_pool
|
||||||
|
|
||||||
td = previous_pool.current_team
|
td = previous_pool.current_team
|
||||||
td.purposed = td.accepted
|
td.purposed = td.accepted
|
||||||
|
@ -1417,14 +1421,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': r1.number,
|
'round': previous_round.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
|
||||||
r1 = await self.tournament.draw.round_set \
|
previous_round = 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 = r1
|
self.tournament.draw.current_round = previous_round
|
||||||
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():
|
||||||
|
@ -1446,7 +1450,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
async for td in r1.team_draws.prefetch_related('participation__team').all():
|
async for td in previous_round.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,
|
||||||
|
|
|
@ -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)
|
* @param round The round number, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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)
|
* @param round The round number, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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)
|
* @param round The current round number, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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)
|
* @param round The current round, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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)
|
* @param round The current round, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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)
|
* @param round The current round, as integer (1 or 2, or 3 for ETEAM)
|
||||||
* @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
|
@ -60,6 +60,7 @@ 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',)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ 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', ]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ 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
|
||||||
|
|
||||||
|
@ -125,6 +126,12 @@ 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['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', )
|
||||||
|
@ -136,10 +143,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',
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
# 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",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
|
@ -315,9 +315,9 @@ class Tournament(models.Model):
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
)
|
)
|
||||||
|
|
||||||
solutions_available_second_phase = models.DateTimeField(
|
solutions_available_second_phase = models.BooleanField(
|
||||||
verbose_name=_("date when the solutions for the second round become available"),
|
verbose_name=_("check this case when solutions for the second round become available"),
|
||||||
default=timezone.now,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
syntheses_second_phase_limit = models.DateTimeField(
|
syntheses_second_phase_limit = models.DateTimeField(
|
||||||
|
@ -325,6 +325,16 @@ class Tournament(models.Model):
|
||||||
default=timezone.now,
|
default=timezone.now,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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,
|
||||||
|
@ -901,6 +911,49 @@ 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"),
|
||||||
|
|
|
@ -39,12 +39,14 @@
|
||||||
<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>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue