237 lines
10 KiB
Python
237 lines
10 KiB
Python
|
|
"""
|
|||
|
|
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 0–100 (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="0–100",
|
|||
|
|
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 (0–100)", "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()
|