import 'package:flutter/material.dart'; enum FieldTestEventType { appLaunched, preRideCheckStarted, preRideCheckCompleted, rideStartRequested, rideStateChanged, foregroundServiceStartRequested, foregroundServiceStarted, wakelockAcquired, gpsStreamStarted, gpsFirstFix, gpsFixReceived, imuStreamStarted, imuFirstSample, telemetryPipelineStarted, firstTelemetrySample, telemetryHeartbeat, databaseOpened, databaseWrite, queueEnqueue, queueFlush, queueDrop, rideStarted, rideStopped, gpsStale, gpsRecovered, gpsJumpRejected, gpsAccuracyDegraded, imuSaturation, imuRecovered, telemetryGap, telemetryRecovered, timestampError, sampleAccepted, sampleSuspect, sampleRejected, accelerationEvent, brakingEvent, performanceRunStarted, performanceRunCompleted, performanceRunRejected, appPaused, appResumed, screenOff, screenOn, foregroundServiceStopped, rideFinishRequested, rideFinalized, rideSummaryCreated, databaseFlush, databaseQueueWarning, databaseQueueOverflow, databaseRecovery, exportStarted, exportCompleted, exportFailed, sensorInitialized, sensorError, gpsInitialized, gpsError, telemetryError, databaseError, serviceError, calibrationStarted, calibrationCompleted, roadAlertReceived, ttsAnnounced, audioFailure, networkError, unhandledException; String get displayName { switch (this) { case FieldTestEventType.appLaunched: return 'APP_LAUNCHED'; case FieldTestEventType.preRideCheckStarted: return 'PRE_RIDE_CHECK_STARTED'; case FieldTestEventType.preRideCheckCompleted: return 'PRE_RIDE_CHECK_COMPLETED'; case FieldTestEventType.rideStartRequested: return 'RIDE_START_REQUESTED'; case FieldTestEventType.rideStateChanged: return 'RIDE_STATE_CHANGED'; case FieldTestEventType.foregroundServiceStartRequested: return 'FOREGROUND_SERVICE_START_REQUESTED'; case FieldTestEventType.foregroundServiceStarted: return 'FOREGROUND_SERVICE_STARTED'; case FieldTestEventType.wakelockAcquired: return 'WAKELOCK_ACQUIRED'; case FieldTestEventType.gpsStreamStarted: return 'GPS_STREAM_STARTED'; case FieldTestEventType.gpsFirstFix: return 'GPS_FIRST_FIX'; case FieldTestEventType.gpsFixReceived: return 'GPS_FIX_RECEIVED'; case FieldTestEventType.imuStreamStarted: return 'IMU_STREAM_STARTED'; case FieldTestEventType.imuFirstSample: return 'IMU_FIRST_SAMPLE'; case FieldTestEventType.telemetryPipelineStarted: return 'TELEMETRY_PIPELINE_STARTED'; case FieldTestEventType.firstTelemetrySample: return 'FIRST_TELEMETRY_SAMPLE'; case FieldTestEventType.telemetryHeartbeat: return 'TELEMETRY_HEARTBEAT'; case FieldTestEventType.databaseOpened: return 'DATABASE_OPENED'; case FieldTestEventType.databaseWrite: return 'DATABASE_WRITE'; case FieldTestEventType.queueEnqueue: return 'QUEUE_ENQUEUE'; case FieldTestEventType.queueFlush: return 'QUEUE_FLUSH'; case FieldTestEventType.queueDrop: return 'QUEUE_DROP'; case FieldTestEventType.rideStarted: return 'RIDE_STARTED'; case FieldTestEventType.rideStopped: return 'RIDE_STOPPED'; case FieldTestEventType.gpsStale: return 'GPS_STALE'; case FieldTestEventType.gpsRecovered: return 'GPS_RECOVERED'; case FieldTestEventType.gpsJumpRejected: return 'GPS_JUMP_REJECTED'; case FieldTestEventType.gpsAccuracyDegraded: return 'GPS_ACCURACY_DEGRADED'; case FieldTestEventType.imuSaturation: return 'IMU_SATURATION'; case FieldTestEventType.imuRecovered: return 'IMU_RECOVERED'; case FieldTestEventType.telemetryGap: return 'TELEMETRY_GAP'; case FieldTestEventType.telemetryRecovered: return 'TELEMETRY_RECOVERED'; case FieldTestEventType.timestampError: return 'TIMESTAMP_ERROR'; case FieldTestEventType.sampleAccepted: return 'SAMPLE_ACCEPTED'; case FieldTestEventType.sampleSuspect: return 'SAMPLE_SUSPECT'; case FieldTestEventType.sampleRejected: return 'SAMPLE_REJECTED'; case FieldTestEventType.accelerationEvent: return 'ACCELERATION_EVENT'; case FieldTestEventType.brakingEvent: return 'BRAKING_EVENT'; case FieldTestEventType.performanceRunStarted: return 'PERFORMANCE_RUN_STARTED'; case FieldTestEventType.performanceRunCompleted: return 'PERFORMANCE_RUN_COMPLETED'; case FieldTestEventType.performanceRunRejected: return 'PERFORMANCE_RUN_REJECTED'; case FieldTestEventType.appPaused: return 'APP_PAUSED'; case FieldTestEventType.appResumed: return 'APP_RESUMED'; case FieldTestEventType.screenOff: return 'SCREEN_OFF'; case FieldTestEventType.screenOn: return 'SCREEN_ON'; case FieldTestEventType.foregroundServiceStopped: return 'FOREGROUND_SERVICE_STOPPED'; case FieldTestEventType.rideFinishRequested: return 'RIDE_FINISH_REQUESTED'; case FieldTestEventType.rideFinalized: return 'RIDE_FINALIZED'; case FieldTestEventType.rideSummaryCreated: return 'RIDE_SUMMARY_CREATED'; case FieldTestEventType.databaseFlush: return 'DATABASE_FLUSH'; case FieldTestEventType.databaseQueueWarning: return 'DATABASE_QUEUE_WARNING'; case FieldTestEventType.databaseQueueOverflow: return 'DATABASE_QUEUE_OVERFLOW'; case FieldTestEventType.databaseRecovery: return 'DATABASE_RECOVERY'; case FieldTestEventType.exportStarted: return 'EXPORT_STARTED'; case FieldTestEventType.exportCompleted: return 'EXPORT_COMPLETED'; case FieldTestEventType.exportFailed: return 'EXPORT_FAILED'; case FieldTestEventType.sensorInitialized: return 'SENSOR_INITIALIZED'; case FieldTestEventType.sensorError: return 'SENSOR_ERROR'; case FieldTestEventType.gpsInitialized: return 'GPS_INITIALIZED'; case FieldTestEventType.gpsError: return 'GPS_ERROR'; case FieldTestEventType.telemetryError: return 'TELEMETRY_ERROR'; case FieldTestEventType.databaseError: return 'DATABASE_ERROR'; case FieldTestEventType.serviceError: return 'SERVICE_ERROR'; case FieldTestEventType.calibrationStarted: return 'CALIBRATION_STARTED'; case FieldTestEventType.calibrationCompleted: return 'CALIBRATION_COMPLETED'; case FieldTestEventType.roadAlertReceived: return 'ROAD_ALERT_RECEIVED'; case FieldTestEventType.ttsAnnounced: return 'TTS_ANNOUNCED'; case FieldTestEventType.audioFailure: return 'AUDIO_FAILURE'; case FieldTestEventType.networkError: return 'NETWORK_ERROR'; case FieldTestEventType.unhandledException: return 'UNHANDLED_EXCEPTION'; } } static FieldTestEventType fromString(String val) { final clean = val.toUpperCase().replaceAll('-', '_'); for (final e in FieldTestEventType.values) { if (e.displayName == clean || e.name.toUpperCase() == clean) { return e; } } return FieldTestEventType.sampleAccepted; } } enum EventSeverity { info, warning, error, critical; String get displayName => name.toUpperCase(); Color get color { switch (this) { case EventSeverity.info: return Colors.cyanAccent; case EventSeverity.warning: return Colors.amberAccent; case EventSeverity.error: return Colors.orangeAccent; case EventSeverity.critical: return Colors.redAccent; } } static EventSeverity fromString(String val) { switch (val.toUpperCase()) { case 'CRITICAL': return EventSeverity.critical; case 'ERROR': return EventSeverity.error; case 'WARNING': return EventSeverity.warning; case 'INFO': default: return EventSeverity.info; } } } class FieldTestEvent { final int? id; final int? rideId; final int? sessionId; final DateTime timestamp; final FieldTestEventType eventType; final EventSeverity severity; final String message; final String? component; final String? rideState; final String? recordingState; final bool? gpsAvailability; final bool? imuAvailability; final double? telemetrySampleRate; final int? queueDepth; final String? databaseStatus; final bool? foregroundServiceStatus; final DateTime? telemetryTimestamp; final int? gpsAgeMs; final double? speed; final double? latitude; final double? longitude; final double? gpsAccuracy; final double? leanAngle; final double? longitudinalG; final double? lateralG; final double? overallConfidence; final Map? metadata; const FieldTestEvent({ this.id, this.rideId, this.sessionId, required this.timestamp, required this.eventType, required this.severity, required this.message, this.component, this.rideState, this.recordingState, this.gpsAvailability, this.imuAvailability, this.telemetrySampleRate, this.queueDepth, this.databaseStatus, this.foregroundServiceStatus, this.telemetryTimestamp, this.gpsAgeMs, this.speed, this.latitude, this.longitude, this.gpsAccuracy, this.leanAngle, this.longitudinalG, this.lateralG, this.overallConfidence, this.metadata, }); }