fixes graphics

This commit is contained in:
2026-07-01 05:04:47 +00:00
parent 1313a12a20
commit 3e48b3a41c
9 changed files with 543 additions and 50 deletions
+8 -17
View File
@@ -6,10 +6,6 @@ def _is_female(sex: str) -> bool:
return sex.lower() in ("f", "female", "ж", "женский", "woman")
def _cm_to_inches(cm: float) -> float:
return cm / 2.54
def _clamp_bf(value: float) -> float:
return round(max(3.0, min(50.0, value)), 1)
@@ -25,30 +21,25 @@ def navy_body_fat_pct(
if height_cm <= 0 or neck_cm <= 0 or waist_cm <= 0:
return None
height_in = _cm_to_inches(height_cm)
neck_in = _cm_to_inches(neck_cm)
waist_in = _cm_to_inches(waist_cm)
if _is_female(sex):
if hip_cm is None or hip_cm <= 0:
return None
hip_in = _cm_to_inches(hip_cm)
sum_in = waist_in + hip_in - neck_in
if sum_in <= 0:
measurement_sum_cm = waist_cm + hip_cm - neck_cm
if measurement_sum_cm <= 0:
return None
denom = (
1.29579
- 0.35004 * math.log10(sum_in)
+ 0.22100 * math.log10(height_in)
- 0.35004 * math.log10(measurement_sum_cm)
+ 0.22100 * math.log10(height_cm)
)
else:
diff_in = waist_in - neck_in
if diff_in <= 0:
measurement_diff_cm = waist_cm - neck_cm
if measurement_diff_cm <= 0:
return None
denom = (
1.0324
- 0.19077 * math.log10(diff_in)
+ 0.15456 * math.log10(height_in)
- 0.19077 * math.log10(measurement_diff_cm)
+ 0.15456 * math.log10(height_cm)
)
if denom <= 0:
+85
View File
@@ -541,6 +541,91 @@ class FitnessService:
},
}
def update_body_metric(
self,
metric_id: int,
updates: dict[str, Any],
) -> dict[str, Any] | None:
row = self.db.get(BodyMetric, metric_id)
if not row or row.user_id != self.user_id:
return None
if "weight_kg" in updates and updates["weight_kg"] is not None:
row.weight_kg = float(updates["weight_kg"])
for field in ("chest_cm", "waist_cm", "neck_cm", "hip_cm"):
if field in updates:
value = updates[field]
setattr(row, field, float(value) if value is not None else None)
if "notes" in updates and updates["notes"] is not None:
row.notes = str(updates["notes"])[:1000]
if "recorded_at" in updates and updates["recorded_at"] is not None:
row.recorded_at = self._resolve_logged_at(logged_at=updates["recorded_at"])
profile_row = self._get_profile_row()
sex = profile_row.sex if profile_row else "male"
height_cm = float(profile_row.height_cm if profile_row else 170)
if "body_fat_pct" in updates:
manual_body_fat = updates["body_fat_pct"]
elif row.body_fat_method == "manual":
manual_body_fat = row.body_fat_pct
else:
manual_body_fat = None
computed = compute_body_composition(
sex=str(sex),
height_cm=height_cm,
weight_kg=row.weight_kg,
neck_cm=row.neck_cm,
waist_cm=row.waist_cm,
hip_cm=row.hip_cm,
body_fat_pct=float(manual_body_fat) if manual_body_fat is not None else None,
)
row.body_fat_pct = computed.get("body_fat_pct")
row.body_fat_method = computed.get("body_fat_method")
row.whr = computed.get("whr")
row.lbm_kg = computed.get("lbm_kg")
row.ffmi = computed.get("ffmi")
latest_id = self.db.scalar(
select(BodyMetric.id)
.where(BodyMetric.user_id == self.user_id)
.order_by(BodyMetric.recorded_at.desc(), BodyMetric.id.desc())
.limit(1)
)
if profile_row and latest_id == row.id:
profile_row.weight_kg = row.weight_kg
targets = compute_targets(
{
"sex": profile_row.sex,
"age": profile_row.age,
"height_cm": profile_row.height_cm,
"weight_kg": row.weight_kg,
"goal": profile_row.goal,
"neat_base_kcal": profile_row.neat_base_kcal,
}
)
profile_row.calorie_target = targets["calorie_target"]
profile_row.protein_g = targets["protein_g"]
profile_row.fat_g = targets["fat_g"]
profile_row.carbs_g = targets["carbs_g"]
profile_row.water_l = targets["water_l"]
self.db.commit()
self.db.refresh(row)
metric = self._body_metric_to_dict(row)
return {
"ok": True,
"metric": metric,
"computed": {
"body_fat_pct": computed.get("body_fat_pct"),
"body_fat_method": computed.get("body_fat_method"),
"whr": computed.get("whr"),
"lbm_kg": computed.get("lbm_kg"),
"ffmi": computed.get("ffmi"),
"warnings": computed.get("warnings") or [],
},
}
def log_workout(
self,
*,