UNITE_GLOBALE.md 7,98 ko
Newer Older
# 🌍 Unité de Temps Globale - Système Unifié

## 🎯 Changement Majeur

L'unité de temps (ms/s) est maintenant **globale** et **synchronisée dans toute l'application**!

## ✅ Ce qui a été fait

### 1. **Store Zustand Global**

Ajout de `timeUnit` dans le store principal:

```typescript
// apps/web/src/store/simulationStore.ts
export type TimeUnit = 'ms' | 's';

interface SimulationState {
  timeUnit: TimeUnit; // Unité globale pour toute l'UI
  setTimeUnit: (unit: TimeUnit) => void;
  // ... autres états
}
```

### 2. **Sélecteur Unique [ms] [s]**

Le sélecteur en haut à droite du panneau de paramètres contrôle **TOUTE** l'application:

```
┌──────────────────────────────────────┐
│ Paramètres du réseau      [ms] s    │ ← Contrôle TOUT
├──────────────────────────────────────┤
│ λ: 6.0 req/s                         │ ← Suit le sélecteur
│ Temps simulation: 100 s              │ ← A son propre sélecteur
│ μc: 0.010 s                          │ ← Suit le sélecteur
│ μ1: 0.120 s                          │ ← Suit le sélecteur
└──────────────────────────────────────┘
```

### 3. **Synchronisation Automatique**

Quand vous changez [ms] ↔ [s], **TOUT** se met à jour:
- ✅ Champ λ (taux d'arrivée)
- ✅ Champs μ (temps de service)
- ✅ Labels et helper texts
- ✅ Unités affichées (req/ms ↔ req/s, ms ↔ s)

### 4. **Fonctions Utilitaires**

Nouveau fichier `apps/web/src/utils/timeFormat.ts`:

```typescript
// Convertir temps selon l'unité
convertTime(timeInMs, unit)  nombre affiché

// Convertir taux selon l'unité
convertRate(rateInReqPerMs, unit)  nombre affiché

// Formater avec l'unité
formatTime(100, 's')  "0.100 s"
formatRate(0.008, 's')  "8.0 req/s"
```

## 🔄 Comment ça fonctionne

### Architecture

```
┌─────────────────────────────────────┐
│      Store Zustand (Global)         │
│  timeUnit: 'ms' | 's'               │
└──────────────┬──────────────────────┘

               ├─► ParameterPanel (utilise timeUnit)
               ├─► ResultsDisplay (utilise timeUnit)
               ├─► MetricsCard (utilise timeUnit)
               └─► Tous les composants...
```

### Avant (❌ Problème)

```
ParameterPanel: [local state] timeUnit = 'ms'
ResultsDisplay: Affiche toujours en ms
MetricsCard: Affiche toujours en ms
→ Incohérent et confus!
```

### Maintenant (✅ Solution)

```
Store Global: timeUnit = 's'

ParameterPanel: Lit store → Affiche en 's'
ResultsDisplay: Lit store → Affiche en 's'
MetricsCard: Lit store → Affiche en 's'
→ Cohérent partout!
```

## 📊 Exemple Concret

**Vous sélectionnez [s]:**

### Panneau de paramètres:
```
λ = 6.0 req/s          (au lieu de 0.006 req/ms)
μc = 0.010 s           (au lieu de 10 ms)
μ1 = 0.120 s           (au lieu de 120 ms)
```

### Résultats de simulation:
```
Temps moyen dans le système: 0.156 s   (au lieu de 156 ms)
Temps d'attente: 0.024 s               (au lieu de 24 ms)
Temps de service: 0.132 s              (au lieu de 132 ms)
```

### Métriques analytiques:
```
W (temps moyen): 0.156 s               (au lieu de 156 ms)
Wq (attente): 0.024 s                  (au lieu de 24 ms)
```

**Tout est synchronisé!**

## 🎯 Deux Sélecteurs Distincts

### 1. Sélecteur Principal [ms] [s]
**Contrôle:** λ, μ, et TOUS les affichages de temps/taux
**Position:** Haut à droite du panneau paramètres

### 2. Sélecteur Temps Simulation (ms/s/min/h)
**Contrôle:** UNIQUEMENT le temps de simulation
**Position:** À côté du champ "Temps de simulation"
**Indépendant:** Ne change PAS l'unité globale

## 💡 Utilisation

### Scénario 1: Tout en secondes
```
1. Sélectionnez [s] en haut à droite
2. Entrez λ = 6 (req/s)
3. Entrez μc = 0.010 (s)
4. Entrez μ1 = 0.120 (s)
5. Temps simulation: 100 (avec son propre sélecteur en 's')
→ Tout affiché en secondes dans l'application
```

### Scénario 2: Tout en millisecondes
```
1. Sélectionnez [ms] en haut à droite
2. Entrez λ = 0.006 (req/ms)
3. Entrez μc = 10 (ms)
4. Entrez μ1 = 120 (ms)
5. Temps simulation: 100000 (avec son propre sélecteur en 'ms')
→ Tout affiché en millisecondes dans l'application
```

## 🔧 Pour les Développeurs

### Utiliser l'unité globale dans un composant

```typescript
import { useSimulationStore } from '../../store/simulationStore';
import { formatTime, formatRate } from '../../utils/timeFormat';

function MyComponent() {
  const { timeUnit } = useSimulationStore();

  // Afficher un temps (stocké en ms)
  const timeInMs = 156;
  const displayTime = formatTime(timeInMs, timeUnit);
  // timeUnit='s' → "0.156 s"
  // timeUnit='ms' → "156 ms"

  // Afficher un taux (stocké en req/ms)
  const rateInReqPerMs = 0.008;
  const displayRate = formatRate(rateInReqPerMs, timeUnit);
  // timeUnit='s' → "8.0 req/s"
  // timeUnit='ms' → "0.008 req/ms"

  return (
    <div>
      <p>Temps: {displayTime}</p>
      <p>Taux: {displayRate}</p>
    </div>
  );
}
```

### Fonctions utilitaires disponibles

```typescript
import {
  convertTime,      // Convertir temps ms → unité display
  convertRate,      // Convertir taux req/ms → unité display
  formatTime,       // Format temps avec unité
  formatRate,       // Format taux avec unité
  getTimeUnitLabel, // "millisecondes" ou "secondes"
  getRateUnitLabel, // "req/ms" ou "req/s"
} from '../utils/timeFormat';
```

## ✅ Avantages

1. **Cohérence**: Toute l'application utilise la même unité
2. **Simplicité**: Un seul sélecteur pour tout contrôler
3. **Clarté**: Plus de confusion entre ms et s
4. **Flexibilité**: Changez d'unité instantanément partout
5. **Maintenabilité**: Code centralisé et réutilisable

## 🐛 Correction du Bug λ

**Problème original:**
- Vous saisissiez λ = 6 req/s
- Le système affichait ~1784 requêtes au lieu de ~600
- Incohérence entre saisie et stockage

**Cause:**
- Le champ λ était "controlled" avec `.toFixed()`
- Problème de synchronisation entre l'affichage et la valeur interne
- Conversion incorrecte entre unités

**Solution appliquée:**
```typescript
// Avant
value={getDisplayedArrivalRate().toFixed(...)}  // ❌ Problème

// Maintenant
const getDisplayedArrivalRate = (): string => {
  const displayValue = timeUnit === 's'
    ? config.arrival_rate * 1000
    : config.arrival_rate;
  return displayValue.toFixed(timeUnit === 's' ? 1 : 3);
};

value={getDisplayedArrivalRate()}  // ✅ Fixé
```

## 📝 Checklist de Migration

Si vous ajoutez un nouveau composant affichant des temps/taux:

- [ ] Importer `useSimulationStore` et récupérer `timeUnit`
- [ ] Utiliser `formatTime()` ou `formatRate()` pour afficher
- [ ] NE PAS hardcoder "ms" ou "req/ms" dans le JSX
- [ ] Tester avec [ms] ET [s] pour vérifier la synchronisation

## 🎓 Exemple Complet

```typescript
import { useSimulationStore } from '../../store/simulationStore';
import { formatTime } from '../../utils/timeFormat';

export default function ServerMetrics({ serverId }) {
  const { timeUnit, simulationResults } = useSimulationStore();

  const stats = simulationResults?.server_stats[serverId];
  if (!stats) return null;

  return (
    <div>
      <h3>Serveur {serverId}</h3>
      <p>Temps moyen: {formatTime(stats.average_system_time, timeUnit)}</p>
      <p>Attente: {formatTime(stats.average_wait_time, timeUnit)}</p>
      <p>Service: {formatTime(stats.average_service_time, timeUnit)}</p>
    </div>
  );
}
```

**Résultat avec [s]:**
```
Temps moyen: 0.156 s
Attente: 0.024 s
Service: 0.132 s
```

**Résultat avec [ms]:**
```
Temps moyen: 156 ms
Attente: 24 ms
Service: 132 ms
```

---

**L'application est maintenant entièrement cohérente avec une unité de temps globale!** 🎉