1139 lines
38 KiB
Python
1139 lines
38 KiB
Python
from datetime import date
|
|
from statistics import mean
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth import get_user_model
|
|
|
|
from django.db.models import (
|
|
Q,
|
|
Avg,
|
|
Sum,
|
|
Min,
|
|
Max,
|
|
)
|
|
from django.http import HttpResponse, JsonResponse
|
|
from django.shortcuts import render, get_object_or_404
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.template.loader import render_to_string
|
|
from django.conf import settings
|
|
|
|
from weasyprint import HTML, CSS
|
|
|
|
# from weasyprint.fonts import FontConfiguration
|
|
|
|
import pendulum
|
|
|
|
from jarvis.followup.models import Event
|
|
from jarvis.followup.models import (
|
|
Plan,
|
|
Skill,
|
|
Point,
|
|
Chrono,
|
|
LearnedSkill,
|
|
)
|
|
|
|
from jarvis.followup.models import LEARNING_STEP_CHOICES
|
|
|
|
from jarvis.followup.views_physiological import get_wellbeing_stats_for_season_week
|
|
from jarvis.followup.views_intensity import get_intensity_stats_for_season_week
|
|
|
|
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,
|
|
from_month_number_to_date,
|
|
from_season_to_date,
|
|
)
|
|
|
|
from .models import Gymnast
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
def __get_distinct_followup_season_for_gymnast(gymnast_id):
|
|
"""Recupère les saisons pour lesquelles le gymnastes à des followup.
|
|
|
|
Args:
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
"""
|
|
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(
|
|
gymnast.injuries.values_list("season", flat=True)
|
|
.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(
|
|
gymnast.wellbeings.values_list("season", flat=True)
|
|
.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")
|
|
)
|
|
|
|
season_list = list(dict.fromkeys(season_list))
|
|
season_list.sort()
|
|
return season_list
|
|
|
|
|
|
def __get_distinct_week_number_for_season_and_gymnast(gymnast_id, season):
|
|
"""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
|
|
"""
|
|
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(
|
|
gymnast.injuries.values_list("week_number", flat=True)
|
|
.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(
|
|
gymnast.wellbeings.values_list("week_number", flat=True)
|
|
.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")
|
|
)
|
|
|
|
weeknumber_list = list(dict.fromkeys(weeknumber_list))
|
|
weeknumber_list.sort(reverse=True)
|
|
return weeknumber_list
|
|
|
|
|
|
def get_distinct_week_number_for_season_and_gymnast(gymnast_id, season=None):
|
|
"""
|
|
|
|
Args:
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
season (int) Numéro de semaine
|
|
"""
|
|
if not season:
|
|
season = Season()
|
|
|
|
weeknumber_list = __get_distinct_week_number_for_season_and_gymnast(
|
|
gymnast_id, season
|
|
)
|
|
return JsonResponse(weeknumber_list, safe=False)
|
|
|
|
|
|
@login_required
|
|
@require_http_methods(["GET"])
|
|
def report_choice(request, gymnast_id):
|
|
"""Recupère les saisons pour lesquelles le gymnastes à des followup.
|
|
|
|
Args:
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
"""
|
|
today = pendulum.now().date()
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
season, week_number = from_date_to_week_number(today)
|
|
season_list = __get_distinct_followup_season_for_gymnast(gymnast_id)
|
|
week_number_list = __get_distinct_week_number_for_season_and_gymnast(
|
|
gymnast_id, season
|
|
)
|
|
|
|
context = {
|
|
"gymnast": gymnast,
|
|
"actual_season": season,
|
|
"season_list": season_list,
|
|
"actual_week_number": week_number,
|
|
"week_number_list": week_number_list,
|
|
}
|
|
|
|
# return render(request, "gymnasts/report_choices.html", context)
|
|
return render(request, "gymnasts/tabs/tab_documents.html", context)
|
|
|
|
|
|
def analyse_score(value, value_list):
|
|
"""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 = ""
|
|
average_value = mean(value_list)
|
|
|
|
if value > value_list[-1]:
|
|
result += "+"
|
|
elif value < value_list[-1]:
|
|
result += "-"
|
|
else:
|
|
result += "="
|
|
|
|
if value > average_value:
|
|
result = "+" + result
|
|
elif value < average_value:
|
|
result = "-" + result
|
|
else:
|
|
result = "=" + result
|
|
|
|
return result
|
|
|
|
|
|
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
|
|
|
|
|
|
def __mindstate_analyse(gymnast, date_begin, date_end, period, mindstate_score):
|
|
"""Analyse de l'état d'esprit entre deux dates."""
|
|
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_mindstate_score = gymnast.wellbeings.filter(
|
|
date__gte=previous_period_date_begin, date__lte=previous_period_date_end
|
|
).aggregate(average_mindstate_value=Avg("mindstate"))
|
|
|
|
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_mindstate_score = gymnast.wellbeings.filter(
|
|
date__gte=previous_previous_period_date_begin,
|
|
date__lte=previous_previous_period_date_end,
|
|
).aggregate(average_mindstate_value=Avg("mindstate"))
|
|
|
|
return __compute_curve_orientation(
|
|
mindstate_score,
|
|
previous_mindstate_score["average_mindstate_value"],
|
|
previous_previous_mindstate_score["average_mindstate_value"],
|
|
)
|
|
|
|
|
|
def __height_analyse(gymnast, date_begin, date_end, period, height_score):
|
|
"""Analyse de la taille du gymnaste entre deux dates."""
|
|
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(average_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(average_height_value=Avg("height"))
|
|
|
|
return __compute_curve_orientation(
|
|
height_score,
|
|
previous_height_score["average_height_value"],
|
|
previous_previous_height_score["average_height_value"],
|
|
)
|
|
|
|
|
|
def __weight_analyse(gymnast, date_begin, date_end, period, weight_score):
|
|
"""Analyse du poids du gymnaste entre deux dates."""
|
|
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(average_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(average_weight_value=Avg("weight"))
|
|
|
|
return __compute_curve_orientation(
|
|
weight_score,
|
|
previous_height_score["average_weight_value"],
|
|
previous_previous_height_score["average_weight_value"],
|
|
)
|
|
|
|
|
|
@login_required
|
|
@require_http_methods(["GET"])
|
|
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.
|
|
|
|
Args:
|
|
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
|
|
"""
|
|
today = pendulum.now().date()
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
season_informations = gymnast.season_informations.filter(season=season).first()
|
|
|
|
# PHYSIOLOGICAL INFORMATIONS
|
|
# WellBeing Score
|
|
wellbeing_score_quantity = gymnast.wellbeings.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).count()
|
|
wellbeing_score = gymnast.wellbeings.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).aggregate(
|
|
min_mindstate_value=Min("mindstate"),
|
|
average_mindstate_value=Avg("mindstate"),
|
|
max_mindstate_value=Max("mindstate"),
|
|
min_sleep_value=Min("sleep"),
|
|
average_sleep_value=Avg("sleep"),
|
|
max_sleep_value=Max("sleep"),
|
|
min_stress_value=Min("stress"),
|
|
average_stress_value=Avg("stress"),
|
|
max_stress_value=Max("stress"),
|
|
min_fatigue_value=Min("fatigue"),
|
|
average_fatigue_value=Avg("fatigue"),
|
|
max_fatigue_value=Max("fatigue"),
|
|
min_muscle_soreness_value=Min("muscle_soreness"),
|
|
average_muscle_soreness_value=Avg("muscle_soreness"),
|
|
max_muscle_soreness_value=Max("muscle_soreness"),
|
|
)
|
|
|
|
height_weight_quantity = gymnast.height_weight.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).count()
|
|
height_weight_value = gymnast.height_weight.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).aggregate(
|
|
min_height_value=Min("height"),
|
|
average_height_value=Avg("height"),
|
|
max_height_value=Max("height"),
|
|
min_weight_value=Min("weight"),
|
|
average_weight_value=Avg("weight"),
|
|
max_weight_value=Max("weight"),
|
|
)
|
|
|
|
intensity_quantity = gymnast.intensities.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).count()
|
|
intensity_value = gymnast.intensities.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).aggregate(
|
|
average_intensity_time_value=Avg("time"),
|
|
average_intensity_difficulty_value=Avg("difficulty"),
|
|
average_quantity_of_skill_value=Avg("quantity_of_skill"),
|
|
average_number_of_passes_value=Avg("number_of_passes"),
|
|
average_time_quality=Avg("time_quality"),
|
|
average_difficulty_quality=Avg("difficulty_quality"),
|
|
average_quantity_of_skill_quality=Avg("quantity_of_skill_quality"),
|
|
average_number_of_passes_quality=Avg("number_of_passes_quality"),
|
|
average_average_training_quality=Avg("average_training_quality"),
|
|
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"),
|
|
min_time_quality=Min("time_quality"),
|
|
min_difficulty_quality=Min("difficulty_quality"),
|
|
min_quantity_of_skill_quality=Min("quantity_of_skill_quality"),
|
|
min_number_of_passes_quality=Min("number_of_passes_quality"),
|
|
min_average_training_quality=Min("average_training_quality"),
|
|
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"),
|
|
max_time_quality=Max("time_quality"),
|
|
max_difficulty_quality=Max("difficulty_quality"),
|
|
max_quantity_of_skill_quality=Max("quantity_of_skill_quality"),
|
|
max_number_of_passes_quality=Max("number_of_passes_quality"),
|
|
max_average_training_quality=Max("average_training_quality"),
|
|
)
|
|
|
|
injury_list = gymnast.injuries.filter(
|
|
date__gte=date_begin, date__lte=date_end
|
|
).order_by("date")
|
|
|
|
# BEST TOF
|
|
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"),
|
|
average_score=Avg("score"),
|
|
average_tof=Avg("tof"),
|
|
max_score=Max("score"),
|
|
max_tof=Max("tof"),
|
|
)
|
|
|
|
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"),
|
|
average_score=Avg("score"),
|
|
average_tof=Avg("tof"),
|
|
max_score=Max("score"),
|
|
max_tof=Max("tof"),
|
|
)
|
|
|
|
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"),
|
|
average_score=Avg("score"),
|
|
average_tof=Avg("tof"),
|
|
max_score=Max("score"),
|
|
max_tof=Max("tof"),
|
|
)
|
|
|
|
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"),
|
|
average_score=Avg("score"),
|
|
average_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"),
|
|
average_score=Avg("score"),
|
|
average_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"),
|
|
average_score=Avg("score"),
|
|
average_tof=Avg("tof"),
|
|
max_score=Max("score"),
|
|
max_tof=Max("tof"),
|
|
)
|
|
|
|
# BEST SCORES
|
|
best_point_routine_1 = (
|
|
Point.objects.filter(
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=1
|
|
)
|
|
.order_by("-total")
|
|
.first()
|
|
)
|
|
best_point_routine_2 = (
|
|
Point.objects.filter(
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=2
|
|
)
|
|
.order_by("-total")
|
|
.first()
|
|
)
|
|
best_point_routine_3 = (
|
|
Point.objects.filter(
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=3
|
|
)
|
|
.order_by("-total")
|
|
.first()
|
|
)
|
|
best_point_routine_4 = (
|
|
Point.objects.filter(
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=4
|
|
)
|
|
.order_by("-total")
|
|
.first()
|
|
)
|
|
best_point_routine_5 = (
|
|
Point.objects.filter(
|
|
gymnast=gymnast, event__date_begin__lte=date_begin, routine_type=5
|
|
)
|
|
.order_by("-total")
|
|
.first()
|
|
)
|
|
# ROUTINES
|
|
q1r1 = (
|
|
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()
|
|
)
|
|
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")
|
|
)
|
|
|
|
q1r2 = (
|
|
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()
|
|
)
|
|
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")
|
|
)
|
|
|
|
q2r1 = (
|
|
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()
|
|
)
|
|
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")
|
|
)
|
|
|
|
sfinal = (
|
|
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()
|
|
)
|
|
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")
|
|
)
|
|
|
|
final = (
|
|
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()
|
|
)
|
|
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")
|
|
)
|
|
|
|
# LAST LEARNED SKILLS
|
|
learned_skills = LearnedSkill.objects.filter(
|
|
gymnast=gymnast.id, date__gte=date_begin, date__lte=date_end
|
|
).order_by("-date")
|
|
|
|
# PLANNED SKILLS
|
|
plan_list = (
|
|
Plan.objects.filter(gymnast=gymnast, educative__in=Skill.objects.all())
|
|
.filter(Q(is_done=False) | Q(date__gte=date.today()))
|
|
.order_by("date")
|
|
.distinct()[:6]
|
|
)
|
|
|
|
# NEXT EVENTS
|
|
next_event_list = Event.objects.filter(
|
|
gymnasts=gymnast, date_begin__gte=date_begin
|
|
).order_by("date_begin")[:5]
|
|
|
|
# NOTES
|
|
# begin_of_the_week = date_begin
|
|
# if date_begin.weekday() != 0:
|
|
# begin_of_the_week -= timedelta(date_begin.weekday())
|
|
|
|
notes = (
|
|
gymnast.remarks.filter(date__gte=date_begin, date__lte=date_end)
|
|
.filter(status=1)
|
|
.order_by("date")
|
|
)
|
|
|
|
context = {
|
|
# HEADER
|
|
"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,
|
|
"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
|
|
"wellbeing_score_quantity": wellbeing_score_quantity,
|
|
"wellbeing_score": wellbeing_score,
|
|
"height_weight_value": height_weight_value,
|
|
"injury_list": injury_list,
|
|
# INTENSITY
|
|
"intensity_quantity": intensity_quantity,
|
|
"intensity_value": intensity_value,
|
|
# TOF
|
|
"number_of_tof_straightjump": number_of_tof_straightjump,
|
|
"best_tof_straightjump": best_tof_straightjump,
|
|
"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,
|
|
"q1r1": q1r1,
|
|
"q1r2": q1r2,
|
|
"q2r1": q2r1,
|
|
"sfinal": sfinal,
|
|
"final": final,
|
|
"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,
|
|
"LEARNING_STEP_CHOICES": LEARNING_STEP_CHOICES,
|
|
"learned_skills": learned_skills,
|
|
"plan_list": plan_list,
|
|
"next_event_list": next_event_list,
|
|
"notes": notes,
|
|
}
|
|
|
|
# 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" # pylint: disable=line-too-long
|
|
|
|
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/a4_paper.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 generate_report_week_comparison(
|
|
request, gymnast_id, season_source, week_source, season_target, week_target
|
|
):
|
|
"""Génère un rapport avec une comparaison de deux semaines entre elles.
|
|
|
|
Args:
|
|
gymnast_id (int) Identifiant de la classe Gymnast
|
|
season_source (str) saison de comparaison
|
|
week_source (int) semaine de comparaison
|
|
season_target (str) saison comparée
|
|
week_target (int) semaine comparée
|
|
"""
|
|
today = pendulum.now().date()
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
# season_informations = gymnast.season_informations.filter(season=season).first()
|
|
|
|
# PHYSIOLOGICAL INFORMATIONS
|
|
# WellBeing Score
|
|
source_wellbeing_score_quantity = gymnast.wellbeings.filter(
|
|
season=season_source, week_number=week_source
|
|
).count()
|
|
source_wellbeing_score = get_wellbeing_stats_for_season_week(
|
|
gymnast_id, season_source, week_source
|
|
)
|
|
target_wellbeing_score_quantity = gymnast.wellbeings.filter(
|
|
season=season_target, week_number=week_target
|
|
).count()
|
|
target_wellbeing_score = get_wellbeing_stats_for_season_week(
|
|
gymnast_id, season_target, week_target
|
|
)
|
|
|
|
# Intensity Score
|
|
source_intensity_quantity = gymnast.intensities.filter(
|
|
season=season_source, week_number=week_source
|
|
).count()
|
|
source_intensity_value = get_intensity_stats_for_season_week(
|
|
gymnast_id, season_source, week_source
|
|
)
|
|
target_intensity_quantity = gymnast.intensities.filter(
|
|
season=season_target, week_number=week_target
|
|
).count()
|
|
target_intensity_value = get_intensity_stats_for_season_week(
|
|
gymnast_id, season_target, week_target
|
|
)
|
|
|
|
context = {
|
|
# HEADER
|
|
"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,
|
|
# "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
|
|
"source_wellbeing_score_quantity": source_wellbeing_score_quantity,
|
|
"source_wellbeing_score": source_wellbeing_score,
|
|
"target_wellbeing_score_quantity": target_wellbeing_score_quantity,
|
|
"target_wellbeing_score": target_wellbeing_score,
|
|
# "height_weight_value": height_weight_value,
|
|
# "injury_list": injury_list,
|
|
# # INTENSITY
|
|
"source_intensity_quantity": source_intensity_quantity,
|
|
"source_intensity_value": source_intensity_value,
|
|
"target_intensity_quantity": target_intensity_quantity,
|
|
"target_intensity_value": target_intensity_value,
|
|
# # TOF
|
|
# "number_of_tof_straightjump": number_of_tof_straightjump,
|
|
# "best_tof_straightjump": best_tof_straightjump,
|
|
# "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,
|
|
# "q1r1": q1r1,
|
|
# "q1r2": q1r2,
|
|
# "q2r1": q2r1,
|
|
# "sfinal": sfinal,
|
|
# "final": final,
|
|
# "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,
|
|
# "LEARNING_STEP_CHOICES": LEARNING_STEP_CHOICES,
|
|
# "learned_skills": learned_skills,
|
|
# "plan_list": plan_list,
|
|
# "next_event_list": next_event_list,
|
|
# "notes": notes,
|
|
}
|
|
|
|
return render(request, "gymnasts/reports/report_week_comparison.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" # pylint: disable=line-too-long
|
|
|
|
# html = render_to_string("gymnasts/reports/report_week_comparison.html", context)
|
|
|
|
# # font_config = FontConfiguration()
|
|
# HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
|
|
# response,
|
|
# stylesheets=[
|
|
# CSS(settings.STATICFILES_DIRS[0] + "/css/a4_paper.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 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",
|
|
)
|
|
|
|
|
|
@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",
|
|
)
|
|
|
|
|
|
@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)
|
|
- blessures
|
|
- GymnastHasRoutine
|
|
et on les trie par date.
|
|
|
|
Args:
|
|
gymnast_id (int) identifiant du gymnast
|
|
season (int) saison
|
|
week_number (int) numéro de semaine
|
|
date (date) date
|
|
"""
|
|
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
|
|
list_record.extend(list(gymnast.injuries.all().order_by("date")))
|
|
# 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/a4_paper.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 generate_week_resume(request, gymnast_id, season=None, week_number=None):
|
|
# """va rechercher les informations nécessaires pour aider à la note de la semaine
|
|
# - wellbeing
|
|
# - intensity
|
|
# - injury
|
|
|
|
# Args:
|
|
# gymnast_id (int) identifiant du gymnast
|
|
# season (int) saison
|
|
# week_number (int) numéro de semaine
|
|
# date (date) date
|
|
# """
|
|
# 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()
|
|
|
|
# wellbeing_list = gymnast.wellbeing.objects.filter(season="season", week_number="week_number")
|
|
# intensity_list = gymnast.intensities.objects.filter(season="season", week_number="week_number") # pylint: disable=line-too-long
|
|
# injury_list = gymnast.injuries.filter(season="season", week_number="week_number")
|