Feature #78
geschlossenTrainingsübersicht: Spalten Belastung und Schwerpunkt
0%
Beschreibung
Ziel: In der Trainingsübersicht die Spalten Belastung und Schwerpunkt anbieten (Standard ausgeblendet, wie andere optionale Spalten über TrainingStatDefinitions / DefaultVisibleInGrid = false). Aufbauend auf #77, dort sind Berechnung (Edwards-TRIMP) und Regeln für den Schwerpunkt beschrieben.
Warum speichern¶
Belastung und Schwerpunkt brauchen die Zeit je Pulszone und damit alle TrainingPoints eines Trainings. Das Grid müsste sonst für jedes Training alle Trainingspunkte laden, was bei vielen Trainings zu langsam ist. Deshalb wird der Wert beim Aufzeichnen einmal berechnet und am Training gespeichert (wie AveragePulse, MaxPulse usw.).
Umsetzung¶
- Neue Spalten in
Training(z. B.TrainingLoadals Zahl,TrainingFocusals Kennung des Schwerpunkts, nullable) inTraining.Persistant.cs. - Migration (nächste Version) mit den neuen Spalten.
- Neue Trainings: Berechnung mit dem
TrainingLoadCalculatoraus #77 beim Speichern des Trainings, dort wo bereitsMaxPulseAtRecordinggesetzt wird (FreiesTrainingWindowViewModel), damit die Werte mit den zum Aufzeichnungszeitpunkt gültigen Zonengrenzen entstehen. - Einmaliger Backfill für Bestandstrainings, wie bei
MaxPulseAtRecordingin der Migration 3.1.1. Dort war es ein SQL-UPDATE; für die Belastung ist die Zeit je Zone aus den Zeitabständen der Punkte nötig, daher entweder SQL mit Fensterfunktion (LAG) oder ein einmaliger Lauf in C# beim ersten Start nach dem Update. Trainings ohneMaxPulseAtRecording(Zonengrenzen nicht bestimmbar) bleiben leer bzw. bekommen den Wert des Benutzers wie beim bisherigen Nachfüllen inUsersViewModel.SaveAsync. - Grid: Spalten "Belastung" und "Schwerpunkt" in
TrainingStatDefinitions(Standard ausgeblendet), Beschriftungen in der Resx unterTrainingSessionsViewModel.*. Leere Werte (kein Maximalpuls, zu kurzes Training) als leere Zelle. - Detailseite (#77) liest bei vorhandenem gespeicherten Wert diesen, sonst berechnet sie ihn weiterhin selbst, damit beides dasselbe Ergebnis zeigt.
Umgesetzt¶
- Gespeicherte Werte:
Training.TrainingLoad(Zahl, eine Nachkommastelle) undTraining.TrainingFocus(EnumTrainingFocus, in der Datenbank als Enum-Name gespeichert,NULL= kein Schwerpunkt). Das Enum liegt jetzt in ErControl.Model. MigrationVersion3120, Datenbankversion 3.1.2.0 (3.1.1 ist veröffentlicht, deshalb keine Faltung in die Migration 3.1.1) - Neue Trainings:
TrainingLoadCalculator.Updateberechnet beim Speichern (FreiesTrainingWindowViewModel) mit dem historisierten Maximalpuls, Fallback auf den aktuellen Benutzer - Bestandstrainings: einmaliger Nachlauf
TrainingLoadBackfillServicebeim nächsten Programmstart (C#, damit die Regeln aus #77 nicht in SQL gedoppelt werden; Prefs-MerkerTrainingLoadBackfillDone, läuft wie der Lat/Lon-Backfill auf dem Threadpool im Splash). Liest ohne Change Tracking und schreibt perExecuteUpdate, weil der Context mit der angemeldeten Sitzung geteilt wird. Fallback für Trainings ohneMaxPulseAtRecording: Maximalpuls des Benutzers, sonst der berechnete Wert (wie die Detailseite). Trainings ohne Pulsdaten bleiben leer - Laufzeit des Nachlaufs: Der Nachlauf lädt je Training nur Zeit und Puls der TrainingPoints, berechnet zuerst alles und schreibt die Ergebnisse dann in einer kurzen Transaktion. Gemessen an einer synthetischen Datenbank mit 600 einstündigen Trainings (2,2 Mio. TrainingPoints): 3 s (die erste Fassung mit Include aller Punkte brauchte 32 s). Beim Nachlauf erscheint nach 4,5 s die Meldung "Migration läuft, bitte warten..." und die Aktionen des Startfensters sind gesperrt (auch ohne vorherige Migration)
- Trainingsübersicht: Spalten "Belastung" und "Schwerpunkt" (Standard ausgeblendet, über die Spaltenauswahl wählbar, vor der Bemerkung). Die Bezeichnung des Schwerpunkts wird erst bei der Anzeige in der aktuellen Sprache aufgelöst (
TrainingFocusConverter) - Detailseite (#77) zeigt bei vorhandenem gespeicherten Wert diesen, sonst berechnet sie ihn selbst
- Tests: Migration von Grund auf und Backfill gegen eine echte SQLite-Datenbank (
TrainingLoadBackfillTests) sowieTrainingLoadCalculator.Update
Entscheidungen¶
- Backfill per C#-Lauf beim Start statt per SQL in der Migration
- Schwerpunkt als Kennung (Enum-Name) gespeichert
- Nur Belastung und Schwerpunkt gespeichert, nicht die Sekunden je Zone. Ändern sich später die Schwellenwerte der Schwerpunkt-Regeln, müssen die gespeicherten Werte neu berechnet werden (dafür den Merker zurücksetzen und
TrainingLoadleeren)
Zu beachten¶
- Ändern sich später die Schwellenwerte für den Schwerpunkt, müssen die gespeicherten Werte neu berechnet werden (erneuter Backfill oder Neuberechnung beim Start). Alternativ nur die Belastung speichern und den Schwerpunkt aus gespeicherten Zonenzeiten ableiten.
- Wird der Maximalpuls eines Benutzers nachträglich geändert, ändern sich die gespeicherten Werte der Trainings nicht (Historisierung wie bei den Pulszonen).
JH Von Julius Haman vor 6 Tagen aktualisiert
- Zielversion wurde auf ErControl 3.1.2 gesetzt
JH Von Julius Haman vor 6 Tagen aktualisiert
- Beschreibung aktualisiert (Vergleich)
JH Von Julius Haman vor 6 Tagen aktualisiert
- Beschreibung aktualisiert (Vergleich)
JH Von Julius Haman vor 6 Tagen aktualisiert
- Status wurde von Neu zu Erledigt geändert
JH Von Julius Haman vor 5 Tagen aktualisiert
Nachtrag (Commit zu #78): Der einmalige Nachlauf TrainingLoadBackfillService übersprang Trainings ohne bestimmbaren Maximalpuls und markierte sich trotzdem als erledigt. Trug der Benutzer den Maximalpuls erst danach ein, wurde nur MaxPulseAtRecording nachgefüllt (#66), Belastung und Schwerpunkt blieben leer - die Trainingsübersicht zeigte nichts, die Detailseite (berechnet selbst) schon. UsersViewModel.SaveAsync führt jetzt nach dem Nachfüllen von MaxPulseAtRecording den Backfill aus.