from django.db import models from django.contrib.auth import get_user_model User = get_user_model() from datetime import date import pendulum from ultron.tools.models import Markdownizable, Seasonisable from ultron.people.models import Gymnast from ultron.planning.models import Event from ultron.objective.models import Educative, Skill, Routine ROUTINE_CHOICE = ( (0, "Other"), (1, "R1"), (2, "R2"), (3, "R3"), (4, "R4"), (5, "R1S"), (6, "R2S"), (7, "R3S"), (8, "R4S"), ) LEARNING_STEP_CHOICES = ( (0, "No"), (1, "With help"), (2, "Without help"), (3, "Chained"), (4, "Masterised"), ) class Chrono(Seasonisable): """ Représente les chronos (de chandelles ou de série) enregistrés pour un(e) gymnaste. """ CHRONO_TYPE_CHOICE = ( (0, "10 |"), (1, "Routine 1"), (2, "Routine 2"), (3, "Routine 3"), (4, "Routine 4"), (9, "Other"), ) SCORE_TYPE_CHOICE = ( (0, "Chrono"), (1, "ToF"), ) class Meta: verbose_name = "Chrono" verbose_name_plural = "Chronos" ordering = ["date", "gymnast"] gymnast = models.ForeignKey( Gymnast, verbose_name="gymnast", related_name="chronos", on_delete=models.CASCADE, ) chrono_type = models.PositiveSmallIntegerField( choices=CHRONO_TYPE_CHOICE, verbose_name="Routine type" ) score_type = models.PositiveSmallIntegerField( choices=SCORE_TYPE_CHOICE, verbose_name="Score type" ) score = models.DecimalField(max_digits=5, decimal_places=3) tof = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return "%s - %s (%s - %s)" % ( self.gymnast, self.score, self.date, self.chrono_type, ) @staticmethod def compute_tof(value): tof = round((value * 13) / 15, 3) * 1000 tof = tof - (tof % 5) return (tof / 1000) class ChronoDetails(models.Model): """ Class permettant d'enregistrer des détails d'un chrono : le temps de chaque saut. """ class Meta: verbose_name = "Chronos Details" verbose_name_plural = "Chronos Details" ordering = ["chrono", "order"] unique_together = ["chrono", "order"] chrono = models.ForeignKey(Chrono, on_delete=models.CASCADE, related_name="details") order = models.SmallIntegerField() value = models.DecimalField(max_digits=5, decimal_places=3) class Accident(Markdownizable, Seasonisable): """ La classe `Accident` permet d'indiquer qu'un gymnaste a eu un accident, en liaison avec un skill ou non. """ class Meta: verbose_name = "Accident" verbose_name_plural = "Accidents" # unique_together = ("gymnast", "skill", "date") gymnast = models.ForeignKey( Gymnast, verbose_name="Gymnast", related_name="accident", on_delete=models.CASCADE, ) skill = models.ForeignKey( "objective.Skill", verbose_name="Skill", related_name="accident", on_delete=models.SET_NULL, default=None, blank=True, null=True, ) nb_week_off = models.SmallIntegerField( blank=True, null=True, verbose_name="# week off" ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return "%s(%s)" % ( self.gymnast, self.date, ) class LearnedSkill(Seasonisable): """ Représente la capacité d'un gymnaste à savori faire un skill de la ligne d'apprentissage. """ class Meta: verbose_name = "Learned Skill" verbose_name_plural = "Learned Skills" unique_together = ("gymnast", "skill", "date", "learning_step") gymnast = models.ForeignKey( Gymnast, verbose_name="gymnast", related_name="known_skills", on_delete=models.CASCADE, ) skill = models.ForeignKey( Skill, verbose_name="Skill", related_name="known_by", on_delete=models.CASCADE, ) learning_step = models.PositiveSmallIntegerField( choices=LEARNING_STEP_CHOICES, verbose_name="Can do type" ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Plan(Seasonisable, Markdownizable): """ Classe représentant les objectifs qu'un gymnaste devra savoir faire pour une date donnée. """ class Meta: verbose_name = "Plan" verbose_name_plural = "Plans" ordering = ["date", "educative", "gymnast"] unique_together = ("gymnast", "educative") gymnast = models.ForeignKey( "people.Gymnast", verbose_name="Gymnast", related_name="todo", on_delete=models.CASCADE, ) educative = models.ForeignKey( Educative, verbose_name="Educative", related_name="plan", on_delete=models.CASCADE, ) learning_step = models.PositiveSmallIntegerField( choices=LEARNING_STEP_CHOICES, verbose_name="Can do type", default=3 ) is_done = models.BooleanField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return "%s - %s - %s" % ( self.gymnast, self.educative.short_label, self.date, ) class Point(models.Model): """ Représente les points obtenus lors d'une compétition. """ ROUTINETYPE_CHOICE = ( (1, "Routine 1"), (2, "Routine 2"), (3, "Final") # Routine 3 ) gymnast = models.ForeignKey( Gymnast, on_delete=models.CASCADE, default=None, related_name="points" ) event = models.ForeignKey(Event, on_delete=models.CASCADE, default=None) routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE) point_execution = models.DecimalField(max_digits=5, decimal_places=3, verbose_name="Execution") point_difficulty = models.DecimalField(max_digits=3, decimal_places=1, verbose_name="Difficulty") point_time_of_flight = models.DecimalField(max_digits=5, decimal_places=3, verbose_name="ToF") point_horizontal_displacement = models.DecimalField(max_digits=4, decimal_places=3, verbose_name="HD") penality = models.DecimalField(max_digits=3, decimal_places=1) total = models.DecimalField(max_digits=6, decimal_places=3) created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created") updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated") def __str__(self): return "%s - %s" % ( self.gymnast, self.total, ) class MindState(Markdownizable, Seasonisable): """ Représente l'état d'esprit psychologique d'un gymnaste """ gymnast = models.ForeignKey( Gymnast, on_delete=models.CASCADE, default=None, related_name="mindstate" ) event = models.ForeignKey( Event, on_delete=models.SET_NULL, default=None, blank=True, null=True, related_name="mindstate", ) score = models.PositiveSmallIntegerField(verbose_name="Score") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return "%s - %s : %s" % (self.gymnast, self.date, self.score) class GymnastHasRoutine(models.Model): """ Classe représentant le lien entre les gymnastes et leurs séries. TODO: il y a un champ "date_begin" et un champ "date_end" --> peut hérité de Temporizable """ class Meta: verbose_name = "Gymnast Has Routine" verbose_name_plural = "Gymnast Has Routines" # unique_together() gymnast = models.ForeignKey( Gymnast, verbose_name="Gymnast", related_name="has_routine", on_delete=models.CASCADE, ) routine = models.ForeignKey( Routine, verbose_name="Routine", related_name="done_by_gymnast", on_delete=models.CASCADE, ) routine_type = models.PositiveSmallIntegerField( choices=ROUTINE_CHOICE, verbose_name="Type", default="1" ) date_begin = models.DateField(default=date.today, verbose_name="Date begin") date_end = models.DateField(verbose_name="Date end", null=True, blank=True) def __str__(self): return "%s - %s : %s" % (self.gymnast, self.routine_type, self.routine) class NumberOfRoutineDone(Seasonisable): """ Classe permettant de suivre le nombre de séries faites par le gymnaste. """ class Meta: verbose_name = "Number of routine done" verbose_name_plural = "Number of routines done" gymnast = models.ForeignKey( Gymnast, verbose_name="Gymnast", related_name="number_of_routine_done", on_delete=models.CASCADE, ) routine = models.ForeignKey( Routine, verbose_name="Routine", related_name="number_of_try", on_delete=models.SET_NULL, null=True, blank=True, ) routine_type = models.PositiveSmallIntegerField( choices=ROUTINE_CHOICE, verbose_name="Type", default="1" ) number_of_try = models.PositiveSmallIntegerField(verbose_name="Number of try", default=0) number_of_successes = models.PositiveSmallIntegerField( verbose_name="number of successes", default=0 ) def __str__(self): return "%s - %s (%s) : %s | %s" % ( self.gymnast, self.routine_type, self.routine, self.number_of_try, self.number_of_successes, ) class HeightWeight(Seasonisable): """ Classe permettant de suivre le poids et la taille d'un gymnaste """ class Meta: verbose_name = "Height & weight" verbose_name_plural = "Heights & weights" unique_together = ("gymnast", "date") gymnast = models.ForeignKey( Gymnast, verbose_name="Gymnast", related_name="height_weight", on_delete=models.CASCADE, ) height = models.DecimalField(max_digits=4, decimal_places=1, verbose_name="Height") hips_height = models.DecimalField( max_digits=4, decimal_places=1, verbose_name="Hips height", null=True, blank=True ) weight = models.DecimalField(max_digits=4, decimal_places=1, verbose_name="Weight") def __str__(self): return "%s : %s/%s - %s" % (self.gymnast, self.height, self.hips_height, self.weight) class Note(Markdownizable, Seasonisable): """ Notes relatives à un gymnaste """ STATUS_CHOICES = ( (0, "Draft"), (1, "Published"), ) gymnast = models.ForeignKey(Gymnast, on_delete=models.CASCADE, related_name="remarks") coach = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, related_name="notes") status = models.PositiveSmallIntegerField( choices=STATUS_CHOICES, verbose_name="Routine type", default=0 ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return "%s - %s : %s" % (self.gymnast, self.created_at, self.coach)