[WIP] Training & more

This commit is contained in:
Gregory Trullemans 2024-03-21 17:30:24 +01:00
parent 6a63776145
commit 8e192e1c11
13 changed files with 726 additions and 646 deletions

View File

@ -7,16 +7,24 @@ from django_admin_listfilter_dropdown.filters import (
) )
from .models import ( from .models import (
TouchPosition,
Skill, Skill,
# Passe,
Routine, Routine,
Educative,
RoutineSkill, RoutineSkill,
# TrainingProgram, TouchPosition,
TrainingRound,
GymnastTraining,
PrerequisiteClosure, PrerequisiteClosure,
GymnastTrainingRound,
) )
# @admin.register(Educative)
# class EducativeAdmin(admin.ModelAdmin):
# model = Educative
# list_display = ("long_label", "short_label", "difficulty", "level", "rank")
@admin.register(TouchPosition) @admin.register(TouchPosition)
class TouchPositionAdmin(admin.ModelAdmin): class TouchPositionAdmin(admin.ModelAdmin):
model = TouchPosition model = TouchPosition
@ -194,57 +202,94 @@ class PrerequisiteClosureAdmin(admin.ModelAdmin):
) )
# @admin.register(Passe) @admin.register(TrainingRound)
# class PasseAdmin(admin.ModelAdmin): class TrainingRoundAdmin(admin.ModelAdmin):
# model = Passe model = TrainingRound
# fields = ( fields = (
# "label", "label",
# "educatives", "educatives",
# "regexp", "regexp",
# "number_of_skill", "number_of_skill",
# "difficulty", "difficulty",
# "informations", "informations",
# ) )
# list_display = ("label", "regexp", "number_of_skill", "difficulty") list_display = ("label", "regexp", "number_of_skill", "difficulty")
# list_filter = ( list_filter = (
# ("number_of_skill", DropdownFilter), ("number_of_skill", DropdownFilter),
# ("difficulty", DropdownFilter), ("difficulty", DropdownFilter),
# ) )
# filter_horizontal = ("educatives",) filter_horizontal = ("educatives",)
# class Media: # def save_model(self, request, obj, form, change):
# js = ( # if obj.educatives:
# "js/core/jquery-3.6.0.min.js", # form.cleaned_data["educatives"] = obj.educatives.all().values_list(
# "js/admin/passe.js", # "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) @admin.register(GymnastTraining)
# class TrainingProgramAdmin(admin.ModelAdmin): class GymnastTrainingAdmin(admin.ModelAdmin):
# model = TrainingProgram model = GymnastTraining
# fields = ( fields = (
# "gymnast", "label",
# "date", "date",
# "rank", "gymnast",
# "passe", # "trainingrounds",
# "repetition", "difficulty",
# "number_of_skill", "number_of_skill",
# "difficulty", "score",
# # "score", )
# )
# list_display = ( list_display = (
# "date", "label",
# "gymnast", "date",
# "passe", "gymnast",
# "rank", # "trainingrounds",
# "repetition", "difficulty",
# "number_of_skill", "number_of_skill",
# "difficulty", "score",
# ) )
# list_filter = (
# ("gymnast", RelatedDropdownFilter), list_filter = (
# ("date", DropdownFilter), ("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),
)

View File

@ -9,7 +9,7 @@ from .models import (
Skill, Skill,
Routine, Routine,
RoutineSkill, RoutineSkill,
# Passe, TrainingRound,
) )
@ -74,87 +74,101 @@ class CombinationSkillForm(forms.ModelForm):
} }
# class PasseForm(forms.ModelForm): class TrainingRoundForm(forms.ModelForm):
# educatives = forms.ModelMultipleChoiceField( educatives = forms.ModelMultipleChoiceField(
# required=False, required=False,
# queryset=Educative.objects.all(), queryset=Educative.objects.all(),
# widget=FilteredSelectMultiple("Educatives", is_stacked=False), widget=FilteredSelectMultiple("Educatives", is_stacked=False),
# # widget=customFilteredSelectMultiple(verbose_name='test2',is_stacked=False) # widget=customFilteredSelectMultiple(verbose_name='test2',is_stacked=False)
# ) )
# class Media: class Media:
# css = { css = {
# "all": ["admin/css/widgets.css"], "all": ["admin/css/widgets.css"],
# } }
# # Adding this javascript is crucial # Adding this javascript is crucial
# js = ["/admin/jsi18n/"] js = ["/admin/jsi18n/"]
# class Meta: class Meta:
# model = Passe model = TrainingRound
# fields = ("label", "regexp", "educatives", "informations") fields = ("label", "regexp", "educatives", "informations")
# widgets = { widgets = {
# "label": forms.TextInput( "label": forms.TextInput(
# attrs={ attrs={
# "class": "form-control", "class": "form-control",
# "placeholder": "Label (not mandatory)", "placeholder": "Label (not mandatory)",
# "maxlength": 30, "maxlength": 30,
# } }
# ), ),
# "regexp": forms.TextInput( "regexp": forms.TextInput(
# attrs={"class": "form-control", "placeholder": "[2-8]"} attrs={"class": "form-control", "placeholder": "[2-8]"}
# ), ),
# "informations": forms.Textarea( "informations": forms.Textarea(
# attrs={ attrs={
# "class": "form-control", "class": "form-control",
# "placeholder": "Informations about the passe…", # pylint: disable=line-too-long "placeholder": "Informations about the passe…", # pylint: disable=line-too-long
# } }
# ), ),
# } }
# def clean_regexp(self): def clean_regexp(self):
# """Vérifie que la regexp entrée par l'utilisateur est valide.""" """Vérifie que la regexp entrée par l'utilisateur est valide."""
# regexp = self.cleaned_data["regexp"] regexp = self.cleaned_data["regexp"]
# if not Passe.is_valid_regexp(regexp): if not TrainingRound.is_valid_regexp(regexp):
# raise ValidationError("Entered regexp not valid.") raise ValidationError("Entered regexp not valid.")
# return regexp return regexp
# def clean(self): def clean(self):
# """Vérifie le contenu des champs `educatives` par rapport à la valeur de `regexp`. Si """Vérifie le contenu des champs `educatives` par rapport à la valeur de `regexp`. Si
# `regexp` est définie par : `regexp` est définie par :
# - valeurs de ROUTINE_TYPE_CHOICE il faut que Educatives soit VIDE - valeurs de ROUTINE_TYPE_CHOICE il faut que Educatives soit VIDE
# - avec [x-y] - avec [x-y]
# - [x-y] " Educatives soit NON VIDE - [x-y] " Educatives soit NON VIDE
# - WC " il y ait 2+ Educatives - WC " il y ait 2+ Educatives
# - x| " il y ait 1! Educatives - x| " il y ait 1! Educatives
# """ """
# cleaned_data = super().clean() cleaned_data = super().clean()
# regexp = ["regexp"] regexp = cleaned_data["regexp"]
# if regexp is not None: if regexp is not None:
# arguments = regexp.split(" ") # print
# educatives = cleaned_data["educatives"] arguments = regexp.split(" ")
educatives = cleaned_data["educatives"]
print("----------------------------------------------------------------")
print(educatives)
print("----------------------------------------------------------------")
# if Passe.is_valid_routine_type(arguments[0]) and educatives is not None: if TrainingRound.is_valid_routine_type(arguments[0]) and educatives:
# raise ValidationError( raise ValidationError(
# "Educatives must be empty with the entered Regexp." "Educatives must be empty with the entered Regexp."
# ) )
# if Passe.is_valid_subset(arguments[0]) and educatives is None: if TrainingRound.is_valid_subset(arguments[0]) and educatives is None:
# raise ValidationError( raise ValidationError(
# "Educatives can't be empty with the entered Regexp." "Educatives can't be empty with the entered Regexp."
# ) )
# if re.match(r"[1-9]+\|", arguments[0]) and len(educatives) != 1: if re.match(r"[1-9]+\|", arguments[0]) and len(educatives) != 1:
# raise ValidationError( raise ValidationError(
# "One and only one Educatives allowed with the entered Regexp." "One and only one Educatives allowed with the entered Regexp."
# ) )
# if arguments[0] == "WC" and (educatives is None or len(educatives) < 2): if arguments[0] == "WC" and (educatives is None or len(educatives) < 2):
# raise ValidationError( raise ValidationError(
# "At least two Educatives with the entered Regexp." "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()

View File

@ -1,4 +1,4 @@
from django.db import models from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
import re import re
@ -8,6 +8,7 @@ from jarvis.tools.models import (
Seasonisable, Seasonisable,
max_even_if_none, max_even_if_none,
) )
from .signals import *
# from jarvis.followup.models import ROUTINE_TYPE_CHOICE # 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}" return f"{self.rank} - {self.routine.short_label} : {self.skill.short_label}"
# class TrainingRound(Markdownizable): class TrainingRound(Markdownizable):
# """Classe représentant les passages (à faire pendant un entraînement).""" """Classe représentant les passages (à faire pendant un entraînement)."""
# class Meta: class Meta:
# ordering = [ ordering = [
# "label", "label",
# ] ]
# label = models.CharField(max_length=30) label = models.CharField(max_length=30)
# educatives = models.ManyToManyField( educatives = models.ManyToManyField(
# Educative, related_name="passes", blank=True, symmetrical=False Educative, related_name="trainingrounds", blank=True, symmetrical=False
# ) )
# regexp = models.CharField(max_length=50, null=True, blank=True) regexp = models.CharField(max_length=50, null=True, blank=True)
# number_of_skill = models.PositiveSmallIntegerField(default=0) number_of_skill = models.PositiveSmallIntegerField(default=0)
# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.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.
# def save(self, *args, **kwargs): @staticmethod
# """Sauve les informations de la personne et initialise les champs nettoyés. def number_of_skill_from_subset(subset, educative=None):
# On part du principe que self.regexp est correct. """ """
# """ if not TrainingRound.is_valid_subset(subset):
# self.difficulty = 0 return 0, 0, 0
# self.number_of_skill = 0
# super().save(*args, **kwargs)
# # print("Dans le save")
# if self.educatives.count() == 0: subset = subset.replace("[", "").replace("]", "")
# # print("educative is none") ranks = subset.split("-")
# present = False
# operation_list = self.regexp.split(" ")
# for item in ROUTINE_TYPE_CHOICE:
# if item[1] == operation_list[0]:
# present = True
# break
# if present and len(operation_list) == 2: if ranks[0] == "":
# # print("present") start = 0
# content = operation_list[1].replace("[", "").replace("]", "") else:
# ranks = content.split("-") start = int(ranks[0])
# if ranks[0] == "": if ranks[1] == "":
# self.number_of_skill += int(ranks[1]) if educative is not None:
# elif ranks[1] == "": end = educative.jumps.all().count()
# self.number_of_skill += (10 - int(ranks[0])) + 1 else:
# else: end = 10
# self.number_of_skill += (int(ranks[1]) - int(ranks[0])) + 1 else:
# else: end = int(ranks[1])
# self.number_of_skill += 10
# else: number_of_skill = (end - start) + 1
# 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
# if is_skill: return start, end, number_of_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("-")
# start = regexp[:position] @staticmethod
# if start == "": def difficulty_from_regexp(educative, start, end):
# start = 0 """ """
# else: difficulty = 0
# start = int(start) list_of_skill = educative.skill_links.filter(rank__gte=start, rank__lte=end)
# .aggregate(total=Sum("value"))
# end = regexp[position + 1 :] for routine_skill in list_of_skill:
# if end == "": difficulty += routine_skill.skill.difficulty
# end = educative.jumps.all().count()
# else:
# end = int(end)
# self.number_of_skill += end - (start - 1) return difficulty
# 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
# else: def update_traininground(self):
# self.number_of_skill += educative.jumps.all().count() """Update `number_of_skill` et `difficulty`.
# self.difficulty += educative.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): if len(operation_list) == 2:
# return f"{self.label} ({self.number_of_skill} | {self.difficulty})" _, _, number_of_skill = TrainingRound.number_of_skill_from_subset(
operation_list[1]
)
else:
number_of_skill += 10
# @staticmethod else:
# def is_valid_regexp_one_arg(arg): for educative in self.educatives.all():
# """Vérifie une regexp avec un paramètre.""" is_skill = False
# if arg == "WC":
# return True
# if re.match(r"[1-9]+\|", arg): try:
# return True 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): if is_skill:
# return False 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(".", "") else:
# is_valid_routine = TrainingRound.is_valid_routine_type(value) number_of_skill += educ.jumps.all().count()
difficulty += educ.difficulty
# if is_valid_routine: self.difficulty = difficulty
# return True 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 # https://stackoverflow.com/questions/13751217/can-the-super-save-method-be-used-several-times-in-a-model
# def is_valid_regexp_two_args(arg1, arg2): # """
# """Vérifie une regexp avec deux paramètres.""" # # print("Object:" + str(self))
# if not TrainingRound.is_valid_dot(arg1): # instance = super().save(*args, **kwargs)
# return False # # print("Calling update_fileds on commit transaction.")
# transaction.on_commit(self.update_fields)
# # print("Fields updated.")
# return instance
# value = arg1.replace(".", "") def __str__(self):
# is_valid_routine = TrainingRound.is_valid_routine_type(value) return f"{self.label} ({self.number_of_skill} | {self.difficulty})"
# if is_valid_routine: def is_regexp_wc(self):
# return TrainingRound.is_valid_subset(arg2) """ """
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 if re.match(r"[1-9]+\|", regexp):
# def is_valid_dot(pattern): return True
# """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.search("\.", pattern): if not TrainingRound.is_valid_dot(regexp):
# last_place = len(pattern) - 1 return False
# if pattern[0] != "." and pattern[last_place] != ".":
# return False
# return True value = regexp.replace(".", "")
is_valid_routine = TrainingRound.is_valid_routine_type(value)
# @staticmethod if is_valid_routine:
# def is_valid_routine_type(routine_type): return True
# """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
# return is_valid return TrainingRound.is_valid_subset(regexp)
# @staticmethod @staticmethod
# def is_valid_subset(subset): def is_valid_regexp_two_args(arg1, arg2):
# """Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme. """Vérifie une regexp avec deux paramètres."""
if not TrainingRound.is_valid_dot(arg1):
return False
# Format attendu : [X-Y] value = arg1.replace(".", "")
# X ou Y peuvent être vide mais pas en même temps. is_valid_routine = TrainingRound.is_valid_routine_type(value)
# X est un entier >= 2
# Y est un entier >= 2 OU Y > X si X est non vide
# Exemples : if is_valid_routine:
# - [2-8] True return TrainingRound.is_valid_subset(arg2)
# - [-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 False
# return True
# if int(ranks[0]) < int(ranks[1]): @staticmethod
# return True 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 return True
# def is_valid_regexp(regexp):
# """Vérifie le champ regexp
# Exemples : @staticmethod
# - Q1R1 True def is_valid_routine_type(routine_type):
# - Q1R2 [2-8] True """Recoit une chaine de caractère et vérifie si elle est présente dans la liste
# - Q2R1 [-5] True ROUTINE_TYPE_CHOICE (Educative vide !)
# - SF [6-] True """
# - FS [3-7] True is_valid_routine = False
# - Q1R1. True for item in ROUTINE_TYPE_CHOICE:
# - .Q1R2 True if item[1] == routine_type:
# - Q1R1. [-4] True is_valid_routine = True
# - .Q1R2 [4-] True break
# - .FS [3-7] True
# - [2-8] True
# - [-5] True
# - WC True
# - 1| True
# """
# argument_list = regexp.split(" ")
# if len(argument_list) >= 3: return is_valid_routine
# return False
# if len(argument_list) == 2: @staticmethod
# return TrainingRound.is_valid_regexp_two_args( def is_valid_subset(subset):
# argument_list[0], argument_list[1] """Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme.
# )
# else:
# return TrainingRound.is_valid_regexp_one_arg(argument_list[0])
# 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): class GymnastTraining(Seasonisable, Markdownizable):
# """Classe représentant un entraînement.""" """Classe représentant un entraînement."""
# label = models.CharField() label = models.CharField()
# gymnast = models.ForeignKey("people.Gymnast", on_delete=models.CASCADE) gymnast = models.ForeignKey(
# training_rounds = models.ManyToManyField( "people.Gymnast",
# TrainingRound, through="GymnastTrainingRound", verbose_name="trainings" on_delete=models.CASCADE,
# ) related_name="trainings",
# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) )
# number_of_skill = models.PositiveSmallIntegerField(default=0) trainingrounds = models.ManyToManyField(
# score = models.PositiveSmallIntegerField(default=1) 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): def __str__(self):
# return f"Training on {self.date} for {self.gymnast}: {self.number_of_skill} | {self.difficulty}" return f"Training on {self.date} for {self.gymnast}: {self.number_of_skill} | {self.difficulty}"
# class GymnastTrainingRound(Markdownizable): class GymnastTrainingRound(Markdownizable):
# """Classe représentant un passage.""" """Classe représentant un passage."""
# class Meta: class Meta:
# verbose_name = "Gymnast Training Round" verbose_name = "Gymnast Training Round"
# verbose_name_plural = "Gymnast Training Rounds" verbose_name_plural = "Gymnast Training Rounds"
# ordering = [ ordering = [
# "rank", "rank",
# ] ]
# unique_together = ["gymnast_training", "rank"] unique_together = ["gymnast_training", "rank"]
# gymnast_training = models.ForeignKey( gymnast_training = models.ForeignKey(
# GymnastTraining, GymnastTraining,
# on_delete=models.CASCADE, on_delete=models.CASCADE,
# related_name="training_rounds", related_name="training_rounds",
# ) )
# training_round = models.ForeignKey(TrainingRound, on_delete=models.CASCADE) training_round = models.ForeignKey(TrainingRound, on_delete=models.CASCADE)
# repetition = models.PositiveSmallIntegerField(default=1) repetition = models.PositiveSmallIntegerField(default=1)
# rank = models.PositiveSmallIntegerField(default=1) rank = models.PositiveSmallIntegerField(default=1)
# updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
# number_of_skill = models.PositiveSmallIntegerField(default=0) number_of_skill = models.PositiveSmallIntegerField(default=0)
# score = models.PositiveSmallIntegerField(blank=True, null=True) score = models.PositiveSmallIntegerField(blank=True, null=True)
# difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0) difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0)
# def __str__(self): def __str__(self):
# return ( return f"{self.gymnast_training} {self.gymnast_training.date} - {self.rank} : {self.training_round} {self.repetition}"
# f"{self.gymnast} {self.date} - {self.rank} : {self.passe} {self.repetition}"
# )
# def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# """Sauve les informations de la personne et initialise les champs nettoyés.""" """Sauve les informations de la personne et initialise les champs nettoyés."""
# super().save(*args, **kwargs) super().save(*args, **kwargs)
# self.difficulty = self.round.difficulty * self.repetition self.difficulty = self.training_round.difficulty * self.repetition
# self.number_of_skill = self.round.number_of_skill * self.repetition self.number_of_skill = self.training_round.number_of_skill * self.repetition
# super().save(*args, **kwargs) super().save(*args, **kwargs)

View File

@ -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

View File

@ -8,29 +8,29 @@
<div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6"> <div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
{% if trainingprogram_list %} {% if gymnast_training %}
<table class="table table-striped tablesorter" id="trainingprogram_table"> <table class="table table-striped tablesorter" id="trainingprogram_table">
<thead> <thead>
<tr> <tr>
<th colspan="5" class="text-center">{% if gymnast %}{{ gymnast }} - {% endif %}{{ date|date:"l j F Y" }}</th> <th colspan="5" class="text-center">{{ gymnast_training.gymnast }} - {{ gymnast_training.date|date:"l j F Y" }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for trainingprogram in trainingprogram_list %} {% for round in training_rounds %}
<tr role="row" class="{% cycle 'odd' 'even' %}"> <tr role="row" class="{% cycle 'odd' 'even' %}">
<td><b>{{ trainingprogram.rank }}</b></td> <td><b>{{ round.rank }}</b></td>
<td class="text-center"><a href="{% url 'passe_details' trainingprogram.passe.id gymnast.id date %}">{{ trainingprogram.passe.label }}</a>{% if trainingprogram.repetition != 1 %}&nbsp;&nbsp;&nbsp;{{ trainingprogram.repetition }}{% endif %}</td> <td class="text-center"><a href="{% url 'traininground_details' round.id %}">{{ round.training_round.label }}</a>{% if round.repetition != 1 %}&nbsp;&nbsp;&nbsp;{{ round.repetition }}{% endif %}</td>
<td class="text-center">{{ trainingprogram.number_of_skill}}</td> <td class="text-center">{{ round.number_of_skill}}</td>
<td class="text-center">{{ trainingprogram.difficulty }}</td> <td class="text-center">{{ round.difficulty }}</td>
{% if request.user|has_group:"trainer" %} {% if request.user|has_group:"trainer" %}
<td class="text-center p-2"> <td class="text-center p-2">
<a href="#" class="up" data-tp_id="{{ trainingprogram.id }}" data-rank="{{ trainingprogram.rank }}"> <a href="#" class="up" data-tp_id="{{ round.id }}" data-rank="{{ round.rank }}">
<button type="submit" value="" class="btn btn-icon btn-warning mr-2"> <button type="submit" value="" class="btn btn-icon btn-warning mr-2">
<i class="fas fa-chevron-up"></i> <i class="fas fa-chevron-up"></i>
</button> </button>
</a> </a>
<a href="#" class="down" data-tp_id="{{ trainingprogram.id }}" data-rank="{{ trainingprogram.rank }}"> <a href="#" class="down" data-tp_id="{{ round.id }}" data-rank="{{ round.rank }}">
<button type="submit" value="add" class="btn btn-icon btn-warning mr-2"> <button type="submit" value="add" class="btn btn-icon btn-warning mr-2">
<i class="fas fa-chevron-down"></i> <i class="fas fa-chevron-down"></i>
</button> </button>
@ -42,8 +42,8 @@
</tbody> </tbody>
<tr> <tr>
<td colspan="2" class="text-right"><b>TOTAL</b></td> <td colspan="2" class="text-right"><b>TOTAL</b></td>
<td class="text-center"><b>{{ number_of_skill }}</b></td> <td class="text-center"><b>{{ gymnast_training.number_of_skill }}</b></td>
<td class="text-center"><b>{{ difficulty }}</b></td> <td class="text-center"><b>{{ gymnast_training.difficulty }}</b></td>
{% if request.user|has_group:"trainer" %} {% if request.user|has_group:"trainer" %}
<td></td> <td></td>
{% endif %} {% endif %}
@ -67,7 +67,7 @@ $(document).ready(function(){
if ($(this).is(".up")) { if ($(this).is(".up")) {
$.ajax({ $.ajax({
url: "{% url 'switch_trainingprogram_line' %}", url: "{% url 'switch_traininground' %}",
method: "POST", method: "POST",
data: { data: {
tpid: $(this).data('tp_id'), tpid: $(this).data('tp_id'),
@ -85,7 +85,7 @@ $(document).ready(function(){
}); });
} else { } else {
$.ajax({ $.ajax({
url: "{% url 'switch_trainingprogram_line' %}", url: "{% url 'switch_traininground' %}",
method: "POST", method: "POST",
data: { data: {
tpid: $(this).data('tp_id'), tpid: $(this).data('tp_id'),

View File

@ -8,7 +8,7 @@
<h4 class="">{% if passe_id %}Edit{% else %}Add{% endif %} Passe</h4> <h4 class="">{% if passe_id %}Edit{% else %}Add{% endif %} Passe</h4>
</div> </div>
<div class="card-body"> <div class="card-body">
<form action="{% if passe_id %}{% url 'passe_update' passe_id %}{% else %}{% url 'passe_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire"> <form action="{% if passe_id %}{% url 'traininground_update' passe_id %}{% else %}{% url 'traininground_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
{% csrf_token %} {% csrf_token %}
{% for hidden in form.hidden_fields %} {% for hidden in form.hidden_fields %}
@ -16,7 +16,7 @@
{% endfor %} {% endfor %}
<div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}">
<label for="id_label" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Label</label> <label for="id_label" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Label<span class="text-danger"><b>*</b></span></label>
<div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10"> <div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
{{ form.label }} {{ form.label }}
{% if form.label.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.label.errors %}{{ error }}{% endfor %}</span>{% endif %} {% if form.label.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.label.errors %}{{ error }}{% endfor %}</span>{% endif %}
@ -24,7 +24,7 @@
</div> </div>
<div class="form-group row {% if form.regexp.errors %}has-error has-feedback{% endif %}"> <div class="form-group row {% if form.regexp.errors %}has-error has-feedback{% endif %}">
<label for="id_regexp" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.regexp.label }}<span class="text-danger"><b>*</b></span></label> <label for="id_regexp" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.regexp.label }}</label>
<div class="col-4 col-sm-4 col-md-4 col-lg-4 col-xl-3"> <div class="col-4 col-sm-4 col-md-4 col-lg-4 col-xl-3">
{{ form.regexp }} {{ form.regexp }}
{% if form.regexp.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.regexp.errors %}{{ error }}{% endfor %}</span>{% endif %} {% if form.regexp.errors %}&nbsp;<span class="btn btn-sm btn-danger-outline">{% for error in form.regexp.errors %}{{ error }}{% endfor %}</span>{% endif %}

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load has_group %} {% load has_group %}
{% block page_title %}Passe details{% endblock %} {% block page_title %}Training Round details{% endblock %}
{% block content %} {% block content %}
<div class="row justify-content-center"> <div class="row justify-content-center">
@ -9,8 +9,8 @@
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h4 class="mb-0">Passe details</h3> <h4 class="mb-0">Training round details</h3>
<h5 class="card-category mb-0">{{ passe.label }} {% if passe.regexp %}{{ passe.regexp }}{% endif %}</a>&nbsp;&nbsp;&nbsp;{{ passe.repetition }}</h4> <h5 class="card-category mb-0">{{ traininground.label }} {% if traininground.regexp and traininground.label != traininground.label %}{{ traininground.regexp }}{% endif %}</a>&nbsp;&nbsp;&nbsp;{{ traininground.repetition }}</h4>
</div> </div>
<div class="card-body"> <div class="card-body">
@ -19,34 +19,48 @@
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_label" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Label</label> <label for="id_label" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Label</label>
<div class="col-8 col-sm-6 col-md-7 col-lg-8 col-xl-9 pt-2"> <div class="col-8 col-sm-6 col-md-7 col-lg-8 col-xl-9 pt-2">
{{ passe.label }} {{ traininground.label }}
</div> </div>
</div> </div>
{% if content %}
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_educative" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Content</label> <label for="id_educative" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Content</label>
<div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2"> <div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2">
<ul class="mb-0 ml-4 pl-0">
{% if routine and not skill_link_list %} {% if routine and not skill_link_list %}
<ul class="mb-0 ml-4 pl-0">
<li><a href="{% url 'educative_details' routine.id %}">{{ routine }}</a></li> <li><a href="{% url 'educative_details' routine.id %}">{{ routine }}</a></li>
</ul>
{% elif routine and skill_link_list %} {% elif routine and skill_link_list %}
<ul class="mb-0 ml-4 pl-0">
{% for routine_skill in skill_link_list %} {% for routine_skill in skill_link_list %}
<li><a href="{% url 'educative_details' routine_skill.skill.id %}">{{ routine_skill.rank }} - {{ routine_skill.skill.notation }}</a></li> <li><a href="{% url 'educative_details' routine_skill.skill.id %}">{{ routine_skill.rank }} - {{ routine_skill.skill.notation }}</a></li>
{% endfor %} {% endfor %}
</ul>
{% else %} {% else %}
{% for educative in passe.educatives.all %} {% if is_wc %}
<li><a href="{% url 'educative_details' educative.id %}">{{ educative }}</a></li> {% for educative in traininground.educatives.all %}
{% endfor %} <a href="{% url 'educative_details' educative.id %}">{{ educative.notation }}</a> -
{% endfor %}
{% else %}
<ul class="mb-0 ml-4 pl-0">
{% for educative in traininground.educatives.all %}
<li><a href="{% url 'educative_details' educative.id %}">{{ educative }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% endif %} {% endif %}
</ul> </ul>
</div> </div>
</div> </div>
{% endif %}
{% if passe.regexp and passe.regexp != passe.label %} {% if traininground.regexp and traininground.regexp != traininground.label %}
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Regexp</label> <label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Regexp</label>
<div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2"> <div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2">
{{ passe.regexp }} {{ traininground.regexp }}
</div> </div>
</div> </div>
{% endif %} {% endif %}
@ -54,22 +68,22 @@
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Number of Skill</label> <label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Number of Skill</label>
<div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2"> <div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2">
{{ number_of_educative }} {{ traininground.number_of_skill }}
</div> </div>
</div> </div>
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Difficulty</label> <label for="id_regexp" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Difficulty</label>
<div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2"> <div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2">
{{ difficulty }} {{ traininground.difficulty }}
</div> </div>
</div> </div>
{% if information %} {% if traininground.information %}
<div class="form-group row mb-0"> <div class="form-group row mb-0">
<label for="id_informations" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Informations</label> <label for="id_informations" class="col-4 col-sm-6 col-md-5 col-lg-4 col-xl-3 col-form-label">Informations</label>
<div class="col-8 col-sm-9 col-md-9 col-lg-9 col-xl-9 {% if form.id_information.errors %}has-danger{% endif %}"> <div class="col-8 col-sm-9 col-md-9 col-lg-9 col-xl-9 {% if form.id_information.errors %}has-danger{% endif %}">
{{ informations }} {{ traininground.informations }}
</div> </div>
</div> </div>
{% endif %} {% endif %}

View File

@ -5,7 +5,7 @@ from jarvis.objective.models import (
TouchPosition, TouchPosition,
Routine, Routine,
RoutineSkill, RoutineSkill,
Passe, TrainingRound,
) )
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
@ -106,7 +106,7 @@ class ToolsModels(TestCase):
) )
class PasseTestCase(TestCase): class TrainingRoundTestCase(TestCase):
def setUp(self): def setUp(self):
""" """
Structure finale : Structure finale :
@ -126,134 +126,134 @@ class PasseTestCase(TestCase):
def test_is_valid_dot(self): def test_is_valid_dot(self):
arg = "" arg = ""
self.assertEqual(Passe.is_valid_dot(arg), True) self.assertEqual(TrainingRound.is_valid_dot(arg), True)
arg = "Q1R1" arg = "Q1R1"
self.assertEqual(Passe.is_valid_dot(arg), True) self.assertEqual(TrainingRound.is_valid_dot(arg), True)
arg = ".Q1R1" arg = ".Q1R1"
self.assertEqual(Passe.is_valid_dot(arg), True) self.assertEqual(TrainingRound.is_valid_dot(arg), True)
arg = "Q1R1." arg = "Q1R1."
self.assertEqual(Passe.is_valid_dot(arg), True) self.assertEqual(TrainingRound.is_valid_dot(arg), True)
arg = "Q1.R1" arg = "Q1.R1"
self.assertEqual(Passe.is_valid_dot(arg), False) self.assertEqual(TrainingRound.is_valid_dot(arg), False)
arg = ".Q1.R1." arg = ".Q1.R1."
self.assertEqual(Passe.is_valid_dot(arg), False) self.assertEqual(TrainingRound.is_valid_dot(arg), False)
def test_is_valid_subset(self): def test_is_valid_subset(self):
subset = "" subset = ""
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[2-8]" subset = "[2-8]"
self.assertEqual(Passe.is_valid_subset(subset), True) self.assertEqual(TrainingRound.is_valid_subset(subset), True)
subset = "[2--8]" subset = "[2--8]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[-5]" subset = "[-5]"
self.assertEqual(Passe.is_valid_subset(subset), True) self.assertEqual(TrainingRound.is_valid_subset(subset), True)
subset = "[3-]" subset = "[3-]"
self.assertEqual(Passe.is_valid_subset(subset), True) self.assertEqual(TrainingRound.is_valid_subset(subset), True)
subset = "[8-2]" subset = "[8-2]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[-]" subset = "[-]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[1-]" subset = "[1-]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[-1]" subset = "[-1]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[4]" subset = "[4]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[6-6]" subset = "[6-6]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "4" subset = "4"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[6-6" subset = "[6-6"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[66]" subset = "[66]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "4-8" subset = "4-8"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "6-]" subset = "6-]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[4-" subset = "[4-"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "[6" subset = "[6"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "Q1R1 [4-8]" subset = "Q1R1 [4-8]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
subset = "Q1R1 [-8]" subset = "Q1R1 [-8]"
self.assertEqual(Passe.is_valid_subset(subset), False) self.assertEqual(TrainingRound.is_valid_subset(subset), False)
def test_is_valid_routine_type(self): def test_is_valid_routine_type(self):
for item in ROUTINE_TYPE_CHOICE: for item in ROUTINE_TYPE_CHOICE:
self.assertEqual(Passe.is_valid_routine_type(item[1]), True) self.assertEqual(TrainingRound.is_valid_routine_type(item[1]), True)
routine_type = "" routine_type = ""
self.assertEqual(Passe.is_valid_routine_type(routine_type), False) self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
routine_type = ".Q1R1" routine_type = ".Q1R1"
self.assertEqual(Passe.is_valid_routine_type(routine_type), False) self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
routine_type = "SFS." routine_type = "SFS."
self.assertEqual(Passe.is_valid_routine_type(routine_type), False) self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
routine_type = "Q1R1 [4-8]" routine_type = "Q1R1 [4-8]"
self.assertEqual(Passe.is_valid_routine_type(routine_type), False) self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
routine_type = "SFS [-8]" routine_type = "SFS [-8]"
self.assertEqual(Passe.is_valid_routine_type(routine_type), False) self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
def test_is_valid_regexp_one_arg(self): def test_is_valid_regexp_one_arg(self):
arg = "" arg = ""
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), False) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
arg = "WC" arg = "WC"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), True) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
arg = "1|" arg = "1|"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), True) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
arg = ".Q1R1" arg = ".Q1R1"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), True) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
arg = "Q1R2." arg = "Q1R2."
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), True) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
arg = ".Q1R1 [4-8" arg = ".Q1R1 [4-8"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), False) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
arg = "Q1R2. [4-8" arg = "Q1R2. [4-8"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), False) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
arg = "Q1R1 [4-8]" arg = "Q1R1 [4-8]"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), False) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
arg = "Q1R1 [8-4]" arg = "Q1R1 [8-4]"
self.assertEqual(Passe.is_valid_regexp_one_arg(arg), False) self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
def test_is_valid_regexp_two_args(self): def test_is_valid_regexp_two_args(self):
arg1 = "" arg1 = ""
arg2 = "" arg2 = ""
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), False) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
arg1 = "Q1R1" arg1 = "Q1R1"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), False) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
arg2 = "[4-8]" arg2 = "[4-8]"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), True) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
arg2 = "[8-8]" arg2 = "[8-8]"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), False) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
arg2 = "[8-4]" arg2 = "[8-4]"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), False) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
arg2 = "[-8]" arg2 = "[-8]"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), True) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
arg2 = "[4-]" arg2 = "[4-]"
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), True) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
arg1 = "Q1R1." arg1 = "Q1R1."
self.assertEqual(Passe.is_valid_regexp_two_args(arg1, arg2), True) self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
def test_is_valid_regexp(self): def test_is_valid_regexp(self):
regexp = "" regexp = ""
self.assertEqual(Passe.is_valid_regexp(regexp), False) self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
regexp = "Q1R1 [4-8]" regexp = "Q1R1 [4-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = "Q1R1 [8-8]" regexp = "Q1R1 [8-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), False) self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
regexp = "Q1R1 [8-4]" regexp = "Q1R1 [8-4]"
self.assertEqual(Passe.is_valid_regexp(regexp), False) self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
regexp = "Q1R1 [-8]" regexp = "Q1R1 [-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = "Q1R1 [4-]" regexp = "Q1R1 [4-]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = "Q1R1. [4-8]" regexp = "Q1R1. [4-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = "Q1R1. [4-]" regexp = "Q1R1. [4-]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = ".Q1R1 [-8]" regexp = ".Q1R1 [-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), True) self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
regexp = "Q1R1. [8-8]" regexp = "Q1R1. [8-8]"
self.assertEqual(Passe.is_valid_regexp(regexp), False) self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
regexp = ".Q1R1 [8-4]" regexp = ".Q1R1 [8-4]"
self.assertEqual(Passe.is_valid_regexp(regexp), False) self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)

View File

@ -90,35 +90,35 @@ urlpatterns = [
), ),
path(r"combination/", views.combination_listing, name="combination_listing"), path(r"combination/", views.combination_listing, name="combination_listing"),
# #
# PASSES # TRAININGROUND
# #
# path( path(
# r"passe/<int:passe_id>/gymnast/<int:gymnast_id>/date/<str:date>/", r"traininground/<int:traininground_id>/",
# views.passe_details, views.traininground_details,
# name="passe_details", name="traininground_details",
# ), ),
# path(r"passe/", views.passe_listing, name="passe_listing"), path(r"traininground/", views.traininground_listing, name="traininground_listing"),
# path( path(
# r"passe/add/", r"traininground/add/",
# views.passe_create_or_update, views.traininground_create_or_update,
# name="passe_create", name="traininground_create",
# ), ),
# path( path(
# r"passe/edit/<int:passe_id>/", r"traininground/edit/<int:passe_id>/",
# views.passe_create_or_update, views.traininground_create_or_update,
# name="passe_update", name="traininground_update",
# ), ),
# #
# TRAININGPROGRAM # GYMNASTTRAINING
# #
# path( path(
# r"trainingprogram/detail/date/<str:date>/gymnast/<int:gymnast_id>/", r"gymnasttraining/detail/<int:gymnast_training_id>/",
# views.trainingprogram_details, views.gymnast_training_details,
# name="trainingprogram_details", name="gymnast_training_details",
# ), ),
# path( path(
# r"trainingprogram/switch_trainingprogram_line/", r"gymnasttraining/switch_traininground/",
# views.switch_trainingprogram_line, views.switch_traininground,
# name="switch_trainingprogram_line", name="switch_traininground",
# ), ),
] ]

View File

@ -5,25 +5,24 @@ from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
from django.urls import reverse from django.urls import reverse
import pendulum
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
from jarvis.people.models import Gymnast from jarvis.people.models import Gymnast
from jarvis.followup.models import GymnastHasRoutine from jarvis.followup.models import GymnastHasRoutine
from .forms import ( from .forms import (
SkillForm, SkillForm,
# PasseForm, TrainingRoundForm,
CombinationForm, CombinationForm,
CombinationSkillForm, CombinationSkillForm,
) )
from .models import ( from .models import (
Skill, Skill,
# Passe, TrainingRound,
Routine, Routine,
Educative, Educative,
RoutineSkill, RoutineSkill,
# TrainingProgram, GymnastTraining,
GymnastTrainingRound,
PrerequisiteClosure, PrerequisiteClosure,
) )
@ -512,189 +511,155 @@ def unlink_skill_from_combination(request):
return HttpResponse(200) return HttpResponse(200)
# @login_required @login_required
# @require_http_methods(["GET"]) @require_http_methods(["GET"])
# def passe_listing(request): def traininground_listing(request):
# """Liste des passages.""" """Liste des passages."""
# passe_listing = Passe.objects.all() passe_listing = TrainingRound.objects.all()
# context = {"passe_listing": passe_listing} context = {"passe_listing": passe_listing}
# return render(request, "passes/list.html", context) return render(request, "trainingrounds/list.html", context)
# @login_required @login_required
# @require_http_methods(["GET"]) @require_http_methods(["GET"])
# def passe_details(request, passe_id, gymnast_id, date): def traininground_details(request, traininground_id, date=None):
# """Détails d'un passage.""" """Détails d'un passage."""
# is_skill = False is_skill = False
# passe = get_object_or_404(Passe, pk=passe_id) traininground = get_object_or_404(TrainingRound, pk=traininground_id)
# educative_list = passe.educatives.all() educative_list = traininground.educatives.all()
# # TODO: décryptage de la regexp
# regexp = passe.regexp
# routine = None
# skill_link_list = None
# if regexp is not None: routine = None
# operation_list = regexp.split(" ") skill_link_list = None
# routine_type = None
# for item in ROUTINE_TYPE_CHOICE: traininground.update_traininground()
# if item[1] == operation_list[0]:
# routine_type = item[0]
# break
# if routine_type is not None: # Decryptage de la regexp
# # Récupération de la série if traininground.regexp is not None and traininground.regexp != "":
# ghr = GymnastHasRoutine.objects.filter( arguments = traininground.regexp.split(" ")
# gymnast=gymnast_id, if TrainingRound.is_valid_routine_type(arguments[0]) and date is not None:
# date_begin__lte=date, # get routine_type
# # date_end__gte=date, routine_type = 0
# routine_type=routine_type, ghr = GymnastHasRoutine.objects.filter(
# ) gymnast=traininground.gymnast,
date_begin__lte=date,
routine_type=routine_type,
).first()
# print(ghr.query) routine = ghr.routine
skill_link_list = routine.skill_links.all()
if len(arguments) == 2:
content = arguments[1].replace("[", "").replace("]", "")
ranks = content.split("-")
# if ghr.count() > 1: if ranks[0] != "":
# print("Plus d'une série trouvée...") skill_link_list = skill_link_list.filter(rank__gte=ranks[0])
# print(ghr) if ranks[1] != "":
skill_link_list = skill_link_list.filter(rank__lte=ranks[1])
# routine = ghr.first().routine content = False
# skill_link_list = routine.skill_links.all() if skill_link_list or routine or educative_list:
# if len(operation_list) == 2: content = True
# content = operation_list[1].replace("[", "").replace("]", "")
# ranks = content.split("-")
# if ranks[0] != "": context = {
# skill_link_list = skill_link_list.filter(rank__gte=ranks[0]) "is_skill": is_skill,
"traininground": traininground,
# if ranks[1] != "": "educative_list": educative_list,
# skill_link_list = skill_link_list.filter(rank__lte=ranks[1]) "routine": routine,
"skill_link_list": skill_link_list,
# number_of_educative = skill_link_list.count() "content": content,
# print(number_of_educative) "is_wc": traininground.is_regexp_wc
# "number_of_educative": number_of_educative,
# else: }
# number_of_educative = educative_list.count() return render(request, "trainingrounds/details.html", context)
# context = {
# "passe": passe,
# "is_skill": is_skill,
# "educative_list": educative_list,
# "routine": routine,
# "skill_link_list": skill_link_list,
# "difficulty": passe.difficulty,
# "number_of_skill": passe.number_of_skill,
# "number_of_educative": number_of_educative,
# }
# return render(request, "passes/details.html", context)
# @login_required @login_required
# @require_http_methods(["GET", "POST"]) @require_http_methods(["GET", "POST"])
# def passe_create_or_update(request, passe_id=None): def traininground_create_or_update(request, traininground_id=None):
# """Création d'un passage. """Création d'un passage.
# Args: Args:
# passe_id (int) identifiant d'un object de classe <Passe>. traininground_id (int) identifiant d'un object de classe <TrainingRound>.
# """ """
# if passe_id: if traininground_id:
# passe = get_object_or_404(Passe, pk=passe_id) traininground = get_object_or_404(TrainingRound, pk=traininground_id)
# else: else:
# passe = None traininground = None
# if request.method == "POST": if request.method == "POST":
# form = PasseForm(request.POST, instance=passe) form = TrainingRoundForm(request.POST, instance=traininground)
# if form.is_valid(): if form.is_valid():
# passe = form.save() traininground = form.save()
# return HttpResponseRedirect(reverse("passe_details", args=(passe.pk,))) return HttpResponseRedirect(
reverse("traininground_details", args=(traininground.pk,))
)
# print(form.errors)
return render(request, "trainingrounds/create.html", {"form": form})
# return render(request, "passes/create.html", {"form": form}) form = TrainingRoundForm(instance=traininground)
context = {"form": form, "traininground_id": traininground_id}
# form = PasseForm(instance=passe) return render(request, "trainingrounds/create.html", context)
# context = {"form": form, "passe_id": passe_id}
# return render(request, "passes/create.html", context)
# @login_required @login_required
# @require_http_methods(["GET"]) @require_http_methods(["GET"])
# def trainingprogram_details(request, date=None, gymnast_id=None): def gymnast_training_details(request, gymnast_training_id):
# """Détails d'un entraînement.""" """Détails d'un entraînement."""
# gymnast = None gymnast_training = get_object_or_404(GymnastTraining, pk=gymnast_training_id)
# trainingprogram_id = None training_rounds = gymnast_training.training_rounds.all()
# if trainingprogram_id is not None:
# trainingprogram = get_object_or_404(TrainingProgram, pk=trainingprogram_id)
# trainingprogram_list = None
# else:
# trainingprogram = None
# trainingprogram_list = TrainingProgram.objects.all()
# parsed_date = pendulum.parse(date).date()
# if date is not None:
# trainingprogram_list = trainingprogram_list.filter(date=parsed_date)
# if gymnast_id is not None: context = {
# gymnast = get_object_or_404(Gymnast, pk=gymnast_id) "gymnast": gymnast_training.gymnast,
# trainingprogram_list = trainingprogram_list.filter(gymnast=gymnast_id) "gymnast_training": gymnast_training,
"training_rounds": training_rounds,
# difficulty = 0 }
# number_of_skill = 0 return render(request, "gymnasttrainings/details.html", context)
# for trainingprogram in trainingprogram_list:
# difficulty += trainingprogram.difficulty
# number_of_skill += trainingprogram.number_of_skill
# context = {
# "gymnast": gymnast,
# "date": parsed_date,
# "difficulty": difficulty,
# "number_of_skill": number_of_skill,
# "trainingprogram": trainingprogram,
# "trainingprogram_list": trainingprogram_list,
# }
# return render(request, "trainingprograms/details.html", context)
# @require_http_methods(["POST"]) @require_http_methods(["POST"])
# def switch_trainingprogram_line(request): def switch_traininground(request):
# """ """
# Recoit dans request deux identifiants de trainingprogram qu'il faut échanger () : Recoit dans request deux identifiants de trainingprogram qu'il faut échanger :
# - tp_id (int) identifiant d'une instance de TraiingProgram - tp_id (int) identifiant d'une instance de TraiingProgram
# - direction (str) la direction du changement (0: haut, 1: bas) - direction (str) la direction du changement (0: haut, 1: bas)
# J'utilise `32767` comme valeur intermédiaire pour le `rank` car c'est la limite supérieure d'un J'utilise `32767` comme valeur intermédiaire pour le `rank` car c'est la limite supérieure d'un
# PositiveSmallIntegerField. PositiveSmallIntegerField.
# """ """
# try: try:
# target_trainingprogram_id = request.POST.get("tpid", None) target_trainingprogram_id = request.POST.get("tpid", None)
# direction = int(request.POST.get("direction", 0)) direction = int(request.POST.get("direction", 0))
# target_trainingprogram = get_object_or_404( target_trainingpround = get_object_or_404(
# TrainingProgram, pk=target_trainingprogram_id GymnastTrainingRound, pk=target_trainingprogram_id
# ) )
# if direction == 0: if direction == 0:
# source_trainingprogram = ( source_traininground = (
# TrainingProgram.objects.filter(rank__lt=target_trainingprogram.rank) GymnastTrainingRound.objects.filter(rank__lt=target_trainingpround.rank)
# .order_by("-id") .order_by("-id")
# .first() .first()
# ) )
# else: else:
# source_trainingprogram = ( source_traininground = (
# TrainingProgram.objects.filter(rank__gt=target_trainingprogram.rank) GymnastTrainingRound.objects.filter(rank__gt=target_trainingpround.rank)
# .order_by("id") .order_by("id")
# .first() .first()
# ) )
# saved_source_rank = source_trainingprogram.rank saved_source_rank = source_traininground.rank
# saved_target_rank = target_trainingprogram.rank saved_target_rank = target_trainingpround.rank
# source_trainingprogram.rank = 32767 source_traininground.rank = 32767
# source_trainingprogram.save() source_traininground.save()
# target_trainingprogram.rank = saved_source_rank target_trainingpround.rank = saved_source_rank
# target_trainingprogram.save() target_trainingpround.save()
# source_trainingprogram.rank = saved_target_rank source_traininground.rank = saved_target_rank
# source_trainingprogram.save() source_traininground.save()
# return HttpResponse(200) return HttpResponse(200)
# except Exception: except Exception:
# return HttpResponse(409) return HttpResponse(409)

View File

@ -82,9 +82,9 @@
<h4>Training Program</h4> <h4>Training Program</h4>
</div> </div>
<div class="card-body"> <div class="card-body">
{% if date_list %} {% if training_list %}
{% for date in date_list %} {% for training in training_list %}
<a href="{% url 'trainingprogram_details' date gymnast_id %}">{{ date|date:"l j F Y" }}</a> <a href="{% url 'gymnast_training_details' training.id %}">{{ training.date|date:"l j F Y" }}</a><br />
{% endfor %} {% endfor %}
{% else %} {% else %}
<p>Pas de training planifié.</p> <p>Pas de training planifié.</p>

View File

@ -21,7 +21,7 @@ import pendulum
from jarvis.followup.models import Event from jarvis.followup.models import Event
from jarvis.followup.forms import GymnastHasRoutineForm from jarvis.followup.forms import GymnastHasRoutineForm
# from jarvis.objective.models import TrainingProgram from jarvis.objective.models import GymnastTraining
from jarvis.followup.models import ( from jarvis.followup.models import (
Note, Note,
Plan, Plan,
@ -258,12 +258,7 @@ def gymnast_display_scores_chrono(request, gymnast_id):
).order_by("date") ).order_by("date")
base_queryset = chrono_list.values("date").annotate(score_avg=Avg("tof")) base_queryset = chrono_list.values("date").annotate(score_avg=Avg("tof"))
today = pendulum.now().date() today = pendulum.now().date()
# date_list = ( training_list = GymnastTraining.objects.filter(gymnast=gymnast_id, date__gte=today)
# TrainingProgram.objects.filter(gymnast=gymnast_id, date__gte=today)
# .values_list("date", flat=True)
# .order_by("date")
# .distinct()
# )
context = { context = {
"intensity_list": intensity_list, "intensity_list": intensity_list,
@ -272,7 +267,7 @@ def gymnast_display_scores_chrono(request, gymnast_id):
"chrono_r1": base_queryset.filter(chrono_type=1), "chrono_r1": base_queryset.filter(chrono_type=1),
"chrono_r2": base_queryset.filter(chrono_type=2), "chrono_r2": base_queryset.filter(chrono_type=2),
"chrono_rf": base_queryset.filter(chrono_type=3), "chrono_rf": base_queryset.filter(chrono_type=3),
# "date_list": date_list, "training_list": training_list,
"gymnast_id": gymnast_id, "gymnast_id": gymnast_id,
} }
return render(request, "gymnasts/tabs/tab_intensity_and_chronos.html", context) return render(request, "gymnasts/tabs/tab_intensity_and_chronos.html", context)