# Perspective Enseignant - Domaines et Compétences
**Date**: 3 décembre 2025
**Type**: Changement de perspective - Ce qui a été évalué vs Résultats des élèves
## 🎯 Objectif du Changement
Passer d'une **perspective centrée sur les résultats des élèves** à une **perspective centrée sur ce qui a été évalué par l'enseignant**.
### Avant (Perspective Élèves)
```
Domaine Algèbre:
- 75 évaluations (25 élèves × 3 questions)
- 187.5 / 250 points
```
→ **Difficile à interpréter** : mélange le nombre d'élèves et les évaluations
### Après (Perspective Enseignant)
```
Domaine Algèbre:
- 3 éléments de notation
- 10 points maximum
```
→ **Clair et actionnable** : l'enseignant voit ce qu'il a créé
---
## 📊 Cas d'Usage Concrets
### Scénario 1: Vérifier l'équilibre d'un trimestre
**Données affichées**:
```
Domaines:
- Algèbre : 8 éléments, 25 points
- Géométrie : 3 éléments, 12 points ← Sous-représenté
- Probabilités : 2 éléments, 8 points ← Sous-représenté
- Calcul : 6 éléments, 18 points
```
**Action enseignant**: Créer plus d'évaluations sur Géométrie et Probabilités pour le prochain contrôle.
### Scénario 2: Analyser une évaluation
**Données affichées**:
```
Compétences:
- Calculer : 5 éléments, 15 points
- Raisonner : 3 éléments, 12 points
- Communiquer : 1 élément, 5 points ← Sous-représenté
```
**Action enseignant**: Ajouter des questions de communication dans la prochaine évaluation.
### Scénario 3: Comparer les trimestres
| Domaine | T1 | T2 | T3 |
|---------|----|----|-----|
| Algèbre | 8 éléments, 25pts | 6 éléments, 18pts | 10 éléments, 30pts |
| Géométrie | 3 éléments, 12pts | 7 éléments, 20pts | 5 éléments, 15pts |
**Insight**: L'enseignant voit qu'il a moins travaillé la géométrie au T3, peut ajuster pour l'année suivante.
---
## 🔧 Modifications Techniques
### Backend
#### 1. Nouveau Service (`backend/domain/services/class_statistics_service.py`)
**Méthode ajoutée**: `calculate_domain_competence_from_elements()`
**Logique**:
```python
for assessment in assessments:
for exercise in assessment.exercises:
for element in exercise.grading_elements:
# Compter par domaine
if element.domain_id:
domain_count[element.domain_id] += 1
domain_points[element.domain_id] += element.max_points
# Compter par compétence (via skill)
if element.skill:
competence = find_competence_by_name(element.skill)
if competence:
competence_count[competence.id] += 1
competence_points[competence.id] += element.max_points
```
**Retourne**:
- `evaluation_count`: Nombre de GradingElements utilisant ce domaine/compétence
- `total_points_possible`: Somme des max_points de ces éléments
- `total_points_obtained`: 0 (non pertinent dans cette perspective)
#### 2. Endpoint modifié (`backend/api/routes/classes.py`)
**Chargement des relations**:
```python
assessments_query = (
select(Assessment)
.options(
selectinload(Assessment.exercises).selectinload(Exercise.grading_elements)
)
.where(...)
)
```
**Utilisation du nouveau service**:
```python
# AVANT
domains_stats, competences_stats = stats_service.aggregate_domain_competence_stats(
student_averages=student_averages,
domains=domains,
competences=competences,
)
# APRÈS
domains_stats, competences_stats = stats_service.calculate_domain_competence_from_elements(
assessments=assessments, # Avec exercises et grading_elements chargés
domains=domains,
competences=competences,
)
```
### Frontend
#### 1. Affichage modifié (`frontend/src/views/ClassDashboardView.vue`)
**Template**:
```vue
{{ domain.name }}
{{ domain.total_points_obtained }}/{{ domain.total_points_possible }}
{{ domain.evaluation_count }} évaluations
{{ domain.name }}
{{ domain.total_points_possible }} points
{{ domain.evaluation_count }} élément(s) de notation
```
**Titres modifiés**:
- "Statistiques par domaine" → "Évaluations par domaine"
- "Statistiques par compétence" → "Évaluations par compétence"
**Sous-titre ajouté**:
- "Perspective enseignant : ce qui a été évalué"
#### 2. Barre de progression relative
**Nouvelle logique**:
```javascript
function getRelativeWidth(item, allItems) {
const maxPoints = Math.max(...allItems.map(d => d.total_points_possible || 0))
if (maxPoints === 0) return 0
return ((item.total_points_possible || 0) / maxPoints) * 100
}
```
**Utilisation**:
```vue
```
La barre montre **la proportion relative** par rapport au domaine le plus évalué, pas un pourcentage absolu.
---
## 📈 Comparaison Avant/Après
### Exemple avec une classe de 25 élèves, 2 contrôles
**Contrôle 1** (Trimestre 1):
- Q1: Algèbre, 5 points
- Q2: Algèbre, 3 points
- Q3: Géométrie, 4 points
**Contrôle 2** (Trimestre 1):
- Q1: Algèbre, 2 points
- Q2: Probabilités, 5 points
### Avant (Perspective Élèves)
**Domaine Algèbre**:
- `evaluation_count`: 75 (3 questions × 25 élèves)
- `total_points_obtained`: 187.5 (moyenne hypothétique)
- `total_points_possible`: 250 ((5+3+2) × 25)
**Affichage**: "75 évaluations - 187.5/250"
→ **Illisible** pour l'enseignant
### Après (Perspective Enseignant)
**Domaine Algèbre**:
- `evaluation_count`: 3 (nombre de questions posées)
- `total_points_possible`: 10 (5+3+2)
**Affichage**: "3 éléments de notation - 10 points"
→ **Très lisible** et actionnable
---
## 🎓 Avantages Pédagogiques
### 1. Clarté
- **Indépendant du nombre d'élèves**: 3 éléments restent 3 éléments
- **Unité cohérente**: Points = barème défini par l'enseignant
### 2. Planification
- **Voir rapidement** quels domaines ont été peu évalués
- **Équilibrer** les évaluations entre domaines
- **Comparer** les trimestres facilement
### 3. Réflexivité
- **Analyse de pratique**: "Ai-je trop évalué l'algèbre ?"
- **Diversification**: "Dois-je ajouter plus de géométrie ?"
- **Cohérence**: "Mon programme est-il équilibré ?"
### 4. Communication
- **Conseil de classe**: "J'ai évalué 8 fois l'algèbre ce trimestre"
- **Parents**: "Voici la répartition de mes évaluations"
- **Équipe pédagogique**: "Comparons nos pratiques d'évaluation"
---
## 🔍 Détails d'Implémentation
### Gestion des Compétences
**Mapping via `element.skill`**:
```python
if element.skill:
matching_competence = next(
(c for c in competences if c.name == element.skill),
None
)
```
**Logique**:
- Les compétences sont stockées dans `GradingElement.skill` (champ texte libre)
- Le matching se fait par nom de compétence
- Si aucune correspondance: la compétence n'est pas comptée
**Amélioration future**: Ajouter `competence_id` dans `GradingElement` pour éviter le matching par nom.
### Performance
**Requête optimisée**:
```python
# Un seul trip à la base de données
assessments = session.execute(
select(Assessment)
.options(selectinload(Assessment.exercises).selectinload(Exercise.grading_elements))
.where(...)
).scalars().all()
```
**Complexité**: O(n) où n = nombre total de GradingElements du trimestre
**Charge typique**:
- 5 évaluations × 15 éléments/évaluation = 75 éléments à parcourir
- Temps: < 10ms
### Données Retournées
**Structure JSON**:
```json
{
"domains_stats": [
{
"id": 1,
"name": "Algèbre",
"color": "#3B82F6",
"evaluation_count": 3,
"total_points_obtained": 0.0,
"total_points_possible": 10.0
}
],
"competences_stats": [
{
"id": 1,
"name": "Calculer",
"color": "#10B981",
"evaluation_count": 5,
"total_points_obtained": 0.0,
"total_points_possible": 15.0
}
]
}
```
**Note**: `total_points_obtained` est à 0 car non pertinent dans cette perspective.
---
## 📁 Fichiers Modifiés
### Backend (2 fichiers)
1. **`backend/domain/services/class_statistics_service.py`**
- Ajout: `calculate_domain_competence_from_elements()`
- Logique: Parcours des GradingElements
- Retour: DomainStats et CompetenceStats
2. **`backend/api/routes/classes.py`**
- Modification: Chargement des assessments avec relations
- Modification: Appel de la nouvelle méthode de calcul
### Frontend (1 fichier)
3. **`frontend/src/views/ClassDashboardView.vue`**
- Modification: Titres ("Évaluations par..." au lieu de "Statistiques par...")
- Modification: Affichage (points seuls au lieu de obtained/possible)
- Modification: Texte ("élément(s) de notation" au lieu de "évaluations")
- Ajout: Fonction `getRelativeWidth()` pour barre proportionnelle
- Ajout: Sous-titre explicatif "Perspective enseignant : ce qui a été évalué"
---
## ✅ Tests Suggérés
### 1. Vérifier le comptage
- Créer 3 évaluations avec 2, 3, 4 éléments respectivement
- Vérifier: `evaluation_count = 9`
### 2. Vérifier les points
- Élément 1: 5 points
- Élément 2: 3 points
- Élément 3: 2 points
- Vérifier: `total_points_possible = 10`
### 3. Vérifier le filtrage par domaine
- 3 éléments Algèbre, 2 éléments Géométrie
- Vérifier: Algèbre montre 3, Géométrie montre 2
### 4. Vérifier les compétences
- Créer des éléments avec `skill = "Calculer"`
- Vérifier: Compétence "Calculer" affiche le bon nombre
### 5. Vérifier l'absence de données
- Domaine sans éléments: `evaluation_count = 0, total_points_possible = 0`
- Affichage: "0 élément(s) de notation - 0 points"
---
## 🚀 Utilisation
### Accéder au Dashboard
```
http://localhost:5173/classes/{id}
```
### Vérifier l'affichage
1. Sélectionner un trimestre
2. Scroller jusqu'aux sections "Évaluations par domaine/compétence"
3. Vérifier:
- ✅ Titre: "Évaluations par domaine/compétence"
- ✅ Sous-titre: "Perspective enseignant : ce qui a été évalué"
- ✅ Affichage: "X points" (pas de fraction)
- ✅ Texte: "X élément(s) de notation"
- ✅ Barre proportionnelle au domaine le plus évalué
---
## 🎯 Conclusion
Cette modification transforme le dashboard d'une **vue résultats** (complexe, orientée élèves) en une **vue enseignant** (simple, orientée pratique pédagogique).
**Impact pédagogique**:
- ✅ Meilleure visibilité sur la répartition des évaluations
- ✅ Aide à l'équilibrage du programme
- ✅ Facilite la réflexion sur les pratiques d'évaluation
- ✅ Indépendant du nombre d'élèves (plus cohérent)
**Impact technique**:
- ✅ Code plus simple (pas de double comptage élèves × éléments)
- ✅ Requêtes optimisées avec selectinload
- ✅ Données plus claires et exploitables