import 'package:xml/xml.dart'; import 'package:latlong2/latlong.dart'; import 'package:aves/model/activity/activity_track.dart'; import 'gps_smoothing.dart'; class TcxActivityParser { static ActivityTrack parse(String xml, {required String fileName}) { final doc = XmlDocument.parse(xml); final points = []; final elevations = []; final times = []; final trackpoints = doc.findAllElements('Trackpoint'); for (final tp in trackpoints) { final lat = tp.findElements('LatitudeDegrees') .map((e) => double.tryParse(e.text)) .firstOrNull; final lon = tp.findElements('LongitudeDegrees') .map((e) => double.tryParse(e.text)) .firstOrNull; final ele = tp.findElements('AltitudeMeters') .map((e) => double.tryParse(e.text)) .firstOrNull; final time = tp.findElements('Time') .map((e) => DateTime.tryParse(e.text)) .firstOrNull; if (lat != null && lon != null) { points.add(LatLng(lat, lon)); elevations.add(ele); times.add(time); } } final smoothed = GpsSmoothing.douglasPeucker(points, 5.0); return ActivityTrack( name: fileName, format: 'TCX', tracks: {smoothed}, pointCount: smoothed.length, distanceMeters: null, elevationGainMeters: null, duration: null, startTime: times.firstOrNull, sport: null, ); } } extension _FirstOrNull on Iterable { E? get firstOrNull { final it = iterator; if (!it.moveNext()) return null; return it.current; } }