2023-04-25 17:06:14 +02:00
|
|
|
|
from django.contrib.auth.decorators import login_required
|
|
|
|
|
from django.contrib.auth.models import Group
|
|
|
|
|
from django.contrib.auth import get_user_model
|
2023-04-29 15:31:14 +02:00
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
from django.db.models import (
|
|
|
|
|
Q,
|
|
|
|
|
Avg,
|
|
|
|
|
Sum,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Min,
|
|
|
|
|
Max,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
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
|
|
|
|
|
from django.template.loader import render_to_string
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
|
|
from django.core.mail import send_mail
|
|
|
|
|
|
|
|
|
|
from weasyprint import HTML, CSS
|
|
|
|
|
|
|
|
|
|
# from weasyprint.fonts import FontConfiguration
|
|
|
|
|
|
|
|
|
|
import pendulum
|
2023-06-19 20:41:14 +02:00
|
|
|
|
from datetime import date
|
2023-04-25 17:06:14 +02:00
|
|
|
|
from statistics import mean
|
|
|
|
|
|
|
|
|
|
from jarvis.followup.models import Event
|
|
|
|
|
from jarvis.followup.forms import GymnastHasRoutineForm
|
|
|
|
|
from jarvis.followup.models import (
|
|
|
|
|
Note,
|
|
|
|
|
Plan,
|
|
|
|
|
Skill,
|
|
|
|
|
Point,
|
|
|
|
|
Chrono,
|
2023-10-11 16:32:09 +02:00
|
|
|
|
Injury,
|
2023-07-05 10:51:49 +02:00
|
|
|
|
WellBeing,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
Intensity,
|
|
|
|
|
LearnedSkill,
|
|
|
|
|
HeightWeight,
|
|
|
|
|
SeasonInformation,
|
|
|
|
|
NumberOfRoutineDone,
|
|
|
|
|
)
|
|
|
|
|
|
2023-04-29 15:31:14 +02:00
|
|
|
|
from jarvis.followup.models import LEARNING_STEP_CHOICES
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
from jarvis.tools.models import Season
|
|
|
|
|
|
|
|
|
|
# from jarvis.tools.pdf_generator import GymnastReportDocument
|
|
|
|
|
|
|
|
|
|
from jarvis.tools.date_week_transition import (
|
|
|
|
|
from_date_to_week_number,
|
|
|
|
|
from_week_number_to_date,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
from_month_number_to_date,
|
|
|
|
|
from_season_to_date,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from .models import Gymnast
|
|
|
|
|
from .forms import GymnastForm, UserForm
|
|
|
|
|
|
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["POST"])
|
|
|
|
|
def gymnast_lookup(request):
|
|
|
|
|
"""
|
|
|
|
|
Récupère la liste des gymnastes à la volée suivant des caractères de
|
2023-05-14 19:10:34 +02:00
|
|
|
|
recherche entrés (min 3 caractères).
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
results = []
|
|
|
|
|
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
|
|
|
|
model_results = Gymnast.objects.filter(
|
|
|
|
|
Q(last_name__icontains=pattern) | Q(first_name__icontains=pattern)
|
|
|
|
|
)
|
|
|
|
|
results = [{"ID": x.id, "Name": str(x)} for x in model_results]
|
|
|
|
|
|
|
|
|
|
return JsonResponse(results, safe=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_listing(request):
|
|
|
|
|
"""
|
2023-10-18 08:13:07 +02:00
|
|
|
|
Si la personne connectée est un entraîneur : liste tous les gymnasts ACTIFS connus.
|
2023-04-25 17:06:14 +02:00
|
|
|
|
Si la personne connectée est un gymnaste : renvoie sa fiche détaillée.
|
|
|
|
|
"""
|
|
|
|
|
season = Season()
|
|
|
|
|
if request.user.groups.filter(name="trainer").exists():
|
|
|
|
|
season_information_list = SeasonInformation.objects.filter(
|
|
|
|
|
season=season.label
|
|
|
|
|
).select_related("gymnast")
|
|
|
|
|
context = {"season_information_list": season_information_list}
|
|
|
|
|
return render(request, "gymnasts/list.html", context)
|
|
|
|
|
else:
|
|
|
|
|
gymnast = Gymnast.objects.get(user=request.user) # a mettre dans un TRY
|
|
|
|
|
return gymnast_details(request, gymnast.id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_details(request, gymnast_id, tab=None):
|
|
|
|
|
"""
|
|
|
|
|
Récupère toutes les informations d'un gymnaste si la personne connectée est un "trainer".
|
|
|
|
|
Si la personne connectée est un gymnaste : renvoie sa fiche détaillée.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
|
|
|
|
tab (str) <string> de l'onglet désiré
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if request.user.groups.filter(name="trainer").exists():
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
else:
|
|
|
|
|
gymnast = Gymnast.objects.get(user=request.user)
|
|
|
|
|
|
|
|
|
|
last_season_information = gymnast.season_informations.order_by("-season").first()
|
|
|
|
|
|
|
|
|
|
gymnast_nb_known_skills = gymnast.known_skills.distinct(
|
|
|
|
|
"skill"
|
|
|
|
|
).count() # devrait disparaitre
|
|
|
|
|
|
|
|
|
|
nb_skill = Skill.objects.all().count()
|
|
|
|
|
nb_known_skill = (
|
|
|
|
|
LearnedSkill.objects.filter(gymnast=gymnast_id).distinct("skill").count()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if nb_skill != 0:
|
|
|
|
|
percentage_known_skill = (nb_known_skill / nb_skill) * 100
|
|
|
|
|
else:
|
|
|
|
|
percentage_known_skill = 0
|
|
|
|
|
|
|
|
|
|
# base_queryset = Chrono.objects.filter(gymnast=gymnast_id).order_by("-date")
|
|
|
|
|
chronos_list = Chrono.objects.filter(gymnast=gymnast_id).order_by("-date")[:10]
|
|
|
|
|
straightjump_score = (
|
|
|
|
|
Chrono.objects.filter(gymnast=gymnast_id)
|
|
|
|
|
.filter(chrono_type=0)
|
|
|
|
|
.order_by("-date")
|
|
|
|
|
)
|
|
|
|
|
best_straightjump = (
|
|
|
|
|
Chrono.objects.filter(gymnast=gymnast_id)
|
|
|
|
|
.filter(chrono_type=0)
|
|
|
|
|
.order_by("-score")[:1]
|
|
|
|
|
)
|
|
|
|
|
best_routine = (
|
|
|
|
|
Chrono.objects.filter(gymnast=gymnast_id)
|
|
|
|
|
.filter(chrono_type=1)
|
|
|
|
|
.order_by("-score")[:1]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
context = {
|
|
|
|
|
"gymnast": gymnast,
|
|
|
|
|
"last_season_information": last_season_information,
|
|
|
|
|
"gymnast_nb_known_skills": gymnast_nb_known_skills,
|
|
|
|
|
"chronos_list": chronos_list,
|
|
|
|
|
"straightjump_score": straightjump_score,
|
|
|
|
|
"best_routine": best_routine,
|
|
|
|
|
"best_straightjump": best_straightjump,
|
|
|
|
|
"nb_skill": nb_skill,
|
|
|
|
|
"nb_known_skill": nb_known_skill,
|
|
|
|
|
"percentage_known_skill": percentage_known_skill,
|
|
|
|
|
"tab": tab,
|
|
|
|
|
}
|
|
|
|
|
context["user_is_trainer"] = request.user.groups.filter(
|
|
|
|
|
name="trainer"
|
|
|
|
|
).exists() # TODO: utiliser les {{ perms }}
|
|
|
|
|
return render(request, "gymnasts/details.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_report_list(request, gymnast_id):
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
|
|
|
|
"""
|
2023-06-20 08:29:19 +02:00
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
today = pendulum.now().date()
|
|
|
|
|
season, week_number = from_date_to_week_number(today)
|
|
|
|
|
|
|
|
|
|
season_list = __get_distinct_followup_season_for_gymnast(gymnast_id)
|
|
|
|
|
week_number_list = sorted(
|
|
|
|
|
__get_distinct_week_number_for_season_and_gymnast(gymnast_id, season)
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
context = {
|
2023-06-20 08:29:19 +02:00
|
|
|
|
"gymnast": gymnast,
|
|
|
|
|
"season": season,
|
|
|
|
|
"season_list": season_list,
|
|
|
|
|
"week_number": week_number,
|
|
|
|
|
"week_number_list": week_number_list,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_documents.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_report_evaluation(request, gymnast_id):
|
|
|
|
|
""" """
|
|
|
|
|
context = {
|
|
|
|
|
"SITE_TITLE": settings.SITE_TITLE,
|
|
|
|
|
"CLUB_NAME": settings.CLUB_NAME,
|
|
|
|
|
"ADDRESS": settings.ADDRESS,
|
|
|
|
|
"CITY": settings.CITY,
|
|
|
|
|
"ZIP": settings.ZIP,
|
|
|
|
|
"HEAD_COACH": settings.HEAD_COACH,
|
|
|
|
|
"MOBILE_PHONE": settings.MOBILE_PHONE,
|
|
|
|
|
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
|
|
|
|
|
# "week_number": week_number,
|
|
|
|
|
# "gymnast": gymnast,
|
|
|
|
|
# "today": date_begin,
|
|
|
|
|
# "season": season,
|
|
|
|
|
# "sorted_records": sorted_records,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/reports/report_evaluation.html", context)
|
|
|
|
|
# response = HttpResponse(content_type="application/pdf")
|
|
|
|
|
# response[
|
|
|
|
|
# "Content-Disposition"
|
|
|
|
|
# ] = "attachment; filename={lastname}-{firstname}-report-timeline.pdf".format(
|
|
|
|
|
# lastname=gymnast.last_name,
|
|
|
|
|
# firstname=gymnast.first_name,
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
# html = render_to_string("people/gymnasts/reports/report_timeline.html", context)
|
|
|
|
|
|
|
|
|
|
# # font_config = FontConfiguration()
|
|
|
|
|
# HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
|
|
|
|
|
# response,
|
|
|
|
|
# stylesheets=[
|
|
|
|
|
# CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
|
|
|
|
|
# CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
|
|
|
|
|
# CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
|
|
|
|
|
# ],
|
|
|
|
|
# ) # , font_config=font_config)
|
|
|
|
|
# return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_display_events_and_notes(request, gymnast_id):
|
|
|
|
|
"""
|
|
|
|
|
Renvoie deux listes d'évènements : ceux à venir et ceux passés.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
today = pendulum.now().date()
|
|
|
|
|
next_event_list = Event.objects.filter(gymnasts=gymnast_id, date_begin__gte=today)
|
|
|
|
|
previous_event_list = Event.objects.filter(
|
|
|
|
|
gymnasts=gymnast_id, date_begin__lte=today
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
base_queryset = Note.objects.filter(gymnast=gymnast_id)
|
|
|
|
|
if not request.user.groups.filter(name="trainer").exists():
|
|
|
|
|
notes_list = base_queryset.filter(status=1)
|
|
|
|
|
else:
|
|
|
|
|
notes_list = base_queryset
|
|
|
|
|
notes_list = notes_list.order_by("-created_at")
|
|
|
|
|
|
2023-06-12 14:05:52 +02:00
|
|
|
|
last_notes_list = notes_list[:6]
|
2023-04-25 17:06:14 +02:00
|
|
|
|
latest_published_note = (
|
|
|
|
|
base_queryset.filter(status=1).order_by("-created_at").first()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
context = {
|
|
|
|
|
"next_event_list": next_event_list,
|
|
|
|
|
"previous_event_list": previous_event_list,
|
|
|
|
|
"last_notes_list": last_notes_list,
|
|
|
|
|
"latest_published_note": latest_published_note,
|
|
|
|
|
"gymnast_id": gymnast_id,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_events_and_notes.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
2023-07-06 23:37:07 +02:00
|
|
|
|
def gymnast_display_injury(request, gymnast_id):
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
|
Renvoie la liste des blessures d'un gymnaste.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
2023-10-11 16:32:09 +02:00
|
|
|
|
injuries_list = Injury.objects.filter(gymnast=gymnast_id)
|
2023-07-06 23:37:07 +02:00
|
|
|
|
context = {"injuries_list": injuries_list, "gymnast_id": gymnast_id}
|
|
|
|
|
return render(request, "gymnasts/list_injury.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_display_physiological(request, gymnast_id):
|
|
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
|
Renvoie les listes des tailles/poids, état d'esprit et blessures.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
2023-10-11 16:32:09 +02:00
|
|
|
|
injuries_list = Injury.objects.filter(gymnast=gymnast_id).order_by("date")
|
2023-07-05 10:51:49 +02:00
|
|
|
|
wellbeing_list = WellBeing.objects.filter(gymnast=gymnast_id).order_by("date")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
height_weight_list = HeightWeight.objects.filter(gymnast=gymnast_id).order_by(
|
|
|
|
|
"date"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
context = {
|
2023-07-06 23:37:07 +02:00
|
|
|
|
"injuries_list": injuries_list,
|
2023-07-05 09:33:03 +02:00
|
|
|
|
"wellbeing_list": wellbeing_list,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"height_weight_list": height_weight_list,
|
|
|
|
|
"gymnast_id": gymnast_id,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_physiological.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_display_scores_chrono(request, gymnast_id):
|
|
|
|
|
"""
|
2023-05-14 19:10:34 +02:00
|
|
|
|
Selectionne tous les scores réalisés par le gymnaste.
|
2023-04-25 17:06:14 +02:00
|
|
|
|
Afin de ne pas avoir plusieurs valeurs pour une même date, nous faisons une
|
|
|
|
|
moyenne par date.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
score_list = Point.objects.filter(gymnast=gymnast_id).order_by("-event__date_begin")
|
|
|
|
|
chrono_list = Chrono.objects.filter(gymnast=gymnast_id).order_by("date")
|
|
|
|
|
base_queryset = chrono_list.values("date").annotate(score_avg=Avg("tof"))
|
|
|
|
|
|
|
|
|
|
context = {
|
|
|
|
|
"score_list": score_list,
|
|
|
|
|
"score_routine1_list": score_list.filter(routine_type=1),
|
|
|
|
|
"score_routine2_list": score_list.filter(routine_type=2),
|
|
|
|
|
"score_routine3_list": score_list.filter(routine_type=3),
|
|
|
|
|
"chrono_list": chrono_list,
|
|
|
|
|
"chrono_10c": base_queryset.filter(chrono_type=0),
|
|
|
|
|
"chrono_r1": base_queryset.filter(chrono_type=1),
|
|
|
|
|
"chrono_r2": base_queryset.filter(chrono_type=2),
|
|
|
|
|
"chrono_rf": base_queryset.filter(chrono_type=3),
|
|
|
|
|
"gymnast_id": gymnast_id,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_scores_and_chronos.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
2023-07-05 09:33:03 +02:00
|
|
|
|
def gymnast_display_wellbeing(request, gymnast_id):
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
2023-05-14 19:10:34 +02:00
|
|
|
|
Selectionne tous les scores réalisés par le gymnaste.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
2023-07-05 10:51:49 +02:00
|
|
|
|
wellbeing_list = WellBeing.objects.filter(gymnast=gymnast_id).order_by("-date")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
context = {
|
2023-07-05 09:33:03 +02:00
|
|
|
|
"wellbeing_list": wellbeing_list,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"gymnast_id": gymnast_id,
|
|
|
|
|
}
|
2023-07-05 09:33:03 +02:00
|
|
|
|
return render(request, "gymnasts/list_wellbeing.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_display_routine_statistics(request, gymnast_id):
|
|
|
|
|
"""
|
|
|
|
|
Tag affichant les statistiques et informations de séries d'un gymnaste.
|
2023-05-08 10:12:15 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
2023-05-14 19:10:34 +02:00
|
|
|
|
gymnast_id (int) identifiant de la classe Gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
ghr_list = gymnast.has_routine.prefetch_related("routine").filter(
|
|
|
|
|
Q(date_end__gte=date.today()) | Q(date_end__isnull=True)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
has_routine_1 = ghr_list.filter(routine_type=1)
|
|
|
|
|
has_routine_2 = ghr_list.filter(routine_type=2)
|
|
|
|
|
has_routine_3 = ghr_list.filter(routine_type=3)
|
|
|
|
|
has_routine_4 = ghr_list.filter(routine_type=4)
|
|
|
|
|
has_routine_5 = ghr_list.filter(routine_type=5)
|
|
|
|
|
|
|
|
|
|
routine_one_done_list = NumberOfRoutineDone.objects.filter(
|
|
|
|
|
gymnast=gymnast_id, routine_type=1
|
|
|
|
|
).order_by("date")
|
|
|
|
|
routine_two_done_list = NumberOfRoutineDone.objects.filter(
|
|
|
|
|
gymnast=gymnast_id, routine_type=2
|
|
|
|
|
).order_by("date")
|
|
|
|
|
intensity_list = Intensity.objects.filter(gymnast=gymnast_id).order_by("date")
|
|
|
|
|
|
|
|
|
|
context = {
|
|
|
|
|
"ghr_list": ghr_list,
|
|
|
|
|
"has_routine_1": has_routine_1,
|
|
|
|
|
"has_routine_2": has_routine_2,
|
|
|
|
|
"has_routine_3": has_routine_3,
|
|
|
|
|
"has_routine_4": has_routine_4,
|
|
|
|
|
"has_routine_5": has_routine_5,
|
|
|
|
|
"routine_one_done_list": routine_one_done_list,
|
|
|
|
|
"routine_two_done_list": routine_two_done_list,
|
|
|
|
|
"intensity_list": intensity_list,
|
|
|
|
|
"gymnast_id": gymnast_id,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_routines_and_routine_stats.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET", "POST"])
|
|
|
|
|
def link_routine_to_gymnast(request, gymnast_id=None):
|
2023-05-08 10:12:15 +02:00
|
|
|
|
"""Lie une série à un gymnaste
|
|
|
|
|
|
|
|
|
|
Args:
|
2023-05-14 19:10:34 +02:00
|
|
|
|
gymnast_id (int) identifiant de la classe Gymnast
|
2023-05-08 10:12:15 +02:00
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
if gymnast_id:
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
data = {
|
|
|
|
|
"gymnast": gymnast_id,
|
|
|
|
|
"gymnast_related": str(gymnast),
|
|
|
|
|
"date_end": None,
|
|
|
|
|
}
|
|
|
|
|
else:
|
|
|
|
|
gymnast = None
|
|
|
|
|
data = {"date_end": None}
|
|
|
|
|
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
form = GymnastHasRoutineForm(request.POST)
|
|
|
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
form.save()
|
|
|
|
|
if not gymnast:
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=form.cleaned_data["gymnast"])
|
2023-04-29 15:31:14 +02:00
|
|
|
|
|
|
|
|
|
receiver = []
|
|
|
|
|
functionality = ContentType.objects.get(model="gymnasthasroutine")
|
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
|
functionality=functionality
|
|
|
|
|
):
|
|
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
send_mail(
|
|
|
|
|
"Nouvelle série",
|
|
|
|
|
"Une nouvelle série vous a été associée.",
|
|
|
|
|
settings.EMAIL_HOST_USER,
|
2023-04-29 15:31:14 +02:00
|
|
|
|
[gymnast.user.email, gymnast.email_trainer].append(receiver),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
fail_silently=False,
|
|
|
|
|
html_message="""<p>Bonjour,</p>
|
|
|
|
|
<p>Une nouvelle série vous a été associée.</p><br />
|
|
|
|
|
<p>Excellente journée</p><p>Jarvis</p>""",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
|
reverse("gymnast_details_tab", args=(gymnast_id, "routine"))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
form = GymnastHasRoutineForm(instance=gymnast, initial=data)
|
|
|
|
|
|
|
|
|
|
context = {"form": form, "gymnast_id": gymnast_id}
|
|
|
|
|
return render(request, "gymnasts/link_to_routine.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET", "POST"])
|
|
|
|
|
def gymnast_create_or_update(request, gymnast_id=None):
|
|
|
|
|
"""
|
2023-05-08 10:12:15 +02:00
|
|
|
|
Formulaire de création et modification d'un gymnaste.
|
|
|
|
|
|
|
|
|
|
Args:
|
2023-05-14 19:10:34 +02:00
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if gymnast_id:
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
else:
|
|
|
|
|
gymnast = None
|
|
|
|
|
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
gymnast_form = GymnastForm(request.POST, instance=gymnast)
|
|
|
|
|
|
|
|
|
|
if gymnast_form.is_valid():
|
|
|
|
|
gymnast = gymnast_form.save()
|
|
|
|
|
form_data = request.POST.dict()
|
|
|
|
|
user_data = {}
|
|
|
|
|
user_data["first_name"] = form_data["first_name"]
|
|
|
|
|
user_data["last_name"] = form_data["last_name"]
|
|
|
|
|
user_data["username"] = (
|
|
|
|
|
form_data["first_name"].lower() + "_" + form_data["last_name"].lower()
|
|
|
|
|
)
|
|
|
|
|
user_data["email"] = form_data["email"].lower()
|
|
|
|
|
user_data["is_active"] = True
|
|
|
|
|
user_form = UserForm(user_data, instance=gymnast.user)
|
|
|
|
|
|
|
|
|
|
if user_form.is_valid():
|
|
|
|
|
user = user_form.save()
|
|
|
|
|
|
|
|
|
|
gymnast_group, _ = Group.objects.get_or_create(name="gymnast")
|
|
|
|
|
user.groups.add(gymnast_group)
|
|
|
|
|
gymnast.user = user
|
|
|
|
|
gymnast.save()
|
|
|
|
|
|
|
|
|
|
# if not user.has_usable_password():
|
|
|
|
|
# user.set_password(gymnast.last_name.lower() + _ + str(gymnast.birthdate)[-2:])
|
|
|
|
|
|
|
|
|
|
return HttpResponseRedirect(reverse("gymnast_details", args=(gymnast.pk,)))
|
|
|
|
|
else:
|
|
|
|
|
return render(
|
|
|
|
|
request, "people/gymnasts/create.html", {"form": gymnast_form}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
form = GymnastForm(instance=gymnast)
|
|
|
|
|
context = {"form": form, "gymnast_id": gymnast_id}
|
|
|
|
|
return render(request, "gymnasts/create.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def gymnast_display_skill(request, gymnast_id):
|
|
|
|
|
"""Tag affichant les statistiques de skill d'un gymnaste
|
|
|
|
|
|
|
|
|
|
Le nombre de saut qu'il sait faire (total, par niveau, par rank, …), calcule la complétude, …
|
|
|
|
|
|
|
|
|
|
.. todo:: Générer UNE fois la liste de skill que le gymnaste ne sait pas faire (1 query)
|
|
|
|
|
et les counts puis, dans le template on parcourt plusieurs fois cette même liste mais on
|
|
|
|
|
affiche conditionnellement (par age, par rank, ...)
|
|
|
|
|
|
|
|
|
|
Il y a 4 étapes dans l'apprentissage :
|
|
|
|
|
- skill confusion syndrom "No" - 0
|
|
|
|
|
- avec aide (tapis, manip, …) "with help" - 1
|
|
|
|
|
- sans aide () "without help" - 2
|
|
|
|
|
- enchaîné (un saut avec et après) "chained" - 3
|
|
|
|
|
- maitrisé (dans n'importe quelle condition) "masterised" - 4
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
context = {}
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
gymnast_nb_known_skills = gymnast.known_skills.distinct("skill").count()
|
|
|
|
|
context = gymnast.get_informations_from_type("level")
|
|
|
|
|
context.update(gymnast.get_informations_from_type("rank"))
|
|
|
|
|
|
|
|
|
|
planned_skill = (
|
|
|
|
|
Plan.objects.filter(gymnast=gymnast.id, educative__in=(Skill.objects.all()))
|
|
|
|
|
.select_related("educative", "educative__skill")
|
|
|
|
|
.order_by("-date", "educative__long_label")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
context["planned_skill"] = planned_skill
|
|
|
|
|
|
|
|
|
|
if gymnast.gender:
|
|
|
|
|
context["skill_by_age"] = Skill.objects.filter(
|
|
|
|
|
age_girl_masterised__lte=gymnast.age
|
|
|
|
|
).exclude(known_by__gymnast=gymnast.id)
|
|
|
|
|
else:
|
|
|
|
|
context["skill_by_age"] = Skill.objects.filter(
|
|
|
|
|
age_boy_masterised__lte=gymnast.age
|
|
|
|
|
).exclude(known_by__gymnast=gymnast.id)
|
|
|
|
|
|
|
|
|
|
learned_skills = (
|
|
|
|
|
LearnedSkill.objects.filter(gymnast=gymnast_id)
|
|
|
|
|
.select_related("skill")
|
|
|
|
|
.order_by("skill_id", "-date")
|
|
|
|
|
.distinct("skill_id")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# skill_learned_by_phase = [[]] * 5
|
|
|
|
|
# print(skill_learned_by_phase)
|
|
|
|
|
confused_skill = list()
|
|
|
|
|
skill_whith_help = list()
|
|
|
|
|
skill_without_help = list()
|
|
|
|
|
skill_chained = list()
|
|
|
|
|
skill_masterised = list()
|
|
|
|
|
for learned_skill in learned_skills:
|
|
|
|
|
# print('Add skill for ' + str(learned_skill.learning_step) + ' phase')
|
|
|
|
|
# skill_learned_by_phase[learned_skill.learning_step].append(learned_skill.skill)
|
|
|
|
|
if learned_skill.learning_step == 0:
|
|
|
|
|
confused_skill.append(learned_skill.skill)
|
|
|
|
|
elif learned_skill.learning_step == 1:
|
|
|
|
|
skill_whith_help.append(learned_skill.skill)
|
|
|
|
|
elif learned_skill.learning_step == 2:
|
|
|
|
|
skill_without_help.append(learned_skill.skill)
|
|
|
|
|
elif learned_skill.learning_step == 3:
|
|
|
|
|
skill_chained.append(learned_skill.skill)
|
|
|
|
|
else:
|
|
|
|
|
skill_masterised.append(learned_skill.skill)
|
|
|
|
|
|
|
|
|
|
# for i in range(0,4):
|
|
|
|
|
# print(skill_learned_by_phase[i])
|
|
|
|
|
|
|
|
|
|
# context["confused_skill"] = skill_learned_by_phase[0]
|
|
|
|
|
# context["skill_whith_help"] = skill_learned_by_phase[1]
|
|
|
|
|
# context["skill_without_help"] = skill_learned_by_phase[2]
|
|
|
|
|
# context["skill_chained"] = skill_learned_by_phase[3]
|
|
|
|
|
# context["skill_masterised"] = skill_learned_by_phase[4]
|
|
|
|
|
context["confused_skill"] = confused_skill
|
|
|
|
|
context["skill_whith_help"] = skill_whith_help
|
|
|
|
|
context["skill_without_help"] = skill_without_help
|
|
|
|
|
context["skill_chained"] = skill_chained
|
|
|
|
|
context["skill_masterised"] = skill_masterised
|
|
|
|
|
|
|
|
|
|
context["gymnast"] = gymnast
|
|
|
|
|
context["gymnast_nb_known_skills"] = gymnast_nb_known_skills
|
|
|
|
|
context["user_is_trainer"] = request.user.groups.filter(
|
|
|
|
|
name="trainer"
|
|
|
|
|
).exists() # TODO: utiliser les {{ perms }}
|
|
|
|
|
return render(request, "gymnasts/tabs/tab_skill.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def analyse_score(value, value_list):
|
2023-06-19 20:41:14 +02:00
|
|
|
|
"""Analyse une valeur (value) par rapport à la moyenne de value_list et à la dernière
|
2023-04-25 17:06:14 +02:00
|
|
|
|
valeur de value_list.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
value float valeur
|
|
|
|
|
value_list array<float> liste de valeurs
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
string
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
"""
|
|
|
|
|
result = ""
|
|
|
|
|
mean_value = mean(value_list)
|
|
|
|
|
|
|
|
|
|
if value > value_list[-1]:
|
|
|
|
|
result += "+"
|
|
|
|
|
elif value < value_list[-1]:
|
|
|
|
|
result += "-"
|
|
|
|
|
else:
|
|
|
|
|
result += "="
|
|
|
|
|
|
|
|
|
|
if value > mean_value:
|
|
|
|
|
result = "+" + result
|
|
|
|
|
elif value < mean_value:
|
|
|
|
|
result = "-" + result
|
|
|
|
|
else:
|
|
|
|
|
result = "=" + result
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
2023-06-19 20:41:14 +02:00
|
|
|
|
def __compute_curve_orientation(value, previous_value, previous_previous_value):
|
|
|
|
|
"""Analyse une valeur (value) par rapport à la moyenne de value_list et à la dernière
|
|
|
|
|
valeur de value_list.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
value float valeur
|
|
|
|
|
value_list array<float> liste de valeurs
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
string
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
"""
|
|
|
|
|
result = ""
|
|
|
|
|
|
|
|
|
|
if value > previous_value:
|
|
|
|
|
result += "+"
|
|
|
|
|
elif value < previous_value:
|
|
|
|
|
result += "-"
|
|
|
|
|
else:
|
|
|
|
|
result += "="
|
|
|
|
|
|
|
|
|
|
if previous_value > previous_previous_value:
|
|
|
|
|
result = "+" + result
|
|
|
|
|
elif previous_value < previous_previous_value:
|
|
|
|
|
result = "-" + result
|
|
|
|
|
else:
|
|
|
|
|
result = "=" + result
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
def __get_distinct_followup_season_for_gymnast(gymnast_id):
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""Recupère les saisons pour lesquelles le gymnastes à des followup.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
season_list = list(
|
|
|
|
|
gymnast.chronos.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
2023-07-06 23:37:07 +02:00
|
|
|
|
gymnast.injuries.values_list("season", flat=True)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.known_skills.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.todo.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
2023-07-05 10:51:49 +02:00
|
|
|
|
gymnast.wellbeings.values_list("season", flat=True)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.number_of_routine_done.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.height_weight.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.remarks.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
season_list += list(
|
|
|
|
|
gymnast.intensities.values_list("season", flat=True)
|
|
|
|
|
.distinct("season")
|
|
|
|
|
.order_by("season")
|
|
|
|
|
)
|
|
|
|
|
return list(dict.fromkeys(season_list))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __get_distinct_week_number_for_season_and_gymnast(gymnast_id, season):
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""Récupère les numéro de semaines pour lesquelles le gymnaste à des followup.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
season (int) Numéro de semaine
|
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
weeknumber_list = list(
|
|
|
|
|
gymnast.chronos.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
2023-07-06 23:37:07 +02:00
|
|
|
|
gymnast.injuries.values_list("week_number", flat=True)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.known_skills.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.todo.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
2023-07-05 10:51:49 +02:00
|
|
|
|
gymnast.wellbeings.values_list("week_number", flat=True)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.number_of_routine_done.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.height_weight.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.remarks.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
weeknumber_list += list(
|
|
|
|
|
gymnast.intensities.values_list("week_number", flat=True)
|
|
|
|
|
.filter(season=season)
|
|
|
|
|
.distinct("week_number")
|
|
|
|
|
.order_by("week_number")
|
|
|
|
|
)
|
|
|
|
|
return list(dict.fromkeys(weeknumber_list))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_distinct_week_number_for_season_and_gymnast(gymnast_id, season):
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
season (int) Numéro de semaine
|
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
if not season:
|
|
|
|
|
season = Season()
|
|
|
|
|
|
|
|
|
|
weeknumber_list = __get_distinct_week_number_for_season_and_gymnast(
|
|
|
|
|
gymnast_id, season
|
|
|
|
|
)
|
|
|
|
|
return JsonResponse(weeknumber_list, safe=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def report_choice(request, gymnast_id):
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""Recupère les saisons pour lesquelles le gymnastes à des followup.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
|
|
|
|
|
today = pendulum.now().date()
|
|
|
|
|
season, week_number = from_date_to_week_number(today)
|
|
|
|
|
|
|
|
|
|
season_list = __get_distinct_followup_season_for_gymnast(gymnast_id)
|
|
|
|
|
week_number_list = sorted(
|
|
|
|
|
__get_distinct_week_number_for_season_and_gymnast(gymnast_id, season)
|
|
|
|
|
)
|
|
|
|
|
context = {
|
|
|
|
|
"gymnast": gymnast,
|
|
|
|
|
"season": season,
|
|
|
|
|
"season_list": season_list,
|
|
|
|
|
"week_number": week_number,
|
|
|
|
|
"week_number_list": week_number_list,
|
|
|
|
|
}
|
|
|
|
|
return render(request, "gymnasts/report_choices.html", context)
|
|
|
|
|
|
|
|
|
|
|
2023-06-19 20:41:14 +02:00
|
|
|
|
def __mindstate_analyse(gymnast, date_begin, date_end, period, mindstate_score):
|
|
|
|
|
""" """
|
|
|
|
|
previous_period_date_end = date_begin
|
|
|
|
|
if period == "week":
|
|
|
|
|
period_length = 7
|
|
|
|
|
elif period == "month":
|
|
|
|
|
period_length = 30
|
|
|
|
|
else:
|
|
|
|
|
period_length = 365
|
|
|
|
|
|
|
|
|
|
previous_period_date_begin = previous_period_date_end.subtract(days=period_length)
|
2023-07-05 10:51:49 +02:00
|
|
|
|
previous_mindstate_score = gymnast.wellbeings.filter(
|
2023-06-19 20:41:14 +02:00
|
|
|
|
date__gte=previous_period_date_begin, date__lte=previous_period_date_end
|
2023-07-05 10:51:49 +02:00
|
|
|
|
).aggregate(mean_mindstate_value=Avg("mindstate"))
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
previous_previous_period_date_end = previous_period_date_begin
|
|
|
|
|
|
|
|
|
|
previous_previous_period_date_begin = previous_previous_period_date_end.subtract(
|
|
|
|
|
days=period_length
|
|
|
|
|
)
|
2023-07-05 10:51:49 +02:00
|
|
|
|
previous_previous_mindstate_score = gymnast.wellbeings.filter(
|
2023-06-19 20:41:14 +02:00
|
|
|
|
date__gte=previous_previous_period_date_begin,
|
|
|
|
|
date__lte=previous_previous_period_date_end,
|
2023-07-05 10:51:49 +02:00
|
|
|
|
).aggregate(mean_mindstate_value=Avg("mindstate"))
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
return __compute_curve_orientation(
|
|
|
|
|
mindstate_score,
|
|
|
|
|
previous_mindstate_score["mean_mindstate_value"],
|
|
|
|
|
previous_previous_mindstate_score["mean_mindstate_value"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __height_analyse(gymnast, date_begin, date_end, period, height_score):
|
|
|
|
|
""" """
|
|
|
|
|
previous_period_date_end = date_begin
|
|
|
|
|
if period == "week":
|
|
|
|
|
period_length = 7
|
|
|
|
|
elif period == "month":
|
|
|
|
|
period_length = 30
|
|
|
|
|
else:
|
|
|
|
|
period_length = 365
|
|
|
|
|
|
|
|
|
|
previous_period_date_begin = previous_period_date_end.subtract(days=period_length)
|
|
|
|
|
|
|
|
|
|
previous_height_score = gymnast.height_weight.filter(
|
|
|
|
|
date__gte=previous_period_date_begin, date__lte=previous_period_date_end
|
|
|
|
|
).aggregate(mean_height_value=Avg("height"))
|
|
|
|
|
|
|
|
|
|
previous_previous_period_date_end = previous_period_date_begin
|
|
|
|
|
|
|
|
|
|
previous_previous_period_date_begin = previous_previous_period_date_end.subtract(
|
|
|
|
|
days=period_length
|
|
|
|
|
)
|
|
|
|
|
previous_previous_height_score = gymnast.height_weight.filter(
|
|
|
|
|
date__gte=previous_previous_period_date_begin,
|
|
|
|
|
date__lte=previous_previous_period_date_end,
|
|
|
|
|
).aggregate(mean_height_value=Avg("height"))
|
|
|
|
|
|
|
|
|
|
return __compute_curve_orientation(
|
|
|
|
|
height_score,
|
|
|
|
|
previous_height_score["mean_height_value"],
|
|
|
|
|
previous_previous_height_score["mean_height_value"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __weight_analyse(gymnast, date_begin, date_end, period, weight_score):
|
|
|
|
|
""" """
|
|
|
|
|
previous_period_date_end = date_begin
|
|
|
|
|
if period == "week":
|
|
|
|
|
period_length = 7
|
|
|
|
|
elif period == "month":
|
|
|
|
|
period_length = 30
|
|
|
|
|
else:
|
|
|
|
|
period_length = 365
|
|
|
|
|
|
|
|
|
|
previous_period_date_begin = previous_period_date_end.subtract(days=period_length)
|
|
|
|
|
|
|
|
|
|
previous_height_score = gymnast.height_weight.filter(
|
|
|
|
|
date__gte=previous_period_date_begin, date__lte=previous_period_date_end
|
|
|
|
|
).aggregate(mean_weight_value=Avg("weight"))
|
|
|
|
|
|
|
|
|
|
previous_previous_period_date_end = previous_period_date_begin
|
|
|
|
|
|
|
|
|
|
previous_previous_period_date_begin = previous_previous_period_date_end.subtract(
|
|
|
|
|
days=period_length
|
|
|
|
|
)
|
|
|
|
|
previous_previous_height_score = gymnast.height_weight.filter(
|
|
|
|
|
date__gte=previous_previous_period_date_begin,
|
|
|
|
|
date__lte=previous_previous_period_date_end,
|
|
|
|
|
).aggregate(mean_weight_value=Avg("weight"))
|
|
|
|
|
|
|
|
|
|
return __compute_curve_orientation(
|
|
|
|
|
weight_score,
|
|
|
|
|
previous_height_score["mean_weight_value"],
|
|
|
|
|
previous_previous_height_score["mean_weight_value"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
2023-06-19 20:41:14 +02:00
|
|
|
|
def generate_report_for_period(
|
|
|
|
|
request, gymnast_id, season, period_value, date_begin, date_end, period="week"
|
|
|
|
|
):
|
|
|
|
|
"""Génère un rapport de toutes les informations entre les deux dates passées en paramètre.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
|
|
Args:
|
2023-06-19 20:41:14 +02:00
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
date_begin (datetime) Date de début de la période à considérer # pendulum
|
|
|
|
|
date_end (datetime) Date de fin de la période à considérer # pendulum
|
2023-05-14 19:10:34 +02:00
|
|
|
|
"""
|
2023-06-19 20:41:14 +02:00
|
|
|
|
today = pendulum.now().date()
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
season_informations = gymnast.season_informations.filter(season=season).first()
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
# PHYSIOLOGICAL INFORMATIONS
|
2023-07-05 12:27:23 +02:00
|
|
|
|
# WellBeing Score
|
|
|
|
|
wellbeing_score = gymnast.wellbeings.filter(
|
2023-06-19 20:41:14 +02:00
|
|
|
|
date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
2023-07-05 10:51:49 +02:00
|
|
|
|
min_mindstate_value=Min("mindstate"),
|
|
|
|
|
mean_mindstate_value=Avg("mindstate"),
|
|
|
|
|
max_mindstate_value=Max("mindstate"),
|
2023-07-05 12:27:23 +02:00
|
|
|
|
min_sleep_value=Min("sleep"),
|
|
|
|
|
mean_sleep_value=Avg("sleep"),
|
|
|
|
|
max_sleep_value=Max("sleep"),
|
|
|
|
|
min_stress_value=Min("stress"),
|
|
|
|
|
mean_stress_value=Avg("stress"),
|
|
|
|
|
max_stress_value=Max("stress"),
|
|
|
|
|
min_fatigue_value=Min("fatigue"),
|
|
|
|
|
mean_fatigue_value=Avg("fatigue"),
|
|
|
|
|
max_fatigue_value=Max("fatigue"),
|
|
|
|
|
min_muscle_soreness_value=Min("muscle_soreness"),
|
|
|
|
|
mean_muscle_soreness_value=Avg("muscle_soreness"),
|
|
|
|
|
max_muscle_soreness_value=Max("muscle_soreness"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-19 20:41:14 +02:00
|
|
|
|
height_weight_value = gymnast.height_weight.filter(
|
|
|
|
|
date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_height_value=Min("height"),
|
|
|
|
|
mean_height_value=Avg("height"),
|
|
|
|
|
max_height_value=Max("height"),
|
|
|
|
|
min_weight_value=Min("weight"),
|
|
|
|
|
mean_weight_value=Avg("weight"),
|
|
|
|
|
max_weight_value=Max("weight"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-19 20:41:14 +02:00
|
|
|
|
intensity_value = gymnast.intensities.filter(
|
|
|
|
|
date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
mean_intensity_time_value=Avg("time"),
|
|
|
|
|
mean_intensity_difficulty_value=Avg("difficulty"),
|
|
|
|
|
mean_quantity_of_skill_value=Avg("quantity_of_skill"),
|
|
|
|
|
mean_number_of_passes_value=Avg("number_of_passes"),
|
|
|
|
|
min_intensity_time_value=Min("time"),
|
|
|
|
|
min_intensity_difficulty_value=Min("difficulty"),
|
|
|
|
|
min_quantity_of_skill_value=Min("quantity_of_skill"),
|
|
|
|
|
min_number_of_passes_value=Min("number_of_passes"),
|
|
|
|
|
max_intensity_time_value=Max("time"),
|
|
|
|
|
max_intensity_difficulty_value=Max("difficulty"),
|
|
|
|
|
max_quantity_of_skill_value=Max("quantity_of_skill"),
|
|
|
|
|
max_number_of_passes_value=Max("number_of_passes"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
# BEST TOF
|
2023-06-19 20:41:14 +02:00
|
|
|
|
number_of_tof_straightjump = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=0
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_straightjump = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=0
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
number_of_tof_q1r1 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=1
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_q1r1 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=1
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
number_of_tof_q1r2 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=2
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_q1r2 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=2
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
number_of_tof_q2r1 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_q2r1 = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
number_of_tof_sf = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_sf = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
number_of_tof_f = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).count()
|
|
|
|
|
best_tof_f = Chrono.objects.filter(
|
|
|
|
|
gymnast=gymnast, date__gte=date_begin, date__lte=date_end, chrono_type=3
|
|
|
|
|
).aggregate(
|
|
|
|
|
min_score=Min("score"),
|
|
|
|
|
min_tof=Min("tof"),
|
|
|
|
|
mean_score=Avg("score"),
|
|
|
|
|
mean_tof=Avg("tof"),
|
|
|
|
|
max_score=Max("score"),
|
|
|
|
|
max_tof=Max("tof"),
|
|
|
|
|
)
|
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
# BEST SCORES
|
|
|
|
|
best_point_routine_1 = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Point.objects.filter(
|
|
|
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=1
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.order_by("-total")
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
best_point_routine_2 = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Point.objects.filter(
|
|
|
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=2
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.order_by("-total")
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
best_point_routine_3 = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Point.objects.filter(
|
|
|
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=3
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.order_by("-total")
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
best_point_routine_4 = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Point.objects.filter(
|
|
|
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=4
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.order_by("-total")
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
best_point_routine_5 = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
Point.objects.filter(
|
|
|
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=5
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.order_by("-total")
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
# ROUTINES
|
2023-06-20 08:29:19 +02:00
|
|
|
|
q1r1 = (
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast.has_routine.filter(routine_type=1)
|
|
|
|
|
.filter(date_begin__lte=date_begin)
|
|
|
|
|
.filter(Q(date_end__gte=date_begin) | Q(date_end__isnull=True))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
routine_1_done_stat = gymnast.number_of_routine_done.filter(
|
|
|
|
|
routine_type=1, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
total_try=Sum("number_of_try"), total_succeeded=Sum("number_of_successes")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-20 08:29:19 +02:00
|
|
|
|
q1r2 = (
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast.has_routine.filter(routine_type=2)
|
|
|
|
|
.filter(date_begin__lte=date_begin)
|
|
|
|
|
.filter(Q(date_end__gte=date_begin) | Q(date_end__isnull=True))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
routine_2_done_stat = gymnast.number_of_routine_done.filter(
|
|
|
|
|
routine_type=2, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
total_try=Sum("number_of_try"), total_succeeded=Sum("number_of_successes")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-20 08:29:19 +02:00
|
|
|
|
q2r1 = (
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast.has_routine.filter(routine_type=3)
|
|
|
|
|
.filter(date_begin__lte=date_begin)
|
|
|
|
|
.filter(Q(date_end__gte=date_begin) | Q(date_end__isnull=True))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
routine_3_done_stat = gymnast.number_of_routine_done.filter(
|
|
|
|
|
routine_type=3, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
total_try=Sum("number_of_try"), total_succeeded=Sum("number_of_successes")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-20 08:29:19 +02:00
|
|
|
|
sfinal = (
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast.has_routine.filter(routine_type=4)
|
|
|
|
|
.filter(date_begin__lte=date_begin)
|
|
|
|
|
.filter(Q(date_end__gte=date_begin) | Q(date_end__isnull=True))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
routine_4_done_stat = gymnast.number_of_routine_done.filter(
|
|
|
|
|
routine_type=4, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
total_try=Sum("number_of_try"), total_succeeded=Sum("number_of_successes")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
|
|
|
|
|
2023-06-20 08:29:19 +02:00
|
|
|
|
final = (
|
2023-04-25 17:06:14 +02:00
|
|
|
|
gymnast.has_routine.filter(routine_type=5)
|
|
|
|
|
.filter(date_begin__lte=date_begin)
|
|
|
|
|
.filter(Q(date_end__gte=date_begin) | Q(date_end__isnull=True))
|
|
|
|
|
.first()
|
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
routine_5_done_stat = gymnast.number_of_routine_done.filter(
|
|
|
|
|
routine_type=5, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).aggregate(
|
|
|
|
|
total_try=Sum("number_of_try"), total_succeeded=Sum("number_of_successes")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
)
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
# LAST LEARNED SKILLS
|
2023-06-19 20:41:14 +02:00
|
|
|
|
learned_skills = LearnedSkill.objects.filter(
|
|
|
|
|
gymnast=gymnast.id, date__gte=date_begin, date__lte=date_end
|
|
|
|
|
).order_by("-date")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
# PLANNED SKILLS
|
|
|
|
|
plan_list = (
|
|
|
|
|
Plan.objects.filter(gymnast=gymnast, educative__in=(Skill.objects.all()))
|
|
|
|
|
.filter(Q(is_done=False) | Q(date__gte=date.today()))
|
2023-06-13 19:32:35 +02:00
|
|
|
|
.order_by("date")
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.distinct()[:6]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# NEXT EVENTS
|
|
|
|
|
next_event_list = Event.objects.filter(
|
2023-06-13 21:26:42 +02:00
|
|
|
|
gymnasts=gymnast, date_begin__gte=date_begin
|
2023-04-25 17:06:14 +02:00
|
|
|
|
).order_by("date_begin")[:5]
|
|
|
|
|
|
|
|
|
|
# NOTES
|
2023-06-19 20:41:14 +02:00
|
|
|
|
# begin_of_the_week = date_begin
|
|
|
|
|
# if date_begin.weekday() != 0:
|
|
|
|
|
# begin_of_the_week -= timedelta(date_begin.weekday())
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
notes = (
|
2023-06-19 20:41:14 +02:00
|
|
|
|
gymnast.remarks.filter(date__gte=date_begin, date__lte=date_end)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
.filter(status=1)
|
|
|
|
|
.order_by("date")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
context = {
|
2023-06-19 20:41:14 +02:00
|
|
|
|
# HEADER
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"SITE_TITLE": settings.SITE_TITLE,
|
|
|
|
|
"CLUB_NAME": settings.CLUB_NAME,
|
|
|
|
|
"ADDRESS": settings.ADDRESS,
|
|
|
|
|
"CITY": settings.CITY,
|
|
|
|
|
"ZIP": settings.ZIP,
|
|
|
|
|
"HEAD_COACH": settings.HEAD_COACH,
|
|
|
|
|
"MOBILE_PHONE": settings.MOBILE_PHONE,
|
|
|
|
|
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
|
|
|
|
|
"season": season,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
"date_begin": date_begin,
|
|
|
|
|
"date_end": date_end,
|
|
|
|
|
"period": period,
|
|
|
|
|
"period_value": period_value,
|
|
|
|
|
"today": today,
|
|
|
|
|
# GYMNAST INFORMATIONS
|
|
|
|
|
"gymnast": gymnast,
|
|
|
|
|
"season_informations": season_informations,
|
|
|
|
|
# MEDICAL INFORMATIONS
|
2023-07-05 12:27:23 +02:00
|
|
|
|
"wellbeing_score": wellbeing_score,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
"height_weight_value": height_weight_value,
|
|
|
|
|
# INTENSITY
|
|
|
|
|
"intensity_value": intensity_value,
|
|
|
|
|
# TOF
|
|
|
|
|
"number_of_tof_straightjump": number_of_tof_straightjump,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"best_tof_straightjump": best_tof_straightjump,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
"number_of_tof_q1r1": number_of_tof_q1r1,
|
|
|
|
|
"best_tof_q1r1": best_tof_q1r1,
|
|
|
|
|
"number_of_tof_q1r2": number_of_tof_q1r2,
|
|
|
|
|
"best_tof_q1r2": best_tof_q1r2,
|
|
|
|
|
"number_of_tof_q2r1": number_of_tof_q2r1,
|
|
|
|
|
"best_tof_q2r1": best_tof_q2r1,
|
|
|
|
|
"number_of_tof_sf": number_of_tof_sf,
|
|
|
|
|
"best_tof_sf": best_tof_sf,
|
|
|
|
|
"number_of_tof_f": number_of_tof_f,
|
|
|
|
|
"best_tof_f": best_tof_f,
|
|
|
|
|
# SCORES
|
|
|
|
|
"best_point_q1r1": best_point_routine_1,
|
|
|
|
|
"best_point_q1r2": best_point_routine_2,
|
|
|
|
|
"best_point_q2r1": best_point_routine_3,
|
|
|
|
|
"best_point_sf": best_point_routine_4,
|
|
|
|
|
"best_point_f": best_point_routine_5,
|
2023-06-20 08:29:19 +02:00
|
|
|
|
"q1r1": q1r1,
|
|
|
|
|
"q1r2": q1r2,
|
|
|
|
|
"q2r1": q2r1,
|
|
|
|
|
"sfinal": sfinal,
|
|
|
|
|
"final": final,
|
2023-06-19 20:41:14 +02:00
|
|
|
|
"q1r1_done_stat": routine_1_done_stat,
|
|
|
|
|
"q1r2_done_stat": routine_2_done_stat,
|
|
|
|
|
"q2r1_done_stat": routine_3_done_stat,
|
|
|
|
|
"sfinal_done_stat": routine_4_done_stat,
|
|
|
|
|
"final_done_stat": routine_5_done_stat,
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"LEARNING_STEP_CHOICES": LEARNING_STEP_CHOICES,
|
|
|
|
|
"learned_skills": learned_skills,
|
|
|
|
|
"plan_list": plan_list,
|
|
|
|
|
"next_event_list": next_event_list,
|
|
|
|
|
"notes": notes,
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-19 21:11:15 +02:00
|
|
|
|
# return render(request, "gymnasts/reports/report_periodical.html", context)
|
|
|
|
|
|
|
|
|
|
response = HttpResponse(content_type="application/pdf")
|
|
|
|
|
response[
|
|
|
|
|
"Content-Disposition"
|
|
|
|
|
] = f"attachment; filename={gymnast.last_name}_{gymnast.first_name}_{period}-report_{date_begin}_{date_end}.pdf"
|
|
|
|
|
|
|
|
|
|
html = render_to_string("gymnasts/reports/report_periodical.html", context)
|
|
|
|
|
|
|
|
|
|
# font_config = FontConfiguration()
|
|
|
|
|
HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
|
|
|
|
|
response,
|
|
|
|
|
stylesheets=[
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
|
|
|
|
|
],
|
|
|
|
|
) # , font_config=font_config)
|
|
|
|
|
return response
|
2023-06-19 20:41:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def generate_season_report(request, gymnast_id, season):
|
|
|
|
|
"""Génère un rapport pour une saison passée en paramètre.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant de gymnaste
|
|
|
|
|
season (str) saison
|
|
|
|
|
"""
|
|
|
|
|
date_begin, date_end = from_season_to_date(season)
|
|
|
|
|
|
|
|
|
|
return generate_report_for_period(
|
|
|
|
|
request,
|
|
|
|
|
gymnast_id,
|
|
|
|
|
season,
|
|
|
|
|
season,
|
|
|
|
|
date_begin,
|
|
|
|
|
date_end,
|
|
|
|
|
period="season",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def generate_month_report(request, gymnast_id, season, month_number):
|
|
|
|
|
"""Génère un rapport pour une saison et un mois passée en paramètre.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) identifiant de gymnaste
|
|
|
|
|
season (str) saison
|
|
|
|
|
month_number (int) mois de l'année
|
|
|
|
|
"""
|
|
|
|
|
date_begin, date_end = from_month_number_to_date(season, month_number)
|
|
|
|
|
month = date_begin.format("MMMM")
|
|
|
|
|
|
|
|
|
|
return generate_report_for_period(
|
|
|
|
|
request,
|
|
|
|
|
gymnast_id,
|
|
|
|
|
season,
|
|
|
|
|
month,
|
|
|
|
|
date_begin,
|
|
|
|
|
date_end,
|
|
|
|
|
period="month",
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
2023-06-19 20:41:14 +02:00
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def generate_week_report(request, gymnast_id, season, week_number):
|
|
|
|
|
"""Génère un rapport hebdomadaire.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
|
|
|
season (int) Numéro de semaine
|
|
|
|
|
week_number (int) Numéro de semaine
|
|
|
|
|
"""
|
|
|
|
|
date_begin, date_end = from_week_number_to_date(season, week_number)
|
|
|
|
|
|
|
|
|
|
return generate_report_for_period(
|
|
|
|
|
request,
|
|
|
|
|
gymnast_id,
|
|
|
|
|
season,
|
|
|
|
|
week_number,
|
|
|
|
|
date_begin,
|
|
|
|
|
date_end,
|
|
|
|
|
period="week",
|
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
|
def generate_timeline_report(
|
|
|
|
|
request, gymnast_id, season=None, week_number=None, date=None
|
|
|
|
|
):
|
|
|
|
|
"""Génère une timeline pour un gymnaste. On va chercher tous les
|
|
|
|
|
- records (Chrono/ToF),
|
|
|
|
|
- points (compétition),
|
|
|
|
|
- nouveau apprentissage (learned skill)
|
2023-07-06 23:37:07 +02:00
|
|
|
|
- blessures
|
2023-04-25 17:06:14 +02:00
|
|
|
|
- GymnastHasRoutine
|
|
|
|
|
eton les trie par date.
|
|
|
|
|
|
2023-05-14 19:10:34 +02:00
|
|
|
|
Args:
|
2023-06-19 20:41:14 +02:00
|
|
|
|
gymnast_id (int) identifiant du gymnast
|
|
|
|
|
season (int) saison
|
|
|
|
|
week_number (int) numéro de semaine
|
|
|
|
|
date (date) date
|
2023-04-25 17:06:14 +02:00
|
|
|
|
"""
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
|
|
|
|
|
if season is None:
|
|
|
|
|
date_begin = pendulum.now().date()
|
|
|
|
|
season, week_number = from_date_to_week_number(date_begin)
|
|
|
|
|
else:
|
|
|
|
|
date_begin, _ = from_week_number_to_date(season, week_number)
|
|
|
|
|
date_begin = date_begin.date()
|
|
|
|
|
|
|
|
|
|
selected_record = []
|
|
|
|
|
|
|
|
|
|
list_record_straightjumps = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=0).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_straightjumps:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
list_record_first_routine = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=1).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_first_routine:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
list_record_second_routine = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=2).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_second_routine:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
list_record_third_routine = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=3).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_third_routine:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
list_record_fourth_routine = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=4).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_fourth_routine:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
list_record_fifth_routine = list(
|
|
|
|
|
gymnast.chronos.filter(chrono_type=5).order_by("date")
|
|
|
|
|
)
|
|
|
|
|
last_top_score = 0
|
|
|
|
|
for record in list_record_fifth_routine:
|
|
|
|
|
if record.score > last_top_score:
|
|
|
|
|
last_top_score = record.score
|
|
|
|
|
selected_record.append(record)
|
|
|
|
|
|
|
|
|
|
# print(selected_record)
|
|
|
|
|
list_record = selected_record
|
2023-07-06 23:37:07 +02:00
|
|
|
|
list_record.extend(list(gymnast.injuries.all().order_by("date")))
|
2023-04-25 17:06:14 +02:00
|
|
|
|
# list_record.extend(list(gymnast.points.all().order_by("date")))
|
|
|
|
|
list_record.extend(list(gymnast.known_skills.all().order_by("date")))
|
|
|
|
|
|
|
|
|
|
# print(list_record)
|
|
|
|
|
sorted_records = sorted(list_record, key=lambda x: x.date)
|
|
|
|
|
# print(sorted_records)
|
|
|
|
|
context = {
|
|
|
|
|
"SITE_TITLE": settings.SITE_TITLE,
|
|
|
|
|
"CLUB_NAME": settings.CLUB_NAME,
|
|
|
|
|
"ADDRESS": settings.ADDRESS,
|
|
|
|
|
"CITY": settings.CITY,
|
|
|
|
|
"ZIP": settings.ZIP,
|
|
|
|
|
"HEAD_COACH": settings.HEAD_COACH,
|
|
|
|
|
"MOBILE_PHONE": settings.MOBILE_PHONE,
|
|
|
|
|
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
|
|
|
|
|
"week_number": week_number,
|
|
|
|
|
"gymnast": gymnast,
|
|
|
|
|
"today": date_begin,
|
|
|
|
|
"season": season,
|
|
|
|
|
"sorted_records": sorted_records,
|
|
|
|
|
}
|
|
|
|
|
# return render(request, "gymnasts/reports/report_timeline.html", context)
|
|
|
|
|
response = HttpResponse(content_type="application/pdf")
|
|
|
|
|
response[
|
|
|
|
|
"Content-Disposition"
|
|
|
|
|
] = "attachment; filename={lastname}-{firstname}-report-timeline.pdf".format(
|
|
|
|
|
lastname=gymnast.last_name,
|
|
|
|
|
firstname=gymnast.first_name,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
html = render_to_string("gymnasts/reports/report_timeline.html", context)
|
|
|
|
|
|
|
|
|
|
# font_config = FontConfiguration()
|
|
|
|
|
HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
|
|
|
|
|
response,
|
|
|
|
|
stylesheets=[
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
|
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
|
|
|
|
|
],
|
|
|
|
|
) # , font_config=font_config)
|
|
|
|
|
return response
|