import { SensorConfig, SensorZoneConfig } from '@/types/sensor'; // Define zone-based default configurations export const ZONE_CONFIGS: Record = { head: { zone: 'head', defaultThresholds: { warningThreshold: 3000, alarmThreshold: 3500, warningDelayMs: 30000 // 30 seconds - critical area needs fast response }, description: 'Head area - most critical, fastest escalation' }, shoulders: { zone: 'shoulders', defaultThresholds: { warningThreshold: 2800, alarmThreshold: 3200, warningDelayMs: 45000 // 45 seconds }, description: 'Shoulder area - high priority, moderate escalation' }, back: { zone: 'back', defaultThresholds: { warningThreshold: 2500, alarmThreshold: 3000, warningDelayMs: 60000 // 1 minute }, description: 'Back area - moderate priority, standard escalation' }, hips: { zone: 'hips', defaultThresholds: { warningThreshold: 2200, alarmThreshold: 2800, warningDelayMs: 90000 // 90 seconds }, description: 'Hip area - moderate priority, longer escalation' }, legs: { zone: 'legs', defaultThresholds: { warningThreshold: 2000, alarmThreshold: 2500, warningDelayMs: 120000 // 2 minutes }, description: 'Leg area - lower priority, extended escalation' }, feet: { zone: 'feet', defaultThresholds: { warningThreshold: 1500, alarmThreshold: 1800, warningDelayMs: 180000 // 3 minutes }, description: 'Feet area - lowest priority, longest escalation' } }; /** * Validates sensor configuration against zone defaults */ export function validateSensorConfig(config: SensorConfig): { isValid: boolean; warnings: string[]; errors: string[]; } { const warnings: string[] = []; const errors: string[] = []; // Check if zone exists const zoneConfig = ZONE_CONFIGS[config.zone]; if (!zoneConfig) { errors.push(`Unknown zone: ${config.zone}`); return { isValid: false, warnings, errors }; } // Validate threshold values if (config.alarmThreshold <= config.warningThreshold) { errors.push(`Alarm threshold (${config.alarmThreshold}) must be greater than warning threshold (${config.warningThreshold})`); } if (config.warningThreshold <= 0 || config.alarmThreshold <= 0) { errors.push('Thresholds must be positive values'); } if (config.warningDelayMs <= 0) { errors.push('Warning delay must be positive'); } // Check against zone defaults (warnings only) const defaults = zoneConfig.defaultThresholds; const tolerance = 0.2; // 20% tolerance if (Math.abs(config.warningThreshold - defaults.warningThreshold) / defaults.warningThreshold > tolerance) { warnings.push(`Warning threshold (${config.warningThreshold}) differs significantly from zone default (${defaults.warningThreshold})`); } if (Math.abs(config.alarmThreshold - defaults.alarmThreshold) / defaults.alarmThreshold > tolerance) { warnings.push(`Alarm threshold (${config.alarmThreshold}) differs significantly from zone default (${defaults.alarmThreshold})`); } if (Math.abs(config.warningDelayMs - defaults.warningDelayMs) / defaults.warningDelayMs > tolerance) { warnings.push(`Warning delay (${config.warningDelayMs}ms) differs significantly from zone default (${defaults.warningDelayMs}ms)`); } return { isValid: errors.length === 0, warnings, errors }; } /** * Creates a sensor config with zone defaults as base */ export function createSensorConfig( id: string, position: { x: number; y: number }, zone: string, label: string, overrides: Partial = {} ): SensorConfig { const zoneConfig = ZONE_CONFIGS[zone]; if (!zoneConfig) { throw new Error(`Unknown zone: ${zone}`); } return { id, x: position.x, y: position.y, zone, label, ...zoneConfig.defaultThresholds, ...overrides }; } /** * Gets human-readable duration string */ export function formatDuration(ms: number): string { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); if (hours > 0) { return `${hours}h ${minutes % 60}m`; } else if (minutes > 0) { return `${minutes}m ${seconds % 60}s`; } else { return `${seconds}s`; } }