- 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.
393 lines
15 KiB
Python
393 lines
15 KiB
Python
"""Registry: Ziele, Fokusbereiche, Kategorie-Scores und formatierte Listen (Phase 0b)."""
|
||
|
||
from placeholder_registry import (
|
||
PlaceholderMetadata,
|
||
MissingValuePolicy,
|
||
OutputType,
|
||
PlaceholderType,
|
||
register_placeholder,
|
||
)
|
||
from ._evidence import tag_standard_evidence
|
||
|
||
CAT = "Ziele & Fokus (Phase 0b)"
|
||
MVP = lambda reason, disp: MissingValuePolicy(
|
||
available=False, value_raw=None, missing_reason=reason, legacy_display=disp
|
||
)
|
||
|
||
|
||
def register_phase_0b_ziele_fokus():
|
||
# Top-Ziel / Top-Fokusbereich
|
||
m = PlaceholderMetadata(
|
||
key="top_goal_name",
|
||
category=CAT,
|
||
description="Name/Typ des höchstpriorisierten Ziels",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_str",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="get_top_priority_goal",
|
||
source_tables=["goals"],
|
||
semantic_contract="Feld name oder goal_type aus get_top_priority_goal",
|
||
business_meaning="Priorisierung für KI-Empfehlungen",
|
||
unit="text",
|
||
time_window="aktuell",
|
||
output_type=OutputType.STRING,
|
||
placeholder_type=PlaceholderType.INTERPRETED,
|
||
format_hint="Kurztext",
|
||
example_output="Gewicht 80kg",
|
||
minimum_data_requirements="Mindestens ein aktives Ziel",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.get_top_priority_goal",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.get_top_priority_goal",
|
||
layer_2a_decision="_safe_str('top_goal_name')",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
m = PlaceholderMetadata(
|
||
key="top_goal_progress_pct",
|
||
category=CAT,
|
||
description="Fortschritt Top-Ziel (%)",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_int",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="get_top_priority_goal",
|
||
source_tables=["goals"],
|
||
semantic_contract="progress_pct aus get_top_priority_goal",
|
||
business_meaning="Priorisierung für KI-Empfehlungen",
|
||
unit="%",
|
||
time_window="aktuell",
|
||
output_type=OutputType.NUMERIC,
|
||
placeholder_type=PlaceholderType.SCORE,
|
||
format_hint="Ganzzahl",
|
||
example_output="65",
|
||
minimum_data_requirements="Mindestens ein aktives Ziel",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.get_top_priority_goal",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.get_top_priority_goal",
|
||
layer_2a_decision="_safe_int('top_goal_progress_pct')",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
m = PlaceholderMetadata(
|
||
key="top_goal_status",
|
||
category=CAT,
|
||
description="Status-Label Top-Ziel",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_str",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="get_top_priority_goal",
|
||
source_tables=["goals"],
|
||
semantic_contract="status aus get_top_priority_goal",
|
||
business_meaning="Priorisierung für KI-Empfehlungen",
|
||
unit="text",
|
||
time_window="aktuell",
|
||
output_type=OutputType.STRING,
|
||
placeholder_type=PlaceholderType.INTERPRETED,
|
||
format_hint="Kurztext",
|
||
example_output="active",
|
||
minimum_data_requirements="Mindestens ein aktives Ziel",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.get_top_priority_goal",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.get_top_priority_goal",
|
||
layer_2a_decision="_safe_str('top_goal_status')",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
m = PlaceholderMetadata(
|
||
key="top_focus_area_name",
|
||
category=CAT,
|
||
description="Bezeichnung des gewichtet stärksten Fokusbereichs",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_str",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="get_top_focus_area",
|
||
source_tables=["user_focus_area_weights", "focus_area_definitions"],
|
||
semantic_contract="label aus get_top_focus_area",
|
||
business_meaning="Priorisierung für KI-Empfehlungen",
|
||
unit="text",
|
||
time_window="aktuell",
|
||
output_type=OutputType.STRING,
|
||
placeholder_type=PlaceholderType.INTERPRETED,
|
||
format_hint="Kurztext",
|
||
example_output="Kraft",
|
||
minimum_data_requirements="Gewichtete Fokusbereiche",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.get_top_focus_area",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.get_top_focus_area",
|
||
layer_2a_decision="_safe_str('top_focus_area_name')",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
m = PlaceholderMetadata(
|
||
key="top_focus_area_progress",
|
||
category=CAT,
|
||
description="Fortschritt Top-Fokusbereich (%)",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_int",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="get_top_focus_area",
|
||
source_tables=["user_focus_area_weights", "focus_area_definitions", "goals"],
|
||
semantic_contract="progress aus get_top_focus_area",
|
||
business_meaning="Priorisierung für KI-Empfehlungen",
|
||
unit="%",
|
||
time_window="aktuell",
|
||
output_type=OutputType.NUMERIC,
|
||
placeholder_type=PlaceholderType.SCORE,
|
||
format_hint="Ganzzahl",
|
||
example_output="58",
|
||
minimum_data_requirements="Gewichtete Fokusbereiche",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.get_top_focus_area",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.get_top_focus_area",
|
||
layer_2a_decision="_safe_int('top_focus_area_progress')",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
# Kategorie Progress / Weight (7 Kategorien)
|
||
for slug in (
|
||
"körper",
|
||
"ernährung",
|
||
"aktivität",
|
||
"recovery",
|
||
"vitalwerte",
|
||
"mental",
|
||
"lebensstil",
|
||
):
|
||
key_p = f"focus_cat_{slug}_progress"
|
||
key_w = f"focus_cat_{slug}_weight"
|
||
m_p = PlaceholderMetadata(
|
||
key=key_p,
|
||
category=CAT,
|
||
description=f"Aggregierter Fortschritt Kategorie „{slug}“ (%)",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_int",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="calculate_category_progress",
|
||
source_tables=["goals", "focus_area_definitions", "user_focus_area_weights"],
|
||
semantic_contract=f"scores.calculate_category_progress(pid, '{slug}')",
|
||
business_meaning="Focus-Area-Kategorie-Score",
|
||
unit="%",
|
||
time_window="aktuell",
|
||
output_type=OutputType.NUMERIC,
|
||
placeholder_type=PlaceholderType.SCORE,
|
||
format_hint="Ganzzahl",
|
||
example_output="55",
|
||
minimum_data_requirements="Gewichtete Bereiche in Kategorie",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.calculate_category_progress",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.calculate_category_progress",
|
||
layer_2a_decision="_safe_int",
|
||
layer_2b_reuse_possible=True,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m_p)
|
||
register_placeholder(m_p)
|
||
|
||
m_w = PlaceholderMetadata(
|
||
key=key_w,
|
||
category=CAT,
|
||
description=f"Nutzer-Gewichtung Kategorie „{slug}“ (Anteil 0–1)",
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function="_safe_float",
|
||
data_layer_module="backend/data_layer/scores.py",
|
||
data_layer_function="calculate_category_weight",
|
||
source_tables=["user_focus_area_weights", "focus_area_definitions"],
|
||
semantic_contract=f"scores.calculate_category_weight(pid, '{slug}')",
|
||
business_meaning="Kategorie-Gewichtung im Fokusmodell",
|
||
unit="0–1",
|
||
time_window="aktuell",
|
||
output_type=OutputType.NUMERIC,
|
||
placeholder_type=PlaceholderType.INTERPRETED,
|
||
format_hint="Dezimal",
|
||
example_output="0.25",
|
||
minimum_data_requirements="user_focus_area_weights",
|
||
quality_filter_policy=None,
|
||
confidence_logic="scores.calculate_category_weight",
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="scores.calculate_category_weight",
|
||
layer_2a_decision="_safe_float",
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m_w)
|
||
register_placeholder(m_w)
|
||
|
||
# Strukturierte Ziele / Fokus
|
||
for key, res_fn, dl_mod, dl_fn, desc, out, ptype in [
|
||
(
|
||
"active_goals_json",
|
||
"_safe_json",
|
||
"backend/goal_utils.py",
|
||
"get_active_goals",
|
||
"Aktive Ziele als JSON",
|
||
OutputType.JSON,
|
||
PlaceholderType.RAW_DATA,
|
||
),
|
||
(
|
||
"active_goals_md",
|
||
"_safe_str",
|
||
"backend/placeholder_resolver.py",
|
||
"_format_goals_as_markdown",
|
||
"Aktive Ziele als Markdown-Tabelle",
|
||
OutputType.TEXT_SUMMARY,
|
||
PlaceholderType.INTERPRETED,
|
||
),
|
||
(
|
||
"focus_areas_weighted_json",
|
||
"_safe_json",
|
||
"backend/placeholder_resolver.py",
|
||
"_get_focus_areas_weighted_json",
|
||
"Gewichtete Fokusbereiche mit Namen (JSON)",
|
||
OutputType.JSON,
|
||
PlaceholderType.RAW_DATA,
|
||
),
|
||
(
|
||
"focus_areas_weighted_md",
|
||
"_safe_str",
|
||
"backend/placeholder_resolver.py",
|
||
"_format_focus_areas_as_markdown",
|
||
"Gewichtete Fokusbereiche als Markdown",
|
||
OutputType.TEXT_SUMMARY,
|
||
PlaceholderType.INTERPRETED,
|
||
),
|
||
(
|
||
"focus_area_weights_json",
|
||
"_safe_json",
|
||
"backend/data_layer/scores.py",
|
||
"get_user_focus_weights",
|
||
"Rohe Gewichtungen key→Anteil (JSON)",
|
||
OutputType.JSON,
|
||
PlaceholderType.RAW_DATA,
|
||
),
|
||
]:
|
||
m = PlaceholderMetadata(
|
||
key=key,
|
||
category=CAT,
|
||
description=desc,
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function=res_fn,
|
||
data_layer_module=dl_mod,
|
||
data_layer_function=dl_fn,
|
||
source_tables=["goals", "focus_area_definitions", "user_focus_area_weights"],
|
||
semantic_contract=f"{dl_fn} (siehe Modul {dl_mod})",
|
||
business_meaning="Strukturierte Übersicht für Prompts",
|
||
unit="JSON" if out == OutputType.JSON else "markdown",
|
||
time_window="aktuell",
|
||
output_type=out,
|
||
placeholder_type=ptype,
|
||
format_hint="String aus Resolver",
|
||
example_output="[]" if out == OutputType.JSON else "—",
|
||
minimum_data_requirements="Ziele bzw. Fokusgewichte",
|
||
quality_filter_policy=None,
|
||
confidence_logic="Resolver + goal_utils / scores",
|
||
missing_value_policy=MVP("insufficient_data", "[]" if out == OutputType.JSON else "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision=dl_fn,
|
||
layer_2a_decision=res_fn,
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 1",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
for key, res_fn, dl_fn, desc, ex in [
|
||
(
|
||
"top_3_focus_areas",
|
||
"_safe_str",
|
||
"_format_top_focus_areas",
|
||
"Top-3 Fokusbereiche als formatierter Text",
|
||
"1. Kraft …",
|
||
),
|
||
(
|
||
"top_3_goals_behind_schedule",
|
||
"_safe_str",
|
||
"_format_goals_behind",
|
||
"Bis zu drei Ziele hinter Zeitplan",
|
||
"—",
|
||
),
|
||
(
|
||
"top_3_goals_on_track",
|
||
"_safe_str",
|
||
"_format_goals_on_track",
|
||
"Bis zu drei Ziele im Plan",
|
||
"—",
|
||
),
|
||
]:
|
||
m = PlaceholderMetadata(
|
||
key=key,
|
||
category=CAT,
|
||
description=desc,
|
||
resolver_module="backend/placeholder_resolver.py",
|
||
resolver_function=res_fn,
|
||
data_layer_module="backend/goal_utils.py",
|
||
data_layer_function="get_active_goals",
|
||
source_tables=["goals", "focus_area_definitions"],
|
||
semantic_contract=f"Resolver {dl_fn}",
|
||
business_meaning="Kurzlisten für Coaching-Prompts",
|
||
unit="text",
|
||
time_window="aktuell",
|
||
output_type=OutputType.TEXT_SUMMARY,
|
||
placeholder_type=PlaceholderType.INTERPRETED,
|
||
format_hint="Freitext / Aufzählung",
|
||
example_output=ex,
|
||
minimum_data_requirements="Ziele / Fokusdaten",
|
||
quality_filter_policy=None,
|
||
confidence_logic=dl_fn,
|
||
missing_value_policy=MVP("insufficient_data", "nicht verfügbar"),
|
||
known_limitations=None,
|
||
layer_1_decision="goals + focus aggregation",
|
||
layer_2a_decision=dl_fn,
|
||
layer_2b_reuse_possible=False,
|
||
architecture_alignment="Phase 0b",
|
||
issue_53_alignment="Layer 2a",
|
||
evidence={},
|
||
)
|
||
tag_standard_evidence(m)
|
||
register_placeholder(m)
|
||
|
||
|
||
register_phase_0b_ziele_fokus()
|