mitai-jinkendo/backend/placeholder_registrations/schlaf_erholung.py
Lars 2ea5f905c4
All checks were successful
Deploy Development / deploy (push) Successful in 50s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 1s
Build Test / build-frontend (push) Successful in 16s
feat: Add new profile and time period placeholders in placeholder_resolver.py
- Introduced functions to retrieve profile name, age, height, and gender for better placeholder resolution.
- Added functions for displaying current date and time period labels (last 7, 30, and 90 days).
- Updated PLACEHOLDER_MAP to utilize new functions for improved readability and maintainability.
- Enhanced placeholder registrations in __init__.py to include new modules for sleep, vital metrics, and profile time periods.

These changes enhance the flexibility and functionality of the placeholder system, allowing for more dynamic content generation.
2026-04-11 21:08:34 +02:00

237 lines
10 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Registry: Schlaf, Ruhetage, Recovery-Score, Schlaf-Metriken, Schlaf-Erholungs-Korrelation.
"""
from placeholder_registry import (
PlaceholderMetadata,
MissingValuePolicy,
EvidenceType,
OutputType,
PlaceholderType,
register_placeholder,
)
CAT = "Schlaf & Erholung"
MVP = lambda reason, disp: MissingValuePolicy(
available=False, value_raw=None, missing_reason=reason, legacy_display=disp
)
def _tag(m: PlaceholderMetadata):
for f in (
"key", "category", "description", "resolver_module", "resolver_function",
"data_layer_module", "data_layer_function", "source_tables", "semantic_contract",
"unit", "time_window", "output_type", "placeholder_type", "format_hint",
"example_output", "minimum_data_requirements", "confidence_logic",
"missing_value_policy", "layer_1_decision", "layer_2a_decision",
"layer_2b_reuse_possible", "architecture_alignment", "issue_53_alignment",
):
m.set_evidence(f, EvidenceType.CODE_DERIVED)
m.set_evidence("business_meaning", EvidenceType.DRAFT_DERIVED)
m.set_evidence("known_limitations", EvidenceType.MIXED)
def register_schlaf_erholung():
# ── formatierte Schlaf-/Ruhetage-Snapshots ───────────────────────────────
m = PlaceholderMetadata(
key="sleep_avg_duration",
category=CAT,
description="Durchschnittliche Schlafdauer (Stunden), formatiert",
resolver_module="backend/placeholder_resolver.py",
resolver_function="get_sleep_avg_duration",
data_layer_module="backend/data_layer/recovery_metrics.py",
data_layer_function="get_sleep_duration_data",
source_tables=["sleep_log"],
semantic_contract="Mittel aus Schlafphasen im Fenster (siehe get_sleep_duration_data).",
business_meaning="KI-Kontext Schlafdauer",
unit="h (Anzeige mit Einheit)",
time_window="7d default im Resolver",
output_type=OutputType.STRING,
placeholder_type=PlaceholderType.INTERPRETED,
format_hint="z. B. 7.2h",
example_output="7.2h",
minimum_data_requirements="sleep_log im Fenster",
quality_filter_policy=None,
confidence_logic="data['confidence'] im Layer1",
missing_value_policy=MVP("no_data", "nicht verfügbar"),
known_limitations="Abhängig von Import/Qualität der Phasen",
layer_1_decision="recovery_metrics.get_sleep_duration_data",
layer_2a_decision="get_sleep_avg_duration",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
m = PlaceholderMetadata(
key="sleep_avg_quality",
category=CAT,
description="Schlafqualität (Deep+REM %), formatiert",
resolver_module="backend/placeholder_resolver.py",
resolver_function="get_sleep_avg_quality",
data_layer_module="backend/data_layer/recovery_metrics.py",
data_layer_function="get_sleep_quality_data",
source_tables=["sleep_log"],
semantic_contract="Anteil Deep+REM aus Segmenten (siehe get_sleep_quality_data).",
business_meaning="KI-Kontext Schlafqualität",
unit="%",
time_window="7d default",
output_type=OutputType.STRING,
placeholder_type=PlaceholderType.INTERPRETED,
format_hint="Prozent oder nicht verfügbar",
example_output="24%",
minimum_data_requirements="sleep_log mit Phasen",
quality_filter_policy=None,
confidence_logic="Layer-1-Confidence",
missing_value_policy=MVP("no_data", "nicht verfügbar"),
known_limitations="Segment-Schreibweise case-sensitiv normalisiert",
layer_1_decision="recovery_metrics.get_sleep_quality_data",
layer_2a_decision="get_sleep_avg_quality",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
m = PlaceholderMetadata(
key="rest_days_count",
category=CAT,
description="Anzahl dokumentierter Ruhetage (30d default)",
resolver_module="backend/placeholder_resolver.py",
resolver_function="get_rest_days_count",
data_layer_module="backend/data_layer/recovery_metrics.py",
data_layer_function="get_rest_days_data",
source_tables=["rest_days"],
semantic_contract="Count rest_days im Zeitraum",
business_meaning="Aktive/passive Erholungstags-Übersicht",
unit="count",
time_window="30d default",
output_type=OutputType.STRING,
placeholder_type=PlaceholderType.RAW_DATA,
format_hint="z. B. 2 Ruhetage",
example_output="2 Ruhetage",
minimum_data_requirements="rest_days",
quality_filter_policy=None,
confidence_logic="Immer Zählung, 0 möglich",
missing_value_policy=MVP("no_data", "0 Ruhetage"),
known_limitations="Nur explizit erfasste Ruhetage",
layer_1_decision="recovery_metrics.get_rest_days_data",
layer_2a_decision="get_rest_days_count",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
m = PlaceholderMetadata(
key="recovery_score",
category=CAT,
description="Recovery-Score 0100 (v2, komposit)",
resolver_module="backend/placeholder_resolver.py",
resolver_function="_safe_int",
data_layer_module="backend/data_layer/recovery_metrics.py",
data_layer_function="calculate_recovery_score_v2",
source_tables=["sleep_log", "vitals_baseline", "activity_log"],
semantic_contract="Gewichteter Score aus Schlaf, Vitaltrends, optional Load (siehe Implementierung).",
business_meaning="Gesamt-Recovery-KPI für Prompts",
unit="0100",
time_window="composite",
output_type=OutputType.NUMERIC,
placeholder_type=PlaceholderType.SCORE,
format_hint="Ganzzahl-String",
example_output="72",
minimum_data_requirements="Teilkomponenten je nach Gewichtung",
quality_filter_policy=None,
confidence_logic="Wie calculate_recovery_score_v2",
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
known_limitations="Abhängig von Datenabdeckung HF/HRV/Schlaf",
layer_1_decision="recovery_metrics.calculate_recovery_score_v2",
layer_2a_decision="_safe_int('recovery_score_v2')",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
for key, dl_fn, desc, unit, tbls, res_fn in [
("sleep_avg_duration_7d", "calculate_sleep_avg_duration_7d", "Durchschnittliche Schlafdauer 7d (h)", "h", ["sleep_log"], "_safe_float"),
("sleep_debt_hours", "calculate_sleep_debt_hours", "Kumulative Schlafschuld (h)", "h", ["sleep_log"], "_safe_float"),
("sleep_regularity_proxy", "calculate_sleep_regularity_proxy", "Schlaf-Regularität (Proxy)", "min", ["sleep_log"], "_safe_float"),
("recent_load_balance_3d", "calculate_recent_load_balance_3d", "Load-Balance 3d (Score)", "score", ["activity_log"], "_safe_int"),
("sleep_quality_7d", "calculate_sleep_quality_7d", "Schlafqualität 7d (0100)", "0-100", ["sleep_log"], "_safe_int"),
]:
m = PlaceholderMetadata(
key=key,
category=CAT,
description=desc,
resolver_module="backend/placeholder_resolver.py",
resolver_function=res_fn,
data_layer_module="backend/data_layer/recovery_metrics.py",
data_layer_function=dl_fn,
source_tables=tbls,
semantic_contract=f"Berechnung {dl_fn} in recovery_metrics.",
business_meaning="Erholungs-Detailmetrik",
unit=unit,
time_window="siehe Funktion",
output_type=OutputType.NUMERIC,
placeholder_type=PlaceholderType.INTERPRETED,
format_hint="numerischer String",
example_output="1.0",
minimum_data_requirements="wie Funktion",
quality_filter_policy=None,
confidence_logic="Funktionsintern",
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
known_limitations=None,
layer_1_decision=f"recovery_metrics.{dl_fn}",
layer_2a_decision="Resolver _safe_float/_safe_int",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
m = PlaceholderMetadata(
key="correlation_sleep_recovery",
category=CAT,
description="JSON: Korrelation Schlaf ↔ Recovery-Indikatoren",
resolver_module="backend/placeholder_resolver.py",
resolver_function="_safe_json",
data_layer_module="backend/data_layer/correlations.py",
data_layer_function="calculate_correlation_sleep_recovery",
source_tables=["sleep_log", "vitals_baseline", "activity_log"],
semantic_contract="Strukturierte Korrelationsauswertung (siehe correlations).",
business_meaning="KI: Zusammenhänge Schlaf und Erholung",
unit="JSON",
time_window="funktionsabhängig",
output_type=OutputType.JSON,
placeholder_type=PlaceholderType.RAW_DATA,
format_hint="JSON-String",
example_output="{}",
minimum_data_requirements="Ausreichend gekoppelte Datenpunkte",
quality_filter_policy=None,
confidence_logic="Wie correlation_metrics",
missing_value_policy=MVP("insufficient_data", "{}"),
known_limitations="Bei wenig Daten leer oder schwach",
layer_1_decision="correlations.calculate_correlation_sleep_recovery",
layer_2a_decision="_safe_json",
layer_2b_reuse_possible=True,
architecture_alignment="Phase 0c",
issue_53_alignment="Layer 1",
evidence={},
)
_tag(m)
register_placeholder(m)
register_schlaf_erholung()