fix: Phase 0b - body_progress_score + placeholder formatting
Fixed remaining placeholder calculation issues: 1. body_progress_score returning 0: - When start_value is NULL, query oldest weight from last 90 days - Prevents progress = 0% when start equals current 2. focus_areas_weighted_json empty: - Changed from goal_utils.get_focus_weights_v2() to scores.get_user_focus_weights() - Now uses same function as focus_area_weights_json 3. Implemented 5 TODO markdown formatting functions: - _format_goals_as_markdown() - table with progress bars - _format_focus_areas_as_markdown() - weighted list - _format_top_focus_areas() - top N by weight - _format_goals_behind() - lowest progress goals - _format_goals_on_track() - goals >= 50% progress All placeholders should now return proper values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b09a7b200a
commit
8da577fe58
|
|
@ -395,11 +395,26 @@ def _score_weight_trend(profile_id: str) -> Optional[int]:
|
||||||
|
|
||||||
current = goal.get('current_value')
|
current = goal.get('current_value')
|
||||||
target = goal.get('target_value')
|
target = goal.get('target_value')
|
||||||
start = goal.get('start_value', current)
|
start = goal.get('start_value')
|
||||||
|
|
||||||
if None in [current, target, start]:
|
if None in [current, target]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# If no start_value, use oldest weight in last 90 days
|
||||||
|
if start is None:
|
||||||
|
with get_db() as conn:
|
||||||
|
cur = get_cursor(conn)
|
||||||
|
cur.execute("""
|
||||||
|
SELECT weight
|
||||||
|
FROM weight_log
|
||||||
|
WHERE profile_id = %s
|
||||||
|
AND date >= CURRENT_DATE - INTERVAL '90 days'
|
||||||
|
ORDER BY date ASC
|
||||||
|
LIMIT 1
|
||||||
|
""", (profile_id,))
|
||||||
|
row = cur.fetchone()
|
||||||
|
start = float(row['weight']) if row else current
|
||||||
|
|
||||||
# Progress percentage
|
# Progress percentage
|
||||||
progress_pct = calculate_goal_progress_pct(current, target, start)
|
progress_pct = calculate_goal_progress_pct(current, target, start)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -677,9 +677,10 @@ def _get_focus_areas_weighted_json(profile_id: str) -> str:
|
||||||
"""Get focus areas with weights as JSON string"""
|
"""Get focus areas with weights as JSON string"""
|
||||||
import json
|
import json
|
||||||
try:
|
try:
|
||||||
from goal_utils import get_focus_weights_v2, get_db, get_cursor
|
from calculations.scores import get_user_focus_weights
|
||||||
|
from goal_utils import get_db, get_cursor
|
||||||
|
|
||||||
weights = get_focus_weights_v2(get_db(), profile_id)
|
weights = get_user_focus_weights(profile_id)
|
||||||
|
|
||||||
# Get focus area details
|
# Get focus area details
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
|
|
@ -713,32 +714,132 @@ def _get_focus_areas_weighted_json(profile_id: str) -> str:
|
||||||
|
|
||||||
def _format_goals_as_markdown(profile_id: str) -> str:
|
def _format_goals_as_markdown(profile_id: str) -> str:
|
||||||
"""Format goals as markdown table"""
|
"""Format goals as markdown table"""
|
||||||
# TODO: Implement
|
try:
|
||||||
return 'Keine Ziele definiert'
|
from goal_utils import get_active_goals
|
||||||
|
|
||||||
|
goals = get_active_goals(profile_id)
|
||||||
|
if not goals:
|
||||||
|
return 'Keine Ziele definiert'
|
||||||
|
|
||||||
|
# Build markdown table
|
||||||
|
lines = ['| Ziel | Aktuell | Ziel | Progress | Status |', '|------|---------|------|----------|--------|']
|
||||||
|
|
||||||
|
for goal in goals:
|
||||||
|
name = goal.get('name') or goal.get('goal_type', 'Unbekannt')
|
||||||
|
current = f"{goal.get('current_value', '-')}"
|
||||||
|
target = f"{goal.get('target_value', '-')}"
|
||||||
|
progress = f"{goal.get('progress_pct', '-')}%" if goal.get('progress_pct') else '-'
|
||||||
|
status = '🎯' if goal.get('is_primary') else '○'
|
||||||
|
|
||||||
|
lines.append(f"| {name} | {current} | {target} | {progress} | {status} |")
|
||||||
|
|
||||||
|
return '\n'.join(lines)
|
||||||
|
except Exception:
|
||||||
|
return 'Keine Ziele definiert'
|
||||||
|
|
||||||
|
|
||||||
def _format_focus_areas_as_markdown(profile_id: str) -> str:
|
def _format_focus_areas_as_markdown(profile_id: str) -> str:
|
||||||
"""Format focus areas as markdown"""
|
"""Format focus areas as markdown"""
|
||||||
# TODO: Implement
|
try:
|
||||||
return 'Keine Focus Areas aktiv'
|
import json
|
||||||
|
weighted_json = _get_focus_areas_weighted_json(profile_id)
|
||||||
|
areas = json.loads(weighted_json)
|
||||||
|
|
||||||
|
if not areas:
|
||||||
|
return 'Keine Focus Areas aktiv'
|
||||||
|
|
||||||
|
# Build markdown list
|
||||||
|
lines = []
|
||||||
|
for area in areas:
|
||||||
|
name = area.get('name', 'Unbekannt')
|
||||||
|
weight = area.get('weight', 0)
|
||||||
|
lines.append(f"- **{name}**: {weight}%")
|
||||||
|
|
||||||
|
return '\n'.join(lines)
|
||||||
|
except Exception:
|
||||||
|
return 'Keine Focus Areas aktiv'
|
||||||
|
|
||||||
|
|
||||||
def _format_top_focus_areas(profile_id: str, n: int = 3) -> str:
|
def _format_top_focus_areas(profile_id: str, n: int = 3) -> str:
|
||||||
"""Format top N focus areas as text"""
|
"""Format top N focus areas as text"""
|
||||||
# TODO: Implement
|
try:
|
||||||
return 'nicht verfügbar'
|
import json
|
||||||
|
weighted_json = _get_focus_areas_weighted_json(profile_id)
|
||||||
|
areas = json.loads(weighted_json)
|
||||||
|
|
||||||
|
if not areas:
|
||||||
|
return 'Keine Focus Areas definiert'
|
||||||
|
|
||||||
|
# Sort by weight descending and take top N
|
||||||
|
sorted_areas = sorted(areas, key=lambda x: x.get('weight', 0), reverse=True)[:n]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for i, area in enumerate(sorted_areas, 1):
|
||||||
|
name = area.get('name', 'Unbekannt')
|
||||||
|
weight = area.get('weight', 0)
|
||||||
|
lines.append(f"{i}. {name} ({weight}%)")
|
||||||
|
|
||||||
|
return ', '.join(lines)
|
||||||
|
except Exception:
|
||||||
|
return 'nicht verfügbar'
|
||||||
|
|
||||||
|
|
||||||
def _format_goals_behind(profile_id: str, n: int = 3) -> str:
|
def _format_goals_behind(profile_id: str, n: int = 3) -> str:
|
||||||
"""Format top N goals behind schedule"""
|
"""Format top N goals behind schedule"""
|
||||||
# TODO: Implement
|
try:
|
||||||
return 'nicht verfügbar'
|
from goal_utils import get_active_goals
|
||||||
|
goals = get_active_goals(profile_id)
|
||||||
|
|
||||||
|
if not goals:
|
||||||
|
return 'Keine Ziele definiert'
|
||||||
|
|
||||||
|
# Filter goals with progress_pct available, sort by lowest progress
|
||||||
|
goals_with_progress = [g for g in goals if g.get('progress_pct') is not None]
|
||||||
|
|
||||||
|
if not goals_with_progress:
|
||||||
|
return 'Keine Ziele mit Fortschritt'
|
||||||
|
|
||||||
|
# Sort by progress ascending (lowest first) and take top N
|
||||||
|
sorted_goals = sorted(goals_with_progress, key=lambda x: x.get('progress_pct', 0))[:n]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for goal in sorted_goals:
|
||||||
|
name = goal.get('name') or goal.get('goal_type', 'Unbekannt')
|
||||||
|
progress = goal.get('progress_pct', 0)
|
||||||
|
lines.append(f"{name} ({progress}%)")
|
||||||
|
|
||||||
|
return ', '.join(lines)
|
||||||
|
except Exception:
|
||||||
|
return 'nicht verfügbar'
|
||||||
|
|
||||||
|
|
||||||
def _format_goals_on_track(profile_id: str, n: int = 3) -> str:
|
def _format_goals_on_track(profile_id: str, n: int = 3) -> str:
|
||||||
"""Format top N goals on track"""
|
"""Format top N goals on track"""
|
||||||
# TODO: Implement
|
try:
|
||||||
return 'nicht verfügbar'
|
from goal_utils import get_active_goals
|
||||||
|
goals = get_active_goals(profile_id)
|
||||||
|
|
||||||
|
if not goals:
|
||||||
|
return 'Keine Ziele definiert'
|
||||||
|
|
||||||
|
# Filter goals with progress >= 50%, sort by highest progress
|
||||||
|
goals_on_track = [g for g in goals if g.get('progress_pct') is not None and g.get('progress_pct', 0) >= 50]
|
||||||
|
|
||||||
|
if not goals_on_track:
|
||||||
|
return 'Keine Ziele auf gutem Weg'
|
||||||
|
|
||||||
|
# Sort by progress descending (highest first) and take top N
|
||||||
|
sorted_goals = sorted(goals_on_track, key=lambda x: x.get('progress_pct', 0), reverse=True)[:n]
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for goal in sorted_goals:
|
||||||
|
name = goal.get('name') or goal.get('goal_type', 'Unbekannt')
|
||||||
|
progress = goal.get('progress_pct', 0)
|
||||||
|
lines.append(f"{name} ({progress}%)")
|
||||||
|
|
||||||
|
return ', '.join(lines)
|
||||||
|
except Exception:
|
||||||
|
return 'nicht verfügbar'
|
||||||
|
|
||||||
|
|
||||||
# ── Placeholder Registry ──────────────────────────────────────────────────────
|
# ── Placeholder Registry ──────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user