ComparaisonPage.tsx 12,7 ko
Newer Older
Hamadou Ba's avatar
Hamadou Ba a validé
import { useEffect } from 'react';
import {
  Container,
  Typography,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Checkbox,
  Button,
  Box,
  Stack,
  Divider
} from '@mui/material';
import { CompareArrows as CompareIcon } from '@mui/icons-material';
import { useComparisonStore } from '../store/comparisonStore';
import { useSimulationStore } from '../store/simulationStore';

export default function ComparaisonPage() {
  const {
    simulations,
    selectedIds,
    comparisonData,
    fetchSimulations,
    toggleSelection,
    compareSelected,
    clearComparison
  } = useComparisonStore();

  const { timeUnit } = useSimulationStore();

  useEffect(() => {
    fetchSimulations();
  }, [fetchSimulations]);

  return (
    <Container maxWidth="xl">
      <Stack spacing={3}>
        <Typography variant="h4" gutterBottom>
          Comparaison de Simulations
        </Typography>

        {/* Table de sélection */}
        <Paper sx={{ p: 3 }}>
          <Typography variant="h6" gutterBottom>
            Sélectionner les simulations à comparer (2 minimum)
          </Typography>

          <Table>
            <TableHead>
              <TableRow>
                <TableCell padding="checkbox"></TableCell>
                <TableCell>Date</TableCell>
                <TableCell>λ (taux d'arrivée)</TableCell>
                <TableCell>Requêtes traitées</TableCell>
                <TableCell>Stable</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {simulations.map((sim) => (
                <TableRow key={sim.session_id}>
                  <TableCell padding="checkbox">
                    <Checkbox
                      checked={selectedIds.includes(sim.session_id)}
                      onChange={() => toggleSelection(sim.session_id)}
                    />
                  </TableCell>
                  <TableCell>{new Date(sim.created_at).toLocaleString()}</TableCell>
                  <TableCell>{sim.arrival_rate}</TableCell>
                  <TableCell>{sim.total_requests}</TableCell>
                  <TableCell>{sim.is_stable ? '' : ''}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>

          <Box sx={{ mt: 2, display: 'flex', gap: 2 }}>
            <Button
              variant="contained"
              startIcon={<CompareIcon />}
              onClick={compareSelected}
              disabled={selectedIds.length < 2}
            >
              Comparer ({selectedIds.length} sélectionnées)
            </Button>
            {comparisonData.length > 0 && (
              <Button variant="outlined" onClick={clearComparison}>
                Effacer
              </Button>
            )}
          </Box>
        </Paper>

        {/* Tableau de comparaison détaillé */}
        {comparisonData.length > 0 && (
          <Paper sx={{ p: 3 }}>
            <Typography variant="h6" gutterBottom>
              Résultats de la comparaison
            </Typography>

            {/* Configuration */}
            <Typography variant="subtitle1" sx={{ mt: 2, mb: 1, fontWeight: 600 }}>
              Configuration
            </Typography>
            <Table size="small">
              <TableHead>
                <TableRow>
                  <TableCell>Métrique</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>
                      Simulation {idx + 1}
                      <br />
                      <Typography variant="caption">
                        {new Date(sim.created_at).toLocaleString()}
                      </Typography>
                    </TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                <TableRow>
                  <TableCell>λ (taux d'arrivée)</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.config.arrival_rate.toFixed(4)} req/{timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>μ coordinateur</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.config.coordinator_service_rate.toFixed(4)} req/{timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>p (sortie coordinateur)</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{(sim.config.coordinator_exit_probability * 100).toFixed(1)}%</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Nombre de serveurs</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.config.servers.length}</TableCell>
                  ))}
                </TableRow>
              </TableBody>
            </Table>

            <Divider sx={{ my: 3 }} />

            {/* Métriques globales */}
            <Typography variant="subtitle1" sx={{ mb: 1, fontWeight: 600 }}>
              Métriques globales du système
            </Typography>
            <Table size="small">
              <TableBody>
                <TableRow>
                  <TableCell>Requêtes arrivées</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.config.simulation_time || 'N/A'} {timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Requêtes traitées</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.total_requests_completed}</TableCell>
                  ))}
                </TableRow>
                <TableRow sx={{ bgcolor: 'primary.50' }}>
                  <TableCell sx={{ fontWeight: 600 }}>W total (temps moyen système)</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx} sx={{ fontWeight: 600 }}>
                      {sim.average_system_time.toFixed(2)} {timeUnit}
                    </TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>L (clients moyens dans système)</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.average_customers_in_system?.toFixed(2) || 'N/A'}</TableCell>
                  ))}
                </TableRow>
              </TableBody>
            </Table>

            <Divider sx={{ my: 3 }} />

            {/* Coordinateur */}
            <Typography variant="subtitle1" sx={{ mb: 1, fontWeight: 600 }}>
              Coordinateur
            </Typography>
            <Table size="small">
              <TableBody>
                <TableRow>
                  <TableCell>Utilisation (ρ)</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>
                      {(sim.coordinator_stats.utilization * 100).toFixed(1)}%
                    </TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Temps d'attente moyen</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.coordinator_stats.average_wait_time.toFixed(2)} {timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Temps de service moyen</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.coordinator_stats.average_service_time.toFixed(2)} {timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Temps système moyen</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.coordinator_stats.average_system_time.toFixed(2)} {timeUnit}</TableCell>
                  ))}
                </TableRow>
                <TableRow>
                  <TableCell>Requêtes traitées</TableCell>
                  {comparisonData.map((sim, idx) => (
                    <TableCell key={idx}>{sim.coordinator_stats.total_departures}</TableCell>
                  ))}
                </TableRow>
              </TableBody>
            </Table>

            <Divider sx={{ my: 3 }} />

            {/* Serveurs */}
            <Typography variant="subtitle1" sx={{ mb: 1, fontWeight: 600 }}>
              Serveurs (moyennes)
            </Typography>
            <Table size="small">
              <TableBody>
                <TableRow>
                  <TableCell>Utilisation moyenne (ρ)</TableCell>
                  {comparisonData.map((sim, idx) => {
                    const serverStats = Object.values(sim.server_stats);
                    const avgUtil = serverStats.reduce((sum: number, s: any) => sum + s.utilization, 0) / serverStats.length;
                    return <TableCell key={idx}>{(avgUtil * 100).toFixed(1)}%</TableCell>;
                  })}
                </TableRow>
                <TableRow>
                  <TableCell>Temps d'attente moyen</TableCell>
                  {comparisonData.map((sim, idx) => {
                    const serverStats = Object.values(sim.server_stats);
                    const avgWait = serverStats.reduce((sum: number, s: any) => sum + s.average_wait_time, 0) / serverStats.length;
                    return <TableCell key={idx}>{avgWait.toFixed(2)} {timeUnit}</TableCell>;
                  })}
                </TableRow>
                <TableRow>
                  <TableCell>Temps de service moyen</TableCell>
                  {comparisonData.map((sim, idx) => {
                    const serverStats = Object.values(sim.server_stats);
                    const avgService = serverStats.reduce((sum: number, s: any) => sum + s.average_service_time, 0) / serverStats.length;
                    return <TableCell key={idx}>{avgService.toFixed(2)} {timeUnit}</TableCell>;
                  })}
                </TableRow>
                <TableRow>
                  <TableCell>Requêtes traitées (total)</TableCell>
                  {comparisonData.map((sim, idx) => {
                    const serverStats = Object.values(sim.server_stats);
                    const totalDepartures = serverStats.reduce((sum: number, s: any) => sum + s.total_departures, 0);
                    return <TableCell key={idx}>{totalDepartures}</TableCell>;
                  })}
                </TableRow>
              </TableBody>
            </Table>

            {/* Détail par serveur */}
            {comparisonData.length > 0 && Object.keys(comparisonData[0].server_stats).length > 0 && (
              <>
                <Divider sx={{ my: 3 }} />
                <Typography variant="subtitle1" sx={{ mb: 1, fontWeight: 600 }}>
                  Détail par serveur
                </Typography>
                {Object.keys(comparisonData[0].server_stats).map((serverId) => (
                  <Box key={serverId} sx={{ mb: 2 }}>
                    <Typography variant="subtitle2" sx={{ mb: 0.5, color: 'primary.main' }}>
                      {serverId.replace('_', ' ')}
                    </Typography>
                    <Table size="small">
                      <TableBody>
                        <TableRow>
                          <TableCell>Utilisation (ρ)</TableCell>
                          {comparisonData.map((sim, idx) => (
                            <TableCell key={idx}>
                              {(sim.server_stats[serverId].utilization * 100).toFixed(1)}%
                            </TableCell>
                          ))}
                        </TableRow>
                        <TableRow>
                          <TableCell>Temps système</TableCell>
                          {comparisonData.map((sim, idx) => (
                            <TableCell key={idx}>
                              {sim.server_stats[serverId].average_system_time.toFixed(2)} {timeUnit}
                            </TableCell>
                          ))}
                        </TableRow>
                        <TableRow>
                          <TableCell>Requêtes traitées</TableCell>
                          {comparisonData.map((sim, idx) => (
                            <TableCell key={idx}>
                              {sim.server_stats[serverId].total_departures}
                            </TableCell>
                          ))}
                        </TableRow>
                      </TableBody>
                    </Table>
                  </Box>
                ))}
              </>
            )}
          </Paper>
        )}
      </Stack>
    </Container>
  );
}