Compare commits
5 Commits
1c8f6c1152
...
198ceeafc0
Author | SHA1 | Date |
---|---|---|
Gregory Trullemans | 198ceeafc0 | |
Gregory Trullemans | 8e192e1c11 | |
Gregory Trullemans | 6a63776145 | |
Gregory Trullemans | e57e414f27 | |
Gregory Trullemans | f5c4ccc68e |
|
@ -27,7 +27,7 @@
|
|||
<h4 class=""><i class="text-primary fal fa-laugh-wink"></i> Hi {{ user.first_name }} !</h4>
|
||||
</div>
|
||||
<div class="card-body text-justify pt-0">
|
||||
<p>Welcome to Jarvi v0.96.1 <span class="text-muted">(last update : 13-2-2024)</span></p>
|
||||
<p>Welcome to Jarvi v0.96.3 <span class="text-muted">(last update : 21-3-2024)</span></p>
|
||||
<p>This application is here to help coaches to manage the gymnasts (evolution, evaluation, routines, scores, …). This tool is not perfect so feel free to make improvement proposals, bug reports, … by sending me an <a href="mailto:gregory@flyingacrobaticstrampoline.be">email</a>.</p>
|
||||
<p>You can find the user manual <a href="{% static "files/Manuel_Utilisateur.pdf" %}" download>here (in french)</a>.</p>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import re
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
|
||||
import re
|
||||
|
||||
from .models import (
|
||||
Educative,
|
||||
Skill,
|
||||
|
@ -12,6 +11,8 @@ from .models import (
|
|||
TrainingRound,
|
||||
)
|
||||
|
||||
from .validators import is_valid_routine_type, is_valid_subset, is_valid_regexp
|
||||
|
||||
|
||||
class SkillForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
@ -102,9 +103,7 @@ class TrainingRoundForm(forms.ModelForm):
|
|||
"maxlength": 30,
|
||||
}
|
||||
),
|
||||
"regexp": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "[2-8]"}
|
||||
),
|
||||
"regexp": forms.TextInput(attrs={"class": "form-control"}),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
|
@ -115,8 +114,9 @@ class TrainingRoundForm(forms.ModelForm):
|
|||
|
||||
def clean_regexp(self):
|
||||
"""Vérifie que la regexp entrée par l'utilisateur est valide."""
|
||||
print(self.cleaned_data)
|
||||
regexp = self.cleaned_data["regexp"]
|
||||
if not TrainingRound.is_valid_regexp(regexp):
|
||||
if not is_valid_regexp(regexp):
|
||||
raise ValidationError("Entered regexp not valid.")
|
||||
|
||||
return regexp
|
||||
|
@ -133,20 +133,16 @@ class TrainingRoundForm(forms.ModelForm):
|
|||
cleaned_data = super().clean()
|
||||
regexp = cleaned_data["regexp"]
|
||||
|
||||
if regexp is not None:
|
||||
# print
|
||||
if not regexp:
|
||||
arguments = regexp.split(" ")
|
||||
educatives = cleaned_data["educatives"]
|
||||
print("----------------------------------------------------------------")
|
||||
print(educatives)
|
||||
print("----------------------------------------------------------------")
|
||||
|
||||
if TrainingRound.is_valid_routine_type(arguments[0]) and educatives:
|
||||
if is_valid_routine_type(arguments[0]) and educatives:
|
||||
raise ValidationError(
|
||||
"Educatives must be empty with the entered Regexp."
|
||||
)
|
||||
|
||||
if TrainingRound.is_valid_subset(arguments[0]) and educatives is None:
|
||||
if is_valid_subset(arguments[0]) and educatives is None:
|
||||
raise ValidationError(
|
||||
"Educatives can't be empty with the entered Regexp."
|
||||
)
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
from django.db import models, transaction
|
||||
import re
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
|
||||
import re
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
from jarvis.tools.models import (
|
||||
Markdownizable,
|
||||
Seasonisable,
|
||||
max_even_if_none,
|
||||
)
|
||||
from .signals import *
|
||||
from .validators import (
|
||||
number_of_skill_from_subset,
|
||||
difficulty_from_regexp,
|
||||
)
|
||||
|
||||
# from jarvis.followup.models import ROUTINE_TYPE_CHOICE
|
||||
# from .signals import *
|
||||
|
||||
|
||||
class Educative(Markdownizable):
|
||||
|
@ -483,46 +485,8 @@ class TrainingRound(Markdownizable):
|
|||
number_of_skill = models.PositiveSmallIntegerField(default=0)
|
||||
difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0)
|
||||
|
||||
@staticmethod
|
||||
def number_of_skill_from_subset(subset, educative=None):
|
||||
""" """
|
||||
if not TrainingRound.is_valid_subset(subset):
|
||||
return 0, 0, 0
|
||||
|
||||
subset = subset.replace("[", "").replace("]", "")
|
||||
ranks = subset.split("-")
|
||||
|
||||
if ranks[0] == "":
|
||||
start = 0
|
||||
else:
|
||||
start = int(ranks[0])
|
||||
|
||||
if ranks[1] == "":
|
||||
if educative is not None:
|
||||
end = educative.jumps.all().count()
|
||||
else:
|
||||
end = 10
|
||||
else:
|
||||
end = int(ranks[1])
|
||||
|
||||
number_of_skill = (end - start) + 1
|
||||
|
||||
return start, end, number_of_skill
|
||||
|
||||
@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"))
|
||||
|
||||
for routine_skill in list_of_skill:
|
||||
difficulty += routine_skill.skill.difficulty
|
||||
|
||||
return difficulty
|
||||
|
||||
def update_traininground(self):
|
||||
"""Update `number_of_skill` et `difficulty`.
|
||||
"""Met à jours les valeurs `number_of_skill` et `difficulty`.
|
||||
S'il n'y a pas d'educatives, la difficulté ne peut pas être calculée.
|
||||
"""
|
||||
difficulty = 0
|
||||
|
@ -532,9 +496,7 @@ class TrainingRound(Markdownizable):
|
|||
operation_list = self.regexp.split(" ")
|
||||
|
||||
if len(operation_list) == 2:
|
||||
_, _, number_of_skill = TrainingRound.number_of_skill_from_subset(
|
||||
operation_list[1]
|
||||
)
|
||||
_, _, number_of_skill = number_of_skill_from_subset(operation_list[1])
|
||||
else:
|
||||
number_of_skill += 10
|
||||
|
||||
|
@ -560,8 +522,8 @@ class TrainingRound(Markdownizable):
|
|||
start,
|
||||
end,
|
||||
number_of_skill,
|
||||
) = TrainingRound.number_of_skill_from_subset(self.regexp)
|
||||
difficulty = TrainingRound.difficulty_from_regexp(educ, start, end)
|
||||
) = number_of_skill_from_subset(self.regexp)
|
||||
difficulty = difficulty_from_regexp(educ, start, end)
|
||||
|
||||
else:
|
||||
number_of_skill += educ.jumps.all().count()
|
||||
|
@ -588,144 +550,8 @@ class TrainingRound(Markdownizable):
|
|||
return f"{self.label} ({self.number_of_skill} | {self.difficulty})"
|
||||
|
||||
def is_regexp_wc(self):
|
||||
""" """
|
||||
return self.regexp == "WC"
|
||||
|
||||
@staticmethod
|
||||
def is_valid_regexp_one_arg(regexp):
|
||||
"""Vérifie une regexp avec un paramètre."""
|
||||
if regexp == "WC":
|
||||
return True
|
||||
|
||||
if re.match(r"[1-9]+\|", regexp):
|
||||
return True
|
||||
|
||||
if not TrainingRound.is_valid_dot(regexp):
|
||||
return False
|
||||
|
||||
value = regexp.replace(".", "")
|
||||
is_valid_routine = TrainingRound.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return True
|
||||
|
||||
return TrainingRound.is_valid_subset(regexp)
|
||||
|
||||
@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
|
||||
|
||||
value = arg1.replace(".", "")
|
||||
is_valid_routine = TrainingRound.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return TrainingRound.is_valid_subset(arg2)
|
||||
|
||||
return False
|
||||
|
||||
@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.search("\.", pattern):
|
||||
last_place = len(pattern) - 1
|
||||
if pattern[0] != "." and pattern[last_place] != ".":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@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
|
||||
|
||||
return is_valid_routine
|
||||
|
||||
@staticmethod
|
||||
def is_valid_subset(subset):
|
||||
"""Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme.
|
||||
|
||||
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."""
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{{ hidden }}
|
||||
{% endfor %}
|
||||
|
||||
<div class="form-group row {% if form.long_label.errors %}has-error has-feedback{% endif %}">
|
||||
<div class="form-group row {% if form.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<span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10">
|
||||
{{ form.label }}
|
||||
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group row ">
|
||||
<label for="id_educative" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.educatives.label }} <span class="text-danger"><b>*</b></span></label>
|
||||
<label for="id_educative" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">{{ form.educatives.label }}</label>
|
||||
<div class="col-8 col-sm-8 col-md-6 col-lg-6 col-xl-6 {% if form.educatives.errors %}has-danger{% endif %}">
|
||||
{{ form.media }}
|
||||
{{ form.educatives }}
|
||||
|
|
|
@ -7,7 +7,6 @@ from jarvis.objective.models import (
|
|||
RoutineSkill,
|
||||
TrainingRound,
|
||||
)
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
|
||||
|
||||
class ToolsModels(TestCase):
|
||||
|
@ -123,137 +122,3 @@ class TrainingRoundTestCase(TestCase):
|
|||
educ_3 = Educative.objects.create(
|
||||
long_label="4 pattes", difficulty=0.1, level=1, rank=1
|
||||
)
|
||||
|
||||
def test_is_valid_dot(self):
|
||||
arg = ""
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), True)
|
||||
arg = "Q1R1"
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), True)
|
||||
arg = ".Q1R1"
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), True)
|
||||
arg = "Q1R1."
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), True)
|
||||
arg = "Q1.R1"
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), False)
|
||||
arg = ".Q1.R1."
|
||||
self.assertEqual(TrainingRound.is_valid_dot(arg), False)
|
||||
|
||||
def test_is_valid_subset(self):
|
||||
subset = ""
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[2-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), True)
|
||||
subset = "[2--8]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[-5]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), True)
|
||||
subset = "[3-]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), True)
|
||||
subset = "[8-2]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[-]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[1-]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[-1]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[4]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[6-6]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "4"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[6-6"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[66]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "4-8"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "6-]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[4-"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "[6"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "Q1R1 [4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
subset = "Q1R1 [-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_subset(subset), False)
|
||||
|
||||
def test_is_valid_routine_type(self):
|
||||
for item in ROUTINE_TYPE_CHOICE:
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(item[1]), True)
|
||||
|
||||
routine_type = ""
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
|
||||
routine_type = ".Q1R1"
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
|
||||
routine_type = "SFS."
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
|
||||
routine_type = "Q1R1 [4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
|
||||
routine_type = "SFS [-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_routine_type(routine_type), False)
|
||||
|
||||
def test_is_valid_regexp_one_arg(self):
|
||||
arg = ""
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
|
||||
arg = "WC"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
|
||||
arg = "1|"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
|
||||
arg = ".Q1R1"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
|
||||
arg = "Q1R2."
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), True)
|
||||
arg = ".Q1R1 [4-8"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R2. [4-8"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R1 [4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R1 [8-4]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_one_arg(arg), False)
|
||||
|
||||
def test_is_valid_regexp_two_args(self):
|
||||
arg1 = ""
|
||||
arg2 = ""
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
|
||||
arg1 = "Q1R1"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
|
||||
arg2 = "[4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
|
||||
arg2 = "[8-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
|
||||
arg2 = "[8-4]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), False)
|
||||
arg2 = "[-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
|
||||
arg2 = "[4-]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
|
||||
arg1 = "Q1R1."
|
||||
self.assertEqual(TrainingRound.is_valid_regexp_two_args(arg1, arg2), True)
|
||||
|
||||
def test_is_valid_regexp(self):
|
||||
regexp = ""
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1 [4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1 [8-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1 [8-4]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1 [-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1 [4-]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1. [4-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1. [4-]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = ".Q1R1 [-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1. [8-8]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
|
||||
regexp = ".Q1R1 [8-4]"
|
||||
self.assertEqual(TrainingRound.is_valid_regexp(regexp), False)
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
from .validators import (
|
||||
is_valid_dot,
|
||||
is_valid_subset,
|
||||
is_valid_regexp,
|
||||
is_valid_routine_type,
|
||||
is_valid_regexp_one_arg,
|
||||
is_valid_regexp_two_args,
|
||||
number_of_skill_from_subset,
|
||||
)
|
||||
|
||||
|
||||
class TestValidatorsModels(TestCase):
|
||||
def test_number_of_skill_from_subset(self):
|
||||
subset = ""
|
||||
educative = None
|
||||
self.assertEqual(number_of_skill_from_subset(subset, educative), (0, 0, 0))
|
||||
subset = "[8-4]"
|
||||
self.assertEqual(number_of_skill_from_subset(subset, educative), (0, 0, 0))
|
||||
subset = "[4-8]"
|
||||
self.assertEqual(number_of_skill_from_subset(subset, educative), (4, 8, 5))
|
||||
subset = "[4-]"
|
||||
self.assertEqual(number_of_skill_from_subset(subset, educative), (4, 10, 7))
|
||||
subset = "[-8]"
|
||||
self.assertEqual(number_of_skill_from_subset(subset, educative), (1, 8, 8))
|
||||
|
||||
def test_is_valid_regexp_one_arg(self):
|
||||
arg = ""
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
arg = "WC"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), True)
|
||||
arg = "1|"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), True)
|
||||
arg = ".Q1R1"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), True)
|
||||
arg = "Q1R2."
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), True)
|
||||
arg = ".Q1R1 [4-8"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R2. [4-8"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
arg = ".Q1R2. [4-8"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R1 [4-8]"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
arg = "Q1R1 [8-4]"
|
||||
self.assertEqual(is_valid_regexp_one_arg(arg), False)
|
||||
|
||||
def test_is_valid_regexp_two_args(self):
|
||||
routine = ""
|
||||
subset = ""
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), False)
|
||||
routine = "Q1R1"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), False)
|
||||
subset = "[4-8]"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), True)
|
||||
subset = "[8-8]"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), False)
|
||||
subset = "[8-4]"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), False)
|
||||
subset = "[-8]"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), True)
|
||||
subset = "[4-]"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), True)
|
||||
routine = "Q1R1."
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), True)
|
||||
routine = ".Q1R1"
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), True)
|
||||
routine = ".Q1R1."
|
||||
self.assertEqual(is_valid_regexp_two_args(routine, subset), False)
|
||||
|
||||
def test_is_valid_dot(self):
|
||||
arg = ""
|
||||
self.assertEqual(is_valid_dot(arg), True)
|
||||
arg = "Q1R1"
|
||||
self.assertEqual(is_valid_dot(arg), True)
|
||||
arg = ".Q1R1"
|
||||
self.assertEqual(is_valid_dot(arg), True)
|
||||
arg = "Q1R1."
|
||||
self.assertEqual(is_valid_dot(arg), True)
|
||||
arg = "Q1.R1"
|
||||
self.assertEqual(is_valid_dot(arg), False)
|
||||
arg = ".Q1.R1."
|
||||
self.assertEqual(is_valid_dot(arg), False)
|
||||
|
||||
def test_is_valid_routine_type(self):
|
||||
for item in ROUTINE_TYPE_CHOICE:
|
||||
self.assertEqual(is_valid_routine_type(item[1]), True)
|
||||
|
||||
routine_type = ""
|
||||
self.assertEqual(is_valid_routine_type(routine_type), False)
|
||||
routine_type = ".Q1R1"
|
||||
self.assertEqual(is_valid_routine_type(routine_type), False)
|
||||
routine_type = "SFS."
|
||||
self.assertEqual(is_valid_routine_type(routine_type), False)
|
||||
routine_type = "Q1R1 [4-8]"
|
||||
self.assertEqual(is_valid_routine_type(routine_type), False)
|
||||
routine_type = "SFS [-8]"
|
||||
self.assertEqual(is_valid_routine_type(routine_type), False)
|
||||
|
||||
def test_is_valid_subset(self):
|
||||
"""Exemples :
|
||||
- [2-8] True
|
||||
- [-5] True
|
||||
- [3-] True
|
||||
- [8-2] False
|
||||
- [4--8] False
|
||||
- [-] False
|
||||
- [1-] False
|
||||
- [-1] False
|
||||
- [4] False
|
||||
- [6-6] False
|
||||
"""
|
||||
|
||||
subset = ""
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[2-8]"
|
||||
self.assertEqual(is_valid_subset(subset), True)
|
||||
subset = "[2--8]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[-5]"
|
||||
self.assertEqual(is_valid_subset(subset), True)
|
||||
subset = "[3-]"
|
||||
self.assertEqual(is_valid_subset(subset), True)
|
||||
subset = "[8-2]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[-]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[1-]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[-1]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[4]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[6-6]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "4"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[6-6"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[66]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "4-8"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "6-]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[4-"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "[6"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "Q1R1 [4-8]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
subset = "Q1R1 [-8]"
|
||||
self.assertEqual(is_valid_subset(subset), False)
|
||||
|
||||
def test_is_valid_regexp(self):
|
||||
"""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
|
||||
"""
|
||||
regexp = ""
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1 [4-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1 [8-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1 [8-4]"
|
||||
self.assertEqual(is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1 [-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1 [4-]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1. [4-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "Q1R1. [4-]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = ".Q1R1 [-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = ".Q1R1. [-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), False)
|
||||
regexp = "Q1R1. [8-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), False)
|
||||
regexp = ".Q1R1 [8-4]"
|
||||
self.assertEqual(is_valid_regexp(regexp), False)
|
||||
regexp = "[2-8]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "[-5]"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "WC"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
||||
regexp = "1|"
|
||||
self.assertEqual(is_valid_regexp(regexp), True)
|
|
@ -0,0 +1,144 @@
|
|||
import re
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
|
||||
|
||||
# Subset function
|
||||
def number_of_skill_from_subset(subset, educative=None):
|
||||
"""Calcule le nombre de sauts par rapport à un subset.
|
||||
Commence par vérifier que le subset est valide (car on ne sait jamais).
|
||||
"""
|
||||
if not is_valid_subset(subset):
|
||||
return 0, 0, 0
|
||||
|
||||
subset = subset.replace("[", "").replace("]", "")
|
||||
ranks = subset.split("-")
|
||||
|
||||
if ranks[0] == "":
|
||||
start = 1
|
||||
else:
|
||||
start = int(ranks[0])
|
||||
|
||||
if ranks[1] == "":
|
||||
if educative is not None:
|
||||
end = educative.jumps.all().count()
|
||||
else:
|
||||
end = 10
|
||||
else:
|
||||
end = int(ranks[1])
|
||||
|
||||
number_of_skill = (end - start) + 1
|
||||
|
||||
return start, end, number_of_skill
|
||||
|
||||
|
||||
# Difficulty function
|
||||
def difficulty_from_regexp(educative, start, end):
|
||||
"""Calcule la difficulté sur base du champs regexp d'un object."""
|
||||
difficulty = 0
|
||||
list_of_skill = educative.skill_links.filter(rank__gte=start, rank__lte=end)
|
||||
# .aggregate(total=Sum("value"))
|
||||
|
||||
for routine_skill in list_of_skill:
|
||||
difficulty += routine_skill.skill.difficulty
|
||||
|
||||
return difficulty
|
||||
|
||||
|
||||
# Validation functions
|
||||
def is_valid_regexp_one_arg(argument):
|
||||
"""Vérifie une regexp avec un paramètre."""
|
||||
if argument == "WC":
|
||||
return True
|
||||
|
||||
if re.match(r"[1-9]+\|", argument):
|
||||
return True
|
||||
|
||||
if not is_valid_dot(argument):
|
||||
return False
|
||||
|
||||
value = argument.replace(".", "")
|
||||
is_valid_routine = is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return True
|
||||
|
||||
return is_valid_subset(argument)
|
||||
|
||||
|
||||
def is_valid_regexp_two_args(routine, subset):
|
||||
"""Vérifie une regexp avec deux paramètres."""
|
||||
if not is_valid_dot(routine):
|
||||
return False
|
||||
|
||||
routine_type = routine.replace(".", "")
|
||||
is_valid_routine = is_valid_routine_type(routine_type)
|
||||
|
||||
if is_valid_routine:
|
||||
return is_valid_subset(subset)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
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.search("\.", pattern):
|
||||
last_place = len(pattern) - 1
|
||||
if pattern[0] != "." and pattern[last_place] != ".":
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
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
|
||||
|
||||
return is_valid_routine
|
||||
|
||||
|
||||
def is_valid_subset(subset):
|
||||
"""Reçoit la description d'un subset sous forme de string et vérifie qu'elle est conforme.
|
||||
|
||||
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
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
def is_valid_regexp(regexp):
|
||||
"""Vérifie une regexp pour la classe TrainingRound."""
|
||||
if not regexp:
|
||||
return True
|
||||
|
||||
arguments = regexp.split(" ")
|
||||
|
||||
if len(arguments) >= 3:
|
||||
return False
|
||||
|
||||
if len(arguments) == 2:
|
||||
return is_valid_regexp_two_args(arguments[0], arguments[1])
|
||||
|
||||
return is_valid_regexp_one_arg(arguments[0])
|
|
@ -5,10 +5,10 @@ from django.shortcuts import render, get_object_or_404
|
|||
from django.views.decorators.http import require_http_methods
|
||||
from django.urls import reverse
|
||||
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
from jarvis.people.models import Gymnast
|
||||
from jarvis.followup.models import GymnastHasRoutine
|
||||
|
||||
from .validators import is_valid_routine_type
|
||||
from .forms import (
|
||||
SkillForm,
|
||||
TrainingRoundForm,
|
||||
|
@ -537,7 +537,7 @@ def traininground_details(request, traininground_id, date=None):
|
|||
# Decryptage de la regexp
|
||||
if traininground.regexp is not None and traininground.regexp != "":
|
||||
arguments = traininground.regexp.split(" ")
|
||||
if TrainingRound.is_valid_routine_type(arguments[0]) and date is not None:
|
||||
if is_valid_routine_type(arguments[0]) and date is not None:
|
||||
# get routine_type
|
||||
routine_type = 0
|
||||
ghr = GymnastHasRoutine.objects.filter(
|
||||
|
|
|
@ -93,9 +93,7 @@
|
|||
<table class="table table-condensed table-striped tablesorter" id="table_planned_skill">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 15%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 15%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 35%">Label</th>
|
||||
<th class="header text-left" style="width: 10%">Phase</th>
|
||||
|
@ -108,7 +106,6 @@
|
|||
<tbody>
|
||||
{% for plan in planned_skill %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<a href="{% url 'plan_update' plan.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
|
@ -126,7 +123,7 @@
|
|||
<i class="far fa-thumbs-up"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ plan.educative.skill.notation }}</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'skill_details' plan.educative.id %}">
|
||||
|
@ -156,9 +153,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_confused_skill">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 10%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 10%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 35%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -169,7 +164,6 @@
|
|||
<tbody>
|
||||
{% for skill in confused_skill %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<!-- WITH HELP -->
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon checkUnknownSkill text-without-help" data-gymnast_id="{{ gymnast.id }}" data-skill_id="{{ skill.id }}" data-learning_step="2">
|
||||
|
@ -185,7 +179,7 @@
|
|||
<i class="far fa-thumbs-down"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a>
|
||||
|
@ -205,9 +199,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_skill_with_help">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 10%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 10%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 35%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -218,7 +210,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_whith_help %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<!-- WITH HELP -->
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon checkUnknownSkill text-without-help" data-gymnast_id="{{ gymnast.id }}" data-skill_id="{{ skill.id }}" data-learning_step="2">
|
||||
|
@ -234,7 +225,7 @@
|
|||
<i class="far fa-thumbs-down"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -252,9 +243,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_skill_without_help">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 12%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 12%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 55%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -265,7 +254,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_without_help %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon checkUnknownSkill text-with-help" data-gymnast_id="{{ gymnast.id }}" data-skill_id="{{ plan.educative.id }}" data-learning_step="1">
|
||||
<i class="far fa-check"></i>
|
||||
|
@ -281,7 +269,7 @@
|
|||
<i class="far fa-thumbs-down"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -299,9 +287,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_skill_chained">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 12%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 12%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 35%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -312,7 +298,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_chained %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon checkUnknownSkill text-with-help" data-gymnast_id="{{ gymnast.id }}" data-skill_id="{{ plan.educative.id }}" data-learning_step="1">
|
||||
<i class="far fa-check"></i>
|
||||
|
@ -328,7 +313,7 @@
|
|||
<i class="far fa-thumbs-down"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -346,9 +331,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_skill_masterised">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 12%"></th>
|
||||
{% endif %}
|
||||
<th style="width: 12%"></th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 35%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -359,7 +342,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_masterised %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon checkUnknownSkill text-with-help" data-gymnast_id="{{ gymnast.id }}" data-skill_id="{{ plan.educative.id }}" data-learning_step="1">
|
||||
<i class="far fa-check"></i>
|
||||
|
@ -375,7 +357,7 @@
|
|||
<i class="far fa-thumbs-down"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -393,9 +375,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_by_rank">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 13%">Actions</th>
|
||||
{% endif %}
|
||||
<th style="width: 13%">Actions</th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 50%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -406,7 +386,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_by_rank %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<a href="{% url 'add_skill_for_gymnast' gymnast.id skill.id %}">
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon planify_skill">
|
||||
|
@ -426,7 +405,7 @@
|
|||
<i class="far fa-thumbs-up"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -444,9 +423,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_by_level">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
{% endif %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 50%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -457,7 +434,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_by_level %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<a href="{% url 'add_skill_for_gymnast' gymnast.id skill.id %}">
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon planify_skill">
|
||||
|
@ -477,7 +453,7 @@
|
|||
<i class="far fa-thumbs-up"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -495,9 +471,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_by_age">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
{% endif %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 50%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -509,7 +483,6 @@
|
|||
<tbody>
|
||||
{% for skill in skill_by_age %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<a href="{% url 'add_skill_for_gymnast' gymnast.id skill.id %}">
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon planify_skill">
|
||||
|
@ -529,7 +502,7 @@
|
|||
<i class="far fa-thumbs-up"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
@ -547,9 +520,7 @@
|
|||
<table class="table table-striped table-condensed tablesorter" id="table_unknown_skill">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
{% endif %}
|
||||
<th style="width: 15%">Actions</th>
|
||||
<th style="width: 10%">Notation</th>
|
||||
<th class="header text-left" style="width: 50%">Label</th>
|
||||
<th class="header" style="width: 7%">Diff.</th>
|
||||
|
@ -560,7 +531,6 @@
|
|||
<tbody>
|
||||
{% for skill in unknown_skill %}
|
||||
<tr>
|
||||
{% if user_is_trainer %}
|
||||
<td>
|
||||
<a href="{% url 'add_skill_for_gymnast' gymnast.id skill.id %}">
|
||||
<button type="button" rel="tooltip" class="btn btn-success btn-link btn-sm btn-icon planify_skill">
|
||||
|
@ -580,7 +550,7 @@
|
|||
<i class="far fa-thumbs-up"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
<td>{{ skill.notation }}</td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td>{{ skill.difficulty }}</td>
|
||||
|
|
|
@ -25,18 +25,11 @@ import pendulum
|
|||
|
||||
from jarvis.followup.models import Event
|
||||
from jarvis.followup.models import (
|
||||
Note,
|
||||
Plan,
|
||||
Skill,
|
||||
Point,
|
||||
Chrono,
|
||||
Injury,
|
||||
WellBeing,
|
||||
Intensity,
|
||||
LearnedSkill,
|
||||
HeightWeight,
|
||||
SeasonInformation,
|
||||
NumberOfRoutineDone,
|
||||
)
|
||||
|
||||
from jarvis.followup.models import LEARNING_STEP_CHOICES
|
||||
|
|
Loading…
Reference in New Issue