import 'package:nmea/nmea.dart'; class Gngga extends TalkerSentence { static const String id = "GxGGA"; Gngga({required super.raw}); @override bool get valid => super.valid && fields.length >= 15; String get utcOfPositionFix => _field(1); int get gpsQualityIndicator => _parseInt(_field(6), fallback: 0); String get latitudeDirection => _field(3).toUpperCase(); double get latitude => _parseLatitude(_field(2), latitudeDirection) ?? 0.0; String get longitudeDirection => _field(5).toUpperCase(); double get longitude => _parseLongitude(_field(4), longitudeDirection) ?? 0.0; int get numberOfSvsInUse => _parseInt(_field(7), fallback: 0); double get hdop => _parseDouble(_field(8), fallback: 0.0); double get altitudeAboveMeanSeaLevel => _parseDouble(_field(9), fallback: 0.0); double get geoidSeparation => _parseDouble(_field(11), fallback: 0.0); String _field(int index) { if (index < 0 || index >= fields.length) return ''; return fields[index].trim(); } int _parseInt(String value, {required int fallback}) { return int.tryParse(value) ?? fallback; } double _parseDouble(String value, {required double fallback}) { return double.tryParse(value) ?? fallback; } double? _parseLatitude(String value, String direction) { if (value.length < 4) return null; // ddmm.mmmm final deg = double.tryParse(value.substring(0, 2)); final min = double.tryParse(value.substring(2)); if (deg == null || min == null) return null; final result = deg + (min / 60.0); return direction == 'S' ? -result : result; } double? _parseLongitude(String value, String direction) { if (value.length < 5) return null; // dddmm.mmmm final deg = double.tryParse(value.substring(0, 3)); final min = double.tryParse(value.substring(3)); if (deg == null || min == null) return null; final result = deg + (min / 60.0); return direction == 'W' ? -result : result; } }