diff --git a/draw/consumers.py b/draw/consumers.py
index 4a47e7b..1101c85 100644
--- a/draw/consumers.py
+++ b/draw/consumers.py
@@ -34,8 +34,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
.prefetch_related('draw__current_round__current_pool__current_team').aget()
self.participations = []
- async for participation in Participation.objects.filter(tournament=self.tournament, valid=True)\
- .prefetch_related('team'):
+ async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team'):
self.participations.append(participation)
user = self.scope['user']
@@ -88,6 +87,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.reject_problem(**content)
case 'export':
await self.export(**content)
+ case 'continue_final':
+ await self.continue_final(**content)
@ensure_orga
async def start_draw(self, fmt, **kwargs):
@@ -487,8 +488,7 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
{'type': 'draw.dice_visibility', 'visible': True})
else:
# Round is ended
- # TODO: For the final tournament, add some adjustments
- if r.number == 1:
+ if r.number == 1 and not self.tournament.final:
# Next round
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
self.tournament.draw.current_round = r2
@@ -505,6 +505,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
{'type': 'draw.dice_visibility', 'visible': True})
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'type': 'draw.dice_visibility', 'visible': True})
+ elif r.number == 1 and self.tournament.final:
+ # For the final tournament, we wait for a manual update between the two rounds.
+ msg += "
Le tirage au sort du tour 1 est terminé."
+ self.tournament.draw.last_message = msg
+ await sync_to_async(self.tournament.draw.save)()
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'type': 'draw.export_visibility', 'visible': True})
@@ -587,6 +592,56 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'type': 'draw.export_visibility', 'visible': False})
+ @ensure_orga
+ async def continue_final(self, **kwargs):
+ if not self.tournament.final:
+ return await self.alert(_("This is only available for the final tournament."), 'danger')
+
+ r2 = await self.tournament.draw.round_set.filter(number=2).aget()
+ self.tournament.draw.current_round = r2
+ msg = "Le tirage au sort pour le tour 2 va commencer. " \
+ "L'ordre de passage est déterminé à partir du classement du premier tour."
+ self.tournament.draw.last_message = msg
+ await sync_to_async(self.tournament.draw.save)()
+
+ pool = await Pool.objects.filter(round=self.tournament.draw.current_round, letter=1).aget()
+ r2.current_pool = pool
+ await sync_to_async(r2.save)()
+
+ notes = dict()
+ async for participation in self.tournament.participations.filter(valid=True).prefetch_related('team').all():
+ notes[participation] = sum([await sync_to_async(pool.average)(participation)
+ async for pool in self.tournament.pools.filter(participations=participation)
+ if pool.results_available])
+ print(participation.team.trigram, notes[participation])
+ ordered_participations = sorted(notes.keys(), key=lambda x: -notes[x])
+ async for pool in r2.pool_set.order_by('letter').all():
+ for i in range(pool.size):
+ participation = ordered_participations.pop(0)
+ td = await TeamDraw.objects.aget(round=r2, participation=participation)
+ td.pool = pool
+ td.passage_index = i
+ await sync_to_async(td.save)()
+ await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
+ {'type': 'draw.send_poules', 'round': r2})
+
+ for participation in self.participations:
+ await self.channel_layer.group_send(
+ f"tournament-{self.tournament.id}",
+ {'type': 'draw.dice', 'team': participation.team.trigram, 'result': None})
+
+ await self.channel_layer.group_send(f"team-{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"volunteer-{self.tournament.id}",
+ {'type': 'draw.continue_visibility', 'visible': False})
+
+ 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 draw_alert(self, content):
return await self.alert(**content)
@@ -611,6 +666,9 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
async def draw_export_visibility(self, content):
await self.send_json({'type': 'export_visibility', 'visible': content['visible']})
+ async def draw_continue_visibility(self, content):
+ await self.send_json({'type': 'continue_visibility', 'visible': content['visible']})
+
async def draw_send_poules(self, content):
await self.send_json({'type': 'set_poules', 'round': content['round'].number,
'poules': [{'letter': pool.get_letter_display(), 'teams': await pool.atrigrams()}
diff --git a/draw/models.py b/draw/models.py
index 7d8a1f3..f91ac5d 100644
--- a/draw/models.py
+++ b/draw/models.py
@@ -42,7 +42,10 @@ class Draw(models.Model):
elif self.current_round.current_pool.current_team is None:
return 'DICE_ORDER_POULE'
elif self.current_round.current_pool.current_team.accepted is not None:
- return 'DRAW_ENDED'
+ if self.current_round.number == 1:
+ return 'WAITING_FINAL'
+ else:
+ return 'DRAW_ENDED'
elif self.current_round.current_pool.current_team.purposed is None:
return 'WAITING_DRAW_PROBLEM'
else:
@@ -93,6 +96,8 @@ class Draw(models.Model):
s += "Refuser ce problème ajoutera une nouvelle pénalité de 0.5 sur le coefficient de l'oral de læ défenseur⋅se."
else:
s += f"Il reste {settings.PROBLEM_COUNT - 5 - len(td.rejected)} refus sans pénalité."
+ case 'WAITING_FINAL':
+ s += "Le tirage au sort pour le tour 2 aura lieu à la fin du premier tour. Bon courage !"
case 'DRAW_ENDED':
s += "Le tirage au sort est terminé. Les solutions des autres équipes peuvent être trouvées dans l'onglet « Ma participation »."
@@ -210,7 +215,8 @@ class Pool(models.Model):
@property
def exportable(self):
- return self.associated_pool is None and all(td.accepted is not None for td in self.teamdraw_set.all())
+ return self.associated_pool is None and self.teamdraw_set.exists() \
+ and all(td.accepted is not None for td in self.teamdraw_set.all())
def export(self):
from django.db import transaction
@@ -222,6 +228,7 @@ class Pool(models.Model):
self.associated_pool.juries.set(self.round.draw.tournament.organizers.all())
tds = list(self.team_draws)
self.associated_pool.participations.set([td.participation for td in tds])
+ self.save()
if len(tds) == 3:
table = [
diff --git a/draw/static/draw.js b/draw/static/draw.js
index 8cd5194..d1d3b2e 100644
--- a/draw/static/draw.js
+++ b/draw/static/draw.js
@@ -32,6 +32,10 @@ function exportDraw(tid) {
sockets[tid].send(JSON.stringify({'type': 'export'}))
}
+function continueFinal(tid) {
+ sockets[tid].send(JSON.stringify({'type': 'continue_final'}))
+}
+
function showNotification(title, body, timeout = 5000) {
let notif = new Notification(title, {'body': body, 'icon': "/static/tfjm.svg"})
if (timeout)
@@ -151,6 +155,14 @@ document.addEventListener('DOMContentLoaded', () => {
div.classList.add('d-none')
}
+ function updateContinueVisibility(visible) {
+ let div = document.getElementById(`continue-${tournament.id}`)
+ if (visible)
+ div.classList.remove('d-none')
+ else
+ div.classList.add('d-none')
+ }
+
function updatePoules(round, poules) {
let roundList = document.getElementById(`recap-${tournament.id}-round-list`)
let poolListId = `recap-${tournament.id}-round-${round}-pool-list`
@@ -508,6 +520,9 @@ document.addEventListener('DOMContentLoaded', () => {
case 'export_visibility':
updateExportVisibility(data.visible)
break
+ case 'continue_visibility':
+ updateContinueVisibility(data.visible)
+ break
case 'set_poules':
updatePoules(data.round, data.poules)
break
diff --git a/draw/templates/draw/tournament_content.html b/draw/templates/draw/tournament_content.html
index f0d68fb..f3a8748 100644
--- a/draw/templates/draw/tournament_content.html
+++ b/draw/templates/draw/tournament_content.html
@@ -155,6 +155,14 @@
📁 {% trans "Export" %}
+ {% if tournament.final %}
+