Jarvis/jarvis/objective/views.py

701 lines
23 KiB
Python
Raw Normal View History

2023-04-25 17:06:14 +02:00
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods
from django.urls import reverse
2024-03-01 13:52:54 +01:00
import pendulum
2024-03-09 08:06:21 +01:00
from jarvis.core.global_vars import ROUTINE_TYPE_CHOICE
2023-04-25 17:06:14 +02:00
from jarvis.people.models import Gymnast
2024-03-09 08:06:21 +01:00
from jarvis.followup.models import GymnastHasRoutine
2023-04-25 17:06:14 +02:00
from .forms import (
SkillForm,
2024-02-25 20:02:20 +01:00
PasseForm,
2023-05-16 12:58:11 +02:00
CombinationForm,
CombinationSkillForm,
2023-04-25 17:06:14 +02:00
)
from .models import (
Skill,
2024-02-25 10:28:58 +01:00
Passe,
2023-04-25 17:06:14 +02:00
Routine,
2024-02-25 20:02:20 +01:00
Educative,
2023-04-25 17:06:14 +02:00
RoutineSkill,
2024-02-29 16:20:29 +01:00
TrainingProgram,
2023-04-25 17:06:14 +02:00
PrerequisiteClosure,
)
2024-02-25 20:02:20 +01:00
@login_required
@require_http_methods(["POST"])
def educative_lookup(request):
"""
Récupère la liste des skill à la volée suivant des caractères de recherche entrés (min 3
caractères).
"""
results = []
pattern = request.POST.get("pattern", None)
# Ignore queries shorter than length 2
if pattern is not None and len(pattern) > 2:
model_results = Educative.objects.filter(
Q(short_label__icontains=pattern) | Q(long_label__icontains=pattern)
)
results = [
{"ID": x.id, "long_label": x.long_label, "short_label": x.short_label}
for x in model_results
]
return JsonResponse(results, safe=False)
@login_required
@require_http_methods(["GET"])
def educative_details(request, educative_id):
"""Renvoie les détails d'un educatif suivant que ce soit une combination ou un skill"""
try:
Routine.objects.get(pk=educative_id)
return combination_details(request, educative_id)
except Routine.DoesNotExist:
return skill_details(request, educative_id)
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["POST"])
def skill_lookup(request):
"""
2024-01-14 14:48:31 +01:00
Récupère la liste des skill à la volée suivant des caractères de recherche entrés (min 3
caractères).
2023-04-25 17:06:14 +02:00
"""
results = []
pattern = request.POST.get("pattern", None)
# Ignore queries shorter than length 2
if pattern is not None and len(pattern) > 2:
model_results = Skill.objects.filter(
Q(short_label__icontains=pattern)
| Q(long_label__icontains=pattern)
| Q(notation__icontains=pattern)
)
results = [
{"ID": x.id, "Name": str(x), "Notation": x.notation} for x in model_results
]
return JsonResponse(results, safe=False)
@login_required
@require_http_methods(["GET"])
def skill_without_prerequisite_listing(request):
"""
2023-05-08 10:12:15 +02:00
Récupère la liste des skills n'ayant aucun prérequis.
2023-04-25 17:06:14 +02:00
"""
skill_list = Skill.objects.filter(prerequisites=None)
context = {"skill_list": skill_list}
return render(request, "skills/list.html", context)
@login_required
@require_http_methods(["GET"])
def skill_listing(request, field=None, expression=None, value=None, level=None):
"""
Récupère la liste des skills suivant un pattern si celui-ci est définit.
2023-05-08 10:12:15 +02:00
Args:
field (str) champ sur lequel doit être effectué la recherche
expression (str) expression de comparaison : le, leq, ge, geq,
value (str) valeur de la recherche
level (int) niveau requis pour les skills cherchés.
2023-04-25 17:06:14 +02:00
"""
pattern = None
if not field or not value or not expression:
pattern = request.GET.get("pattern", None)
if pattern:
skill_list = Skill.objects.filter(
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
elif field and expression and value:
2024-01-14 14:48:31 +01:00
kwargs = {f"{field}__{expression}": value}
2023-04-25 17:06:14 +02:00
skill_list = Skill.objects.filter(**kwargs)
elif level is not None:
skill_list = Skill.objects.filter(level=level)
else:
skill_list = Skill.objects.all()
context = {"skill_list": skill_list}
return render(request, "skills/list.html", context)
@login_required
@require_http_methods(["GET"])
def skill_tree(request, skill_id):
2023-05-08 10:12:15 +02:00
"""Récupère tout l'arbre des prérequis pour une saut passé en paramètre
Args:
skill_id (int) identifiant de la classe Skill
2023-05-08 10:12:15 +02:00
"""
2023-04-25 17:06:14 +02:00
skill = get_object_or_404(Skill, pk=skill_id)
node_dict = {}
skill_closure = PrerequisiteClosure.objects.filter(descendant=skill)
for closure in skill_closure:
node_dict[closure.ancestor] = closure.ancestor.prerequisites.all()
context = {"skill": skill, "node_dict": node_dict}
return render(request, "skills/learning_line.html", context)
@login_required
@require_http_methods(["GET"])
def skill_details(request, skill_id):
"""Récupère toutes les informations d'un skill.
La méthode en profite pour vérifier les champs level, rank, age_boy et age_girl
par rapport aux pré-requis.
2023-05-08 10:12:15 +02:00
Args:
skill_id (int) identifiant de la classe Skill
2023-04-25 17:06:14 +02:00
"""
skill = get_object_or_404(Skill, pk=skill_id)
for prerequisite in skill.prerequisites.all():
skill.level = max(prerequisite.level + 1, skill.level)
skill.rank = max(prerequisite.rank + 1, skill.rank)
skill.age_boy_with_help = max(
skill.age_boy_with_help, prerequisite.age_boy_with_help
)
skill.age_boy_without_help = max(
skill.age_boy_without_help, prerequisite.age_boy_without_help
)
skill.age_boy_chained = max(skill.age_boy_chained, prerequisite.age_boy_chained)
skill.age_boy_masterised = max(
skill.age_boy_masterised, prerequisite.age_boy_masterised
)
skill.age_girl_with_help = max(
skill.age_girl_with_help, prerequisite.age_girl_with_help
)
skill.age_girl_without_help = max(
skill.age_girl_without_help, prerequisite.age_girl_without_help
)
skill.age_girl_chained = max(
skill.age_girl_chained, prerequisite.age_girl_chained
)
skill.age_girl_masterised = max(
skill.age_girl_masterised, prerequisite.age_girl_masterised
)
skill.save()
2024-01-14 14:48:31 +01:00
# Je sépare les educatifs de type "skill" et les éducatifs de type "combination" pour mieux
# gérer l'affichage. Du code bien dégueulasse !
2023-05-08 10:12:15 +02:00
# QTF : une idée pour faire ca de manière plus propre, plus élégante ?
combination_dict = {}
2024-01-14 14:48:31 +01:00
educative_skill = skill.educatives.filter(id__in=Skill.objects.all())
for educative in skill.educatives.filter(id__in=Routine.objects.all()):
2023-05-08 10:12:15 +02:00
combination = Routine.objects.get(pk=educative.id)
combination_dict[combination] = []
for educ_skill in combination.routine.skill_links.all():
combination_dict[combination].append(educ_skill)
context = {
"skill": skill,
"combination_dict": combination_dict,
"educative_skill": educative_skill,
}
2023-04-25 17:06:14 +02:00
return render(request, "skills/details.html", context)
@login_required
@require_http_methods(["GET", "POST"])
def skill_create_or_update(request, skill_id=None):
"""Création ou modification d'un saut.
Args:
skill_id (int) identifiant d'un object de classe <Skill>.
2023-04-25 17:06:14 +02:00
"""
if skill_id:
skill = get_object_or_404(Skill, pk=skill_id)
else:
skill = None
if request.method == "POST":
form = SkillForm(request.POST, instance=skill)
if form.is_valid():
skill = form.save()
return HttpResponseRedirect(reverse("skill_details", args=(skill.pk,)))
2024-01-14 14:48:31 +01:00
return render(request, "skill/create.html", {"form": form})
2023-04-25 17:06:14 +02:00
form = SkillForm(instance=skill)
context = {"form": form, "skill_id": skill_id}
return render(request, "skills/create.html", context)
2023-05-01 17:07:50 +02:00
@login_required
@require_http_methods(["GET"])
def competition_routine_listing(request, gymnast_id=None):
2024-01-14 14:48:31 +01:00
"""Récupère la liste des routines (séries) de compétition suivant un pattern si celui-ci est
défini.
2023-05-08 10:12:15 +02:00
Args:
gymnast_id (int) identifiant de la classe Gymnast
2023-05-08 10:12:15 +02:00
"""
2023-05-01 17:07:50 +02:00
gymnast = None
pattern = request.GET.get("pattern", None)
2023-05-08 10:12:15 +02:00
if pattern is not None and len(pattern) > 2:
2023-05-01 17:07:50 +02:00
routine_list = Routine.objects.filter(
is_routine=True, is_competitive=True
).filter(Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern))
else:
if gymnast_id:
routine_list = Routine.objects.filter(
is_routine=True, is_competitive=True
).filter(done_by_gymnast__gymnast=gymnast_id)
gymnast = Gymnast.objects.get(pk=gymnast_id)
else:
routine_list = Routine.objects.filter(is_routine=True, is_competitive=True)
context = {
"title": "Competition Routines",
"routine_list": routine_list,
"gymnast_id": gymnast_id,
"gymnast": gymnast,
}
return render(request, "combinations/list.html", context)
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["GET"])
def routine_listing(request, gymnast_id=None):
2023-05-08 10:12:15 +02:00
"""Récupère la liste des routines (série) suivant un pattern si celui-ci est défini
Args:
gymnast_id (int) identifiant de la classe Gymnast
2023-05-08 10:12:15 +02:00
"""
2023-04-25 17:06:14 +02:00
2023-05-01 17:07:50 +02:00
gymnast = None
pattern = request.GET.get("pattern", None)
2024-02-06 11:00:21 +01:00
base_queryset = Routine.objects.filter(is_routine=True)
2023-05-08 10:12:15 +02:00
if pattern is not None and len(pattern) > 2:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset.filter(
2023-05-01 17:07:50 +02:00
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
else:
if gymnast_id:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset.filter(done_by_gymnast__gymnast=gymnast_id)
2023-05-01 17:07:50 +02:00
gymnast = Gymnast.objects.get(pk=gymnast_id)
else:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset
2023-05-01 17:07:50 +02:00
context = {
"title": "Routines",
"routine_list": routine_list,
"gymnast_id": gymnast_id,
"gymnast": gymnast,
}
return render(request, "combinations/list.html", context)
@login_required
@require_http_methods(["GET"])
def educative_combination_listing(request, gymnast_id=None):
2023-05-08 10:12:15 +02:00
"""Récupère la liste des educatifs suivant un pattern si celui-ci est défini
Args:
gymnast_id (int) identifiant de la classe Gymnast
2023-05-08 10:12:15 +02:00
"""
2023-05-01 17:07:50 +02:00
gymnast = None
pattern = request.GET.get("pattern", None)
2024-02-06 11:00:21 +01:00
base_queryset = Routine.objects.filter(is_routine=False)
2023-05-08 10:12:15 +02:00
if pattern is not None and len(pattern) > 2:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset.filter(
2023-05-01 17:07:50 +02:00
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
else:
if gymnast_id:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset.filter(done_by_gymnast__gymnast=gymnast_id)
2023-05-01 17:07:50 +02:00
gymnast = Gymnast.objects.get(pk=gymnast_id)
else:
2024-02-06 11:00:21 +01:00
routine_list = base_queryset
2023-05-01 17:07:50 +02:00
context = {
"title": "Educative",
"routine_list": routine_list,
"gymnast_id": gymnast_id,
"gymnast": gymnast,
}
return render(request, "combinations/list.html", context)
@login_required
@require_http_methods(["GET"])
def combination_listing(request, gymnast_id=None):
2023-05-08 10:12:15 +02:00
"""Récupère la liste des combinaisons suivant un pattern si celui-ci est défini
Args:
gymnast_id (int) identifiant de la classe Gymnast
2023-05-08 10:12:15 +02:00
"""
2023-05-01 17:07:50 +02:00
2023-04-25 17:06:14 +02:00
gymnast = None
pattern = request.GET.get("pattern", None)
2023-05-08 10:12:15 +02:00
if pattern is not None and len(pattern) > 2:
2023-04-25 17:06:14 +02:00
routine_list = Routine.objects.filter(
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
else:
if gymnast_id:
routine_list = Routine.objects.filter(done_by_gymnast__gymnast=gymnast_id)
gymnast = Gymnast.objects.get(pk=gymnast_id)
else:
routine_list = Routine.objects.all()
context = {
2023-05-01 17:07:50 +02:00
"title": "Combinations",
2023-04-25 17:06:14 +02:00
"routine_list": routine_list,
"gymnast_id": gymnast_id,
"gymnast": gymnast,
}
2023-05-01 17:07:50 +02:00
return render(request, "combinations/list.html", context)
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["POST"])
2024-02-20 19:34:01 +01:00
def combination_lookup(request, search_type=None):
2023-04-25 17:06:14 +02:00
"""
2024-02-20 19:34:01 +01:00
Récupère la liste des combinaisons à la volée suivant des caractères de recherche entrés.
2023-04-25 17:06:14 +02:00
"""
pattern = request.POST.get("pattern", None)
2023-05-08 10:12:15 +02:00
if pattern is not None and len(pattern) > 2:
2023-04-25 17:06:14 +02:00
results = Routine.objects.filter(
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
)
2024-02-20 19:34:01 +01:00
if search_type:
if search_type == "competitive":
results = results.filter(is_competitive=1)
elif search_type == "routine":
results = results.filter(is_routine=1)
combination_list = [{"id": x.id, "label": str(x)} for x in results]
return JsonResponse(combination_list, safe=False)
2023-04-25 17:06:14 +02:00
@login_required
2023-05-08 10:12:15 +02:00
@require_http_methods(["GET"])
2023-05-01 17:07:50 +02:00
def combination_details(request, combination_id):
2023-04-25 17:06:14 +02:00
"""
2023-05-08 10:12:15 +02:00
Récupère toutes les informations d'une combinaison.
2023-04-25 17:06:14 +02:00
Args:
combination_id (int) identifiant d'une routine
2023-04-25 17:06:14 +02:00
"""
2024-02-25 10:28:58 +01:00
combination = get_object_or_404(Routine, pk=combination_id)
combination.compute_informations()
combination_string = combination.inline_str()
context = {
"combination": combination,
"combination_string": combination_string,
"skill_link_list": combination.skill_links.all(),
}
2023-05-01 17:07:50 +02:00
return render(request, "combinations/details.html", context)
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["GET", "POST"])
2023-05-01 17:07:50 +02:00
def combination_create_or_update(request, combination_id=None):
2023-04-25 17:06:14 +02:00
"""Création d'une série.
Args:
combination_id (int) identifiant d'un object de classe <routine>.
2023-04-25 17:06:14 +02:00
"""
2023-05-01 17:07:50 +02:00
if combination_id:
2023-05-16 12:58:11 +02:00
combination = get_object_or_404(Routine, pk=combination_id)
2023-04-25 17:06:14 +02:00
else:
2023-05-16 12:58:11 +02:00
combination = None
2023-04-25 17:06:14 +02:00
if request.method == "POST":
2023-05-16 12:58:11 +02:00
form = CombinationForm(request.POST, instance=combination)
2023-04-25 17:06:14 +02:00
if form.is_valid():
2023-05-16 12:58:11 +02:00
combination = form.save()
2023-04-25 17:06:14 +02:00
# ici faire un FOR skill in form_skills_list:
# record.save() # ca sauve le record dans la table RoutineSkill
2024-01-14 14:48:31 +01:00
# something like this :
# http://stackoverflow.com/questions/3074938/django-m2m-form-save-through-table
2023-05-01 17:07:50 +02:00
# QTF : can you help me ?
return HttpResponseRedirect(
2023-05-16 12:58:11 +02:00
reverse("combination_details", args=(combination.pk,))
2023-05-01 17:07:50 +02:00
)
2024-01-14 14:48:31 +01:00
return render(request, "combinations/create.html", {"form": form})
2023-04-25 17:06:14 +02:00
2023-05-16 12:58:11 +02:00
form = CombinationForm(instance=combination)
2023-05-01 17:07:50 +02:00
context = {"form": form, "combination_id": combination_id}
return render(request, "combinations/create.html", context)
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["GET"])
2023-05-01 17:07:50 +02:00
def compose_combination(request, combination_id):
2023-04-25 17:06:14 +02:00
"""
2023-05-01 17:07:50 +02:00
Récupère une routine et les sauts associés sur base d'un id passé en paramètre.
Args:
combination_id (int) identifiant d'un object de classe <routine>.
2023-04-25 17:06:14 +02:00
"""
2023-05-01 17:07:50 +02:00
routine = get_object_or_404(Routine, pk=combination_id)
2023-04-25 17:06:14 +02:00
skill_link_list = routine.skill_links.all()
skill_list = Skill.objects.all()
context = {
"routine": routine,
"skill_link_list": skill_link_list,
"number_of_skill": skill_link_list.count(),
"skill_list": skill_list,
}
2023-05-01 17:07:50 +02:00
return render(request, "combinations/compose.html", context)
2023-04-25 17:06:14 +02:00
@require_http_methods(["POST"])
2023-05-01 17:07:50 +02:00
def link_skill_to_combination(request):
2023-04-25 17:06:14 +02:00
"""
2023-05-01 17:07:50 +02:00
Recoit dans request trois informations permettant de lier complètement un saut à une routine :
- combination_id (int) identifiant d'un object de classe <routine>
- skill_id (int) identifiant d'un object de classe <skill>
- rank (int) numéro de place du skill dans la routine
2023-04-25 17:06:14 +02:00
"""
data = {
2023-05-01 17:07:50 +02:00
"routine": get_object_or_404(Routine, pk=request.POST.get("combination_id", 0)),
2023-04-25 17:06:14 +02:00
"skill": get_object_or_404(Skill, pk=request.POST.get("skill_id", 0)),
"rank": request.POST.get("rank", 0),
}
2023-05-16 12:58:11 +02:00
form = CombinationSkillForm(data)
2023-04-25 17:06:14 +02:00
if form.is_valid():
link, created = RoutineSkill.objects.get_or_create(
routine=form.cleaned_data["routine"],
skill=form.cleaned_data["skill"],
rank=form.cleaned_data["rank"],
)
return HttpResponse(200, (link, created))
2024-01-14 14:48:31 +01:00
return HttpResponse(406)
2023-04-25 17:06:14 +02:00
@require_http_methods(["POST"])
2023-05-08 10:12:15 +02:00
def unlink_skill_from_combination(request):
2023-04-25 17:06:14 +02:00
"""
2023-05-01 17:07:50 +02:00
Recoit dans request deux informations permettant d'enlever un skill d'une routine :
- rank (int) numéro de place du skill dans la routine
- combination_id (int) identifiant d'un object de classe <routine>
2023-04-25 17:06:14 +02:00
"""
2023-05-08 10:12:15 +02:00
rank = request.POST.get("rank", None)
2023-05-01 17:07:50 +02:00
combination_id = request.POST.get("combination_id", None)
combination = get_object_or_404(Routine, pk=combination_id)
2023-04-25 17:06:14 +02:00
try:
2023-05-01 17:07:50 +02:00
RoutineSkill.objects.get(routine=combination, rank=rank).delete()
2023-04-25 17:06:14 +02:00
except Exception:
return HttpResponse(409)
return HttpResponse(200)
2024-02-25 10:28:58 +01:00
@login_required
@require_http_methods(["GET"])
def passe_listing(request):
"""Liste des passages."""
passe_listing = Passe.objects.all()
context = {"passe_listing": passe_listing}
return render(request, "passes/list.html", context)
@login_required
@require_http_methods(["GET"])
2024-03-09 08:06:21 +01:00
def passe_details(request, passe_id, gymnast_id, date):
2024-02-25 10:28:58 +01:00
"""Détails d'un passage."""
2024-02-29 16:20:29 +01:00
is_skill = False
2024-02-25 10:28:58 +01:00
passe = get_object_or_404(Passe, pk=passe_id)
2024-02-29 16:20:29 +01:00
educative_list = passe.educatives.all()
2024-03-06 15:13:09 +01:00
# TODO: décryptage de la regexp
2024-03-09 08:06:21 +01:00
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()
2024-02-25 20:02:20 +01:00
2024-02-25 10:28:58 +01:00
context = {
"passe": passe,
2024-02-25 20:02:20 +01:00
"is_skill": is_skill,
2024-02-29 16:20:29 +01:00
"educative_list": educative_list,
2024-03-09 08:06:21 +01:00
"routine": routine,
"skill_link_list": skill_link_list,
2024-02-29 16:20:29 +01:00
"difficulty": passe.difficulty,
"number_of_skill": passe.number_of_skill,
"number_of_educative": number_of_educative,
2024-02-25 10:28:58 +01:00
}
return render(request, "passes/details.html", context)
2024-02-25 20:02:20 +01:00
@login_required
@require_http_methods(["GET", "POST"])
def passe_create_or_update(request, passe_id=None):
"""Création d'un passage.
Args:
passe_id (int) identifiant d'un object de classe <Passe>.
"""
if passe_id:
passe = get_object_or_404(Passe, pk=passe_id)
else:
passe = None
if request.method == "POST":
form = PasseForm(request.POST, instance=passe)
if form.is_valid():
passe = form.save()
return HttpResponseRedirect(reverse("passe_details", args=(passe.pk,)))
return render(request, "passes/create.html", {"form": form})
form = PasseForm(instance=passe)
context = {"form": form, "passe_id": passe_id}
return render(request, "passes/create.html", context)
2024-02-29 16:20:29 +01:00
@login_required
@require_http_methods(["GET"])
def trainingprogram_details(request, date=None, gymnast_id=None):
"""Détails d'un entraînement."""
gymnast = None
2024-02-29 16:20:29 +01:00
trainingprogram_id = None
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()
2024-03-01 13:52:54 +01:00
parsed_date = pendulum.parse(date).date()
2024-02-29 16:20:29 +01:00
if date is not None:
2024-03-01 13:52:54 +01:00
trainingprogram_list = trainingprogram_list.filter(date=parsed_date)
2024-02-29 16:20:29 +01:00
if gymnast_id is not None:
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
2024-02-29 16:20:29 +01:00
trainingprogram_list = trainingprogram_list.filter(gymnast=gymnast_id)
2024-03-01 13:52:54 +01:00
difficulty = 0
number_of_skill = 0
for trainingprogram in trainingprogram_list:
difficulty += trainingprogram.difficulty
number_of_skill += trainingprogram.number_of_skill
2024-02-29 16:20:29 +01:00
context = {
"gymnast": gymnast,
2024-03-01 13:52:54 +01:00
"date": parsed_date,
"difficulty": difficulty,
"number_of_skill": number_of_skill,
2024-02-29 16:20:29 +01:00
"trainingprogram": trainingprogram,
"trainingprogram_list": trainingprogram_list,
}
return render(request, "trainingprograms/details.html", context)
2024-03-02 18:13:02 +01:00
@require_http_methods(["POST"])
def switch_trainingprogram_line(request):
"""
Recoit dans request deux identifiants de trainingprogram qu'il faut échanger () :
- tp_id (int) identifiant d'une instance de TraiingProgram
- direction (str) la direction du changement (0: haut, 1: bas)
2024-03-02 18:13:02 +01:00
J'utilise `32767` comme valeur intermédiaire pour le `rank` car c'est la limite supérieure d'un
PositiveSmallIntegerField.
"""
try:
target_trainingprogram_id = request.POST.get("tpid", None)
direction = int(request.POST.get("direction", 0))
2024-03-02 18:13:02 +01:00
target_trainingprogram = get_object_or_404(
TrainingProgram, pk=target_trainingprogram_id
)
if direction == 0:
source_trainingprogram = (
TrainingProgram.objects.filter(rank__lt=target_trainingprogram.rank)
.order_by("-id")
.first()
)
else:
source_trainingprogram = (
TrainingProgram.objects.filter(rank__gt=target_trainingprogram.rank)
.order_by("id")
.first()
)
2024-03-02 18:13:02 +01:00
saved_source_rank = source_trainingprogram.rank
saved_target_rank = target_trainingprogram.rank
source_trainingprogram.rank = 32767
source_trainingprogram.save()
target_trainingprogram.rank = saved_source_rank
target_trainingprogram.save()
source_trainingprogram.rank = saved_target_rank
source_trainingprogram.save()
return HttpResponse(200)
2024-03-02 18:13:02 +01:00
except Exception:
return HttpResponse(409)