ComparisonTable.tsx 5,92 ko
Newer Older
 * Comparison table component with Material-UI - displays analytical vs simulation comparison.
import {
  Box,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  Typography,
  Stack,
} from '@mui/material';
import type { NetworkComparison, QueueComparison } from '../../types/simulation';

interface ComparisonTableProps {
  comparison: NetworkComparison;
}

interface ComparisonRowProps {
  label: string;
  analytical: number;
  simulation: number;
  diffPercent: number;
  decimals?: number;
}

function ComparisonRow({
  label,
  analytical,
  simulation,
  diffPercent,
  decimals = 4,
}: ComparisonRowProps) {
  const absDiff = Math.abs(diffPercent);
  const isGoodMatch = absDiff < 5; // Less than 5% difference is good
  const isOkMatch = absDiff < 10; // Less than 10% is acceptable

  const color = isGoodMatch ? 'success.main' : isOkMatch ? 'warning.main' : 'error.main';

    <TableRow>
      <TableCell>{label}</TableCell>
      <TableCell align="right" sx={{ fontFamily: 'monospace' }}>
        {analytical.toFixed(decimals)}
      </TableCell>
      <TableCell align="right" sx={{ fontFamily: 'monospace' }}>
        {simulation.toFixed(decimals)}
      </TableCell>
      <TableCell align="right" sx={{ fontFamily: 'monospace', fontWeight: 600, color }}>
        {diffPercent >= 0 ? '+' : ''}
        {diffPercent.toFixed(2)}%
  );
}

function QueueComparisonSection({
  queueName,
  queueComparison,
}: {
  queueName: string;
  queueComparison: QueueComparison;
}) {
  return (
    <>
      <TableRow sx={{ bgcolor: 'grey.100' }}>
        <TableCell colSpan={4} sx={{ fontWeight: 600, py: 1 }}>
      <ComparisonRow
        label="  Utilisation (ρ)"
        analytical={queueComparison.utilization.analytical}
        simulation={queueComparison.utilization.simulation}
        diffPercent={queueComparison.utilization.difference_percent}
      />
      <ComparisonRow
        label="  Nombre moyen (L)"
        analytical={queueComparison.average_customers.analytical}
        simulation={queueComparison.average_customers.simulation}
        diffPercent={queueComparison.average_customers.difference_percent}
      />
      <ComparisonRow
        label="  Temps moyen (W)"
        analytical={queueComparison.average_time.analytical}
        simulation={queueComparison.average_time.simulation}
        diffPercent={queueComparison.average_time.difference_percent}
      />
      <ComparisonRow
        label="  Temps d'attente (Wq)"
        analytical={queueComparison.average_wait.analytical}
        simulation={queueComparison.average_wait.simulation}
        diffPercent={queueComparison.average_wait.difference_percent}
      />
    </>
  );
}

export default function ComparisonTable({ comparison }: ComparisonTableProps) {
  return (
    <Box>
      <TableContainer component={Paper} variant="outlined">
        <Table size="small">
          <TableHead>
            <TableRow sx={{ bgcolor: 'grey.50' }}>
              <TableCell sx={{ fontWeight: 600 }}>Métrique</TableCell>
              <TableCell align="right" sx={{ fontWeight: 600 }}>
                Analytique
              </TableCell>
              <TableCell align="right" sx={{ fontWeight: 600 }}>
                Simulation
              </TableCell>
              <TableCell align="right" sx={{ fontWeight: 600 }}>
                Différence
              </TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {/* System totals */}
            <TableRow sx={{ bgcolor: 'primary.50' }}>
              <TableCell colSpan={4} sx={{ fontWeight: 700, color: 'primary.dark', py: 1 }}>
                Système total
              </TableCell>
            </TableRow>
            <ComparisonRow
              label="  L total"
              analytical={comparison.total_L.analytical}
              simulation={comparison.total_L.simulation}
              diffPercent={comparison.total_L.difference_percent}
            />
            <ComparisonRow
              label="  W total"
              analytical={comparison.total_W.analytical}
              simulation={comparison.total_W.simulation}
              diffPercent={comparison.total_W.difference_percent}
            />
              queueName="Coordinateur"
              queueComparison={comparison.coordinator}

            {/* Servers */}
            {Object.entries(comparison.servers).map(([serverId, serverComparison]) => (
              <QueueComparisonSection
                key={serverId}
                queueName={
                  serverId.replace('_', ' ').charAt(0).toUpperCase() +
                  serverId.replace('_', ' ').slice(1)
                }
                queueComparison={serverComparison}
              />
            ))}
          </TableBody>
        </Table>
      </TableContainer>
      <Stack direction="row" spacing={3} justifyContent="flex-end" sx={{ mt: 2 }}>
        <Stack direction="row" spacing={0.5} alignItems="center">
          <Box sx={{ width: 12, height: 12, bgcolor: 'success.main', borderRadius: 0.5 }} />
          <Typography variant="caption" color="text.secondary">
            &lt; 5% (excellent)
          </Typography>
        </Stack>
        <Stack direction="row" spacing={0.5} alignItems="center">
          <Box sx={{ width: 12, height: 12, bgcolor: 'warning.main', borderRadius: 0.5 }} />
          <Typography variant="caption" color="text.secondary">
            5-10% (acceptable)
          </Typography>
        </Stack>
        <Stack direction="row" spacing={0.5} alignItems="center">
          <Box sx={{ width: 12, height: 12, bgcolor: 'error.main', borderRadius: 0.5 }} />
          <Typography variant="caption" color="text.secondary">
            &gt; 10% (important)
          </Typography>
        </Stack>
      </Stack>
    </Box>