from django.db import models from django.utils.translation import gettext_lazy as _ from accounts.models import EmailUser class InterludesActivity(models.Model): """une activité des interludes (i.e. JDR, murder)...""" class Status(models.TextChoices): """en presentiel ou non""" PRESENT = "P", _("En présentiel uniquement") DISTANT = "D", _("En distanciel uniquement") BOTH = "2", _("Les deux") class Types(models.TextChoices): """types d'activités""" TOURNAMENT = "Tournoi", _("Tournoi") GAME = "partie", _("Une partie") GAMES = "parties", _("Quelques parties") FREEPLAY = "freeplay", _("Freeplay") CARD_GAME = "jeu cartes", _("Jeu de cartes") BOARD_GAME = "jeu plateau", _("Jeu de société") TABLETOP_RPG = "table RPG", _("Jeu de rôle sur table") LARGE_RPG = "large RPG", _("Jeu de rôle grandeur nature") VIDEOGAME = "videogame", _("Jeu vidéo") PARTYGAME = "partygame", _("Party game") PUZZLE = "puzzle", _("Puzzle ou analogue") SECRET_ROLES = "secret roles", _("Jeu à rôles secrets") COOP = "coop", _("Jeu coopératif") OTHER = "other", _("Autre") title = models.CharField("Titre", max_length=200) status = models.CharField("Présentiel/distanciel", choices=Status.choices, max_length=1) act_type = models.CharField("Type", choices=Types.choices, max_length=12) duration = models.DurationField("Durée", help_text="format hh:mm:ss") max_participants = models.PositiveIntegerField( "Nombre maximum de participants", help_text="0 pour illimité" ) min_participants = models.PositiveIntegerField( "Nombre minimum de participants" ) communicate_participants = models.BooleanField("communiquer la liste des participants à l'orga avant l'événement") display = models.BooleanField("afficher dans la liste d'activités", default=False) must_subscribe = models.BooleanField("sur inscription", default=False, help_text="Une activité doit être affichée dans la liste également pour que l'on puisse si inscrire" ) host_name = models.CharField("nom de l'organisateur", max_length=50) host_email = models.EmailField("email de l'organisateur") description = models.TextField("description", max_length=2000) on_planning = models.BooleanField( "afficher sur le planning", default=False, help_text="Nécessite de salle et heure de début non vide" ) start = models.DateTimeField("début", null=True, blank=True) room = models.CharField("salle", max_length=100, null=True, blank=True) notes = models.TextField("Notes privées", max_length=2000, blank=True) @property def end(self): if (not self.start) or (not self.duration): return None return self.start + self.duration @property def nb_participants(self) -> str: if self.max_participants == 0: ret = "Illimités" else: ret = "{} - {}".format(self.min_participants, self.max_participants) if self.must_subscribe: ret += " (sur inscription)" return ret @property def pretty_duration(self) -> str: hours, rem = divmod(self.duration.seconds, 3600) minutes = "{:02}".format(rem // 60) if rem // 60 else "" return "{}h{}".format(hours, minutes) @property def pretty_type(self) -> str: type = self.Types(self.act_type).label status = self.Status(self.status) status_repr = "présentiel ou distanciel" if status == self.Status.DISTANT: status_repr = "distanciel" elif status == self.Status.PRESENT: status_repr = "présentiel" return "{} ({})".format(type, status_repr) def conflicts(self, other: "InterludesActivity") -> bool: """Check whether these activites overlap""" if self.end is None or other.end is None: return False if self.start <= other.start: return other.start <= self.end return self.start <= other.end def __str__(self): return self.title class Meta: verbose_name = "activité" class InterludesParticipant(models.Model): """un participant aux interludes""" class ENS(models.TextChoices): """enum representant les ENS""" ENS_ULM = "U", _("ENS Ulm") ENS_LYON = "L", _("ENS Lyon") ENS_RENNES = "R", _("ENS Rennes") ENS_CACHAN = "C", _("ENS Paris Saclay") user = models.OneToOneField(EmailUser, on_delete=models.CASCADE, related_name="Utilisateur") school = models.CharField("ENS de rattachement", choices=ENS.choices, max_length=1) is_registered = models.BooleanField("est inscrit", default=False) meal_friday_evening = models.BooleanField("repas de vendredi soir", default=False) meal_saturday_morning = models.BooleanField("repas de samedi matin", default=False) meal_saturday_midday = models.BooleanField("repas de samedi midi", default=False) meal_saturday_evening = models.BooleanField("repas de samedi soir", default=False) meal_sunday_morning = models.BooleanField("repas de dimanche matin", default=False) meal_sunday_midday = models.BooleanField("repas de dimanche soir", default=False) sleeps = models.BooleanField("dormir sur place", default=False) # mug = models.BooleanField("commander une tasse", default=False) def __str__(self) -> str: school = self.ENS(self.school).label.replace("ENS ", "") if self.school else "" return "{} {} ({})".format(self.user.first_name, self.user.last_name, school) @property def nb_meals(self) -> int: return ( self.meal_friday_evening + self.meal_saturday_evening + self.meal_saturday_midday + self.meal_saturday_morning + self.meal_sunday_midday + self.meal_sunday_morning ) class Meta: verbose_name = "participant" class ActivityList(models.Model): """liste d'activités souhaitée de chaque participant, avec un order de priorité""" priority = models.PositiveIntegerField("priorité") participant = models.ForeignKey( InterludesParticipant, on_delete=models.CASCADE, db_column="participant" ) activity = models.ForeignKey( InterludesActivity, on_delete=models.CASCADE, db_column="activité" ) accepted = models.BooleanField("Obtenue", default=False) class Meta: # couples uniques unique_together = (("priority", "participant"), ("participant", "activity")) ordering = ("participant", "priority") verbose_name = "choix d'activités" verbose_name_plural = "choix d'activités" EmailUser.profile = property(lambda user: InterludesParticipant.objects.get_or_create(user=user)[0])