Check passe.regexp improvement
This commit is contained in:
parent
74fc13f5cd
commit
97ff0edbb3
|
@ -221,7 +221,15 @@ class TrainingProgramAdmin(admin.ModelAdmin):
|
|||
"difficulty",
|
||||
# "score",
|
||||
)
|
||||
list_display = ("date", "gymnast", "passe", "rank")
|
||||
list_display = (
|
||||
"date",
|
||||
"gymnast",
|
||||
"passe",
|
||||
"rank",
|
||||
"repetition",
|
||||
"number_of_skill",
|
||||
"difficulty",
|
||||
)
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("date", DropdownFilter),
|
||||
|
|
|
@ -110,3 +110,12 @@ class PasseForm(forms.ModelForm):
|
|||
# "step": "1",
|
||||
# }
|
||||
# ),
|
||||
|
||||
def clean_regexp(self):
|
||||
""" """
|
||||
cleaned_data = self.clean()
|
||||
regexp = cleaned_data.get("regexp")
|
||||
if not Passe.is_valid_regexp(regexp, None, None):
|
||||
self.add_error("regexp", "Entered regexp not valid.")
|
||||
|
||||
return regexp
|
||||
|
|
|
@ -477,13 +477,41 @@ class Passe(Markdownizable):
|
|||
regexp = models.CharField(max_length=50, null=True, blank=True)
|
||||
number_of_skill = models.PositiveSmallIntegerField(default=0)
|
||||
difficulty = models.DecimalField(max_digits=4, decimal_places=1, default=0.0)
|
||||
# TODO: number_of_skill doit être calculé correctement dans tous les cas.
|
||||
|
||||
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.
|
||||
On part du principe que self.regexp est correct.
|
||||
"""
|
||||
self.difficulty = 0
|
||||
self.number_of_skill = 0
|
||||
super().save(*args, **kwargs)
|
||||
print("Dans le save")
|
||||
|
||||
if self.educatives.count() == 0:
|
||||
print("educative is none")
|
||||
present = False
|
||||
operation_list = self.regexp.split(" ")
|
||||
for item in ROUTINE_TYPE_CHOICE:
|
||||
if item[1] == operation_list[0]:
|
||||
present = True
|
||||
break
|
||||
|
||||
if present and len(operation_list) == 2:
|
||||
print("present")
|
||||
content = operation_list[1].replace("[", "").replace("]", "")
|
||||
ranks = content.split("-")
|
||||
|
||||
if ranks[0] == "":
|
||||
self.number_of_skill += int(ranks[1])
|
||||
elif ranks[1] == "":
|
||||
self.number_of_skill += (10 - int(ranks[0])) + 1
|
||||
else:
|
||||
self.number_of_skill += (int(ranks[1]) - int(ranks[0])) + 1
|
||||
else:
|
||||
self.number_of_skill += 10
|
||||
|
||||
else:
|
||||
for educative in self.educatives.all():
|
||||
is_skill = False
|
||||
try:
|
||||
|
@ -532,7 +560,63 @@ class Passe(Markdownizable):
|
|||
return f"{self.label} ({self.number_of_skill} | {self.difficulty})"
|
||||
|
||||
@staticmethod
|
||||
def check_regexp(regexp, label, educatives_list):
|
||||
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.
|
||||
"""
|
||||
last_place = len(pattern) - 1
|
||||
if re.search("\.", pattern):
|
||||
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 une liste."""
|
||||
is_valid = False
|
||||
for item in ROUTINE_TYPE_CHOICE:
|
||||
if item[1] == routine_type:
|
||||
is_valid = True
|
||||
break
|
||||
|
||||
return is_valid
|
||||
|
||||
@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
|
||||
- [-] False
|
||||
- [1-] False
|
||||
- [-1] False
|
||||
- [4] False
|
||||
- [6-6] False
|
||||
"""
|
||||
if re.match(r"^\[[2-9]*\-[2-9]*\]$", subset):
|
||||
value = subset.replace("[", "").replace("]", "")
|
||||
if len(value) > 1:
|
||||
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
|
||||
|
||||
Type de string pris en compte :
|
||||
|
@ -546,14 +630,84 @@ class Passe(Markdownizable):
|
|||
- Q1R1 True (si educatives.count() vide)
|
||||
- Q1R2 [2-8] True (si educatives.count() vide)
|
||||
- Q1R1 [8-2] False
|
||||
- Q2R3 [-5] True (si educatives.count() vide)
|
||||
- Q1R1 [-] False (not working)
|
||||
- Q2R1 [-5] True (si educatives.count() vide)
|
||||
- SF [6-] True (si educatives.count() vide)
|
||||
- FS [3-7] True (si educatives.count() vide)
|
||||
- Q1R1. True (si educatives.count() == 1) (NOT WOKRING)
|
||||
- .Q1R2 True (si educatives.count() == 1) (NOT WOKRING)
|
||||
- WC True (si educatives.count() >= 2)
|
||||
- 1| True (si educatives.count() >= 2)
|
||||
- 1| True (si educatives.count() >= 1)
|
||||
"""
|
||||
operation_list = regexp.split(" ")
|
||||
|
||||
if len(operation_list) >= 3:
|
||||
return False
|
||||
|
||||
if len(operation_list) == 2:
|
||||
if not Passe.is_valid_dot(operation_list[0]):
|
||||
return False
|
||||
|
||||
value = operation_list[0].replace(".", "")
|
||||
is_valid_routine = Passe.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return Passe.is_valid_subset(operation_list[1])
|
||||
else:
|
||||
if operation_list[0] == "WC":
|
||||
return True
|
||||
|
||||
if re.match(r"[1-9]+\|", operation_list[0]):
|
||||
return True
|
||||
|
||||
if not Passe.is_valid_dot(operation_list[0]):
|
||||
return False
|
||||
|
||||
value = operation_list[0].replace(".", "")
|
||||
is_valid_routine = Passe.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return True
|
||||
|
||||
return Passe.is_valid_subset(operation_list[0])
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_valid_regexp_extended(regexp, label, educatives_list):
|
||||
"""Vérifie le champ regexp
|
||||
|
||||
Type de string pris en compte :
|
||||
- Toutes les valeurs de ROUTINE_TYPE_CHOICE (Educative vide !)
|
||||
- avec [x-y] (avec X ou Y vide mais pas les deux en même temps)
|
||||
- [x-y] (avec X ou Y vide mais pas les deux en même temps) (EDUCATIVE non vide !!!)
|
||||
- WC
|
||||
- x| (x entier)
|
||||
|
||||
Exemples :
|
||||
- Q1R1 True (si educatives.count() vide)
|
||||
- Q1R2 [2-8] True (si educatives.count() vide)
|
||||
- Q1R1 [8-2] False
|
||||
- Q1R1 [-] False
|
||||
- Q2R1 [-5] True (si educatives.count() vide)
|
||||
- SF [6-] True (si educatives.count() vide)
|
||||
- FS [3-7] True (si educatives.count() vide)
|
||||
- Q1R1. True (si educatives.count() vide)
|
||||
- .Q1R2 True (si educatives.count() vide)
|
||||
- Q1R1. [-4] True (si educatives.count() vide)
|
||||
- .Q1R2 [4-] True (si educatives.count() vide)
|
||||
- .FS [3-7] True (si educatives.count() vide)
|
||||
- [2-8] True (si educative.count() == 1 et educative est une routine >= 8 sauts)
|
||||
- [8-2] False
|
||||
- [-] False
|
||||
- [-5] True (si educative.count() == 1 et educative est une routine >= 8 sauts)
|
||||
- WC True (si educatives.count() >= 2)
|
||||
- 1| True (si educatives.count() >= 1)
|
||||
"""
|
||||
# devrait être en dehors de cette fonction -->
|
||||
if label is None and educatives_list is None and regexp is None:
|
||||
return False
|
||||
# <--
|
||||
|
||||
operation_list = regexp.split(" ")
|
||||
|
||||
|
@ -561,27 +715,36 @@ class Passe(Markdownizable):
|
|||
return False
|
||||
|
||||
if len(operation_list) == 2:
|
||||
if operation_list[0] in ROUTINE_TYPE_CHOICE:
|
||||
if re.match(r"\[[1-9]*\-[1-9]*\]", operation_list[1]):
|
||||
content = operation_list[1].replace("[", "").replace("]", "")
|
||||
ranks = content.split("-")
|
||||
if ranks.count() > 1:
|
||||
if ranks[1] > ranks[1]:
|
||||
return True
|
||||
else:
|
||||
if not Passe.is_valid_dot(operation_list[0]):
|
||||
return False
|
||||
return True
|
||||
|
||||
value = operation_list[0].replace(".", "")
|
||||
is_valid_routine = Passe.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return Passe.is_valid_subset(operation_list[1])
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if operation_list[0] == "WC" and len(educatives_list) == 2:
|
||||
if (
|
||||
operation_list[0] == "WC"
|
||||
and educatives_list is not None
|
||||
and len(educatives_list) == 2
|
||||
):
|
||||
return True
|
||||
|
||||
if re.match(r"[1-9]+\|", operation_list[0]) and len(educatives_list) >= 1:
|
||||
return True
|
||||
|
||||
if not Passe.is_valid_dot(operation_list[0]):
|
||||
return False
|
||||
|
||||
value = operation_list[0].replace(".", "")
|
||||
is_valid_routine = Passe.is_valid_routine_type(value)
|
||||
|
||||
if is_valid_routine:
|
||||
return True
|
||||
|
||||
return Passe.is_valid_subset(operation_list[0])
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">Passe details</h3>
|
||||
<h5 class="card-category mb-0">{{ passe.label }}{% if passe.regexp %}{{ passe.regexp }}{% endif %}</a> {{ passe.repetition }}</h4>
|
||||
<h5 class="card-category mb-0">{{ passe.label }} {% if passe.regexp %}{{ passe.regexp }}{% endif %}</a> {{ passe.repetition }}</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
@ -27,16 +27,24 @@
|
|||
<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">
|
||||
<ul class="mb-0 ml-4 pl-0">
|
||||
{% if routine and not skill_link_list %}
|
||||
<li><a href="{% url 'educative_details' routine.id %}">{{ routine }}</a></li>
|
||||
{% elif routine and 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>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for educative in passe.educatives.all %}
|
||||
<li><a href="{% url 'educative_details' educative.id %}">{{ educative }}</a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if passe.regexp %}
|
||||
{% if passe.regexp and passe.regexp != passe.label %}
|
||||
<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<span class="text-danger"><b>*</b></span></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">
|
||||
{{ passe.regexp }}
|
||||
</div>
|
||||
|
@ -46,7 +54,7 @@
|
|||
<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>
|
||||
<div class="col-8 col-sm-8 col-md-7 col-lg-8 col-xl-9 pt-2">
|
||||
{{ number_of_skill }}
|
||||
{{ number_of_educative }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
<table class="table table-striped tablesorter" id="trainingprogram_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="5" class="text-center">{% if gymnast %}{{ gymnast}} - {% endif %}{{ date|date:"l j F Y" }}</th>
|
||||
<th colspan="5" class="text-center">{% if gymnast %}{{ gymnast }} - {% endif %}{{ date|date:"l j F Y" }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for trainingprogram in trainingprogram_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td><b>{{ trainingprogram.rank }}</b></td>
|
||||
<td class="text-center"><a href="{% url 'passe_details' trainingprogram.passe.id %}">{{ trainingprogram.passe.label }}</a>{% if trainingprogram.repetition != 1 %} {{ trainingprogram.repetition }}{% endif %}</td>
|
||||
<td class="text-center"><a href="{% url 'passe_details' trainingprogram.passe.id gymnast.id date %}">{{ trainingprogram.passe.label }}</a>{% if trainingprogram.repetition != 1 %} {{ trainingprogram.repetition }}{% endif %}</td>
|
||||
<td class="text-center">{{ trainingprogram.number_of_skill}}</td>
|
||||
<td class="text-center">{{ trainingprogram.difficulty }}</td>
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
|
|
|
@ -132,7 +132,7 @@ class PasseTestCase(TestCase):
|
|||
educ_1 = Educative.objects.get(long_label="1/2 vrille")
|
||||
educatives_list.append(educ_1)
|
||||
regexp = "1|"
|
||||
self.assertEqual(Passe.check_regexp(regexp, label, educatives_list), False)
|
||||
self.assertEqual(Passe.check_regexp(regexp, label, educatives_list), True)
|
||||
educ_3 = Educative.objects.get(long_label="4 pattes")
|
||||
educatives_list.append(educ_3)
|
||||
self.assertEqual(Passe.check_regexp(regexp, label, educatives_list), True)
|
||||
|
|
|
@ -92,7 +92,11 @@ urlpatterns = [
|
|||
#
|
||||
# PASSES
|
||||
#
|
||||
path(r"passe/<int:passe_id>/", views.passe_details, name="passe_details"),
|
||||
path(
|
||||
r"passe/<int:passe_id>/gymnast/<int:gymnast_id>/date/<str:date>/",
|
||||
views.passe_details,
|
||||
name="passe_details",
|
||||
),
|
||||
path(r"passe/", views.passe_listing, name="passe_listing"),
|
||||
path(
|
||||
r"passe/add/",
|
||||
|
|
|
@ -7,7 +7,9 @@ from django.urls import reverse
|
|||
|
||||
import pendulum
|
||||
|
||||
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
|
||||
from jarvis.people.models import Gymnast
|
||||
from jarvis.followup.models import GymnastHasRoutine
|
||||
|
||||
from .forms import (
|
||||
SkillForm,
|
||||
|
@ -521,19 +523,66 @@ def passe_listing(request):
|
|||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def passe_details(request, passe_id):
|
||||
def passe_details(request, passe_id, gymnast_id, date):
|
||||
"""Détails d'un passage."""
|
||||
|
||||
is_skill = False
|
||||
passe = get_object_or_404(Passe, pk=passe_id)
|
||||
educative_list = passe.educatives.all()
|
||||
# TODO: décryptage de la regexp
|
||||
regexp = passe.regexp
|
||||
routine = None
|
||||
skill_link_list = None
|
||||
|
||||
if regexp is not None:
|
||||
operation_list = regexp.split(" ")
|
||||
routine_type = None
|
||||
|
||||
for item in ROUTINE_TYPE_CHOICE:
|
||||
if item[1] == operation_list[0]:
|
||||
routine_type = item[0]
|
||||
break
|
||||
|
||||
if routine_type is not None:
|
||||
# Récupération de la série
|
||||
ghr = GymnastHasRoutine.objects.filter(
|
||||
gymnast=gymnast_id,
|
||||
date_begin__lte=date,
|
||||
# date_end__gte=date,
|
||||
routine_type=routine_type,
|
||||
)
|
||||
|
||||
print(ghr.query)
|
||||
|
||||
if ghr.count() > 1:
|
||||
print("Plus d'une série trouvée...")
|
||||
|
||||
print(ghr)
|
||||
|
||||
routine = ghr.first().routine
|
||||
skill_link_list = routine.skill_links.all()
|
||||
if len(operation_list) == 2:
|
||||
content = operation_list[1].replace("[", "").replace("]", "")
|
||||
ranks = content.split("-")
|
||||
|
||||
if ranks[0] != "":
|
||||
skill_link_list = skill_link_list.filter(rank__gte=ranks[0])
|
||||
|
||||
if ranks[1] != "":
|
||||
skill_link_list = skill_link_list.filter(rank__lte=ranks[1])
|
||||
|
||||
number_of_educative = skill_link_list.count()
|
||||
print(number_of_educative)
|
||||
|
||||
else:
|
||||
number_of_educative = educative_list.count()
|
||||
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue