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)}%
</TableCell>
</TableRow>
);
}
function QueueComparisonSection({
queueName,
queueComparison,
}: {
queueName: string;
queueComparison: QueueComparison;
}) {
return (
<>
<TableRow sx={{ bgcolor: 'grey.100' }}>
<TableCell colSpan={4} sx={{ fontWeight: 600, py: 1 }}>
{queueName}
</TableCell>
</TableRow>
<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 (
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<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}
/>
{/* Coordinator */}
<QueueComparisonSection
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>
{/* Legend */}
<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">
< 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">
> 10% (important)
</Typography>
</Stack>
</Stack>
</Box>