feat: add score histo
This commit is contained in:
182
docs/features/STUDENT_AVERAGES_HISTOGRAM.md
Normal file
182
docs/features/STUDENT_AVERAGES_HISTOGRAM.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# 📊 Histogramme des Moyennes des Élèves
|
||||
|
||||
## 🎯 **Vue d'ensemble**
|
||||
|
||||
Cette fonctionnalité ajoute un **histogramme interactif** des moyennes individuelles des élèves dans la card "Résultats" du dashboard de classe. L'histogramme se met à jour dynamiquement selon le trimestre sélectionné et offre une visualisation claire de la distribution des performances de la classe.
|
||||
|
||||
## ✨ **Fonctionnalités**
|
||||
|
||||
### **Affichage visuel**
|
||||
- **Graphique en barres** utilisant Chart.js
|
||||
- **Bins de 1 point** : 0-1, 1-2, ..., 19-20, 20+
|
||||
- **Couleurs orange** cohérentes avec le thème de la card résultats
|
||||
- **Animation fluide** lors des changements de trimestre
|
||||
- **Design responsive** s'adaptant à tous les écrans
|
||||
|
||||
### **Interactivité**
|
||||
- **Tooltips informatifs** : affichage du nombre d'élèves au survol
|
||||
- **Mise à jour automatique** lors du changement de trimestre
|
||||
- **Gestion des cas vides** avec message explicatif
|
||||
|
||||
### **Données calculées**
|
||||
- **Moyennes individuelles** : calculées pour chaque élève sur le trimestre sélectionné
|
||||
- **Normalisation sur 20** : toutes les moyennes sont ramenées sur 20 pour comparaison
|
||||
- **Distribution automatique** : regroupement en bins de 1 point
|
||||
|
||||
## 🏗️ **Architecture technique**
|
||||
|
||||
### **Backend - Calcul des données**
|
||||
|
||||
#### Méthode `get_class_results()` dans `models.py`
|
||||
```python
|
||||
# Calcul des moyennes finales des élèves
|
||||
student_final_averages = []
|
||||
for student_id, scores in student_averages.items():
|
||||
if scores:
|
||||
avg = statistics.mean(scores)
|
||||
student_final_averages.append(round(avg, 2))
|
||||
|
||||
# Création de l'histogramme des moyennes
|
||||
if student_final_averages:
|
||||
avg_bins = list(range(0, 22)) # 0-1, 1-2, ..., 20+
|
||||
avg_bin_counts = [0] * (len(avg_bins) - 1)
|
||||
|
||||
for avg in student_final_averages:
|
||||
bin_index = min(int(avg), len(avg_bin_counts) - 1)
|
||||
avg_bin_counts[bin_index] += 1
|
||||
```
|
||||
|
||||
**Retour enrichi :**
|
||||
- `student_averages` : Liste des moyennes individuelles
|
||||
- `student_averages_distribution` : Histogramme avec format `{range, count}`
|
||||
|
||||
#### API `/classes/{id}/stats`
|
||||
```json
|
||||
{
|
||||
"results": {
|
||||
"average": 12.46,
|
||||
"min": 4.77,
|
||||
"max": 17.79,
|
||||
"student_averages": [11.8, 13.46, 13.84, ...],
|
||||
"student_averages_distribution": [
|
||||
{"range": "9-10", "count": 1},
|
||||
{"range": "10-11", "count": 1},
|
||||
{"range": "11-12", "count": 5},
|
||||
{"range": "12-13", "count": 11}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **Frontend - Affichage**
|
||||
|
||||
#### Template HTML (`class_dashboard.html`)
|
||||
```html
|
||||
<div class="bg-orange-50 rounded-lg p-4 border border-orange-100">
|
||||
<h4 class="text-sm font-semibold text-orange-900 mb-3">
|
||||
Distribution des moyennes
|
||||
</h4>
|
||||
<div class="relative h-32">
|
||||
<canvas id="studentAveragesChart" class="w-full h-full"></canvas>
|
||||
<div class="absolute inset-0 flex items-center justify-center"
|
||||
data-chart-no-data style="display: none;">
|
||||
Aucune donnée disponible
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### JavaScript (`ClassDashboard.js`)
|
||||
```javascript
|
||||
updateStudentAveragesChart(distribution) {
|
||||
const canvas = document.getElementById('studentAveragesChart');
|
||||
|
||||
// Configuration Chart.js
|
||||
this.studentAveragesChart = new Chart(canvas, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: distribution.map(item => item.range),
|
||||
datasets: [{
|
||||
label: 'Nombre d\'élèves',
|
||||
data: distribution.map(item => item.count),
|
||||
backgroundColor: 'rgba(251, 146, 60, 0.8)',
|
||||
borderColor: 'rgba(251, 146, 60, 1)'
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
// Configuration complète...
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 **Configuration et Personnalisation**
|
||||
|
||||
### **Couleurs**
|
||||
- **Barres** : `rgba(251, 146, 60, 0.8)` (orange avec transparence)
|
||||
- **Bordures** : `rgba(251, 146, 60, 1)` (orange plein)
|
||||
- **Grille** : `rgba(251, 146, 60, 0.1)` (orange très léger)
|
||||
|
||||
### **Paramètres Chart.js**
|
||||
- **Type** : `bar` (graphique en barres)
|
||||
- **Hauteur** : 128px (8rem en Tailwind)
|
||||
- **Animation** : 800ms avec easing `easeInOutCubic`
|
||||
- **Responsive** : Activé avec `maintainAspectRatio: false`
|
||||
|
||||
### **Bins de distribution**
|
||||
- **Plage** : 0 à 20+ (21 bins au total)
|
||||
- **Largeur** : 1 point par bin
|
||||
- **Format** : "X-Y" (ex: "12-13") ou "20+" pour le dernier
|
||||
|
||||
## 📊 **Exemple d'utilisation**
|
||||
|
||||
### **Cas concret - 6ème A, Trimestre 1**
|
||||
- **28 élèves** évalués
|
||||
- **Moyennes** : entre 9.76 et 13.87
|
||||
- **Distribution** :
|
||||
- 1 élève entre 9-10
|
||||
- 1 élève entre 10-11
|
||||
- 5 élèves entre 11-12
|
||||
- **11 élèves entre 12-13** (pic principal)
|
||||
- **10 élèves entre 13-14**
|
||||
|
||||
### **Interprétation pédagogique**
|
||||
- **Concentration** : Majorité des élèves entre 11 et 14
|
||||
- **Homogénéité** : Classe relativement homogène
|
||||
- **Niveau global** : Bon niveau avec moyenne générale de 12.46
|
||||
|
||||
## 🚀 **Activation**
|
||||
|
||||
La fonctionnalité est **automatiquement active** sur toutes les pages de dashboard de classe :
|
||||
|
||||
1. **Navigation** : Aller sur `/classes/{id}/dashboard`
|
||||
2. **Sélection trimestre** : Choisir un trimestre (1, 2, 3 ou Global)
|
||||
3. **Visualisation** : L'histogramme apparaît dans la card "Résultats"
|
||||
|
||||
## 🔍 **Dépannage**
|
||||
|
||||
### **Histogramme vide**
|
||||
- **Cause** : Aucune évaluation corrigée pour ce trimestre
|
||||
- **Solution** : Vérifier que les évaluations ont des notes saisies
|
||||
|
||||
### **Erreur Chart.js**
|
||||
- **Cause** : Problème de chargement de la librairie
|
||||
- **Solution** : Vérifier la connexion CDN Chart.js
|
||||
|
||||
### **Données incohérentes**
|
||||
- **Cause** : Problème dans le calcul des moyennes
|
||||
- **Solution** : Vérifier les types de notation (notes vs score)
|
||||
|
||||
## 📈 **Évolutions futures**
|
||||
|
||||
- **Export** : Possibilité d'exporter l'histogramme en PNG/SVG
|
||||
- **Comparaison** : Affichage de plusieurs trimestres simultanément
|
||||
- **Filtres** : Filtrage par élèves ou groupes d'élèves
|
||||
- **Statistiques avancées** : Ajout de la courbe normale théorique
|
||||
- **Personnalisation** : Choix des bins et des couleurs par l'utilisateur
|
||||
|
||||
---
|
||||
|
||||
✨ **Cette fonctionnalité enrichit considérablement l'analyse des résultats de classe en offrant une visualisation intuitive et interactive des performances des élèves.**
|
||||
Reference in New Issue
Block a user