diff --git a/jarvis/objective/admin.py b/jarvis/objective/admin.py index 287696c..6d784a2 100644 --- a/jarvis/objective/admin.py +++ b/jarvis/objective/admin.py @@ -7,16 +7,24 @@ from django_admin_listfilter_dropdown.filters import ( ) from .models import ( - TouchPosition, Skill, - # Passe, Routine, + Educative, RoutineSkill, - # TrainingProgram, + TouchPosition, + TrainingRound, + GymnastTraining, PrerequisiteClosure, + GymnastTrainingRound, ) +# @admin.register(Educative) +# class EducativeAdmin(admin.ModelAdmin): +# model = Educative +# list_display = ("long_label", "short_label", "difficulty", "level", "rank") + + @admin.register(TouchPosition) class TouchPositionAdmin(admin.ModelAdmin): model = TouchPosition @@ -194,57 +202,94 @@ class PrerequisiteClosureAdmin(admin.ModelAdmin): ) -# @admin.register(Passe) -# class PasseAdmin(admin.ModelAdmin): -# model = Passe +@admin.register(TrainingRound) +class TrainingRoundAdmin(admin.ModelAdmin): + model = TrainingRound -# fields = ( -# "label", -# "educatives", -# "regexp", -# "number_of_skill", -# "difficulty", -# "informations", -# ) + fields = ( + "label", + "educatives", + "regexp", + "number_of_skill", + "difficulty", + "informations", + ) -# list_display = ("label", "regexp", "number_of_skill", "difficulty") -# list_filter = ( -# ("number_of_skill", DropdownFilter), -# ("difficulty", DropdownFilter), -# ) -# filter_horizontal = ("educatives",) + list_display = ("label", "regexp", "number_of_skill", "difficulty") + list_filter = ( + ("number_of_skill", DropdownFilter), + ("difficulty", DropdownFilter), + ) + filter_horizontal = ("educatives",) -# class Media: -# js = ( -# "js/core/jquery-3.6.0.min.js", -# "js/admin/passe.js", -# ) + # def save_model(self, request, obj, form, change): + # if obj.educatives: + # form.cleaned_data["educatives"] = obj.educatives.all().values_list( + # "id", flat=True + # ) + + # super(TrainingRoundAdmin, self).save_model(request, obj, form, change) + + class Media: + js = ( + "js/core/jquery-3.6.0.min.js", + "js/admin/passe.js", + ) -# @admin.register(TrainingProgram) -# class TrainingProgramAdmin(admin.ModelAdmin): -# model = TrainingProgram +@admin.register(GymnastTraining) +class GymnastTrainingAdmin(admin.ModelAdmin): + model = GymnastTraining -# fields = ( -# "gymnast", -# "date", -# "rank", -# "passe", -# "repetition", -# "number_of_skill", -# "difficulty", -# # "score", -# ) -# list_display = ( -# "date", -# "gymnast", -# "passe", -# "rank", -# "repetition", -# "number_of_skill", -# "difficulty", -# ) -# list_filter = ( -# ("gymnast", RelatedDropdownFilter), -# ("date", DropdownFilter), -# ) + fields = ( + "label", + "date", + "gymnast", + # "trainingrounds", + "difficulty", + "number_of_skill", + "score", + ) + + list_display = ( + "label", + "date", + "gymnast", + # "trainingrounds", + "difficulty", + "number_of_skill", + "score", + ) + + list_filter = ( + ("gymnast", RelatedDropdownFilter), + ("trainingrounds", RelatedDropdownFilter), + ) + + +@admin.register(GymnastTrainingRound) +class GymnastTrainingRoundAdmin(admin.ModelAdmin): + model = TrainingRound + + fields = ( + "gymnast_training", + "training_round", + "repetition", + "rank", + "number_of_skill", + "score", + "difficulty", + ) + list_display = ( + "gymnast_training", + "training_round", + "repetition", + "rank", + "number_of_skill", + "score", + "difficulty", + ) + list_filter = ( + ("gymnast_training", RelatedDropdownFilter), + ("training_round", RelatedDropdownFilter), + ) diff --git a/jarvis/objective/forms.py b/jarvis/objective/forms.py index b271b79..0311533 100644 --- a/jarvis/objective/forms.py +++ b/jarvis/objective/forms.py @@ -9,7 +9,7 @@ from .models import ( Skill, Routine, RoutineSkill, - # Passe, + TrainingRound, ) @@ -74,87 +74,101 @@ class CombinationSkillForm(forms.ModelForm): } -# class PasseForm(forms.ModelForm): +class TrainingRoundForm(forms.ModelForm): -# educatives = forms.ModelMultipleChoiceField( -# required=False, -# queryset=Educative.objects.all(), -# widget=FilteredSelectMultiple("Educatives", is_stacked=False), -# # widget=customFilteredSelectMultiple(verbose_name='test2',is_stacked=False) -# ) + educatives = forms.ModelMultipleChoiceField( + required=False, + queryset=Educative.objects.all(), + widget=FilteredSelectMultiple("Educatives", is_stacked=False), + # widget=customFilteredSelectMultiple(verbose_name='test2',is_stacked=False) + ) -# class Media: -# css = { -# "all": ["admin/css/widgets.css"], -# } -# # Adding this javascript is crucial -# js = ["/admin/jsi18n/"] + class Media: + css = { + "all": ["admin/css/widgets.css"], + } + # Adding this javascript is crucial + js = ["/admin/jsi18n/"] -# class Meta: -# model = Passe -# fields = ("label", "regexp", "educatives", "informations") + class Meta: + model = TrainingRound + fields = ("label", "regexp", "educatives", "informations") -# widgets = { -# "label": forms.TextInput( -# attrs={ -# "class": "form-control", -# "placeholder": "Label (not mandatory)", -# "maxlength": 30, -# } -# ), -# "regexp": forms.TextInput( -# attrs={"class": "form-control", "placeholder": "[2-8]"} -# ), -# "informations": forms.Textarea( -# attrs={ -# "class": "form-control", -# "placeholder": "Informations about the passe…", # pylint: disable=line-too-long -# } -# ), -# } + widgets = { + "label": forms.TextInput( + attrs={ + "class": "form-control", + "placeholder": "Label (not mandatory)", + "maxlength": 30, + } + ), + "regexp": forms.TextInput( + attrs={"class": "form-control", "placeholder": "[2-8]"} + ), + "informations": forms.Textarea( + attrs={ + "class": "form-control", + "placeholder": "Informations about the passe…", # pylint: disable=line-too-long + } + ), + } -# def clean_regexp(self): -# """Vérifie que la regexp entrée par l'utilisateur est valide.""" -# regexp = self.cleaned_data["regexp"] -# if not Passe.is_valid_regexp(regexp): -# raise ValidationError("Entered regexp not valid.") + def clean_regexp(self): + """Vérifie que la regexp entrée par l'utilisateur est valide.""" + regexp = self.cleaned_data["regexp"] + if not TrainingRound.is_valid_regexp(regexp): + raise ValidationError("Entered regexp not valid.") -# return regexp + return regexp -# def clean(self): -# """Vérifie le contenu des champs `educatives` par rapport à la valeur de `regexp`. Si -# `regexp` est définie par : -# - valeurs de ROUTINE_TYPE_CHOICE il faut que Educatives soit VIDE -# - avec [x-y] -# - [x-y] " Educatives soit NON VIDE -# - WC " il y ait 2+ Educatives -# - x| " il y ait 1! Educatives -# """ -# cleaned_data = super().clean() -# regexp = ["regexp"] + def clean(self): + """Vérifie le contenu des champs `educatives` par rapport à la valeur de `regexp`. Si + `regexp` est définie par : + - valeurs de ROUTINE_TYPE_CHOICE il faut que Educatives soit VIDE + - avec [x-y] + - [x-y] " Educatives soit NON VIDE + - WC " il y ait 2+ Educatives + - x| " il y ait 1! Educatives + """ + cleaned_data = super().clean() + regexp = cleaned_data["regexp"] -# if regexp is not None: -# arguments = regexp.split(" ") -# educatives = cleaned_data["educatives"] + if regexp is not None: + # print + arguments = regexp.split(" ") + educatives = cleaned_data["educatives"] + print("----------------------------------------------------------------") + print(educatives) + print("----------------------------------------------------------------") -# if Passe.is_valid_routine_type(arguments[0]) and educatives is not None: -# raise ValidationError( -# "Educatives must be empty with the entered Regexp." -# ) + if TrainingRound.is_valid_routine_type(arguments[0]) and educatives: + raise ValidationError( + "Educatives must be empty with the entered Regexp." + ) -# if Passe.is_valid_subset(arguments[0]) and educatives is None: -# raise ValidationError( -# "Educatives can't be empty with the entered Regexp." -# ) + if TrainingRound.is_valid_subset(arguments[0]) and educatives is None: + raise ValidationError( + "Educatives can't be empty with the entered Regexp." + ) -# if re.match(r"[1-9]+\|", arguments[0]) and len(educatives) != 1: -# raise ValidationError( -# "One and only one Educatives allowed with the entered Regexp." -# ) + if re.match(r"[1-9]+\|", arguments[0]) and len(educatives) != 1: + raise ValidationError( + "One and only one Educatives allowed with the entered Regexp." + ) -# if arguments[0] == "WC" and (educatives is None or len(educatives) < 2): -# raise ValidationError( -# "At least two Educatives with the entered Regexp." -# ) + if arguments[0] == "WC" and (educatives is None or len(educatives) < 2): + raise ValidationError( + "At least two Educatives with the entered Regexp." + ) -# return cleaned_data + return cleaned_data + + # def save_model(self, request, obj, form, change): + # obj.save() + # for educative in form.cleaned_data["educatives"]: + # print(educative) + # book = Book.objects.get(pk=bk.id) + # book.quantity -= 1 + # if book.quantity == 0: + # book.sold = True; + # book.save() diff --git a/jarvis/objective/models.py b/jarvis/objective/models.py index eacdd0b..7ca8fd5 100644 --- a/jarvis/objective/models.py +++ b/jarvis/objective/models.py @@ -1,4 +1,4 @@ -from django.db import models +from django.db import models, transaction from django.db.models import Q import re @@ -8,6 +8,7 @@ from jarvis.tools.models import ( Seasonisable, max_even_if_none, ) +from .signals import * # from jarvis.followup.models import ROUTINE_TYPE_CHOICE @@ -466,281 +467,316 @@ class RoutineSkill(models.Model): return f"{self.rank} - {self.routine.short_label} : {self.skill.short_label}" -# class TrainingRound(Markdownizable): -# """Classe représentant les passages (à faire pendant un entraînement).""" +class TrainingRound(Markdownizable): + """Classe représentant les passages (à faire pendant un entraînement).""" -# class Meta: -# ordering = [ -# "label", -# ] + class Meta: + ordering = [ + "label", + ] -# label = models.CharField(max_length=30) -# educatives = models.ManyToManyField( -# Educative, related_name="passes", blank=True, symmetrical=False -# ) -# regexp = models.CharField(max_length=50, null=True, blank=True) -# number_of_skill = models.PositiveSmallIntegerField(default=0) -# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) -# # TODO: number_of_skill doit être calculé correctement dans tous les cas. + label = models.CharField(max_length=30) + educatives = models.ManyToManyField( + Educative, related_name="trainingrounds", blank=True, symmetrical=False + ) + regexp = models.CharField(max_length=50, null=True, blank=True) + number_of_skill = models.PositiveSmallIntegerField(default=0) + difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) -# def save(self, *args, **kwargs): -# """Sauve les informations de la personne et initialise les champs nettoyés. -# On part du principe que self.regexp est correct. -# """ -# self.difficulty = 0 -# self.number_of_skill = 0 -# super().save(*args, **kwargs) -# # print("Dans le save") + @staticmethod + def number_of_skill_from_subset(subset, educative=None): + """ """ + if not TrainingRound.is_valid_subset(subset): + return 0, 0, 0 -# if self.educatives.count() == 0: -# # print("educative is none") -# present = False -# operation_list = self.regexp.split(" ") -# for item in ROUTINE_TYPE_CHOICE: -# if item[1] == operation_list[0]: -# present = True -# break + subset = subset.replace("[", "").replace("]", "") + ranks = subset.split("-") -# if present and len(operation_list) == 2: -# # print("present") -# content = operation_list[1].replace("[", "").replace("]", "") -# ranks = content.split("-") + if ranks[0] == "": + start = 0 + else: + start = int(ranks[0]) -# if ranks[0] == "": -# self.number_of_skill += int(ranks[1]) -# elif ranks[1] == "": -# self.number_of_skill += (10 - int(ranks[0])) + 1 -# else: -# self.number_of_skill += (int(ranks[1]) - int(ranks[0])) + 1 -# else: -# self.number_of_skill += 10 + if ranks[1] == "": + if educative is not None: + end = educative.jumps.all().count() + else: + end = 10 + else: + end = int(ranks[1]) -# else: -# for educative in self.educatives.all(): -# is_skill = False -# try: -# educative = Routine.objects.get(pk=educative) -# except Routine.DoesNotExist: -# educative = Skill.objects.get(pk=educative) -# is_skill = True + number_of_skill = (end - start) + 1 -# if is_skill: -# self.difficulty += educative.difficulty -# self.number_of_skill += 1 -# else: -# if self.regexp is not None: -# regexp = self.regexp.replace("[", "").replace("]", "") -# position = regexp.find("-") + return start, end, number_of_skill -# start = regexp[:position] -# if start == "": -# start = 0 -# else: -# start = int(start) + @staticmethod + def difficulty_from_regexp(educative, start, end): + """ """ + difficulty = 0 + list_of_skill = educative.skill_links.filter(rank__gte=start, rank__lte=end) + # .aggregate(total=Sum("value")) -# end = regexp[position + 1 :] -# if end == "": -# end = educative.jumps.all().count() -# else: -# end = int(end) + for routine_skill in list_of_skill: + difficulty += routine_skill.skill.difficulty -# self.number_of_skill += end - (start - 1) -# list_of_skill = educative.skill_links.filter( -# rank__gte=start, rank__lte=end -# ) -# # .aggregate(total=Sum("value")) -# tmp_difficulty = 0 -# for routine_skill in list_of_skill: -# tmp_difficulty += routine_skill.skill.difficulty -# self.difficulty += tmp_difficulty + return difficulty -# else: -# self.number_of_skill += educative.jumps.all().count() -# self.difficulty += educative.difficulty + def update_traininground(self): + """Update `number_of_skill` et `difficulty`. + S'il n'y a pas d'educatives, la difficulté ne peut pas être calculée. + """ + difficulty = 0 + number_of_skill = 0 -# super().save(*args, **kwargs) + if self.educatives.count() == 0: + operation_list = self.regexp.split(" ") -# def __str__(self): -# return f"{self.label} ({self.number_of_skill} | {self.difficulty})" + if len(operation_list) == 2: + _, _, number_of_skill = TrainingRound.number_of_skill_from_subset( + operation_list[1] + ) + else: + number_of_skill += 10 -# @staticmethod -# def is_valid_regexp_one_arg(arg): -# """Vérifie une regexp avec un paramètre.""" -# if arg == "WC": -# return True + else: + for educative in self.educatives.all(): + is_skill = False -# if re.match(r"[1-9]+\|", arg): -# return True + try: + educ = Routine.objects.get(pk=educative) + except Routine.DoesNotExist: + educ = Skill.objects.get(pk=educative) + is_skill = True -# if not TrainingRound.is_valid_dot(arg): -# return False + if is_skill: + difficulty += educ.difficulty + number_of_skill += 1 + elif ( + self.regexp is not None + and self.regexp != "WC" + and not re.match(r"[1-9]+\|", self.regexp) + ): + ( + start, + end, + number_of_skill, + ) = TrainingRound.number_of_skill_from_subset(self.regexp) + difficulty = TrainingRound.difficulty_from_regexp(educ, start, end) -# value = arg.replace(".", "") -# is_valid_routine = TrainingRound.is_valid_routine_type(value) + else: + number_of_skill += educ.jumps.all().count() + difficulty += educ.difficulty -# if is_valid_routine: -# return True + self.difficulty = difficulty + self.number_of_skill = number_of_skill + self.save() -# return TrainingRound.is_valid_subset(arg) + # def save(self, *args, **kwargs): + # """Sauve les informations de la personne et initialise les champs nettoyés. + # On part du principe que self.regexp est correct. -# @staticmethod -# def is_valid_regexp_two_args(arg1, arg2): -# """Vérifie une regexp avec deux paramètres.""" -# if not TrainingRound.is_valid_dot(arg1): -# return False + # https://stackoverflow.com/questions/13751217/can-the-super-save-method-be-used-several-times-in-a-model + # """ + # # print("Object:" + str(self)) + # instance = super().save(*args, **kwargs) + # # print("Calling update_fileds on commit transaction.") + # transaction.on_commit(self.update_fields) + # # print("Fields updated.") + # return instance -# value = arg1.replace(".", "") -# is_valid_routine = TrainingRound.is_valid_routine_type(value) + def __str__(self): + return f"{self.label} ({self.number_of_skill} | {self.difficulty})" -# if is_valid_routine: -# return TrainingRound.is_valid_subset(arg2) + def is_regexp_wc(self): + """ """ + return self.regexp == "WC" -# return False + @staticmethod + def is_valid_regexp_one_arg(regexp): + """Vérifie une regexp avec un paramètre.""" + if regexp == "WC": + return True -# @staticmethod -# def is_valid_dot(pattern): -# """Reçoit une chaine de caratère et vérifie que si elle contient un point (.), il se trouve -# soit à la première position soit à la dernière position. -# """ -# if len(re.findall("\.", pattern)) > 1: -# return False + if re.match(r"[1-9]+\|", regexp): + return True -# if re.search("\.", pattern): -# last_place = len(pattern) - 1 -# if pattern[0] != "." and pattern[last_place] != ".": -# return False + if not TrainingRound.is_valid_dot(regexp): + return False -# return True + value = regexp.replace(".", "") + is_valid_routine = TrainingRound.is_valid_routine_type(value) -# @staticmethod -# def is_valid_routine_type(routine_type): -# """Recoit une chaine de caractère et vérifie si elle est présente dans la liste -# ROUTINE_TYPE_CHOICE (Educative vide !) -# """ -# is_valid = False -# for item in ROUTINE_TYPE_CHOICE: -# if item[1] == routine_type: -# is_valid = True -# break + if is_valid_routine: + return True -# return is_valid + return TrainingRound.is_valid_subset(regexp) -# @staticmethod -# def is_valid_subset(subset): -# """Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme. + @staticmethod + def is_valid_regexp_two_args(arg1, arg2): + """Vérifie une regexp avec deux paramètres.""" + if not TrainingRound.is_valid_dot(arg1): + return False -# Format attendu : [X-Y] -# X ou Y peuvent être vide mais pas en même temps. -# X est un entier >= 2 -# Y est un entier >= 2 OU Y > X si X est non vide + value = arg1.replace(".", "") + is_valid_routine = TrainingRound.is_valid_routine_type(value) -# Exemples : -# - [2-8] True -# - [-5] True -# - [3-] True -# - [8-2] False -# - [4--8] False -# - [-] False -# - [1-] False -# - [-1] False -# - [4] False -# - [6-6] False -# """ -# if re.match(r"^\[(([2-9]+\-{1})|([2-9]+\-{1}[2-9]+)|(\-{1}[2-9]+))\]$", subset): -# value = subset.replace("[", "").replace("]", "") -# ranks = value.split("-") + if is_valid_routine: + return TrainingRound.is_valid_subset(arg2) -# if ranks[0] == "" or ranks[1] == "": -# return True + return False -# if int(ranks[0]) < int(ranks[1]): -# return True + @staticmethod + def is_valid_dot(pattern): + """Reçoit une chaine de caratère et vérifie que si elle contient un point (.), il se trouve + soit à la première position soit à la dernière position. + """ + if len(re.findall("\.", pattern)) > 1: + return False -# return False + if re.search("\.", pattern): + last_place = len(pattern) - 1 + if pattern[0] != "." and pattern[last_place] != ".": + return False -# @staticmethod -# def is_valid_regexp(regexp): -# """Vérifie le champ regexp + return True -# Exemples : -# - Q1R1 True -# - Q1R2 [2-8] True -# - Q2R1 [-5] True -# - SF [6-] True -# - FS [3-7] True -# - Q1R1. True -# - .Q1R2 True -# - Q1R1. [-4] True -# - .Q1R2 [4-] True -# - .FS [3-7] True -# - [2-8] True -# - [-5] True -# - WC True -# - 1| True -# """ -# argument_list = regexp.split(" ") + @staticmethod + def is_valid_routine_type(routine_type): + """Recoit une chaine de caractère et vérifie si elle est présente dans la liste + ROUTINE_TYPE_CHOICE (Educative vide !) + """ + is_valid_routine = False + for item in ROUTINE_TYPE_CHOICE: + if item[1] == routine_type: + is_valid_routine = True + break -# if len(argument_list) >= 3: -# return False + return is_valid_routine -# if len(argument_list) == 2: -# return TrainingRound.is_valid_regexp_two_args( -# argument_list[0], argument_list[1] -# ) -# else: -# return TrainingRound.is_valid_regexp_one_arg(argument_list[0]) + @staticmethod + def is_valid_subset(subset): + """Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme. -# return False + Format attendu : [X-Y] + X ou Y peuvent être vide mais pas en même temps. + X est un entier >= 2 + Y est un entier >= 2 OU Y > X si X est non vide + + Exemples : + - [2-8] True + - [-5] True + - [3-] True + - [8-2] False + - [4--8] False + - [-] False + - [1-] False + - [-1] False + - [4] False + - [6-6] False + """ + if re.match(r"^\[(([2-9]+\-{1})|([2-9]+\-{1}[2-9]+)|(\-{1}[2-9]+))\]$", subset): + value = subset.replace("[", "").replace("]", "") + ranks = value.split("-") + + if ranks[0] == "" or ranks[1] == "": + return True + + if int(ranks[0]) < int(ranks[1]): + return True + + return False + + @staticmethod + def is_valid_regexp(regexp): + """Vérifie le champ regexp + + Exemples : + - "" True + - Q1R1 True + - Q1R2 [2-8] True + - Q2R1 [-5] True + - SF [6-] True + - FS [3-7] True + - Q1R1. True + - .Q1R2 True + - Q1R1. [-4] True + - .Q1R2 [4-] True + - .FS [3-7] True + - [2-8] True + - [-5] True + - WC True + - 1| True + """ + if regexp == "" or regexp is None: + return True + + print("---" + regexp + "---") + + argument_list = regexp.split(" ") + + if len(argument_list) >= 3: + return False + + if len(argument_list) == 2: + return TrainingRound.is_valid_regexp_two_args( + argument_list[0], argument_list[1] + ) + else: + return TrainingRound.is_valid_regexp_one_arg(argument_list[0]) + + return False -# class GymnastTraining(Seasonisable, Markdownizable): -# """Classe représentant un entraînement.""" +class GymnastTraining(Seasonisable, Markdownizable): + """Classe représentant un entraînement.""" -# label = models.CharField() -# gymnast = models.ForeignKey("people.Gymnast", on_delete=models.CASCADE) -# training_rounds = models.ManyToManyField( -# TrainingRound, through="GymnastTrainingRound", verbose_name="trainings" -# ) -# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) -# number_of_skill = models.PositiveSmallIntegerField(default=0) -# score = models.PositiveSmallIntegerField(default=1) + label = models.CharField() + gymnast = models.ForeignKey( + "people.Gymnast", + on_delete=models.CASCADE, + related_name="trainings", + ) + trainingrounds = models.ManyToManyField( + TrainingRound, through="GymnastTrainingRound", verbose_name="trainings" + ) + difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) + number_of_skill = models.PositiveSmallIntegerField(default=0) + score = models.PositiveSmallIntegerField(default=1) -# def __str__(self): -# return f"Training on {self.date} for {self.gymnast}: {self.number_of_skill} | {self.difficulty}" + def __str__(self): + return f"Training on {self.date} for {self.gymnast}: {self.number_of_skill} | {self.difficulty}" -# class GymnastTrainingRound(Markdownizable): -# """Classe représentant un passage.""" +class GymnastTrainingRound(Markdownizable): + """Classe représentant un passage.""" -# class Meta: -# verbose_name = "Gymnast Training Round" -# verbose_name_plural = "Gymnast Training Rounds" -# ordering = [ -# "rank", -# ] -# unique_together = ["gymnast_training", "rank"] + class Meta: + verbose_name = "Gymnast Training Round" + verbose_name_plural = "Gymnast Training Rounds" + ordering = [ + "rank", + ] + unique_together = ["gymnast_training", "rank"] -# gymnast_training = models.ForeignKey( -# GymnastTraining, -# on_delete=models.CASCADE, -# related_name="training_rounds", -# ) -# training_round = models.ForeignKey(TrainingRound, on_delete=models.CASCADE) -# repetition = models.PositiveSmallIntegerField(default=1) -# rank = models.PositiveSmallIntegerField(default=1) -# updated_at = models.DateTimeField(auto_now=True) -# number_of_skill = models.PositiveSmallIntegerField(default=0) -# score = models.PositiveSmallIntegerField(blank=True, null=True) -# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) + gymnast_training = models.ForeignKey( + GymnastTraining, + on_delete=models.CASCADE, + related_name="training_rounds", + ) + training_round = models.ForeignKey(TrainingRound, on_delete=models.CASCADE) + repetition = models.PositiveSmallIntegerField(default=1) + rank = models.PositiveSmallIntegerField(default=1) + updated_at = models.DateTimeField(auto_now=True) + number_of_skill = models.PositiveSmallIntegerField(default=0) + score = models.PositiveSmallIntegerField(blank=True, null=True) + difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) -# def __str__(self): -# return ( -# f"{self.gymnast} {self.date} - {self.rank} : {self.passe} {self.repetition}" -# ) + def __str__(self): + return f"{self.gymnast_training} {self.gymnast_training.date} - {self.rank} : {self.training_round} {self.repetition}" -# def save(self, *args, **kwargs): -# """Sauve les informations de la personne et initialise les champs nettoyés.""" -# super().save(*args, **kwargs) -# self.difficulty = self.round.difficulty * self.repetition -# self.number_of_skill = self.round.number_of_skill * self.repetition -# super().save(*args, **kwargs) + def save(self, *args, **kwargs): + """Sauve les informations de la personne et initialise les champs nettoyés.""" + super().save(*args, **kwargs) + self.difficulty = self.training_round.difficulty * self.repetition + self.number_of_skill = self.training_round.number_of_skill * self.repetition + super().save(*args, **kwargs) diff --git a/jarvis/objective/signals.py b/jarvis/objective/signals.py new file mode 100644 index 0000000..d59aa5e --- /dev/null +++ b/jarvis/objective/signals.py @@ -0,0 +1,11 @@ +# from django.db.models.signals import post_save +# from django.dispatch import receiver +# from .models import TrainingRound + + +# @receiver(post_save, sender=TrainingRound) +# def compute_traininground_fields(**kwargs): +# print("In the post_save function.") +# # job = kwargs.get("instance") +# # logger.info("POST_SAVE : Job : %s" % job) +# # find people to email based on `job` instance diff --git a/jarvis/objective/templates/trainingprograms/details.html b/jarvis/objective/templates/gymnasttrainings/details.html similarity index 76% rename from jarvis/objective/templates/trainingprograms/details.html rename to jarvis/objective/templates/gymnasttrainings/details.html index 36a69d1..b3a510f 100644 --- a/jarvis/objective/templates/trainingprograms/details.html +++ b/jarvis/objective/templates/gymnasttrainings/details.html @@ -8,29 +8,29 @@
{% if gymnast %}{{ gymnast }} - {% endif %}{{ date|date:"l j F Y" }} | +{{ gymnast_training.gymnast }} - {{ gymnast_training.date|date:"l j F Y" }} | ||||||||
---|---|---|---|---|---|---|---|---|---|
{{ trainingprogram.rank }} | -{{ trainingprogram.passe.label }}{% if trainingprogram.repetition != 1 %} {{ trainingprogram.repetition }}{% endif %} | -{{ trainingprogram.number_of_skill}} | -{{ trainingprogram.difficulty }} | +{{ round.rank }} | +{{ round.training_round.label }}{% if round.repetition != 1 %} {{ round.repetition }}{% endif %} | +{{ round.number_of_skill}} | +{{ round.difficulty }} | {% if request.user|has_group:"trainer" %}- + - + @@ -42,8 +42,8 @@ | |
TOTAL | -{{ number_of_skill }} | -{{ difficulty }} | +{{ gymnast_training.number_of_skill }} | +{{ gymnast_training.difficulty }} | {% if request.user|has_group:"trainer" %}{% endif %} @@ -67,7 +67,7 @@ $(document).ready(function(){ if ($(this).is(".up")) { $.ajax({ - url: "{% url 'switch_trainingprogram_line' %}", + url: "{% url 'switch_traininground' %}", method: "POST", data: { tpid: $(this).data('tp_id'), @@ -85,7 +85,7 @@ $(document).ready(function(){ }); } else { $.ajax({ - url: "{% url 'switch_trainingprogram_line' %}", + url: "{% url 'switch_traininground' %}", method: "POST", data: { tpid: $(this).data('tp_id'), diff --git a/jarvis/objective/templates/passes/create.html b/jarvis/objective/templates/trainingrounds/create.html similarity index 93% rename from jarvis/objective/templates/passes/create.html rename to jarvis/objective/templates/trainingrounds/create.html index 7113248..b719dc7 100644 --- a/jarvis/objective/templates/passes/create.html +++ b/jarvis/objective/templates/trainingrounds/create.html @@ -8,7 +8,7 @@ |