1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-24 11:08:46 +02:00

Problems can be accepted or rejected. Draw can go to the end

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello
2023-03-25 06:21:39 +01:00
parent e90005b192
commit cebe977d49
4 changed files with 282 additions and 26 deletions

View File

@ -27,8 +27,8 @@ def ensure_orga(f):
class DrawConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
tournament_id = self.scope['url_route']['kwargs']['tournament_id']
self.tournament = await Tournament.objects.filter(pk=tournament_id)\
self.tournament_id = self.scope['url_route']['kwargs']['tournament_id']
self.tournament = await Tournament.objects.filter(pk=self.tournament_id)\
.prefetch_related('draw__current_round__current_pool__current_team').aget()
self.participations = []
@ -65,6 +65,10 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
async def receive_json(self, content, **kwargs):
print(content)
# Refresh tournament
self.tournament = await Tournament.objects.filter(pk=self.tournament_id)\
.prefetch_related('draw__current_round__current_pool__current_team').aget()
match content['type']:
case 'start_draw':
await self.start_draw(**content)
@ -74,6 +78,10 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
await self.process_dice(**content)
case 'draw_problem':
await self.select_problem(**content)
case 'accept':
await self.accept_problem(**content)
case 'reject':
await self.reject_problem(**content)
@ensure_orga
async def start_draw(self, fmt, **kwargs):
@ -104,6 +112,12 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
draw.current_round = r1
await sync_to_async(draw.save)()
async for td in r1.teamdraw_set.prefetch_related('participation__team').all():
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.alert(_("Draw started!"), 'success')
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
@ -131,8 +145,23 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
async def process_dice(self, trigram: str | None = None, **kwargs):
state = await sync_to_async(self.tournament.draw.get_state)()
if self.registration.is_volunteer:
participation = await Participation.objects.filter(team__trigram=trigram).prefetch_related('team').aget()
if trigram:
participation = await Participation.objects.filter(team__trigram=trigram)\
.prefetch_related('team').aget()
else:
# First free team
if state == 'DICE_ORDER_POULE':
participation = await Participation.objects\
.filter(teamdraw__pool=self.tournament.draw.current_round.current_pool,
teamdraw__last_dice__isnull=True).prefetch_related('team').afirst()
else:
participation = await Participation.objects\
.filter(teamdraw__round=self.tournament.draw.current_round,
teamdraw__last_dice__isnull=True).prefetch_related('team').afirst()
trigram = participation.team.trigram
else:
participation = await Participation.objects.filter(team__participants=self.registration)\
.prefetch_related('team').aget()
@ -141,7 +170,6 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
team_draw = await TeamDraw.objects.filter(participation=participation,
round_id=self.tournament.draw.current_round_id).aget()
state = await sync_to_async(self.tournament.draw.get_state)()
match state:
case 'DICE_SELECT_POULES':
if team_draw.last_dice is not None:
@ -207,10 +235,10 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
if self.tournament.draw.current_round.number == 2 \
and await self.tournament.draw.current_round.pool_set.acount() >= 2:
# Check that we don't have a same pool as the first day
async for p1 in Pool.objects.filter(round__draw=self.tournament.draw, number=1).all():
async for p1 in Pool.objects.filter(round__draw=self.tournament.draw, round__number=1).all():
async for p2 in Pool.objects.filter(round_id=self.tournament.draw.current_round_id).all():
if set(await p1.teamdraw_set.avalues('id')) \
== set(await p2.teamdraw_set.avalues('id')):
if await sync_to_async(lambda: set(td['id'] for td in p1.teamdraw_set.values('id')))() \
== await sync_to_async(lambda:set(td['id'] for td in p2.teamdraw_set.values('id')))():
await TeamDraw.objects.filter(round=self.tournament.draw.current_round)\
.aupdate(last_dice=None, pool=None, passage_index=None)
for td in tds:
@ -248,6 +276,8 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
async for td in pool.teamdraw_set.prefetch_related('participation__team').all():
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.send_poules',
@ -349,9 +379,166 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
{'type': 'draw.buttons_visibility', 'visible': True})
await self.channel_layer.group_send(f"team-{self.tournament.id}",
{'type': 'draw.draw_problem', 'team': trigram, 'problem': problem})
self.tournament.draw.last_message = ""
await sync_to_async(self.tournament.draw.save)()
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'type': 'draw.set_info', 'draw': self.tournament.draw})
async def accept_problem(self, **kwargs):
state = await sync_to_async(self.tournament.draw.get_state)()
if state != 'WAITING_CHOOSE_PROBLEM':
return await self.alert(_("This is not the time for this."), 'danger')
r = await sync_to_async(lambda: self.tournament.draw.current_round)()
pool = await sync_to_async(lambda: r.current_pool)()
td = await sync_to_async(lambda: pool.current_team)()
if not self.registration.is_volunteer:
participation = await Participation.objects.filter(team__participants=self.registration)\
.prefetch_related('team').aget()
if participation.id != td.participation_id:
return await self.alert("This is not your turn.", 'danger')
td.accepted = td.purposed
td.purposed = None
await sync_to_async(td.save)()
trigram = await sync_to_async(lambda: td.participation.team.trigram)()
msg = f"L'équipe <strong>{trigram}</strong> a accepté le problème <strong>{td.accepted}</strong>. "
if pool.size == 5 and await pool.teamdraw_set.filter(accepted=td.accepted).acount() < 2:
msg += "Une équipe peut encore l'accepter."
else:
msg += "Plus personne ne peut l'accepter."
self.tournament.draw.last_message = msg
await sync_to_async(self.tournament.draw.save)()
await self.channel_layer.group_send(f"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"tournament-{self.tournament.id}",
{'type': 'draw.set_problem',
'round': r.number,
'team': trigram,
'problem': td.accepted})
if await pool.teamdraw_set.filter(accepted__isnull=True).aexists():
# Continue
next_td = await pool.next_td()
pool.current_team = next_td
await sync_to_async(pool.save)()
new_trigram = await sync_to_async(lambda: next_td.participation.team.trigram)()
await self.channel_layer.group_send(f"team-{new_trigram}",
{'type': 'draw.box_visibility', 'visible': True})
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'type': 'draw.box_visibility', 'visible': True})
else:
# Pool is ended
msg += f"<br><br>Le tirage de la poule {pool.get_letter_display()}{r.number} est terminé. " \
f"Le tableau récapitulatif est en bas."
self.tournament.draw.last_message = msg
await sync_to_async(self.tournament.draw.save)()
if await r.teamdraw_set.filter(accepted__isnull=True).aexists():
# Next pool
next_pool = await r.next_pool()
r.current_pool = next_pool
await sync_to_async(r.save)()
await self.channel_layer.group_send(f"tournament-{self.tournament.id}",
{'type': 'draw.dice_visibility', 'visible': True})
else:
# Round is ended
# TODO: For the final tournament, add some adjustments
# TODO: Make some adjustments for 5-teams-pools
if r.number == 1:
# Next round
r2 = await self.tournament.draw.round_set.filter(number=2).aget()
self.tournament.draw.current_round = r2
msg += "<br><br>Le tirage au sort du tour 1 est terminé."
self.tournament.draw.last_message = msg
await sync_to_async(self.tournament.draw.save)()
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"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 reject_problem(self, **kwargs):
state = await sync_to_async(self.tournament.draw.get_state)()
if state != 'WAITING_CHOOSE_PROBLEM':
return await self.alert(_("This is not the time for this."), 'danger')
r = await sync_to_async(lambda: self.tournament.draw.current_round)()
pool = await sync_to_async(lambda: r.current_pool)()
td = await sync_to_async(lambda: pool.current_team)()
if not self.registration.is_volunteer:
participation = await Participation.objects.filter(team__participants=self.registration)\
.prefetch_related('team').aget()
if participation.id != td.participation_id:
return await self.alert("This is not your turn.", 'danger')
problem = td.purposed
already_refused = problem in td.rejected
if not already_refused:
td.rejected.append(problem)
td.purposed = None
await sync_to_async(td.save)()
remaining = settings.PROBLEM_COUNT - 5 - len(td.rejected)
trigram = await sync_to_async(lambda: td.participation.team.trigram)()
msg = f"L'équipe <strong>{trigram}</strong> a refusé le problème <strong>{problem}</strong>. "
if remaining >= 0:
msg += f"Il lui reste {remaining} refus sans pénalité."
else:
if already_refused:
msg += "Cela n'ajoute pas de pénalité."
else:
msg += "Cela ajoute une pénalité de 0.5 sur le coefficient de l'oral de læ défenseur⋅se."
self.tournament.draw.last_message = msg
await sync_to_async(self.tournament.draw.save)()
await self.channel_layer.group_send(f"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"tournament-{self.tournament.id}",
{'type': 'draw.reject_problem',
'round': r.number, 'team': trigram, 'rejected': td.rejected})
if already_refused:
next_td = td
else:
next_td = await pool.next_td()
pool.current_team = next_td
await sync_to_async(pool.save)()
new_trigram = await sync_to_async(lambda: next_td.participation.team.trigram)()
await self.channel_layer.group_send(f"team-{new_trigram}",
{'type': 'draw.box_visibility', 'visible': True})
await self.channel_layer.group_send(f"volunteer-{self.tournament.id}",
{'type': 'draw.box_visibility', 'visible': True})
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)
@ -388,3 +575,11 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
'team': r.current_pool.current_team.participation.team.trigram \
if r.current_pool and r.current_pool.current_team else None,
})())
async def draw_set_problem(self, content):
await self.send_json({'type': 'set_problem', 'round': content['round'],
'team': content['team'], 'problem': content['problem']})
async def draw_reject_problem(self, content):
await self.send_json({'type': 'reject_problem', 'round': content['round'],
'team': content['team'], 'rejected': content['rejected']})