// Format numbers to 2-3 decimal places for better readability export const formatNumber = (num, decimals = 2) => { if (typeof num !== 'number' || isNaN(num)) return '0.00'; return Number(num.toFixed(decimals)); }; // Format risk score with appropriate color class export const getRiskLevel = (score) => { if (score < 0.3) return { level: 'Low', class: 'risk-low' }; if (score < 0.7) return { level: 'Medium', class: 'risk-medium' }; return { level: 'High', class: 'risk-high' }; }; // Format timestamp to readable time export const formatTime = (timestamp) => { try { const date = new Date(timestamp); return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', second: '2-digit', hour12: true }); } catch (error) { return 'Invalid time'; } }; // Format device ID for display export const formatDeviceId = (vid, pid) => { return `${vid}/${pid}`; }; // Calculate progress bar width and color export const getProgressBarStyle = (value, type = 'default') => { const width = Math.max(0, Math.min(100, value * 100)); let backgroundColor = '#3b82f6'; // Default blue switch (type) { case 'risk': if (value > 0.7) backgroundColor = '#dc2626'; // Red else if (value > 0.3) backgroundColor = '#d97706'; // Orange else backgroundColor = '#059669'; // Green break; case 'ml-score': if (value > 0.7) backgroundColor = '#dc2626'; // Red for high anomaly else if (value > 0.3) backgroundColor = '#d97706'; // Orange for medium else backgroundColor = '#059669'; // Green for low anomaly break; case 'confidence': if (value > 0.8) backgroundColor = '#1e59f0'; // Blue for high confidence else if (value > 0.6) backgroundColor = '#d97706'; // Orange for medium else backgroundColor = '#dc2626'; // Red for low confidence break; default: backgroundColor = '#3b82f6'; // Default blue } return { width: `${width}%`, backgroundColor, }; }; // Device reference database export const DEVICE_DATABASE = { '0x046d': { name: 'Logitech', devices: { '0xc077': 'MX Master 3', '0xc52b': 'MX Master 2S', '0xc548': 'MX Master 3S', '0xc52f': 'MX Anywhere 2S', '0xc541': 'MX Anywhere 3', '0xc52e': 'G Pro Wireless', '0xc539': 'G Pro X Superlight', '0xc534': 'G502 Hero', '0xc332': 'G403 Hero', '0xc336': 'G703 Hero', } }, '0x045e': { name: 'Microsoft', devices: { '0x00cb': 'Surface Mouse', '0x00f6': 'Surface Precision Mouse', '0x0745': 'Wireless Mouse 5000', '0x07a5': 'Wireless Mouse 4000', '0x07b2': 'Wireless Mouse 3000', } }, '0x1532': { name: 'Razer', devices: { '0x0067': 'DeathAdder V2', '0x0073': 'Viper Ultimate', '0x007c': 'Basilisk V3', '0x0084': 'Naga Pro', '0x0090': 'DeathAdder V3 Pro', } }, '0x1038': { name: 'SteelSeries', devices: { '0x1384': 'Rival 600', '0x1392': 'Rival 650', '0x1394': 'Rival 710', '0x1396': 'Sensei 310', '0x1398': 'Rival 310', } } }; // Get device information from VID/PID export const getDeviceInfo = (vid, pid) => { const vendor = DEVICE_DATABASE[vid]; if (!vendor) { return { vendor: 'Unknown', model: 'Unknown Device', fullName: `${vid}/${pid}` }; } const model = vendor.devices[pid] || 'Unknown Model'; return { vendor: vendor.name, model, fullName: `${vendor.name} ${model}` }; };