fixes graphics
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user