# Copyright (C) 2023 by Animath # SPDX-License-Identifier: GPL-3.0-or-later from asgiref.sync import sync_to_async from django.conf import settings from django.db import models from django.utils.text import format_lazy from django.utils.translation import gettext_lazy as _ from participation.models import Participation, Tournament class Draw(models.Model): tournament = models.OneToOneField( Tournament, on_delete=models.CASCADE, verbose_name=_('tournament'), ) current_round = models.ForeignKey( 'Round', on_delete=models.CASCADE, null=True, default=None, related_name='+', verbose_name=_('current round'), ) last_message = models.TextField( blank=True, default="", verbose_name=_("last message"), ) def get_state(self): if self.current_round.current_pool is None: return 'DICE_SELECT_POULES' elif self.current_round.current_pool.current_team is None: return 'DICE_ORDER_POULE' elif self.current_round.current_pool.current_team.purposed is None: return 'WAITING_DRAW_PROBLEM' elif self.current_round.current_pool.current_team.accepted is None: return 'WAITING_CHOOSE_PROBLEM' else: return 'DRAW_ENDED' @property def information(self): s = "" if self.last_message: s += self.last_message + "

" match self.get_state(): case 'DICE_SELECT_POULES': if self.current_round.number == 1: s += """Nous allons commencer le tirage des problèmes.
Vous pouvez à tout moment poser toute question si quelque chose n'est pas clair ou ne va pas.

Nous allons d'abord tirer les poules et l'ordre de passage pour le premier tour avec toutes les équipes puis pour chaque poule, nous tirerons l'ordre de tirage pour le tour et les problèmes.

""" s += """ Les capitaines, vous pouvez désormais toustes lancer un dé 100, en cliquant sur le gros bouton. Les poules et l'ordre de passage lors du premier tour sera l'ordre croissant des dés, c'est-à-dire que le plus petit lancer sera le premier à passer dans la poule A.""" case 'DICE_ORDER_POULE': s += f"""Nous passons au tirage des problèmes pour la poule {self.current_round.current_pool}, entre les équipes {', '.join(td.participation.team.trigram for td in self.current_round.current_pool.teamdraw_set.all())}. Les capitaines peuvent lancer un dé 100 en cliquant sur le gros bouton pour déterminer l'ordre de tirage. L'équipe réalisant le plus gros score pourra tirer en premier.""" case 'WAITING_DRAW_PROBLEM': td = self.current_round.current_pool.current_team s += f"""C'est au tour de l'équipe {td.participation.team.trigram} de choisir son problème. Cliquez sur l'urne au milieu pour tirer un problème au sort.""" case 'WAITING_CHOOSE_PROBLEM': td = self.current_round.current_pool.current_team s += f"""L'équipe {td.participation.team.trigram} a tiré le problème {td.purposed}. """ if td.purposed in td.rejected: s += """Elle a déjà refusé ce problème auparavant, elle peut donc le refuser sans pénalité et tirer un nouveau problème immédiatement, ou bien revenir sur son choix.""" else: s += "Elle peut décider d'accepter ou de refuser ce problème. " if len(td.rejected) >= settings.PROBLEM_COUNT - 5: 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é." s += "

" if s else "" s += """Pour plus de détails sur le déroulement du tirage au sort, le règlement est accessible sur https://tfjm.org/reglement.""" return s async def ainformation(self): return await sync_to_async(lambda: self.information)() class Meta: verbose_name = _('draw') verbose_name_plural = _('draws') class Round(models.Model): draw = models.ForeignKey( Draw, on_delete=models.CASCADE, verbose_name=_('draw'), ) number = models.PositiveSmallIntegerField( choices=[ (1, _('Round 1')), (2, _('Round 2')), ], verbose_name=_('number'), ) current_pool = models.ForeignKey( 'Pool', on_delete=models.CASCADE, null=True, default=None, related_name='+', verbose_name=_('current pool'), ) @property def team_draws(self): return self.teamdraw_set.order_by('pool__letter', 'passage_index').all() def __str__(self): return self.get_number_display() class Meta: verbose_name = _('round') verbose_name_plural = _('rounds') class Pool(models.Model): round = models.ForeignKey( Round, on_delete=models.CASCADE, ) letter = models.PositiveSmallIntegerField( choices=[ (1, 'A'), (2, 'B'), (3, 'C'), ], verbose_name=_('letter'), ) size = models.PositiveSmallIntegerField( verbose_name=_('size'), ) current_team = models.ForeignKey( 'TeamDraw', on_delete=models.CASCADE, null=True, default=None, related_name='+', verbose_name=_('current team'), ) @property def team_draws(self): return self.teamdraw_set.order_by('passage_index').all() @property def trigrams(self): return [td.participation.team.trigram for td in self.teamdraw_set.order_by('passage_index').all()] async def atrigrams(self): return await sync_to_async(lambda: self.trigrams)() def __str__(self): return f"{self.get_letter_display()}{self.round.number}" class Meta: verbose_name = _('pool') verbose_name_plural = _('pools') class TeamDraw(models.Model): participation = models.ForeignKey( Participation, on_delete=models.CASCADE, verbose_name=_('participation'), ) round = models.ForeignKey( Round, on_delete=models.CASCADE, verbose_name=_('round'), ) pool = models.ForeignKey( Pool, on_delete=models.CASCADE, null=True, default=None, verbose_name=_('pool'), ) passage_index = models.PositiveSmallIntegerField( choices=zip(range(1, 5), range(1, 5)), null=True, default=None, verbose_name=_('passage index'), ) choose_index = models.PositiveSmallIntegerField( choices=zip(range(1, 5), range(1, 5)), null=True, default=None, verbose_name=_('choose index'), ) accepted = models.PositiveSmallIntegerField( choices=[ (i, format_lazy(_("Problem #{problem}"), problem=i)) for i in range(1, settings.PROBLEM_COUNT + 1) ], null=True, default=None, verbose_name=_("accepted problem"), ) last_dice = models.PositiveSmallIntegerField( choices=zip(range(1, 101), range(1, 101)), null=True, default=None, verbose_name=_("last dice"), ) purposed = models.PositiveSmallIntegerField( choices=[ (i, format_lazy(_("Problem #{problem}"), problem=i)) for i in range(1, settings.PROBLEM_COUNT + 1) ], null=True, default=None, verbose_name=_("accepted problem"), ) rejected = models.JSONField( default=list, verbose_name=_('rejected problems'), ) def current(self): return TeamDraw.objects.get(participation=self.participation, round=self.round.draw.current_round) class Meta: verbose_name = _('team draw') verbose_name_plural = _('team draws')