from datetime import date, datetime from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.views.decorators.http import require_http_methods from django.http import HttpResponse, HttpResponseRedirect from django.db.models import Q, Min, Avg, Max, Sum from django.urls import reverse from django.contrib.auth import get_user_model User = get_user_model() from ultron.people.models import Gymnast from ultron.planning.models import Event from ultron.objective.models import Skill from .models import ( Plan, Point, Chrono, Accident, MindState, LearnedSkill, HeightWeight, ChronoDetails, NumberOfRoutineDone, ) from .forms import ( PlanForm, ScoreForm, ChronoForm, AccidentForm, MindStateForm, HeightWeightForm, LearnedSkillForm, NumberOfRoutineDoneForm, ) @login_required @require_http_methods(["GET"]) def jump_chrono_details(request, chrono_id): """Récupère toutes les informations d'un chrono""" chrono = get_object_or_404(Chrono, pk=chrono_id) sum_value = chrono.details.all().aggregate(total=Sum('value')) chrono.score = sum_value['total'] if chrono.score_type == 0: chrono.tof = Chrono.compute_tof(sum_value['total']) chrono.save() mean_value = chrono.details.all().aggregate(Avg('value')) tmp_min_value = chrono.details.all().aggregate(Min('value')) tmp_max_value = chrono.details.all().aggregate(Max('value')) min_value = mean_value['value__avg'] - (tmp_min_value['value__min'] / 20) max_value = mean_value['value__avg'] - (tmp_max_value['value__max'] / 20) context = {"chrono": chrono, "average_value": mean_value['value__avg'], "min_value": min_value, "max_value": max_value} return render(request, "followup/chronos/details.html", context) @login_required @require_http_methods(["GET"]) def average_jump_chrono_details(request, gymnast_id, routine_type=1, date_begin=None, date_end=None): """Récupère toutes les informations d'un chrono""" # Pendant le dev date_begin = datetime(2022, 1, 20) date_end = datetime(2022, 1, 25) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) stat_values = ChronoDetails.objects \ .filter(chrono__gymnast=gymnast_id, chrono__chrono_type=routine_type, chrono__date__gte=date_begin, chrono__date__lte=date_end) \ .values('order') \ .annotate(avg_score=Avg('value'), max_score=Max('value'), min_score=Min('value')) \ .order_by('order') chrono_list = Chrono.objects.filter(gymnast=gymnast_id, date__gte=date_begin, date__lte=date_end, chrono_type=routine_type) context = { "gymnast": gymnast, "date_begin": date_begin, "date_end": date_end, "chrono_list": chrono_list, "stat_values": stat_values, } return render(request, "followup/chronos/list_details.html", context) @require_http_methods(["POST"]) def remove_jump_chrono_value(request, chrono_id): """ Recoit trois informations permettant d'ajouter le chrono d'un saut à un chrono """ chrono = get_object_or_404(Chrono, pk=chrono_id) order = request.POST.get("order", None) row, created = ChronoDetails.objects.filter(chrono=chrono, order=order).delete() return HttpResponse(200, (row, created)) @require_http_methods(["POST"]) def add_jump_chrono_value(request, chrono_id): """ Recoit trois informations permettant d'ajouter le chrono d'un saut à un chrono """ chrono = get_object_or_404(Chrono, pk=chrono_id) order = request.POST.get("order", None) value = request.POST.get("value", None) row, created = ChronoDetails.objects.get_or_create( chrono=chrono, order=order, value=value ) return HttpResponse(200, (row, created)) @login_required @require_http_methods(["GET"]) def jump_chrono_values_create_or_update(request, chrono_id): """ Ajoute des scores de saut à un chrono """ chrono = get_object_or_404(Chrono, pk=chrono_id) jump_list = chrono.details.all() number_of_jump = jump_list.count() context = { "chrono": chrono, "jump_list": jump_list, "number_of_jump": number_of_jump, "score_type": chrono.score_type, } return render(request, "followup/chronos/add_details.html", context) @login_required @require_http_methods(["GET"]) def chrono_listing(request, gymnast_id=None): """Récupère la liste des chronos""" gymnast = None if gymnast_id: chrono_list = Chrono.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: chrono_list = Chrono.objects.all() context = {"chrono_list": chrono_list, "gymnast": gymnast} return render(request, "followup/chronos/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def chrono_create_or_update(request, chrono_id=None, gymnast_id=None): """Création ou modification d'un chrono""" if chrono_id: chrono = get_object_or_404(Chrono, pk=chrono_id) data = { "gymnast": chrono.gymnast.id, "gymnast_related": str(chrono.gymnast), } else: chrono = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": gymnast} if request.method == "POST": form = ChronoForm(request.POST, instance=chrono) if form.is_valid(): new_chrono = form.save(commit=False) if new_chrono.score_type == 1: new_chrono.tof = new_chrono.score else: new_chrono.tof = Chrono.compute_tof(new_chrono.score) new_chrono.save() return HttpResponseRedirect(reverse("gymnast_details", args=(new_chrono.gymnast.id,))) else: print(form.errors) else: form = ChronoForm(instance=chrono, initial=data) context = {"form": form, "chrono_id": chrono_id} return render(request, "followup/chronos/create.html", context) @login_required @require_http_methods(["POST"]) def gymnast_learn_skill(request): """ Lie un gymnast à une figure. """ # print(request) # utiliser un FORM pour cette fonction. gymnast_id = request.POST.get("gymnast_id", None) skill_id = request.POST.get("skill_id", None) cando = request.POST.get("cando", 0) if gymnast_id and skill_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) skill = Skill.objects.get(pk=skill_id) learned_skill = LearnedSkill( gymnast=gymnast, skill=skill, cando=cando, date=datetime.now() ) learned_skill.save() return HttpResponse(status=200) if gymnast_id: print("Error : can not link Gymnast and skill. Missing Skill_ID.") else: print("Error : can not link Gymnast and skill. Missing Gymnast_ID.") return HttpResponse(status=500) @login_required @require_http_methods(["GET", "POST"]) def learnedskill_create_or_update(request, gymnast_id=None): """ Formulaire de creation et modification d'un lien skill/gymnaste. """ if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = { "gymnast": gymnast.id, "gymnast_related": str(gymnast), } else: data = None if request.method == "POST": form = LearnedSkillForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: form = LearnedSkillForm(initial=data) context = {"form": form, "gymnast_id": gymnast_id} return render(request, "followup/learnedskills/create.html", context) @login_required @require_http_methods(["GET", "POST"]) def score_create_or_update(request, score_id=None, gymnast_id=None): """ Formulaire de création d'un nouveau score. """ if score_id: score = get_object_or_404(Point, pk=score_id) data = { "gymnast_related": str(score.gymnast), "event_related": str(score.event), } else: score = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = ScoreForm(request.POST, instance=score) if form.is_valid(): form.save() if form.cleaned_data['add_to_chrono']: new_chrono = Chrono( gymnast=form.cleaned_data["gymnast"], chrono_type=form.cleaned_data["routine_type"], score_type=1, score=form.cleaned_data["point_time_of_flight"], tof=form.cleaned_data["point_time_of_flight"], date=form.cleaned_data["event"].datebegin, ) new_chrono.save() return HttpResponseRedirect( reverse( "gymnast_details", args=(form.cleaned_data["gymnast"].id,) ) ) else: form = ScoreForm(instance=score, initial=data) context = {"form": form, "score_id": score_id} return render(request, "followup/scores/create.html", context) @login_required @require_http_methods(["GET"]) def score_listing(request, gymnast_id=None): """ Revoie la liste des scores """ pattern = request.GET.get("pattern", None) gymnast = None if pattern: score_list = Point.objects.filter( Q(event__icontains=pattern) | Q(gymnast__icontains=pattern) ) elif gymnast_id: score_list = Point.objects.filter(gymnast=gymnast_id) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) else: score_list = Point.objects.all() context = {"score_list": score_list, "gymnast": gymnast} return render(request, "followup/scores/list.html", context) @login_required @require_http_methods(["GET"]) def accident_listing(request): """ Récupère la liste des accidents suivant un pattern si celui-ci est définit. """ pattern = request.GET.get("pattern", None) if pattern: accident_list = Accident.objects.filter( Q(gymnast__lastname__icontains=pattern) | Q(gymnast__firstname__icontains=pattern) ) else: accident_list = Accident.objects.all() context = {"accident_list": accident_list} return render(request, "followup/accidents/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def accident_create_or_update(request, accident_id=None, gymnast_id=None): """ Formulaire de création d'un nouvel accident. """ if accident_id: accident = get_object_or_404(Accident, pk=accident_id) data = { "gymnast_related": accident.gymnast, "skill_related": accident.skill, } else: accident = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = AccidentForm(request.POST, instance=accident) if form.is_valid(): accident = form.save() return HttpResponseRedirect(reverse("accident_details", args=(accident.pk,))) else: form = AccidentForm(instance=accident, initial=data) context = {"form": form, "accident_id": accident_id} return render(request, "followup/accidents/create.html", context) @login_required @require_http_methods(["GET"]) def accident_detail(request, accident_id): """ Récupère toutes les informations d'un accident. """ accident = get_object_or_404(Accident, pk=accident_id) context = {"accident": accident} return render(request, "followup/accidents/details.html", context) @login_required @require_http_methods(["GET"]) def mindstate_listing(request, gymnast_id=None): """ Récupère la liste des évaluations mentales suivant (d'un gymnaste si définit en paramètre). """ gymnast = None if gymnast_id: mindstate_list = MindState.objects.filter(gymnast=gymnast_id) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) else: mindstate_list = MindState.objects.all() context = {"mindstate_list": mindstate_list, "gymnast": gymnast} return render(request, "followup/mindstates/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def mindstate_create_or_update( request, mindstate_id=None, gymnast_id=None, event_id=None ): """ Formulaire de création d'un nouvel accident. """ if mindstate_id: mindstate = get_object_or_404(MindState, pk=mindstate_id) data = {"gymnast_related": mindstate.gymnast, "event_related": mindstate.event} else: mindstate = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if event_id is not None: event = get_object_or_404(Event, pk=event_id) data = {"event": event_id, "event_related": str(event)} if request.method == "POST": form = MindStateForm(request.POST, instance=mindstate) if form.is_valid(): mindstate = form.save() return HttpResponseRedirect(reverse("mindstate_details", args=(mindstate.pk,))) else: form = MindStateForm(instance=mindstate, initial=data) context = {"form": form, "mindstate_id": mindstate_id} return render(request, "followup/mindstates/create.html", context) @login_required @require_http_methods(["GET"]) def mindstate_detail(request, mindstate_id): """ Récupère toutes les informations d'une évaluation psychologique. """ mindstate = get_object_or_404(MindState, pk=mindstate_id) context = {"mindstate": mindstate} return render(request, "followup/mindstates/details.html", context) @login_required @require_http_methods(["GET"]) def heightweight_listing(request, gymnast_id=None): """ Récupère la liste des couples taille/poids suivant (d'un gymnast si définit en paramètre). """ gymnast = None if gymnast_id: heightweight_list = HeightWeight.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: heightweight_list = HeightWeight.objects.all() context = {"heightweight_list": heightweight_list, "gymnast": gymnast} return render(request, "followup/heightweight/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None): """ Formulaire de creation et modification d'un couple taille/couple. """ if heightweight_id: heightweight = get_object_or_404(HeightWeight, pk=heightweight_id) data = {"gymnast_related": heightweight.gymnast} else: heightweight = None data = None if gymnast_id: heightweight = ( HeightWeight.objects.filter(gymnast=gymnast_id) .order_by("-date") .first() ) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = HeightWeightForm(request.POST, instance=heightweight) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: form = HeightWeightForm(instance=heightweight, initial=data) context = { "form": form, "gymnast_id": gymnast_id, "heightweight_id": heightweight_id, } return render(request, "followup/heightweight/create.html", context) @login_required @require_http_methods(["GET"]) def routine_done_listing(request, gymnast_id=None): """ Liste tous les record de la table NumberOfRoutineDone """ gymnast = None if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) routine_done_list = gymnast.number_of_routine_done.all() else: routine_done_list = NumberOfRoutineDone.objects.all() context = {"routine_done_list": routine_done_list, "gymnast": gymnast} return render(request, "followup/routinedone/list.html", context) @require_http_methods(["POST"]) def increment_routinedone(request): """ Incrémente le nombre de routine faite pour aujourd'hui et incrémente, si besoin, le nombre de routine réussie """ data = { 'gymnast': get_object_or_404(Gymnast, pk=request.POST.get("gymnast_id", None)), 'routine_type': request.POST.get("routine_type", 1), 'date': request.POST.get("date", date.today()), } routinedone, _ = NumberOfRoutineDone.objects.get_or_create(date=data["date"], gymnast=data["gymnast"], routine_type=data["routine_type"]) data["number_of_try"] = routinedone.number_of_try + 1 success = request.POST.get("success", 0) if int(success) == 1: data["number_of_successes"] = routinedone.number_of_successes + 1 else: data["number_of_successes"] = routinedone.number_of_successes form = NumberOfRoutineDoneForm(data, instance=routinedone) if form.is_valid(): form.save() return HttpResponse(status=200) else: return HttpResponse(status=406) @login_required @require_http_methods(["GET", "POST"]) def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None): """Création ou modification d'un chrono""" if routinedone_id: routinedone = get_object_or_404(NumberOfRoutineDone, pk=routinedone_id) data = { "gymnast": routinedone.gymnast.id, "gymnast_related": str(routinedone.gymnast), "routine": routinedone.routine.id, "routine_related": str(routinedone.routine), } else: routinedone = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": gymnast} if request.method == "POST": form = NumberOfRoutineDoneForm(request.POST, instance=routinedone) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: form = NumberOfRoutineDoneForm(instance=routinedone, initial=data) context = {"form": form, "routinedone_id": routinedone_id} return render(request, "followup/routinedone/create.html", context) @login_required @require_http_methods(["GET", "POST"]) def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None): """Création d'un plan. Args: plan_id (int): identifiant d'un plan (classe ). gymnast_id (int): identifiant d'un gymnaste (classe ). skill_id (int): identifiant d'un skill (classe ). """ if plan_id: plan = get_object_or_404(Plan, pk=plan_id) data = { "gymnast": plan.gymnast.id, "gymnast_related": str(plan.gymnast), "skill": plan.skill.id, "skill_related": str(plan.skill), } else: plan = None data = {} if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data["gymnast"] = gymnast_id data["gymnast_related"] = str(gymnast) if skill_id: skill = get_object_or_404(Skill, pk=skill_id) data["educative"] = skill_id data["educative_related"] = str(skill) if request.method == "POST": form = PlanForm(request.POST, instance=plan) if form.is_valid(): plan = form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: form = PlanForm(instance=plan, initial=data) context = {"form": form, "plan_id": plan_id} return render(request, "followup/plan/create.html", context)