diff --git a/code/corelation.py b/code/corelation.py index 15cad3a..47917ad 100644 --- a/code/corelation.py +++ b/code/corelation.py @@ -2,82 +2,236 @@ import pandas as pd import matplotlib.pyplot as plt import numpy as np from datetime import datetime - +import os +# Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch +# month_translation = { +# 'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun', +# 'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec', 'Mrz': 'Mar' +# } + + +# Funktion, um 'Okt 10-16' in eine Kalenderwoche zu konvertieren und das Startdatum zurückzugeben +# def convert_to_week_number_and_start_date(date_range_str): +# # Splitte den Datumsbereich in Monat und Tage +# start_part, end_part = date_range_str.split(" - ") +# start_month_str, start_day = start_part.split(" ") +# start_day = int(start_day) # Nimm den Starttag +# +# # Konvertiere den deutschen Monatsnamen in den englischen +# if start_month_str in month_translation: +# start_month_str = month_translation[start_month_str] +# +# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr +# current_year = datetime.now().year +# date_str = f"{start_month_str} {start_day} {current_year}" +# +# try: +# start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum +# except ValueError: +# raise ValueError(f"Ungültiges Datum: {date_str}") +# +# week_number = start_date.isocalendar()[1] # Kalenderwoche ermitteln +# +# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück +# Funktion, um 'Okt 10-16' oder 'Okt 10 - 16' in eine Kalenderwoche zu konvertieren und das Startdatum zurückzugeben +# def convert_to_week_number_and_start_date(date_range_str): +# # Entferne zusätzliche Leerzeichen um den Bindestrich herum +# date_range_str = date_range_str.replace(" - ", "-") +# +# # Splitte den Datumsbereich in Start- und Endbereich +# start_part, end_part = date_range_str.split("-") +# start_month_str, start_day = start_part.split(" ") +# start_day = int(start_day.strip()) # Nimm den Starttag und entferne etwaige Leerzeichen +# +# # Konvertiere den deutschen Monatsnamen in den englischen +# if start_month_str in month_translation: +# start_month_str = month_translation[start_month_str] +# +# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr +# current_year = datetime.now().year +# date_str = f"{start_month_str} {start_day} {current_year}" +# +# try: +# start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum +# except ValueError: +# raise ValueError(f"Ungültiges Datum: {date_str}") +# +# week_number = start_date.isocalendar()[1] # Kalenderwoche ermitteln +# +# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück + +# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Okt 10-16' in die Kalenderwoche zu konvertieren +# und das Startdatum zurückzugeben +# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Okt 10-16' in die Kalenderwoche zu konvertieren +# und das Startdatum zurückzugeben +# def convert_to_week_number_and_start_date(date_range_str): +# # Entferne zusätzliche Leerzeichen um den Bindestrich herum +# date_range_str = date_range_str.replace(" - ", "-") +# +# # Splitte den Datumsbereich in Start- und Endteil +# start_part, end_part = date_range_str.split("-") +# +# # Verarbeite den Startteil +# start_month_str, start_day = start_part.split(" ") +# start_day = int(start_day.strip()) # Nimm den Starttag und entferne etwaige Leerzeichen +# +# # Wenn der Endteil einen Monat enthält, verarbeite ihn ebenfalls +# if " " in end_part: +# end_month_str, end_day = end_part.split(" ") +# end_day = int(end_day.strip()) # Nimm den Endtag +# else: +# # Wenn der Endteil keinen Monat enthält, verwenden wir denselben Monat wie im Startteil +# end_month_str = start_month_str +# end_day = int(end_part.strip()) +# +# # Konvertiere den deutschen Monatsnamen in den englischen für beide Monate +# if start_month_str in month_translation: +# start_month_str = month_translation[start_month_str] +# if end_month_str in month_translation: +# end_month_str = month_translation[end_month_str] +# +# # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr +# current_year = datetime.now().year +# start_date_str = f"{start_month_str} {start_day} {current_year}" +# +# try: +# # Konvertiere in ein Datum +# start_date = datetime.strptime(start_date_str, "%b %d %Y") +# except ValueError: +# raise ValueError(f"Ungültiges Startdatum: {start_date_str}") +# +# # Berechne die Kalenderwoche basierend auf dem Startdatum +# week_number = start_date.isocalendar()[1] +# +# return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück # Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch month_translation = { - 'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun', + 'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Mrz': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun', 'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec' } -# Funktion, um 'Okt 10-16' in eine Kalenderwoche zu konvertieren -def convert_to_week_number(date_range_str): - # Splitte den Datumsbereich in Monat und Tage - month_str, day_range = date_range_str.split(" ") - start_day = int(day_range.split("-")[0]) # Nimm den Starttag - current_year = datetime.now().year - # Konvertiere den deutschen Monatsnamen in den englischen - if month_str in month_translation: - month_str = month_translation[month_str] +# Funktion, um Datumsbereiche wie 'Mrz 29-Apr 4' oder 'Dez 29, 2023-Jan 4, 2024' in die Kalenderwoche und das Startdatum zu konvertieren +def convert_to_week_number_and_start_date(date_range_str): + # Entferne zusätzliche Leerzeichen um den Bindestrich herum + date_range_str = date_range_str.replace(" - ", "-").replace(",", "") - # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr - date_str = f"{month_str} {start_day} {current_year}" - start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum - return start_date.isocalendar()[1] # Gib die Kalenderwoche zurück + # Splitte den Datumsbereich in Start- und Endteil + start_part, end_part = date_range_str.split("-") + + # Verarbeite den Startteil + start_parts = start_part.split(" ") + start_month_str = start_parts[0] + start_day = int(start_parts[1].strip()) # Nimm den Starttag und entferne etwaige Leerzeichen + + # Verarbeite den Endteil + end_parts = end_part.split(" ") + + if len(end_parts) == 2: + end_month_str = end_parts[0] + end_day = int(end_parts[1].strip()) # Nimm den Endtag + else: + end_month_str = start_month_str # Falls kein Monat angegeben, setze den Startmonat + end_day = int(end_parts[0].strip()) + + # Konvertiere den deutschen Monatsnamen in den englischen für beide Monate + if start_month_str in month_translation: + start_month_str = month_translation[start_month_str] + if end_month_str in month_translation: + end_month_str = month_translation[end_month_str] + + # Wenn der Startteil ein Jahr enthält, nutze dieses + if len(start_parts) == 3: + current_year = int(start_parts[2]) + else: + current_year = datetime.now().year + + # Wenn der Datumsbereich über den Dezember hinausgeht, endet das Enddatum im nächsten Jahr + if start_month_str == 'Dec' and end_month_str == 'Jan': + end_year = current_year + 1 + else: + end_year = current_year + + try: + # Konvertiere das Startdatum in ein Datum + start_date = datetime.strptime(f"{start_month_str} {start_day} {current_year}", "%b %d %Y") + except ValueError: + raise ValueError(f"Ungültiges Startdatum: {start_month_str} {start_day} {current_year}") + + try: + # Konvertiere das Enddatum in ein Datum + end_date = datetime.strptime(f"{end_month_str} {end_day} {end_year}", "%b %d %Y") + except ValueError: + raise ValueError(f"Ungültiges Enddatum: {end_month_str} {end_day} {end_year}") + + # Berechne die Kalenderwoche basierend auf dem Startdatum + week_number = start_date.isocalendar()[1] + + return week_number, start_date.strftime('%Y-%m-%d') # Gib KW und das Startdatum zurück -# Schritt 1: Lade die HR-Daten (mit Semikolon separiert) und entferne 'bpm' -hr_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/hr_gramic.csv', sep=';') +# Funktion zum Bereinigen und Zwischenspeichern der Daten +def clean_and_save_data(hr_data, sleep_data, output_dir='sandbox'): + # Entferne 'bpm' und konvertiere die Werte in numerische Daten + hr_data['In Ruhe'] = hr_data['In Ruhe'].str.replace(' bpm', '').astype(float) + hr_data['Hoch'] = hr_data['Hoch'].str.replace(' bpm', '').astype(float) -# Zeige die ersten Zeilen der HR-Daten vor der Bereinigung -print("HR-Daten (vor der Bereinigung):") -print(hr_data.head()) + # Konvertiere die Spalte 'Datum' in Kalenderwoche (KW) und Startdatum + hr_data[['week', 'start_date']] = hr_data['Datum'].apply( + lambda x: pd.Series(convert_to_week_number_and_start_date(x))) -# Entferne 'bpm' und konvertiere die Werte in numerische Daten -hr_data['In Ruhe'] = hr_data['In Ruhe'].str.replace(' bpm', '').astype(float) -hr_data['Hoch'] = hr_data['Hoch'].str.replace(' bpm', '').astype(float) + # Berechne den Durchschnitt der Herzfrequenzdaten (In Ruhe und Hoch) + hr_data['avg_hr'] = hr_data[['In Ruhe', 'Hoch']].mean(axis=1) -# Konvertiere die Spalte 'Datum' in Kalenderwoche (KW) -hr_data['week'] = hr_data['Datum'].apply(convert_to_week_number) + # Konvertiere auch das 'Datum' der Schlafdaten in Kalenderwoche (KW) und Startdatum + sleep_data[['week', 'start_date']] = sleep_data['Datum'].apply( + lambda x: pd.Series(convert_to_week_number_and_start_date(x))) -# Zeige die HR-Daten nach der Umwandlung in Wochen -print("\nHR-Daten (nach der Umwandlung in KW):") -print(hr_data.head()) + # Speichere die bereinigten Daten in 'sandbox' + if not os.path.exists(output_dir): + os.makedirs(output_dir) -# Schritt 2: Berechne den Durchschnitt der Herzfrequenzdaten (In Ruhe und Hoch) -hr_data['avg_hr'] = hr_data[['In Ruhe', 'Hoch']].mean(axis=1) + hr_data_clean_path = os.path.join(output_dir, 'hr_data_clean.csv') + sleep_data_clean_path = os.path.join(output_dir, 'sleep_data_clean.csv') -# Schritt 3: Lade die Schlafdaten (mit Komma separiert) -sleep_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/sleep_gramic.csv', sep=',') + hr_data.to_csv(hr_data_clean_path, sep=';', index=False) + sleep_data.to_csv(sleep_data_clean_path, sep=',', index=False) -# Zeige die ersten Zeilen der Schlafdaten -print("\nSchlafdaten:") -print(sleep_data.head()) + print(f"HR-Daten wurden bereinigt und in {hr_data_clean_path} gespeichert.") + print(f"Schlafdaten wurden bereinigt und in {sleep_data_clean_path} gespeichert.") -# Konvertiere auch das 'Datum' der Schlafdaten in Kalenderwoche (KW) -sleep_data['week'] = sleep_data['Datum'].apply(convert_to_week_number) + return hr_data, sleep_data -# Schritt 4: Sicherstellen, dass beide Datensätze nach 'week' sortiert sind -hr_data = hr_data.sort_values(by='week') -sleep_data = sleep_data.sort_values(by='week') -# Schritt 5: Kombiniere die beiden Datensätze anhand der 'week' Spalte mit einem äußeren Join -combined_data = pd.merge(hr_data, sleep_data, on='week', how='outer') +# Schritt 1: Lade die HR- und Schlafdaten +hr_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/hr_gramic.csv', + sep=';') +sleep_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/sleep_gramic.csv', + sep=',') + +# Bereinige und speichere die Daten +hr_data, sleep_data = clean_and_save_data(hr_data, sleep_data) + +# Schritt 2: Sortiere beide Datensätze nach 'week' und 'start_date' +hr_data = hr_data.sort_values(by=['week', 'start_date']) +sleep_data = sleep_data.sort_values(by=['week', 'start_date']) + +# Schritt 3: Kombiniere die beiden Datensätze anhand der 'week' und 'start_date' Spalten mit einem äußeren Join +combined_data = pd.merge(hr_data, sleep_data, on=['week', 'start_date'], how='outer') # Zeige die kombinierten Daten print("\nKombinierte Daten:") print(combined_data) -# Schritt 6: Entferne alle Zeilen mit fehlenden Daten +# Schritt 4: Entferne alle Zeilen mit fehlenden Daten combined_data = combined_data.dropna() -# Schritt 7: Berechne die Korrelation zwischen dem durchschnittlichen Herzfrequenzwert ('avg_hr') und der Schlafdauer ('Durchschnittliche Dauer') +# Schritt 5: Berechne die Korrelation zwischen 'avg_hr' und 'Durchschnittliche Dauer' correlation = combined_data['avg_hr'].corr(combined_data['Durchschnittliche Dauer']) - print(f"\nDie Korrelation zwischen der durchschnittlichen Herzfrequenz und der Schlafdauer ist: {correlation}") -# Schritt 8: Visualisiere den Zusammenhang zwischen Herzfrequenz und Schlafdauer +# Schritt 6: Visualisiere den Zusammenhang zwischen Herzfrequenz und Schlafdauer plt.figure(figsize=(10, 6)) plt.scatter(combined_data['avg_hr'], combined_data['Durchschnittliche Dauer'], color='blue', label='Datenpunkte') plt.title('Zusammenhang zwischen Herzfrequenz (Durchschnitt) und Schlafdauer') diff --git a/code/corelation_old3.py b/code/corelation_old3.py new file mode 100644 index 0000000..15cad3a --- /dev/null +++ b/code/corelation_old3.py @@ -0,0 +1,94 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +from datetime import datetime + + +# Manuelle Zuordnung der Monatsnamen von Deutsch auf Englisch +month_translation = { + 'Jan': 'Jan', 'Feb': 'Feb', 'Mär': 'Mar', 'Apr': 'Apr', 'Mai': 'May', 'Jun': 'Jun', + 'Jul': 'Jul', 'Aug': 'Aug', 'Sep': 'Sep', 'Okt': 'Oct', 'Nov': 'Nov', 'Dez': 'Dec' +} + +# Funktion, um 'Okt 10-16' in eine Kalenderwoche zu konvertieren +def convert_to_week_number(date_range_str): + # Splitte den Datumsbereich in Monat und Tage + month_str, day_range = date_range_str.split(" ") + start_day = int(day_range.split("-")[0]) # Nimm den Starttag + current_year = datetime.now().year + + # Konvertiere den deutschen Monatsnamen in den englischen + if month_str in month_translation: + month_str = month_translation[month_str] + + # Erstelle das Datum basierend auf dem Starttag und dem aktuellen Jahr + date_str = f"{month_str} {start_day} {current_year}" + start_date = datetime.strptime(date_str, "%b %d %Y") # Konvertiere in ein Datum + return start_date.isocalendar()[1] # Gib die Kalenderwoche zurück + + +# Schritt 1: Lade die HR-Daten (mit Semikolon separiert) und entferne 'bpm' +hr_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/hr_gramic.csv', sep=';') + +# Zeige die ersten Zeilen der HR-Daten vor der Bereinigung +print("HR-Daten (vor der Bereinigung):") +print(hr_data.head()) + +# Entferne 'bpm' und konvertiere die Werte in numerische Daten +hr_data['In Ruhe'] = hr_data['In Ruhe'].str.replace(' bpm', '').astype(float) +hr_data['Hoch'] = hr_data['Hoch'].str.replace(' bpm', '').astype(float) + +# Konvertiere die Spalte 'Datum' in Kalenderwoche (KW) +hr_data['week'] = hr_data['Datum'].apply(convert_to_week_number) + +# Zeige die HR-Daten nach der Umwandlung in Wochen +print("\nHR-Daten (nach der Umwandlung in KW):") +print(hr_data.head()) + +# Schritt 2: Berechne den Durchschnitt der Herzfrequenzdaten (In Ruhe und Hoch) +hr_data['avg_hr'] = hr_data[['In Ruhe', 'Hoch']].mean(axis=1) + +# Schritt 3: Lade die Schlafdaten (mit Komma separiert) +sleep_data = pd.read_csv('/home/gra/PycharmProjects/cds_introduction_data_science_assignment/data/raw/sleep_gramic.csv', sep=',') + +# Zeige die ersten Zeilen der Schlafdaten +print("\nSchlafdaten:") +print(sleep_data.head()) + +# Konvertiere auch das 'Datum' der Schlafdaten in Kalenderwoche (KW) +sleep_data['week'] = sleep_data['Datum'].apply(convert_to_week_number) + +# Schritt 4: Sicherstellen, dass beide Datensätze nach 'week' sortiert sind +hr_data = hr_data.sort_values(by='week') +sleep_data = sleep_data.sort_values(by='week') + +# Schritt 5: Kombiniere die beiden Datensätze anhand der 'week' Spalte mit einem äußeren Join +combined_data = pd.merge(hr_data, sleep_data, on='week', how='outer') + +# Zeige die kombinierten Daten +print("\nKombinierte Daten:") +print(combined_data) + +# Schritt 6: Entferne alle Zeilen mit fehlenden Daten +combined_data = combined_data.dropna() + +# Schritt 7: Berechne die Korrelation zwischen dem durchschnittlichen Herzfrequenzwert ('avg_hr') und der Schlafdauer ('Durchschnittliche Dauer') +correlation = combined_data['avg_hr'].corr(combined_data['Durchschnittliche Dauer']) + +print(f"\nDie Korrelation zwischen der durchschnittlichen Herzfrequenz und der Schlafdauer ist: {correlation}") + +# Schritt 8: Visualisiere den Zusammenhang zwischen Herzfrequenz und Schlafdauer +plt.figure(figsize=(10, 6)) +plt.scatter(combined_data['avg_hr'], combined_data['Durchschnittliche Dauer'], color='blue', label='Datenpunkte') +plt.title('Zusammenhang zwischen Herzfrequenz (Durchschnitt) und Schlafdauer') +plt.xlabel('Durchschnittliche Herzfrequenz (bpm)') +plt.ylabel('Schlafdauer (Stunden)') +plt.grid(True) + +# Linie zur Visualisierung des Trends hinzufügen +m, b = np.polyfit(combined_data['avg_hr'], combined_data['Durchschnittliche Dauer'], 1) +plt.plot(combined_data['avg_hr'], m * combined_data['avg_hr'] + b, color='red', + label=f'Trendlinie (Kor = {correlation:.2f})') + +plt.legend() +plt.show() diff --git a/data/raw/Schlaf.csv b/data/raw/Schlaf.csv new file mode 100644 index 0000000..1296df2 --- /dev/null +++ b/data/raw/Schlaf.csv @@ -0,0 +1,53 @@ +Datum,Ø Score,Ø Qualität,Durchschnittliche Dauer,Ø Schlafenszeit,Ø Aufstehzeit +Okt 11-17,45,Schlecht,5h 59min,1:40,7:50 +Okt 4-10,52,Schlecht,6h 38min,0:29,7:25 +Sep 27 - Okt 3,53,Schlecht,6h 5min,0:14,6:31 +Sep 20-26,60,Ausreichend,7h 5min,0:12,7:23 +Sep 13-19,61,Ausreichend,6h 27min,0:44,7:18 +Sep 6-12,53,Schlecht,6h 8min,1:08,7:22 +Aug 30 - Sep 5,66,Ausreichend,6h 59min,0:11,7:19 +Aug 23-29,61,Ausreichend,6h 39min,0:35,7:19 +Aug 16-22,67,Ausreichend,6h 25min,0:41,7:17 +Aug 9-15,57,Schlecht,5h 43min,0:17,6:04 +Aug 2-8,61,Ausreichend,6h 30min,0:31,7:24 +Jul 26 - Aug 1,62,Ausreichend,6h 55min,0:31,7:48 +Jul 19-25,55,Schlecht,7h 0min,2:35,10:14 +Jul 12-18,72,Ausreichend,6h 48min,0:03,7:05 +Jul 5-11,58,Schlecht,7h 42min,0:32,8:57 +Jun 28 - Jul 4,66,Ausreichend,6h 26min,1:24,7:57 +Jun 21-27,65,Ausreichend,6h 25min,0:39,7:17 +Jun 14-20,59,Schlecht,5h 43min,0:24,6:14 +Jun 7-13,61,Ausreichend,6h 34min,23:47,6:26 +Mai 31 - Jun 6,61,Ausreichend,6h 47min,0:35,7:33 +Mai 24-30,52,Schlecht,6h 33min,1:00,7:38 +Mai 17-23,51,Schlecht,6h 11min,1:12,7:30 +Mai 10-16,48,Schlecht,5h 44min,0:48,6:39 +Mai 3-9,45,Schlecht,5h 55min,0:49,6:48 +Apr 26 - Mai 2,56,Schlecht,6h 11min,1:26,7:41 +Apr 19-25,51,Schlecht,6h 19min,2:55,9:31 +Apr 12-18,57,Schlecht,6h 24min,1:28,8:03 +Apr 5-11,62,Ausreichend,6h 4min,0:56,7:09 +Mrz 29 - Apr 4,73,Ausreichend,6h 59min,1:34,8:53 +Mrz 22-28,59,Schlecht,5h 59min,1:05,7:11 +Mrz 15-21,55,Schlecht,6h 25min,0:47,7:23 +Mrz 8-14,53,Schlecht,6h 22min,0:56,7:25 +Mrz 1-7,47,Schlecht,5h 56min,0:51,6:56 +Feb 23-29,64,Ausreichend,7h 11min,0:09,7:27 +Feb 16-22,46,Schlecht,6h 56min,0:24,7:52 +Feb 9-15,50,Schlecht,8h 26min,23:58,8:48 +Feb 2-8,43,Schlecht,6h 13min,1:06,7:26 +Jan 26 - Feb 1,55,Schlecht,7h 17min,1:12,8:32 +Jan 19-25,55,Schlecht,6h 33min,0:59,7:37 +Jan 12-18,49,Schlecht,6h 16min,1:39,8:04 +Jan 5-11,54,Schlecht,6h 35min,1:28,8:14 +Dez 29, 2023 - Jan 4, 2024,55,Schlecht,7h 15min,0:52,8:34 +Dez 22-28, 2023,56,Schlecht,7h 10min,1:02,8:33 +Dez 15-21, 2023,61,Ausreichend,7h 40min,0:18,8:18 +Dez 8-14, 2023,43,Schlecht,7h 45min,23:45,8:52 +Dez 1-7, 2023,47,Schlecht,6h 51min,0:31,7:25 +Nov 24-30, 2023,48,Schlecht,7h 5min,0:29,8:01 +Nov 17-23, 2023,53,Schlecht,7h 1min,0:26,7:34 +Nov 10-16, 2023,47,Schlecht,7h 5min,0:19,7:28 +Nov 3-9, 2023,49,Schlecht,6h 10min,23:58,7:12 +Okt 27 - Nov 2, 2023,61,Ausreichend,6h 33min,0:08,6:50 +Okt 20-26, 2023,47,Schlecht,6h 11min,0:41,7:14 \ No newline at end of file