- Introduced Activity Session Metrics for enhanced tracking of session data. - Updated backend to support new API endpoints for managing session metrics. - Added new Pydantic models for activity metrics and replaced metrics functionality. - Enhanced data layer to include session metrics in recent training session data. - Updated documentation to reflect changes in session metrics handling.
188 lines
8.6 KiB
Python
188 lines
8.6 KiB
Python
"""
|
|
Registry: Trainings-Häufigkeit, Pausen zwischen Einheiten, wöchentliche Session-JSON (KI-Rohkontext).
|
|
"""
|
|
|
|
from placeholder_registry import (
|
|
PlaceholderMetadata,
|
|
MissingValuePolicy,
|
|
EvidenceType,
|
|
OutputType,
|
|
PlaceholderType,
|
|
register_placeholder,
|
|
)
|
|
|
|
|
|
def _ev(meta: PlaceholderMetadata, field: str, et: EvidenceType = EvidenceType.CODE_DERIVED):
|
|
meta.set_evidence(field, et)
|
|
|
|
|
|
def register_activity_session_insights():
|
|
md_freq = PlaceholderMetadata(
|
|
key="training_frequency_by_type_md",
|
|
category="Aktivität",
|
|
description=(
|
|
"Markdown-Tabelle: pro Trainingsart (activity_type) Sessions, Ø/Woche, "
|
|
"Dauer, kcal, HF, RPE, kcal/min (Intensitätsproxy)"
|
|
),
|
|
resolver_module="backend/placeholder_resolver.py",
|
|
resolver_function="get_training_frequency_by_type_md",
|
|
data_layer_module="backend/data_layer/activity_metrics.py",
|
|
data_layer_function="get_training_frequency_by_type_data",
|
|
source_tables=["activity_log"],
|
|
semantic_contract=(
|
|
"Aggregat über activity_log gruppiert nach activity_type (Roh-Label). "
|
|
"sessions_per_week = count / (days/7). avg_kcal_per_min = Summe kcal / Summe min."
|
|
),
|
|
business_meaning="KI: Häufigkeit & Belastung pro Sportart, Erholungs-/Überlastungs-Kontext",
|
|
unit="Markdown",
|
|
time_window="default 28 Tage",
|
|
output_type=OutputType.TEXT_SUMMARY,
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|
format_hint="GitHub-Flavored Markdown-Tabelle",
|
|
example_output="| Art | n | Ø/Woche | … |",
|
|
minimum_data_requirements="Mindestens eine Session im Fenster",
|
|
quality_filter_policy=None,
|
|
confidence_logic="Wie calculate_confidence anhand Session-Anzahl",
|
|
missing_value_policy=MissingValuePolicy(
|
|
available=False,
|
|
value_raw=None,
|
|
missing_reason="no_data",
|
|
legacy_display="Keine Trainingsdaten",
|
|
),
|
|
known_limitations=(
|
|
"Gruppierung nach activity_type-String (Import-Namen), nicht nur training_type_id. "
|
|
"HF/RPE oft NULL je nach Quelle. Pausen-Analyse separater Platzhalter."
|
|
),
|
|
layer_1_decision="activity_metrics.get_training_frequency_by_type_data",
|
|
layer_2a_decision="get_training_frequency_by_type_md",
|
|
layer_2b_reuse_possible=True,
|
|
architecture_alignment="Phase 0c",
|
|
issue_53_alignment="Layer 1",
|
|
evidence={},
|
|
)
|
|
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",
|
|
):
|
|
_ev(md_freq, f)
|
|
_ev(md_freq, "business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
_ev(md_freq, "known_limitations", EvidenceType.MIXED)
|
|
register_placeholder(md_freq)
|
|
|
|
md_gap = PlaceholderMetadata(
|
|
key="training_inter_session_gap_md",
|
|
category="Aktivität",
|
|
description="Median/Mittel/Min der Stunden zwischen aufeinanderfolgenden Trainingseinheiten",
|
|
resolver_module="backend/placeholder_resolver.py",
|
|
resolver_function="get_training_inter_session_gap_md",
|
|
data_layer_module="backend/data_layer/activity_metrics.py",
|
|
data_layer_function="get_training_inter_session_gap_data",
|
|
source_tables=["activity_log"],
|
|
semantic_contract=(
|
|
"Sessions chronologisch; Zeitstempel = date + start_time oder 12:00. "
|
|
"Lücken in Stunden zwischen aufeinanderfolgenden Starts."
|
|
),
|
|
business_meaning="KI: ausreichend Erholung zwischen Belastungen? Doppelbelastung?",
|
|
unit="Markdown",
|
|
time_window="default 28 Tage",
|
|
output_type=OutputType.TEXT_SUMMARY,
|
|
placeholder_type=PlaceholderType.INTERPRETED,
|
|
format_hint="Kurzer Markdown-Fließtext",
|
|
example_output="**Pause zwischen Trainings** …",
|
|
minimum_data_requirements="Mindestens 2 Sessions",
|
|
quality_filter_policy=None,
|
|
confidence_logic="calculate_confidence über Session-Anzahl",
|
|
missing_value_policy=MissingValuePolicy(
|
|
available=False,
|
|
value_raw=None,
|
|
missing_reason="insufficient_data",
|
|
legacy_display="Zu wenige Trainings",
|
|
),
|
|
known_limitations=(
|
|
"Kein Unterscheidung aktiv/passiv außerhalb activity_log. "
|
|
"Fehlende Uhrzeit verzerrt Reihenfolge am selben Tag nicht (nur ein künstlicher Mittag)."
|
|
),
|
|
layer_1_decision="activity_metrics.get_training_inter_session_gap_data",
|
|
layer_2a_decision="get_training_inter_session_gap_md",
|
|
layer_2b_reuse_possible=True,
|
|
architecture_alignment="Phase 0c",
|
|
issue_53_alignment="Layer 1",
|
|
evidence={},
|
|
)
|
|
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",
|
|
):
|
|
_ev(md_gap, f)
|
|
_ev(md_gap, "business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
_ev(md_gap, "known_limitations", EvidenceType.MIXED)
|
|
register_placeholder(md_gap)
|
|
|
|
pj = PlaceholderMetadata(
|
|
key="training_sessions_recent_json",
|
|
category="Aktivität",
|
|
description=(
|
|
"JSON: letzte ISO-Kalenderwochen mit Einheiten (Datum, Art, Dauer, kcal, HF Ø/max, RPE, Kategorie, "
|
|
"session_id, session_metrics[] aus EAV)"
|
|
),
|
|
resolver_module="backend/placeholder_resolver.py",
|
|
resolver_function="_safe_json",
|
|
data_layer_module="backend/data_layer/activity_metrics.py",
|
|
data_layer_function="get_training_sessions_recent_weeks_data",
|
|
source_tables=["activity_log", "training_types", "activity_session_metrics", "training_parameters"],
|
|
semantic_contract=(
|
|
"Struktur weeks[].week_iso, sessions[] mit Feldern für KI-Auswertung; "
|
|
"session_metrics[] = Layer-1-EAV-Werte (key, data_type, unit, value) wenn konfiguriert/gespeichert. "
|
|
"Default 4 ISO-Wochen zurück."
|
|
),
|
|
business_meaning="Rohkontext für wochenweise Auswertung (Erholung, Intensität) in der KI",
|
|
unit="JSON string",
|
|
time_window="4 ISO-Wochen (28 Tage Datenfenster)",
|
|
output_type=OutputType.JSON,
|
|
placeholder_type=PlaceholderType.RAW_DATA,
|
|
format_hint="JSON-Objekt als String",
|
|
example_output='{"weeks":[...],"meta":{...}}',
|
|
minimum_data_requirements="Optional Sessions; meta.confidence bei leer insufficient",
|
|
quality_filter_policy=None,
|
|
confidence_logic="meta.confidence aus Session-Anzahl",
|
|
missing_value_policy=MissingValuePolicy(
|
|
available=False,
|
|
value_raw=None,
|
|
missing_reason="no_data",
|
|
legacy_display="{}",
|
|
),
|
|
known_limitations=(
|
|
"Token-Länge bei vielen Sessions beachten. training_type_name nur bei gesetztem training_type_id. "
|
|
"session_metrics nur befüllt, wenn Admin-Profile zugeordnet und Werte in EAV gespeichert sind."
|
|
),
|
|
layer_1_decision="activity_metrics.get_training_sessions_recent_weeks_data",
|
|
layer_2a_decision="_safe_json('training_sessions_recent_json')",
|
|
layer_2b_reuse_possible=True,
|
|
architecture_alignment="Phase 0c",
|
|
issue_53_alignment="Layer 1",
|
|
evidence={},
|
|
)
|
|
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",
|
|
):
|
|
_ev(pj, f)
|
|
_ev(pj, "business_meaning", EvidenceType.DRAFT_DERIVED)
|
|
_ev(pj, "known_limitations", EvidenceType.MIXED)
|
|
register_placeholder(pj)
|
|
|
|
|
|
register_activity_session_insights()
|