Marche 6 minutes, et la vraie recuperation cardiaque
Deux ajouts lies par le meme constat : ce qu'on peut mesurer honnetement. MARCHE 6 MINUTES — troisieme protocole de la vue de test. Sous-maximal, sans risque, c'est la reference en cardiologie et le seul des trois qui ne demande aucun effort maximal. Type d'activite HealthKit .walking (la distance et la vitesse ne vivent pas sur le meme quantity type que la course). RECUPERATION CARDIAQUE — le pont collecte desormais heartRateRecoveryOneMinute, la valeur calculee par la Watch elle-meme. Pourquoi ne pas la deriver de la serie de FC post-seance, deja en base : mesure faite sur les 19 seances exploitables de la prod, la baisse mediane a 1 minute ressort a 2 bpm, avec 7 valeurs nulles ou negatives (min -10, max 15). Ce n'est pas physiologique : la fin de seance HealthKit ne coincide pas avec l'arret de l'effort. Une courbe batie la-dessus monterait et descendrait sans rien mesurer. ⚠️ Le sample n'est PAS rattache au workout : predicateForObjects(from:) ne le rendrait jamais. Apple l'ecrit comme un echantillon independant horodate juste apres la seance, d'ou une requete par fenetre temporelle. ⚠️ NON COMPILE. La courbe de tendance cote web attend ce build : sans lui, le champ reste absent et il n'y a rien a tracer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,10 @@ import WatchKit
|
||||
struct VmaTestView: View {
|
||||
enum Protocole: String, CaseIterable {
|
||||
case stages = "Paliers"
|
||||
case sixMin = "6 minutes"
|
||||
case sixMin = "6 min course"
|
||||
// Test de marche 6 minutes : sous-maximal, référence en cardiologie.
|
||||
// Le seul des trois qui ne demande aucun effort maximal.
|
||||
case walk6 = "6 min marche"
|
||||
}
|
||||
|
||||
@StateObject private var workout = WorkoutManager.shared
|
||||
@@ -80,9 +83,7 @@ struct VmaTestView: View {
|
||||
.labelsHidden()
|
||||
.frame(height: 60)
|
||||
|
||||
Text(proto == .stages
|
||||
? "Paliers d'une minute, de 8 km/h par pas de 0,5. La montre vibre à chaque changement. Arrête-toi quand tu ne tiens plus l'allure."
|
||||
: "Six minutes à allure maximale régulière, sur terrain plat. La distance parcourue donne la VMA.")
|
||||
Text(protocolHelp)
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
@@ -94,6 +95,17 @@ struct VmaTestView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var protocolHelp: String {
|
||||
switch proto {
|
||||
case .stages:
|
||||
return "Paliers d'une minute, de 8 km/h par pas de 0,5. La montre vibre à chaque changement. Arrête-toi quand tu ne tiens plus l'allure."
|
||||
case .sixMin:
|
||||
return "Six minutes à allure maximale régulière, sur terrain plat. La distance parcourue donne la VMA."
|
||||
case .walk6:
|
||||
return "Marche six minutes à ton pas le plus rapide, sans courir. Sous-maximal : c'est le test de référence en cardiologie."
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Pendant le test
|
||||
|
||||
private var runningView: some View {
|
||||
@@ -162,7 +174,8 @@ struct VmaTestView: View {
|
||||
.font(.caption2).foregroundStyle(.secondary)
|
||||
} else {
|
||||
Text(String(format: "%.0f m", workout.distanceMeters)).font(.title3)
|
||||
Text("en 6 minutes").font(.caption2).foregroundStyle(.secondary)
|
||||
Text(proto == .walk6 ? "en 6 minutes de marche" : "en 6 minutes")
|
||||
.font(.caption2).foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
if maxHr > 0 {
|
||||
@@ -196,7 +209,12 @@ struct VmaTestView: View {
|
||||
finished = false
|
||||
started = true
|
||||
// startWorkout est async (@MainActor) : même appel que ContentView.
|
||||
Task { await workout.startWorkout(activityType: .running, locationType: .outdoor) }
|
||||
// Marche et course sont deux types HealthKit distincts : la distance
|
||||
// et la vitesse ne sont pas collectées sur le même quantity type.
|
||||
Task {
|
||||
await workout.startWorkout(activityType: proto == .walk6 ? .walking : .running,
|
||||
locationType: .outdoor)
|
||||
}
|
||||
WKInterfaceDevice.current().play(.start)
|
||||
}
|
||||
|
||||
@@ -228,7 +246,7 @@ struct VmaTestView: View {
|
||||
sendError = nil
|
||||
var payload: [String: Any] = [
|
||||
"vmaTest": true,
|
||||
"protocol": proto == .stages ? "stages" : "cooper6",
|
||||
"protocol": protocolKey,
|
||||
"maxHr": Int(maxHr.rounded()),
|
||||
]
|
||||
if proto == .stages {
|
||||
@@ -248,6 +266,14 @@ struct VmaTestView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var protocolKey: String {
|
||||
switch proto {
|
||||
case .stages: return "stages"
|
||||
case .sixMin: return "cooper6"
|
||||
case .walk6: return "walk6"
|
||||
}
|
||||
}
|
||||
|
||||
private func timeString(_ s: Double) -> String {
|
||||
let t = Int(s.rounded())
|
||||
return String(format: "%d:%02d", t / 60, t % 60)
|
||||
|
||||
Reference in New Issue
Block a user