feat(class): improve class/id
This commit is contained in:
@@ -35,8 +35,12 @@ from schemas.class_group import (
|
||||
HistogramBin,
|
||||
DomainStats,
|
||||
CompetenceStats,
|
||||
AssessmentScore,
|
||||
DomainStudentStats,
|
||||
CompetenceStudentStats,
|
||||
)
|
||||
from domain.services.grading_calculator import GradingCalculator
|
||||
from domain.services.class_statistics_service import ClassStatisticsService
|
||||
from schemas.student import StudentWithClass, StudentList
|
||||
from schemas.csv_import import (
|
||||
CSVImportResponse,
|
||||
@@ -221,10 +225,10 @@ async def get_class_stats(
|
||||
Récupère les statistiques complètes d'une classe pour un trimestre.
|
||||
|
||||
Inclut:
|
||||
- Moyennes par élève
|
||||
- Moyennes par élève avec détail par évaluation
|
||||
- Statistiques globales (moyenne, médiane, écart-type)
|
||||
- Histogramme des moyennes
|
||||
- Analyse par domaines et compétences
|
||||
- Analyse par domaines et compétences (nombre d'évaluations + points)
|
||||
"""
|
||||
# Vérifier que la classe existe
|
||||
class_query = select(ClassGroup).where(ClassGroup.id == class_id)
|
||||
@@ -247,26 +251,34 @@ async def get_class_stats(
|
||||
students_result = await session.execute(students_query)
|
||||
students = students_result.scalars().all()
|
||||
|
||||
# Récupérer les évaluations du trimestre
|
||||
assessments_query = select(Assessment).where(
|
||||
Assessment.class_group_id == class_id,
|
||||
Assessment.trimester == trimester
|
||||
# Récupérer les évaluations du trimestre avec leurs relations
|
||||
assessments_query = (
|
||||
select(Assessment)
|
||||
.options(
|
||||
selectinload(Assessment.exercises).selectinload(Exercise.grading_elements)
|
||||
)
|
||||
.where(
|
||||
Assessment.class_group_id == class_id,
|
||||
Assessment.trimester == trimester
|
||||
)
|
||||
.order_by(Assessment.date)
|
||||
)
|
||||
assessments_result = await session.execute(assessments_query)
|
||||
assessments = assessments_result.scalars().all()
|
||||
|
||||
# Calculer les moyennes de chaque élève
|
||||
calculator = GradingCalculator()
|
||||
student_averages = []
|
||||
all_averages = []
|
||||
# Récupérer les domaines et compétences
|
||||
domains_query = select(Domain).order_by(Domain.name)
|
||||
domains_result = await session.execute(domains_query)
|
||||
domains = domains_result.scalars().all()
|
||||
|
||||
competences_query = select(Competence).order_by(Competence.order_index)
|
||||
competences_result = await session.execute(competences_query)
|
||||
competences = competences_result.scalars().all()
|
||||
|
||||
# Récupérer toutes les notes en une seule requête pour optimiser
|
||||
grades_by_student_assessment = {}
|
||||
for student in students:
|
||||
weighted_sum = 0.0
|
||||
total_coefficient = 0.0
|
||||
assessment_count = 0
|
||||
|
||||
for assessment in assessments:
|
||||
# Récupérer les notes de l'élève pour cette évaluation
|
||||
grades_query = (
|
||||
select(Grade, GradingElement)
|
||||
.join(GradingElement, Grade.grading_element_id == GradingElement.id)
|
||||
@@ -277,45 +289,30 @@ async def get_class_stats(
|
||||
)
|
||||
)
|
||||
grades_result = await session.execute(grades_query)
|
||||
grades_data = grades_result.all()
|
||||
grades_by_student_assessment[(student.id, assessment.id)] = grades_result.all()
|
||||
|
||||
if grades_data:
|
||||
total_score = 0.0
|
||||
total_max_points = 0.0
|
||||
# Utiliser le service pour calculer les statistiques
|
||||
stats_service = ClassStatisticsService()
|
||||
student_averages = await stats_service.calculate_student_statistics(
|
||||
students=students,
|
||||
assessments=assessments,
|
||||
grades_by_student_assessment=grades_by_student_assessment,
|
||||
domains=domains,
|
||||
competences=competences,
|
||||
)
|
||||
|
||||
for grade, element in grades_data:
|
||||
if grade.value:
|
||||
score = calculator.calculate_score(
|
||||
grade.value, element.grading_type, element.max_points
|
||||
)
|
||||
if score is not None and calculator.is_counted_in_total(grade.value):
|
||||
total_score += score
|
||||
total_max_points += element.max_points
|
||||
|
||||
if total_max_points > 0:
|
||||
# Ramener sur 20
|
||||
score_on_20 = total_score / total_max_points * 20
|
||||
weighted_sum += score_on_20 * assessment.coefficient
|
||||
total_coefficient += assessment.coefficient
|
||||
assessment_count += 1
|
||||
|
||||
# Calculer la moyenne pondérée
|
||||
average = None
|
||||
if total_coefficient > 0:
|
||||
average = round(weighted_sum / total_coefficient, 2)
|
||||
all_averages.append(average)
|
||||
|
||||
student_averages.append(StudentAverage(
|
||||
student_id=student.id,
|
||||
first_name=student.first_name,
|
||||
last_name=student.last_name,
|
||||
full_name=f"{student.first_name} {student.last_name}",
|
||||
average=average,
|
||||
assessment_count=assessment_count
|
||||
))
|
||||
# Calculer les statistiques domaines/compétences depuis les éléments de notation
|
||||
# Perspective enseignant : ce qui a été évalué, pas les résultats des élèves
|
||||
domains_stats, competences_stats = stats_service.calculate_domain_competence_from_elements(
|
||||
assessments=assessments,
|
||||
domains=domains,
|
||||
competences=competences,
|
||||
)
|
||||
|
||||
# Calculer les statistiques globales
|
||||
all_averages = [s.average for s in student_averages if s.average is not None]
|
||||
mean = median = std_dev = min_score = max_score = None
|
||||
|
||||
if all_averages:
|
||||
mean = round(sum(all_averages) / len(all_averages), 2)
|
||||
sorted_averages = sorted(all_averages)
|
||||
@@ -345,9 +342,10 @@ async def get_class_stats(
|
||||
count=count
|
||||
))
|
||||
# Ajouter le dernier bin pour 20
|
||||
count_20 = sum(1 for avg in all_averages if avg == 20)
|
||||
if count_20 > 0:
|
||||
histogram[-1].count += count_20
|
||||
if histogram:
|
||||
count_20 = sum(1 for avg in all_averages if avg == 20)
|
||||
if count_20 > 0:
|
||||
histogram[-1].count += count_20
|
||||
|
||||
# Compter les évaluations par statut
|
||||
assessments_completed = 0
|
||||
@@ -379,36 +377,6 @@ async def get_class_stats(
|
||||
elif grades_count > 0:
|
||||
assessments_in_progress += 1
|
||||
|
||||
# Statistiques par domaine et compétence (simplifié)
|
||||
domains_stats = []
|
||||
competences_stats = []
|
||||
|
||||
# Récupérer les domaines
|
||||
domains_query = select(Domain).order_by(Domain.name)
|
||||
domains_result = await session.execute(domains_query)
|
||||
domains = domains_result.scalars().all()
|
||||
for domain in domains:
|
||||
domains_stats.append(DomainStats(
|
||||
id=domain.id,
|
||||
name=domain.name,
|
||||
color=domain.color,
|
||||
mean=None,
|
||||
elements_count=0
|
||||
))
|
||||
|
||||
# Récupérer les compétences
|
||||
competences_query = select(Competence).order_by(Competence.order_index)
|
||||
competences_result = await session.execute(competences_query)
|
||||
competences = competences_result.scalars().all()
|
||||
for competence in competences:
|
||||
competences_stats.append(CompetenceStats(
|
||||
id=competence.id,
|
||||
name=competence.name,
|
||||
color=competence.color,
|
||||
mean=None,
|
||||
elements_count=0
|
||||
))
|
||||
|
||||
return ClassDashboardStats(
|
||||
class_id=class_id,
|
||||
class_name=cls.name,
|
||||
|
||||
Reference in New Issue
Block a user