/** * Parameter panel with Material-UI - input fields for simulation configuration */ import { useState } from 'react'; import { Box, TextField, Typography, Divider, Button, IconButton, Paper, Alert, Stack, ToggleButtonGroup, ToggleButton, } from '@mui/material'; import { Add as AddIcon, Delete as DeleteIcon, CheckCircle as CheckCircleIcon, Error as ErrorIcon, } from '@mui/icons-material'; import { useSimulationStore } from '../../store/simulationStore'; import TimeConverter from '../tools/TimeConverter'; type TimeUnit = 'ms' | 's'; export default function ParameterPanel() { const { config, updateConfig, addServer, removeServer, updateServer, isRunning, } = useSimulationStore(); const [timeUnit, setTimeUnit] = useState('ms'); if (!config) { return ( Aucune configuration chargée ); } // Conversion helpers const convertToRate = (meanTime: number): number => { if (meanTime === 0) return 0; const timeInMs = timeUnit === 's' ? meanTime * 1000 : meanTime; return 1 / timeInMs; }; const convertFromRate = (rate: number): number => { if (rate === 0) return 0; const timeInMs = 1 / rate; return timeUnit === 's' ? timeInMs / 1000 : timeInMs; }; const handleTimeUnitChange = (_: React.MouseEvent, newUnit: TimeUnit | null) => { if (newUnit !== null) { setTimeUnit(newUnit); } }; const handleArrivalRateChange = (e: React.ChangeEvent) => { const meanTime = parseFloat(e.target.value) || 0; updateConfig({ arrival_rate: convertToRate(meanTime) }); }; const handleCoordinatorServiceRateChange = (e: React.ChangeEvent) => { const meanTime = parseFloat(e.target.value) || 0; updateConfig({ coordinator_service_rate: convertToRate(meanTime) }); }; const handleExitProbabilityChange = (e: React.ChangeEvent) => { updateConfig({ coordinator_exit_probability: parseFloat(e.target.value) || 0 }); }; const handleServerServiceRateChange = (serverId: string, value: string) => { const meanTime = parseFloat(value) || 0; updateServer(serverId, { service_rate: convertToRate(meanTime) }); }; const handleServerRoutingProbChange = (serverId: string, value: string) => { updateServer(serverId, { routing_probability: parseFloat(value) || 0 }); }; // Calculate total routing probability const totalRoutingProb = config.coordinator_exit_probability + config.servers.reduce((sum, s) => sum + s.routing_probability, 0); const isProbabilityValid = Math.abs(totalRoutingProb - 1.0) < 0.001; return ( Paramètres du réseau ms s {/* External arrival rate */} {timeUnit} }} /> {/* Coordinator parameters */} Coordinateur {timeUnit} }} /> {/* Servers */} Serveurs {config.servers.map((server, index) => ( Serveur {index + 1} {config.servers.length > 1 && ( removeServer(server.id)} disabled={isRunning} color="error" > )} handleServerServiceRateChange(server.id, e.target.value)} disabled={isRunning} fullWidth size="small" helperText={`En ${timeUnit === 'ms' ? 'millisecondes' : 'secondes'}`} InputProps={{ endAdornment: {timeUnit} }} /> handleServerRoutingProbChange(server.id, e.target.value)} disabled={isRunning} fullWidth size="small" /> ))} {/* Probability validation */} : } > Conservation des probabilités p + Σq = {totalRoutingProb.toFixed(3)} {isProbabilityValid ? ' = 1.0 ✓' : ' ≠ 1.0 ✗'} {/* Time unit converter */} ); }