feat(watch): remonte les séances de renfo pour la complétion auto de la routine
Pendant natif de coach_sportif c12caef. À la détection d'un HKWorkout de type renforcement, POST /api/routine/auto-complete avec les faits bruts. Volontairement bête côté natif : aucune règle de correspondance ici. Fenêtre de 12 h depuis l'envoi explicite, tolérance de durée, choix du bloc — tout vit côté serveur et reste donc ajustable sans rebuild iOS. NON COMPILÉ — à inclure au prochain build Xcode. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -335,7 +335,48 @@ public class CoachWorkoutObserverPlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remonte au serveur la fin d'une séance de renfo, qui décide seul si elle
|
||||||
|
/// correspond à une routine poussée dans l'app Exercice.
|
||||||
|
///
|
||||||
|
/// Volontairement bête : on n'envoie que des faits bruts (type, durée). Les
|
||||||
|
/// règles de correspondance — fenêtre de 12 h depuis l'envoi explicite,
|
||||||
|
/// tolérance de durée — vivent dans `/api/routine/auto-complete`, donc
|
||||||
|
/// ajustables sans rebuild iOS.
|
||||||
|
private func reportToRoutineIfStrength(_ workout: HKWorkout) {
|
||||||
|
let activity = workout.workoutActivityType
|
||||||
|
guard activity == .functionalStrengthTraining
|
||||||
|
|| activity == .traditionalStrengthTraining else { return }
|
||||||
|
|
||||||
|
guard let url = URL(string: "https://coach.hypnotruck.ch/api/routine/auto-complete") else { return }
|
||||||
|
var req = URLRequest(url: url)
|
||||||
|
req.httpMethod = "POST"
|
||||||
|
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
req.setValue("coach_web_token=\(CoachAuth.kCoachWebToken)", forHTTPHeaderField: "Cookie")
|
||||||
|
req.httpBody = try? JSONSerialization.data(withJSONObject: [
|
||||||
|
"activity": "functionalStrengthTraining",
|
||||||
|
"duration_min": workout.duration / 60,
|
||||||
|
])
|
||||||
|
req.timeoutInterval = 15
|
||||||
|
|
||||||
|
URLSession.shared.dataTask(with: req) { data, _, error in
|
||||||
|
if let error = error {
|
||||||
|
NSLog("[CoachWorkoutObserver] auto-complete routine: %@", error.localizedDescription)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let data = data,
|
||||||
|
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
|
||||||
|
if (json["matched"] as? Bool) == true {
|
||||||
|
let n = (json["done"] as? [String])?.count ?? 0
|
||||||
|
NSLog("[CoachWorkoutObserver] routine '%@' cochée automatiquement (%d exercices)",
|
||||||
|
(json["moment"] as? String) ?? "?", n)
|
||||||
|
} else {
|
||||||
|
NSLog("[CoachWorkoutObserver] pas une routine (%@)", (json["reason"] as? String) ?? "?")
|
||||||
|
}
|
||||||
|
}.resume()
|
||||||
|
}
|
||||||
|
|
||||||
private func scheduleNotification(for workout: HKWorkout) {
|
private func scheduleNotification(for workout: HKWorkout) {
|
||||||
|
reportToRoutineIfStrength(workout)
|
||||||
let durationMin = Int(workout.duration / 60)
|
let durationMin = Int(workout.duration / 60)
|
||||||
var bodyParts: [String] = ["\(durationMin) min"]
|
var bodyParts: [String] = ["\(durationMin) min"]
|
||||||
if let kcal = workout.totalEnergyBurned?.doubleValue(for: .kilocalorie()), kcal > 0 {
|
if let kcal = workout.totalEnergyBurned?.doubleValue(for: .kilocalorie()), kcal > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user