|
|
|
|
@@ -35,12 +35,7 @@ def dashboard():
|
|
|
|
|
# Calculate weekly averages via SQL
|
|
|
|
|
systolic_avg, diastolic_avg, heart_rate_avg = calculate_weekly_summary_sql(current_user.id)
|
|
|
|
|
|
|
|
|
|
# Badges need paginated or all readings. We'll fetch all readings for badges
|
|
|
|
|
# Note: To avoid huge queries, we might want a specific badge query in the future.
|
|
|
|
|
# For now, let's fetch current month readings + previous as a rough approximation or keep behavior.
|
|
|
|
|
# A generic query for badges:
|
|
|
|
|
all_readings = Reading.query.filter_by(user_id=current_user.id).order_by(Reading.timestamp.desc()).all()
|
|
|
|
|
badges = calculate_progress_badges(all_readings)
|
|
|
|
|
badges = calculate_progress_badges(current_user.id, user_tz)
|
|
|
|
|
|
|
|
|
|
# We will default to showing the list view on initial load
|
|
|
|
|
page = request.args.get('page', 1, type=int)
|
|
|
|
|
@@ -248,47 +243,58 @@ def prepare_graph_data(readings):
|
|
|
|
|
'heart_rate': [r.heart_rate for r in readings],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def calculate_progress_badges(readings):
|
|
|
|
|
"""Generate badges based on user activity and milestones."""
|
|
|
|
|
now = datetime.utcnow().date()
|
|
|
|
|
def calculate_progress_badges(user_id, user_tz):
|
|
|
|
|
"""Generate badges based on user activity and milestones using optimized queries."""
|
|
|
|
|
now_local = datetime.now(user_tz).date()
|
|
|
|
|
badges = []
|
|
|
|
|
|
|
|
|
|
if not readings:
|
|
|
|
|
total_readings = Reading.query.filter_by(user_id=user_id).count()
|
|
|
|
|
if total_readings == 0:
|
|
|
|
|
return badges
|
|
|
|
|
|
|
|
|
|
# Use reversed() instead of re-sorting — readings come in desc order from DB
|
|
|
|
|
sorted_readings = list(reversed(readings))
|
|
|
|
|
streak_count = 1
|
|
|
|
|
daily_streak = True
|
|
|
|
|
# Fetch only timestamps (highly optimized compared to fetching full objects)
|
|
|
|
|
timestamps = db.session.query(Reading.timestamp).filter(Reading.user_id == user_id).order_by(Reading.timestamp.desc()).all()
|
|
|
|
|
|
|
|
|
|
previous_date = sorted_readings[0].timestamp.date()
|
|
|
|
|
streak_count = 0
|
|
|
|
|
if timestamps:
|
|
|
|
|
distinct_dates = []
|
|
|
|
|
last_date = None
|
|
|
|
|
for (ts,) in timestamps:
|
|
|
|
|
local_date = utc.localize(ts).astimezone(user_tz).date()
|
|
|
|
|
if local_date != last_date:
|
|
|
|
|
distinct_dates.append(local_date)
|
|
|
|
|
last_date = local_date
|
|
|
|
|
|
|
|
|
|
for reading in sorted_readings[1:]:
|
|
|
|
|
current_date = reading.timestamp.date()
|
|
|
|
|
if distinct_dates:
|
|
|
|
|
most_recent_date = distinct_dates[0]
|
|
|
|
|
if (now_local - most_recent_date).days <= 1:
|
|
|
|
|
streak_count = 1
|
|
|
|
|
current_check_date = most_recent_date
|
|
|
|
|
|
|
|
|
|
for d in distinct_dates[1:]:
|
|
|
|
|
if (current_check_date - d).days == 1:
|
|
|
|
|
streak_count += 1
|
|
|
|
|
current_check_date = d
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if (current_date - previous_date).days == 1:
|
|
|
|
|
streak_count += 1
|
|
|
|
|
elif (current_date - previous_date).days > 1:
|
|
|
|
|
daily_streak = False
|
|
|
|
|
|
|
|
|
|
previous_date = current_date
|
|
|
|
|
|
|
|
|
|
if daily_streak and streak_count >= 1:
|
|
|
|
|
if streak_count >= 1:
|
|
|
|
|
badges.append(f"Current Streak: {streak_count} Days")
|
|
|
|
|
if daily_streak and streak_count >= 7:
|
|
|
|
|
if streak_count >= 7:
|
|
|
|
|
badges.append("Logged Every Day for a Week")
|
|
|
|
|
|
|
|
|
|
if daily_streak and streak_count >= 30 and previous_date == now:
|
|
|
|
|
if streak_count >= 30:
|
|
|
|
|
badges.append("Monthly Streak")
|
|
|
|
|
|
|
|
|
|
if all(5 <= r.timestamp.hour < 12 for r in sorted_readings[-7:]):
|
|
|
|
|
badges.append("Morning Riser: Logged Readings Every Morning for a Week")
|
|
|
|
|
|
|
|
|
|
if all(18 <= r.timestamp.hour <= 23 for r in sorted_readings[-7:]):
|
|
|
|
|
badges.append("Night Owl: Logged Readings Every Night for a Week")
|
|
|
|
|
last_7_readings = db.session.query(Reading.timestamp).filter(Reading.user_id == user_id).order_by(Reading.timestamp.desc()).limit(7).all()
|
|
|
|
|
if len(last_7_readings) == 7:
|
|
|
|
|
if all(5 <= utc.localize(ts).astimezone(user_tz).hour < 12 for (ts,) in last_7_readings):
|
|
|
|
|
badges.append("Morning Riser: Logged Readings Every Morning for a Week")
|
|
|
|
|
|
|
|
|
|
if all(18 <= utc.localize(ts).astimezone(user_tz).hour <= 23 for (ts,) in last_7_readings):
|
|
|
|
|
badges.append("Night Owl: Logged Readings Every Night for a Week")
|
|
|
|
|
|
|
|
|
|
milestones = [10, 50, 100, 500, 1000, 5000, 10000]
|
|
|
|
|
highest_milestone = max((m for m in milestones if len(readings) >= m), default=None)
|
|
|
|
|
highest_milestone = max((m for m in milestones if total_readings >= m), default=None)
|
|
|
|
|
if highest_milestone:
|
|
|
|
|
badges.append(f"{highest_milestone} Readings Logged")
|
|
|
|
|
|
|
|
|
|
|