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')
|
||||
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
|
||||
|
||||
# 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_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"""
|
||||
import json
|
||||
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
|
||||
with get_db() as conn:
|
||||
|
|
@ -713,31 +714,131 @@ def _get_focus_areas_weighted_json(profile_id: str) -> str:
|
|||
|
||||
def _format_goals_as_markdown(profile_id: str) -> str:
|
||||
"""Format goals as markdown table"""
|
||||
# TODO: Implement
|
||||
try:
|
||||
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:
|
||||
"""Format focus areas as markdown"""
|
||||
# TODO: Implement
|
||||
try:
|
||||
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:
|
||||
"""Format top N focus areas as text"""
|
||||
# TODO: Implement
|
||||
try:
|
||||
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:
|
||||
"""Format top N goals behind schedule"""
|
||||
# TODO: Implement
|
||||
try:
|
||||
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:
|
||||
"""Format top N goals on track"""
|
||||
# TODO: Implement
|
||||
try:
|
||||
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'
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user