[WIP] Improvement based on Fred's advies.
This commit is contained in:
parent
e84733b3b5
commit
ec5f2bd44d
|
@ -40,7 +40,12 @@ Ce paramètre permet de construire des séries pour une gymnaste bien précis en
|
||||||
|
|
||||||
## Localisations
|
## Localisations
|
||||||
|
|
||||||
|
Ce module permet de gérer les localisations et les clubs. (plus d'informations à venir)
|
||||||
|
|
||||||
## Compétitions
|
## Compétitions
|
||||||
|
|
||||||
|
Ce module permet de gérer les compétitions. (plus d'informations à venir)
|
||||||
|
|
||||||
## Personnes
|
## Personnes
|
||||||
|
|
||||||
|
Ce module permet de gérer les personnes. (plus d'informations à venir)
|
|
@ -25,7 +25,7 @@ class Country(models.Model):
|
||||||
|
|
||||||
class Place(models.Model):
|
class Place(models.Model):
|
||||||
"""
|
"""
|
||||||
Classe représentant un lieu. En plus de l'adresse, un lieu est spécifié par un nombre
|
Représente un lieu. En plus de l'adresse, un lieu est spécifié par un nombre
|
||||||
de kilomètres et une durée de trajet. Pour faciliter les filtres, un lieu peut être
|
de kilomètres et une durée de trajet. Pour faciliter les filtres, un lieu peut être
|
||||||
actif ou non.
|
actif ou non.
|
||||||
"""
|
"""
|
||||||
|
@ -51,7 +51,7 @@ class Place(models.Model):
|
||||||
|
|
||||||
class Club(models.Model):
|
class Club(models.Model):
|
||||||
"""
|
"""
|
||||||
Classe représentant un club. Un club est associé à un lieu. Pour faciliter les filtres,
|
Représente un club. Un club est associé à un lieu. Pour faciliter les filtres,
|
||||||
un club peut être actif ou non.
|
un club peut être actif ou non.
|
||||||
|
|
||||||
.. todo:: Un club peut avoir plusieurs salle et une salle peut-être louée par plusieurs clubs... M2M ?
|
.. todo:: Un club peut avoir plusieurs salle et une salle peut-être louée par plusieurs clubs... M2M ?
|
||||||
|
|
|
@ -17,24 +17,24 @@ class Educative(Markdownizable):
|
||||||
verbose_name_plural = "Educatifs"
|
verbose_name_plural = "Educatifs"
|
||||||
ordering = ["longLabel", "shortLabel"] # 'level',
|
ordering = ["longLabel", "shortLabel"] # 'level',
|
||||||
|
|
||||||
longLabel = models.CharField(max_length=255, verbose_name="Long Name")
|
longLabel = models.CharField(max_length = 255, verbose_name = "Long Name")
|
||||||
shortLabel = models.CharField(max_length=255, verbose_name="Short Name")
|
shortLabel = models.CharField(max_length = 255, verbose_name = "Short Name")
|
||||||
difficulty = models.DecimalField(
|
difficulty = models.DecimalField(
|
||||||
max_digits=3, decimal_places=1, verbose_name="Difficulty"
|
max_digits = 3, decimal_places = 1, verbose_name = "Difficulty"
|
||||||
)
|
)
|
||||||
level = models.PositiveSmallIntegerField(verbose_name="Level", default=0)
|
level = models.PositiveSmallIntegerField(verbose_name = "Level", default = 0)
|
||||||
rank = models.PositiveSmallIntegerField(verbose_name="Rank", default=0)
|
rank = models.PositiveSmallIntegerField(verbose_name = "Rank", default = 0)
|
||||||
educative = models.ManyToManyField(
|
educative = models.ManyToManyField(
|
||||||
"self", related_name="educativeOf", blank=True, symmetrical=False
|
"self", related_name = "educativeOf", blank = True, symmetrical = False
|
||||||
)
|
)
|
||||||
prerequisite = models.ManyToManyField(
|
prerequisite = models.ManyToManyField(
|
||||||
"self", related_name="prerequisiteOf", blank=True, symmetrical=False
|
"self", related_name = "prerequisiteOf", blank = True, symmetrical = False
|
||||||
)
|
)
|
||||||
ageBoy = models.PositiveSmallIntegerField(
|
ageBoy = models.PositiveSmallIntegerField(
|
||||||
blank=True, null=True, verbose_name="Boy's age"
|
blank = True, null = True, verbose_name = "Boy's age"
|
||||||
)
|
)
|
||||||
ageGirl = models.PositiveSmallIntegerField(
|
ageGirl = models.PositiveSmallIntegerField(
|
||||||
blank=True, null=True, verbose_name="Girl's age"
|
blank = True, null = True, verbose_name = "Girl's age"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -56,10 +56,10 @@ class TouchPosition(models.Model):
|
||||||
verbose_name_plural = "Landings"
|
verbose_name_plural = "Landings"
|
||||||
ordering = ["longLabel", "shortLabel", "default", "competition"]
|
ordering = ["longLabel", "shortLabel", "default", "competition"]
|
||||||
|
|
||||||
longLabel = models.CharField(max_length=30, verbose_name="Nom long")
|
longLabel = models.CharField(max_length = 30, verbose_name = "Nom long")
|
||||||
shortLabel = models.CharField(max_length=15, verbose_name="Nom court")
|
shortLabel = models.CharField(max_length = 15, verbose_name = "Nom court")
|
||||||
competition = models.BooleanField(verbose_name="Compétition")
|
competition = models.BooleanField(verbose_name = "Compétition")
|
||||||
default = models.BooleanField(verbose_name="Défaut")
|
default = models.BooleanField(verbose_name = "Défaut")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s" % (self.longLabel)
|
return "%s" % (self.longLabel)
|
||||||
|
@ -104,29 +104,29 @@ class Skill(Educative):
|
||||||
(2, "Backward"),
|
(2, "Backward"),
|
||||||
)
|
)
|
||||||
|
|
||||||
position = models.CharField(max_length=2, choices=POSITION_CHOICES)
|
position = models.CharField(max_length = 2, choices = POSITION_CHOICES)
|
||||||
departure = models.ForeignKey(
|
departure = models.ForeignKey(
|
||||||
TouchPosition,
|
TouchPosition,
|
||||||
related_name="depart_of",
|
related_name = "depart_of",
|
||||||
default=get_default_position,
|
default = get_default_position,
|
||||||
verbose_name="Take-off position",
|
verbose_name = "Take-off position",
|
||||||
on_delete=models.CASCADE,
|
on_delete = models.CASCADE,
|
||||||
)
|
)
|
||||||
landing = models.ForeignKey(
|
landing = models.ForeignKey(
|
||||||
TouchPosition,
|
TouchPosition,
|
||||||
related_name="landing_of",
|
related_name = "landing_of",
|
||||||
default=get_default_position,
|
default = get_default_position,
|
||||||
verbose_name="Landing position",
|
verbose_name = "Landing position",
|
||||||
on_delete=models.CASCADE,
|
on_delete = models.CASCADE,
|
||||||
)
|
)
|
||||||
rotationType = models.PositiveSmallIntegerField(
|
rotationType = models.PositiveSmallIntegerField(
|
||||||
choices=ROTATION_CHOICES, verbose_name="Type de rotation"
|
choices = ROTATION_CHOICES, verbose_name = "Type de rotation"
|
||||||
)
|
)
|
||||||
rotation = models.PositiveSmallIntegerField(verbose_name="1/4 de rotation")
|
rotation = models.PositiveSmallIntegerField(verbose_name = "1/4 de rotation")
|
||||||
twist = models.PositiveSmallIntegerField(verbose_name="1/2 Vrille")
|
twist = models.PositiveSmallIntegerField(verbose_name = "1/2 Vrille")
|
||||||
notation = models.CharField(max_length=25)
|
notation = models.CharField(max_length = 25)
|
||||||
simplyNotation = models.CharField(max_length=25, verbose_name="Notation simplifiée")
|
simplyNotation = models.CharField(max_length = 25, verbose_name = "Notation simplifiée")
|
||||||
is_competitive = models.BooleanField(default=False)
|
is_competitive = models.BooleanField(default = False)
|
||||||
# importance = models.PositiveSmallIntegerField(default = 1)
|
# importance = models.PositiveSmallIntegerField(default = 1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -144,9 +144,9 @@ class Routine(Educative):
|
||||||
|
|
||||||
active = models.BooleanField()
|
active = models.BooleanField()
|
||||||
jumps = models.ManyToManyField(
|
jumps = models.ManyToManyField(
|
||||||
Skill, through="Routine_Skill", verbose_name="routine"
|
Skill, through = "Routine_Skill", verbose_name = "routine"
|
||||||
) # ceci n'est pas un vrai champ
|
) # ceci n'est pas un vrai champ
|
||||||
is_competitive = models.BooleanField(default=False)
|
is_competitive = models.BooleanField(default = False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s (%s)" % (self.shortLabel, self.shortLabel)
|
return "%s (%s)" % (self.shortLabel, self.shortLabel)
|
||||||
|
@ -216,10 +216,10 @@ class Routine_Skill(models.Model):
|
||||||
ordering = ("rank",)
|
ordering = ("rank",)
|
||||||
|
|
||||||
routine = models.ForeignKey(
|
routine = models.ForeignKey(
|
||||||
Routine, on_delete=models.CASCADE, default=None, related_name="skill_links"
|
Routine, on_delete = models.CASCADE, default = None, related_name = "skill_links"
|
||||||
)
|
)
|
||||||
skill = models.ForeignKey(
|
skill = models.ForeignKey(
|
||||||
Skill, on_delete=models.CASCADE, default=None, related_name="routine_links"
|
Skill, on_delete = models.CASCADE, default = None, related_name = "routine_links"
|
||||||
)
|
)
|
||||||
rank = models.PositiveSmallIntegerField()
|
rank = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
|
@ -247,13 +247,13 @@ class Chrono(models.Model):
|
||||||
(99, "Other"),
|
(99, "Other"),
|
||||||
)
|
)
|
||||||
|
|
||||||
routine = models.ForeignKey(Routine, on_delete=models.CASCADE, default=None)
|
routine = models.ForeignKey(Routine, on_delete = models.CASCADE, default = None)
|
||||||
routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE)
|
routine_type = models.PositiveSmallIntegerField(choices = ROUTINETYPE_CHOICE)
|
||||||
gymnast = models.ForeignKey(
|
gymnast = models.ForeignKey(
|
||||||
"people.gymnast", on_delete=models.CASCADE, default=None
|
"people.gymnast", on_delete = models.CASCADE, default = None
|
||||||
)
|
)
|
||||||
date = models.DateField(default=date.today, verbose_name="Date")
|
date = models.DateField(default = date.today, verbose_name = "Date")
|
||||||
score = models.DecimalField(max_digits=5, decimal_places=2)
|
score = models.DecimalField(max_digits = 5, decimal_places = 2)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s le %s : %s pour %s" % (
|
return "%s le %s : %s pour %s" % (
|
||||||
|
@ -278,13 +278,13 @@ class Evaluation(models.Model):
|
||||||
Classe permettant l'évaluation des éducatifs.
|
Classe permettant l'évaluation des éducatifs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
date = models.DateField(default=date.today, verbose_name="Date")
|
date = models.DateField(default = date.today, verbose_name = "Date")
|
||||||
value = models.PositiveSmallIntegerField(default=0)
|
value = models.PositiveSmallIntegerField(default = 0)
|
||||||
educative = models.ForeignKey(
|
educative = models.ForeignKey(
|
||||||
Educative,
|
Educative,
|
||||||
related_name="depart_of",
|
related_name = "depart_of",
|
||||||
verbose_name="Take-off position",
|
verbose_name = "Take-off position",
|
||||||
on_delete=models.CASCADE,
|
on_delete = models.CASCADE,
|
||||||
)
|
)
|
||||||
type_of_evaluator = models.BooleanField(default=0)
|
type_of_evaluator = models.BooleanField(default = 0)
|
||||||
evaluator = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
evaluator = models.ForeignKey(User, null = True, on_delete = models.SET_NULL)
|
||||||
|
|
|
@ -349,16 +349,7 @@ def random_skill(request, number=None):
|
||||||
return render(request, "judge_training_diff.html", context)
|
return render(request, "judge_training_diff.html", context)
|
||||||
|
|
||||||
|
|
||||||
def __construct_routine(skill_list, routine):
|
def __construct_routine(
|
||||||
""" """
|
|
||||||
pass
|
|
||||||
# routine.append(random(skill_list))
|
|
||||||
# if len(routine) < 10:
|
|
||||||
# __construct_routine(skill_list, routine)
|
|
||||||
|
|
||||||
|
|
||||||
def suggest_routine(
|
|
||||||
request,
|
|
||||||
routine_length,
|
routine_length,
|
||||||
total_difficulty_score=None,
|
total_difficulty_score=None,
|
||||||
competition=True,
|
competition=True,
|
||||||
|
@ -369,10 +360,10 @@ def suggest_routine(
|
||||||
""" Construit et propose des séries.
|
""" Construit et propose des séries.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
routine_length (int): nombre de sauts que doit contenir la série.
|
routine_length (int): nombre de sauts qui compose la série.
|
||||||
total_difficulty_score (int): score de difficulté total souhaité de la série.
|
total_difficulty_score (int): score total de difficulté souhaité de la série.
|
||||||
competition (bool): indique si la série doit pouvoir être utilisée en compétition.
|
competition (bool): indique si la série doit respecter les règles de compétition.
|
||||||
logic (bool): indique si la série doit suivre certaines règles de logique (sportive).
|
logic (bool): indique si la série doit suivre les règles de logique (sportive).
|
||||||
gymnast (gymnast): gymnaste.
|
gymnast (gymnast): gymnaste.
|
||||||
last_jump (skill): dernier saut sélectionné pour la série.
|
last_jump (skill): dernier saut sélectionné pour la série.
|
||||||
|
|
||||||
|
@ -382,41 +373,42 @@ def suggest_routine(
|
||||||
|
|
||||||
current_routine = []
|
current_routine = []
|
||||||
|
|
||||||
if last_jump:
|
skill_list = Skill.objects.all()
|
||||||
skill_list = Skill.objects.filter(
|
|
||||||
departure=last_jump.landing, difficulty__lte=total_difficulty_score
|
|
||||||
)
|
|
||||||
if logic and last_jump.landing == "Debout":
|
|
||||||
skill_list = skill_list.exclude(rotationType=last_jump.rotationType)
|
|
||||||
else:
|
|
||||||
skill_list = Skill.objects.filter(departure__longLabel="Debout")
|
|
||||||
|
|
||||||
if competition:
|
# if last_jump:
|
||||||
skill_list = skill_list.filter(is_competitive=True)
|
# skill_list = Skill.objects.filter(
|
||||||
|
# departure = last_jump.landing, difficulty__lte = total_difficulty_score
|
||||||
|
# )
|
||||||
|
# if logic and last_jump.landing == "Debout":
|
||||||
|
# skill_list = skill_list.exclude(rotationType = last_jump.rotationType)
|
||||||
|
# else:
|
||||||
|
# skill_list = Skill.objects.filter(departure__longLabel = "Debout")
|
||||||
|
|
||||||
if logic and total_difficulty_score:
|
# if competition:
|
||||||
min_difficulty_score = math.ceil(max(0, ((total_difficulty_score / 10) - 5)))
|
# skill_list = skill_list.filter(is_competitive = True)
|
||||||
|
|
||||||
if total_difficulty_score <= 65:
|
# if logic and total_difficulty_score:
|
||||||
max_difficulty_score = math.ceil(total_difficulty_score / 5) + 1
|
# min_difficulty_score = math.ceil(max(0, ((total_difficulty_score / 10) - 5)))
|
||||||
elif total_difficulty_score <= 120:
|
|
||||||
max_difficulty_score = math.ceil(total_difficulty_score / 10) + 7
|
|
||||||
else:
|
|
||||||
max_difficulty_score = math.ceil(total_difficulty_score / 15) + 11
|
|
||||||
|
|
||||||
skill_list = skill_list.filter(
|
# if total_difficulty_score <= 65:
|
||||||
difficulty__gte=min_difficulty_score, difficulty__lte=max_difficulty_score
|
# max_difficulty_score = math.ceil(total_difficulty_score / 5) + 1
|
||||||
)
|
# elif total_difficulty_score <= 120:
|
||||||
|
# max_difficulty_score = math.ceil(total_difficulty_score / 10) + 7
|
||||||
|
# else:
|
||||||
|
# max_difficulty_score = math.ceil(total_difficulty_score / 15) + 11
|
||||||
|
|
||||||
if gymnast:
|
# skill_list = skill_list.filter(
|
||||||
# skill_list = skill_list.filter(can_do__ blablabla)
|
# difficulty__gte = min_difficulty_score,
|
||||||
pass
|
# difficulty__lte = max_difficulty_score
|
||||||
|
# )
|
||||||
|
|
||||||
|
# if gymnast:
|
||||||
|
# skill_list = skill_list.filter(can_do__gymnast = gymnast)
|
||||||
|
|
||||||
for skill in skill_list:
|
for skill in skill_list:
|
||||||
current_routine.append(skill)
|
current_routine.append(skill)
|
||||||
current_routine.append(
|
current_routine.append(
|
||||||
self.suggest_routine(
|
self.suggest_routine(
|
||||||
request,
|
|
||||||
total_difficulty_score - skill.difficulty,
|
total_difficulty_score - skill.difficulty,
|
||||||
max_difficulty_score,
|
max_difficulty_score,
|
||||||
routine_length - 1,
|
routine_length - 1,
|
||||||
|
@ -444,6 +436,42 @@ def suggest_routine(
|
||||||
# n = len(val)
|
# n = len(val)
|
||||||
# print(knapSack(W, wt, val, n))
|
# print(knapSack(W, wt, val, n))
|
||||||
|
|
||||||
|
return current_routine
|
||||||
|
|
||||||
|
|
||||||
|
def suggest_routine(
|
||||||
|
request,
|
||||||
|
routine_length,
|
||||||
|
total_difficulty_score=None,
|
||||||
|
competition=True,
|
||||||
|
logic=True,
|
||||||
|
gymnast=None,
|
||||||
|
last_jump=None,
|
||||||
|
):
|
||||||
|
""" Construit et propose des séries.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
routine_length (int): nombre de sauts qui compose la série.
|
||||||
|
total_difficulty_score (int): score total de difficulté souhaité de la série.
|
||||||
|
competition (bool): indique si la série doit respecter les règles de compétition.
|
||||||
|
logic (bool): indique si la série doit suivre les règles de logique (sportive).
|
||||||
|
gymnast (gymnast): gymnaste.
|
||||||
|
last_jump (skill): dernier saut sélectionné pour la série.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
??? (list): liste des séries correspondantes aux criètres.
|
||||||
|
"""
|
||||||
|
|
||||||
|
current_routine = suggest_routine(
|
||||||
|
routine_length,
|
||||||
|
total_difficulty_score,
|
||||||
|
competition,
|
||||||
|
logic,
|
||||||
|
gymnast,
|
||||||
|
last_jump
|
||||||
|
)
|
||||||
|
print(current_routine)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def chrono_listing(request, gymnastid=None, routineid=None):
|
def chrono_listing(request, gymnastid=None, routineid=None):
|
||||||
|
|
|
@ -95,8 +95,7 @@ class Gymnast(Markdownizable):
|
||||||
Soit le jour/mois pour cette année
|
Soit le jour/mois pour cette année
|
||||||
Soit le jour/mois pour l'année prochaine.
|
Soit le jour/mois pour l'année prochaine.
|
||||||
|
|
||||||
Examples:
|
Examples: en supposant qu'on soit le 23/05/2019
|
||||||
>>> "en supposant qu'on soit le 23/05/2019 :-)"
|
|
||||||
>>> from datetime import date
|
>>> from datetime import date
|
||||||
>>> gregg = People(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5)
|
>>> gregg = People(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5)
|
||||||
>>> gregg.next_birthday()
|
>>> gregg.next_birthday()
|
||||||
|
@ -120,9 +119,7 @@ class Gymnast(Markdownizable):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def age(self):
|
def age(self):
|
||||||
"""
|
""" Renvoie l'âge d'un gymnaste. """
|
||||||
Renvoie l'âge d'un gymnaste.
|
|
||||||
"""
|
|
||||||
today = date.today()
|
today = date.today()
|
||||||
return (
|
return (
|
||||||
today.year
|
today.year
|
||||||
|
@ -132,16 +129,12 @@ class Gymnast(Markdownizable):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def nextAge(self):
|
def nextAge(self):
|
||||||
"""
|
""" Renvoie l'âge prochain du gymnaste. """
|
||||||
Renvoie l'âge prochain du gymnaste.
|
|
||||||
"""
|
|
||||||
return (self.age) + 1
|
return (self.age) + 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def known_skills(self):
|
def known_skills(self):
|
||||||
"""
|
""" Renvoie la liste des objectifs qu'un gymnaste sait faire. """
|
||||||
Renvoie la liste des objectifs qu'un gymnaste sait faire.
|
|
||||||
"""
|
|
||||||
return CanDoRelation.objects.filter(gymnast=self.id)
|
return CanDoRelation.objects.filter(gymnast=self.id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -189,7 +182,7 @@ class Accident(Markdownizable):
|
||||||
|
|
||||||
class CanDoRelation(models.Model):
|
class CanDoRelation(models.Model):
|
||||||
"""
|
"""
|
||||||
Classe représentant les objectifs qu'un gymnaste sait faire (à partir d'une date donnée).
|
Représente les objectifs qu'un gymnaste sait faire (à partir d'une date donnée).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -206,7 +199,7 @@ class CanDoRelation(models.Model):
|
||||||
# QUESTIONS
|
# QUESTIONS
|
||||||
# ---------
|
# ---------
|
||||||
#
|
#
|
||||||
# 1) Cela ne dervait pas être deux relation ManyToMany dans chacune des tables GYMNAST et EDUCATIVE (ou SKILL) ?
|
# 1) Cela ne dervait pas être deux relations ManyToMany dans chacune des tables GYMNAST et EDUCATIVE (ou SKILL) ?
|
||||||
# Un élève saura faire plusieurs figures.
|
# Un élève saura faire plusieurs figures.
|
||||||
# Et une figure pourra savoir être faite par plusieurs élèves... Donc, ?
|
# Et une figure pourra savoir être faite par plusieurs élèves... Donc, ?
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue