- Adjusted the total number of placeholders from 116 to 114 across various documentation and code files to reflect the current state of the system. - Enhanced TDEE calculation logic in `nutrition_metrics.py` to prioritize Mifflin–St Jeor BMR with PAL when demographic data is available, with a fallback to a weight-based estimate. - Updated placeholder registrations to ensure consistency with the new metadata structure and improved data handling. - Revised documentation to clarify the authoritative source of placeholder metadata and the implications of the changes on existing functionalities. These updates improve the accuracy and consistency of the placeholder system and enhance the nutritional assessment capabilities within the application.
216 lines
9.8 KiB
Python
216 lines
9.8 KiB
Python
"""
|
|
Nutrition Part A Placeholder Registrations
|
|
|
|
Registers the 4 basis nutrition metrics in the central placeholder registry:
|
|
- kcal_avg
|
|
- protein_avg
|
|
- carb_avg
|
|
- fat_avg
|
|
|
|
Evidence-based metadata with clear tagging of source.
|
|
"""
|
|
|
|
from placeholder_registry import (
|
|
PlaceholderMetadata,
|
|
MissingValuePolicy,
|
|
EvidenceType,
|
|
OutputType,
|
|
PlaceholderType,
|
|
register_placeholder
|
|
)
|
|
|
|
|
|
def register_nutrition_part_a():
|
|
"""
|
|
Register Part A nutrition placeholders.
|
|
|
|
Metadata sources:
|
|
- code-derived: extracted from actual code
|
|
- draft-derived: from canonical requirements draft
|
|
- mixed: combination of code and draft
|
|
- unresolved: not explicitly documented
|
|
- to_verify: claimed but not verified
|
|
"""
|
|
|
|
# Common metadata for all 4 placeholders
|
|
common_metadata = {
|
|
"category": "Ernährung",
|
|
"resolver_module": "backend/placeholder_resolver.py",
|
|
"resolver_function": "get_nutrition_avg",
|
|
"data_layer_module": "backend/data_layer/nutrition_metrics.py",
|
|
"data_layer_function": "get_nutrition_average_data",
|
|
"source_tables": ["nutrition_log"],
|
|
"time_window": "30d",
|
|
"output_type": OutputType.NUMERIC,
|
|
"placeholder_type": PlaceholderType.INTERPRETED,
|
|
"confidence_logic": "datenpunktbasierte Coverage-Logik (calculate_confidence)",
|
|
"missing_value_policy": MissingValuePolicy(
|
|
available=False,
|
|
value_raw=None,
|
|
missing_reason="insufficient_data",
|
|
legacy_display="nicht genug Daten"
|
|
),
|
|
"layer_1_decision": "Data Layer (nutrition_metrics.get_nutrition_average_data)",
|
|
"layer_2a_decision": "Placeholder Resolver (formatting only)",
|
|
"architecture_alignment": "Phase 0c Multi-Layer Architecture conform",
|
|
"minimum_data_requirements": (
|
|
"Mind. ein Kalendertag mit nutrition_log im Fenster; Mittelwerte aus täglicher Aggregation. "
|
|
"Confidence über calculate_confidence(day_count, days) in get_nutrition_average_data."
|
|
),
|
|
"quality_filter_policy": (
|
|
"Kein Outlier-Filter auf Tagesaggregaten; leere Tage fehlen in der Aggregation (kein Imputing)."
|
|
),
|
|
}
|
|
|
|
# Common evidence for shared fields
|
|
common_evidence = {
|
|
"category": EvidenceType.CODE_DERIVED, # from placeholder_resolver.py:1380
|
|
"resolver_module": EvidenceType.CODE_DERIVED,
|
|
"resolver_function": EvidenceType.CODE_DERIVED,
|
|
"data_layer_module": EvidenceType.CODE_DERIVED, # from import statement
|
|
"data_layer_function": EvidenceType.CODE_DERIVED, # from resolver code
|
|
"source_tables": EvidenceType.CODE_DERIVED, # from SQL query
|
|
"time_window": EvidenceType.CODE_DERIVED, # from PLACEHOLDER_MAP lambda
|
|
"output_type": EvidenceType.CODE_DERIVED, # from resolver return type
|
|
"placeholder_type": EvidenceType.MIXED, # draft classification + code shows aggregation
|
|
"confidence_logic": EvidenceType.CODE_DERIVED, # from data layer
|
|
"missing_value_policy": EvidenceType.CODE_DERIVED, # from resolver code
|
|
"layer_1_decision": EvidenceType.CODE_DERIVED,
|
|
"layer_2a_decision": EvidenceType.CODE_DERIVED,
|
|
"layer_2b_reuse_possible": EvidenceType.TO_VERIFY, # not verified in charts
|
|
"architecture_alignment": EvidenceType.CODE_DERIVED, # imports from data_layer
|
|
"issue_53_alignment": EvidenceType.MIXED, # layer separation visible, issue conformity derived
|
|
"minimum_data_requirements": EvidenceType.CODE_DERIVED,
|
|
"quality_filter_policy": EvidenceType.CODE_DERIVED,
|
|
}
|
|
|
|
# ── kcal_avg ──────────────────────────────────────────────────────────────
|
|
|
|
kcal_metadata = PlaceholderMetadata(
|
|
key="kcal_avg",
|
|
description="Durchschn. Kalorien (30d)",
|
|
semantic_contract=(
|
|
"Liefert den Durchschnitt der dokumentierten täglichen Kalorienaufnahme "
|
|
"über das definierte Auswertungsfenster. Der Wert ist als Intake-Mittelwert "
|
|
"zu interpretieren, nicht als Energiebedarf oder Energiebilanz."
|
|
),
|
|
business_meaning="Kernwert für Ernährungsstatus, Defizit-/Überschussbewertung und Zielabgleich",
|
|
unit="kcal/day",
|
|
format_hint="Ganzzahl",
|
|
example_output="2140",
|
|
known_limitations="nur Intake, kein Bedarf; sagt allein nichts über Zielpassung",
|
|
layer_2b_reuse_possible=None, # to_verify - not checked in chart code
|
|
issue_53_alignment="Layer separation established",
|
|
**common_metadata
|
|
)
|
|
|
|
kcal_metadata.evidence.update(common_evidence)
|
|
kcal_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
kcal_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
kcal_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED) # from resolver: no " g" suffix
|
|
kcal_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED) # int(value)
|
|
kcal_metadata.set_evidence("example_output", EvidenceType.CODE_DERIVED) # runtime testable
|
|
kcal_metadata.set_evidence("known_limitations", EvidenceType.DRAFT_DERIVED)
|
|
|
|
register_placeholder(kcal_metadata)
|
|
|
|
# ── protein_avg ───────────────────────────────────────────────────────────
|
|
|
|
protein_metadata = PlaceholderMetadata(
|
|
key="protein_avg",
|
|
description="Durchschn. Protein in g (30d)",
|
|
semantic_contract=(
|
|
"Liefert den Durchschnitt der dokumentierten täglichen Proteinzufuhr "
|
|
"über das definierte Auswertungsfenster."
|
|
),
|
|
business_meaning=(
|
|
"Zentraler Placeholder für Muskelerhalt, Muskelaufbau, Recomposition "
|
|
"und Absicherung im Defizit"
|
|
),
|
|
unit="g/day",
|
|
format_hint="Ganzzahl in g/day",
|
|
example_output="156",
|
|
known_limitations=(
|
|
"absoluter Wert allein reicht nicht immer; sollte oft relativ zum "
|
|
"Körpergewicht interpretiert werden"
|
|
),
|
|
layer_2b_reuse_possible=None,
|
|
issue_53_alignment="Layer separation established",
|
|
**common_metadata
|
|
)
|
|
|
|
protein_metadata.evidence.update(common_evidence)
|
|
protein_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
protein_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
protein_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED) # from resolver: " g" suffix
|
|
protein_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
|
protein_metadata.set_evidence("example_output", EvidenceType.CODE_DERIVED)
|
|
protein_metadata.set_evidence("known_limitations", EvidenceType.DRAFT_DERIVED)
|
|
|
|
register_placeholder(protein_metadata)
|
|
|
|
# ── carb_avg ──────────────────────────────────────────────────────────────
|
|
|
|
carb_metadata = PlaceholderMetadata(
|
|
key="carb_avg",
|
|
description="Durchschn. Kohlenhydrate in g (30d)",
|
|
semantic_contract=(
|
|
"Liefert den Durchschnitt der dokumentierten täglichen Kohlenhydratzufuhr "
|
|
"über das definierte Auswertungsfenster."
|
|
),
|
|
business_meaning="Relevanter Makroindikator für Leistungs-, Energie- und Belastungskontext",
|
|
unit="g/day",
|
|
format_hint="Ganzzahl in g/day",
|
|
example_output="210",
|
|
known_limitations=(
|
|
"allein selten aussagekräftig; meist im Kontext von Ziel, Energie und "
|
|
"Belastung relevant"
|
|
),
|
|
layer_2b_reuse_possible=None,
|
|
issue_53_alignment="Layer separation established",
|
|
**common_metadata
|
|
)
|
|
|
|
carb_metadata.evidence.update(common_evidence)
|
|
carb_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
carb_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
carb_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
|
carb_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
|
carb_metadata.set_evidence("example_output", EvidenceType.CODE_DERIVED)
|
|
carb_metadata.set_evidence("known_limitations", EvidenceType.DRAFT_DERIVED)
|
|
|
|
register_placeholder(carb_metadata)
|
|
|
|
# ── fat_avg ───────────────────────────────────────────────────────────────
|
|
|
|
fat_metadata = PlaceholderMetadata(
|
|
key="fat_avg",
|
|
description="Durchschn. Fett in g (30d)",
|
|
semantic_contract=(
|
|
"Liefert den Durchschnitt der dokumentierten täglichen Fettzufuhr "
|
|
"über das definierte Auswertungsfenster."
|
|
),
|
|
business_meaning="Relevanter Makroindikator für Ernährungsstruktur und Zielpassung",
|
|
unit="g/day",
|
|
format_hint="Ganzzahl in g/day",
|
|
example_output="72",
|
|
known_limitations="meist im Gesamtkontext der Makroverteilung relevant",
|
|
layer_2b_reuse_possible=None,
|
|
issue_53_alignment="Layer separation established",
|
|
**common_metadata
|
|
)
|
|
|
|
fat_metadata.evidence.update(common_evidence)
|
|
fat_metadata.set_evidence("semantic_contract", EvidenceType.DRAFT_DERIVED)
|
|
fat_metadata.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
fat_metadata.set_evidence("unit", EvidenceType.CODE_DERIVED)
|
|
fat_metadata.set_evidence("format_hint", EvidenceType.CODE_DERIVED)
|
|
fat_metadata.set_evidence("example_output", EvidenceType.CODE_DERIVED)
|
|
fat_metadata.set_evidence("known_limitations", EvidenceType.DRAFT_DERIVED)
|
|
|
|
register_placeholder(fat_metadata)
|
|
|
|
|
|
# Auto-register on import
|
|
register_nutrition_part_a()
|