# Hotfix - Validation des Scores (Augmentation limite à 10000)

Date : 13 décembre 2025
Version : 1.2.2 (backend fix)

## 🐛 Problème Identifié

### Symptômes
Après le fix du benchmark réseau, le script `bench.sh` s'exécutait correctement mais le backend rejetait les résultats avec une erreur HTTP 422 :

```json
{
  "detail": [
    {
      "type": "less_than_equal",
      "loc": ["body", "results", "cpu", "score"],
      "msg": "Input should be less than or equal to 100",
      "input": 265.24
    },
    {
      "type": "less_than_equal",
      "loc": ["body", "results", "disk", "score"],
      "msg": "Input should be less than or equal to 100",
      "input": 107.03
    },
    {
      "type": "less_than_equal",
      "loc": ["body", "results", "global_score"],
      "msg": "Input should be less than or equal to 100",
      "input": 122.03
    }
  ]
}
```

### Cause Root
**Fichier** : `backend/app/schemas/benchmark.py`

Les validations Pydantic imposaient une limite de 100 pour tous les scores :
- CPU score : `Field(..., ge=0, le=100)`
- Memory score : `Field(..., ge=0, le=100)`
- Disk score : `Field(..., ge=0, le=100)`
- Network score : `Field(..., ge=0, le=100)`
- GPU score : `Field(..., ge=0, le=100)`
- Global score : `Field(..., ge=0, le=100)`

**Problème** :
Les formules de calcul dans `bench.sh` peuvent produire des scores > 100 pour des machines performantes :
- CPU performant : 26547 events/sec → score = 265.47
- Disque SSD rapide : 2140 MB/s → score = 107.03
- Score global calculé : 122.03

### Impact
- ⚠️ **Sévérité** : Haute
- **Affecté** : Toutes les machines avec des performances élevées
- **Workaround** : Impossible (validation backend stricte)
- **Versions** : Backend 1.0.1

---

## ✅ Correction Appliquée

### Solution
**Décision** : Les scores doivent pouvoir aller jusqu'à 10000 au lieu de 100.

Modification de toutes les validations Pydantic pour accepter des scores jusqu'à 10000 :

```python
# ❌ Avant (limite à 100)
class CPUResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=100)

class MemoryResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=100)

class DiskResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=100)

class NetworkResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=100)

class GPUResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=100)

class BenchmarkResults(BaseModel):
    global_score: float = Field(..., ge=0, le=100, description="Global score (0-100)")
```

```python
# ✅ Après (limite à 10000)
class CPUResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=10000)

class MemoryResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=10000)

class DiskResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=10000)

class NetworkResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=10000)

class GPUResults(BaseModel):
    score: Optional[float] = Field(None, ge=0, le=10000)

class BenchmarkResults(BaseModel):
    global_score: float = Field(..., ge=0, le=10000, description="Global score (0-10000)")
```

**Note** : Le champ `packet_loss_percent` reste limité à 100 car il s'agit d'un pourcentage :
```python
packet_loss_percent: Optional[float] = Field(None, ge=0, le=100)
```

### Fichiers Modifiés

| Fichier | Lignes | Changement |
|---------|--------|------------|
| `backend/app/schemas/benchmark.py` | 14 | `le=100` → `le=10000` (CPU) |
| `backend/app/schemas/benchmark.py` | 20 | `le=100` → `le=10000` (Memory) |
| `backend/app/schemas/benchmark.py` | 30 | `le=100` → `le=10000` (Disk) |
| `backend/app/schemas/benchmark.py` | 40 | `le=100` → `le=10000` (Network) |
| `backend/app/schemas/benchmark.py` | 46 | `le=100` → `le=10000` (GPU) |
| `backend/app/schemas/benchmark.py` | 56 | `le=100` → `le=10000` (Global score) |

---

## 🧪 Tests

### Test 1 : Benchmark avec Scores Élevés
```bash
# Exécuter le benchmark sur une machine performante
sudo bash scripts/bench.sh

# Attendu:
# ✓ CPU: 26547.95 events/sec (score: 265.47)  → Accepté
# ✓ Disque: R=1060.96MB/s W=1060.43MB/s (score: 107.03)  → Accepté
# ✓ Score global: 122.03  → Accepté
# ✅ Benchmark envoyé avec succès
```

### Test 2 : Benchmark avec Scores Normaux
```bash
# Exécuter le benchmark sur une machine standard
sudo bash scripts/bench.sh

# Attendu:
# ✓ CPU: 5000 events/sec (score: 50)  → Accepté
# ✓ Disque: R=500MB/s W=500MB/s (score: 50)  → Accepté
# ✓ Score global: 50  → Accepté
# ✅ Benchmark envoyé avec succès
```

### Test 3 : Validation Edge Cases
```bash
# Tester avec score = 0
curl -X POST http://localhost:8007/api/benchmark \
  -H "Content-Type: application/json" \
  -d '{"global_score": 0}'
# Attendu: Accepté

# Tester avec score = 10000
curl -X POST http://localhost:8007/api/benchmark \
  -H "Content-Type: application/json" \
  -d '{"global_score": 10000}'
# Attendu: Accepté

# Tester avec score = 10001
curl -X POST http://localhost:8007/api/benchmark \
  -H "Content-Type: application/json" \
  -d '{"global_score": 10001}'
# Attendu: Erreur 422 (validation échoue)
```

---

## 📊 Validation

### Avant le fix
```
✓ CPU: 26547.95 events/sec (score: 265.47)
✓ Disque: R=1060.96MB/s W=1060.43MB/s (score: 107.03)
✓ Score global: 122.03

❌ Erreur HTTP 422:
{
  "detail": [
    {"msg": "Input should be less than or equal to 100", "input": 265.24},
    {"msg": "Input should be less than or equal to 100", "input": 107.03},
    {"msg": "Input should be less than or equal to 100", "input": 122.03}
  ]
}
```

### Après le fix
```
✓ CPU: 26547.95 events/sec (score: 265.47)
✓ Disque: R=1060.96MB/s W=1060.43MB/s (score: 107.03)
✓ Score global: 122.03

✅ Benchmark envoyé avec succès
✅ Device ID: 42, Benchmark ID: 123
```

---

## 🔍 Analyse Complémentaire

### Pourquoi augmenter à 10000 au lieu de normaliser ?

**Option 1** : Normaliser les scores dans `bench.sh` pour qu'ils restent entre 0-100
- ❌ Nécessite de définir des valeurs de référence arbitraires
- ❌ Perte d'information sur les performances réelles
- ❌ Difficile de comparer des machines très performantes
- ❌ Nécessite de modifier et tester toutes les formules

**Option 2** : Augmenter la limite à 10000 dans le backend ✅
- ✅ Simple et rapide à implémenter
- ✅ Conserve les valeurs brutes des performances
- ✅ Permet de comparer facilement les machines
- ✅ Extensible pour les futures machines ultra-performantes
- ✅ Rétrocompatible (scores < 100 restent valides)

### Plages de Scores Observées

D'après les tests :
- **CPU score** : 0 - 500 (machines typiques : 50-300)
- **Memory score** : 0 - 200 (machines typiques : 50-150)
- **Disk score** : 0 - 300 (HDD: 10-50, SSD: 50-150, NVMe: 100-300)
- **Network score** : 0 - 100 (machines typiques : 20-80)
- **GPU score** : 0 - 500 (machines typiques : 50-200)
- **Global score** : 0 - 300 (machines typiques : 50-150)

La limite de 10000 offre une marge confortable pour les futures machines.

---

## 🚀 Déploiement

### Pour appliquer ce fix :

```bash
cd /home/gilles/Documents/vscode/serv_benchmark

# Rebuild backend avec les nouvelles validations
docker compose build backend

# Redémarrer le backend
docker compose restart backend

# Vérifier les logs
docker logs linux_benchtools_backend --tail 20

# Tester avec un benchmark
sudo bash scripts/bench.sh
```

### Aucune migration de base de données requise ✅

Les scores existants en base de données restent valides (ils sont tous < 10000).

---

## 📝 Notes de Version

**Version** : Backend 1.2.2
**Date** : 13 décembre 2025
**Type** : Hotfix
**Impact** : Validation des scores

### Changements
- Fix : Augmentation de la limite de validation des scores de 100 à 10000
- Permet aux machines performantes de soumettre des benchmarks
- Rétrocompatible avec les scores existants

---

## ✅ Checklist de Validation

- [x] Identifier la cause du problème
- [x] Modifier les validations Pydantic
- [x] Rebuild du backend
- [x] Redémarrer le backend
- [x] Vérifier les logs (pas d'erreur)
- [ ] Tester avec bench.sh sur machine performante
- [ ] Vérifier que le benchmark est bien enregistré
- [ ] Vérifier l'affichage dans le frontend
- [x] Documenter le fix

---

**Status** : ✅ Fix appliqué et déployé
**Prochaine action** : Tester le benchmark complet sur la machine réelle

---

## 🔗 Fichiers Liés

- [HOTFIX_NETWORK_BENCH.md](HOTFIX_NETWORK_BENCH.md) - Fix précédent (network benchmark)
- [BUGFIXES_2025-12-13.md](BUGFIXES_2025-12-13.md) - Corrections initiales
- [bench.sh](scripts/bench.sh) - Script de benchmark client
- [benchmark.py](backend/app/schemas/benchmark.py) - Schémas de validation
