diff --git a/analyze_sport_data/file_records.py b/analyze_sport_data/file_records.py index d0c6cff..d2e3dac 100644 --- a/analyze_sport_data/file_records.py +++ b/analyze_sport_data/file_records.py @@ -1,6 +1,7 @@ -from datetime import timedelta +from datetime import datetime, timedelta from analyze_sport_data.heart_rate_record import HeartRateRecord from garmin_fit_sdk import Decoder, Stream +from xml.etree import ElementTree class FileRecords: @@ -30,3 +31,49 @@ def from_fit_file(file_path: str, ] return FileRecords(friendly_name if friendly_name != None else file_path, heart_rate_records) + + +def from_tcx_file(file_path: str, + friendly_name: str | None = None) -> FileRecords: + empty_file_records = FileRecords(file_path, []) + heart_rate_records: list[HeartRateRecord] = [] + + activities_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Activities' + activity_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Activity' + lap_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Lap' + track_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Track' + trackpoint_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Trackpoint' + time_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Time' + heart_rate_bpm_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}HeartRateBpm' + value_tag = '{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Value' + + activities = ElementTree.parse(file_path).getroot().find(activities_tag) + if activities == None: + return empty_file_records + + for activity in activities.findall(activity_tag): + for lap in activity.findall(lap_tag): + for track in lap.findall(track_tag): + for trackpoint in track.findall(trackpoint_tag): + heart_rate = trackpoint.find(heart_rate_bpm_tag) + if heart_rate == None: + continue + if type(heart_rate) is not ElementTree.Element: + continue + heart_rate_value = heart_rate.find(value_tag) + if heart_rate_value is None or heart_rate_value.text is None: + continue + + iso_time_element = trackpoint.find(time_tag) + if type(iso_time_element) is not ElementTree.Element: + continue + if iso_time_element.text is None: + continue + + record_at = datetime.fromisoformat(iso_time_element.text) + heart_rate_records.append( + HeartRateRecord(record_at, + float(heart_rate_value.text))) + + return FileRecords(friendly_name if friendly_name != None else file_path, + heart_rate_records)