added RAG, Multiuser, TG bot
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import math
|
||||
from typing import Any
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def navy_body_fat_pct(
|
||||
*,
|
||||
sex: str,
|
||||
height_cm: float,
|
||||
neck_cm: float,
|
||||
waist_cm: float,
|
||||
hip_cm: float | None = None,
|
||||
) -> float | None:
|
||||
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:
|
||||
return None
|
||||
denom = (
|
||||
1.29579
|
||||
- 0.35004 * math.log10(sum_in)
|
||||
+ 0.22100 * math.log10(height_in)
|
||||
)
|
||||
else:
|
||||
diff_in = waist_in - neck_in
|
||||
if diff_in <= 0:
|
||||
return None
|
||||
denom = (
|
||||
1.0324
|
||||
- 0.19077 * math.log10(diff_in)
|
||||
+ 0.15456 * math.log10(height_in)
|
||||
)
|
||||
|
||||
if denom <= 0:
|
||||
return None
|
||||
|
||||
return _clamp_bf(495.0 / denom - 450.0)
|
||||
|
||||
|
||||
def whr(waist_cm: float, hip_cm: float) -> float | None:
|
||||
if waist_cm <= 0 or hip_cm <= 0:
|
||||
return None
|
||||
return round(waist_cm / hip_cm, 2)
|
||||
|
||||
|
||||
def lean_body_mass(weight_kg: float, body_fat_pct: float) -> float:
|
||||
return round(weight_kg * (1.0 - body_fat_pct / 100.0), 1)
|
||||
|
||||
|
||||
def ffmi(weight_kg: float, height_cm: float, body_fat_pct: float) -> float | None:
|
||||
if height_cm <= 0:
|
||||
return None
|
||||
height_m = height_cm / 100.0
|
||||
lbm = weight_kg * (1.0 - body_fat_pct / 100.0)
|
||||
raw = lbm / (height_m * height_m)
|
||||
normalized = raw + 6.1 * (1.8 - height_m)
|
||||
return round(normalized, 1)
|
||||
|
||||
|
||||
def compute_body_composition(
|
||||
*,
|
||||
sex: str,
|
||||
height_cm: float,
|
||||
weight_kg: float,
|
||||
neck_cm: float | None = None,
|
||||
waist_cm: float | None = None,
|
||||
hip_cm: float | None = None,
|
||||
body_fat_pct: float | None = None,
|
||||
) -> dict[str, Any]:
|
||||
warnings: list[str] = []
|
||||
result: dict[str, Any] = {
|
||||
"body_fat_pct": None,
|
||||
"body_fat_method": None,
|
||||
"whr": None,
|
||||
"lbm_kg": None,
|
||||
"ffmi": None,
|
||||
"warnings": warnings,
|
||||
}
|
||||
|
||||
bf = body_fat_pct
|
||||
method: str | None = "manual" if bf is not None else None
|
||||
|
||||
if bf is None and neck_cm and waist_cm:
|
||||
navy_bf = navy_body_fat_pct(
|
||||
sex=sex,
|
||||
height_cm=height_cm,
|
||||
neck_cm=neck_cm,
|
||||
waist_cm=waist_cm,
|
||||
hip_cm=hip_cm,
|
||||
)
|
||||
if navy_bf is not None:
|
||||
bf = navy_bf
|
||||
method = "navy"
|
||||
elif _is_female(sex) and not hip_cm:
|
||||
warnings.append("Для Navy у женщин нужен обхват бёдер (hip_cm).")
|
||||
elif neck_cm and waist_cm and waist_cm <= neck_cm:
|
||||
warnings.append("Обхват талии должен быть больше шеи для Navy.")
|
||||
|
||||
if bf is not None:
|
||||
result["body_fat_pct"] = round(float(bf), 1)
|
||||
result["body_fat_method"] = method
|
||||
result["lbm_kg"] = lean_body_mass(weight_kg, float(bf))
|
||||
result["ffmi"] = ffmi(weight_kg, height_cm, float(bf))
|
||||
|
||||
if waist_cm and hip_cm:
|
||||
result["whr"] = whr(waist_cm, hip_cm)
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user