Move nested functions

This commit is contained in:
Peter Stockings
2024-12-29 22:59:08 +11:00
parent 91b3ef0e7e
commit 6291c37820
3 changed files with 131 additions and 134 deletions

View File

@@ -36,4 +36,3 @@ def logout():
logout_user() # Logs out the current user logout_user() # Logs out the current user
flash('You have been logged out.', 'success') flash('You have been logged out.', 'success')
return redirect(url_for('auth.login')) # Redirect to login page or home page return redirect(url_for('auth.login')) # Redirect to login page or home page

View File

@@ -23,132 +23,6 @@ def health():
@main.route('/dashboard', methods=['GET', 'POST']) @main.route('/dashboard', methods=['GET', 'POST'])
@login_required @login_required
def dashboard(): def dashboard():
# Helper function to get first and last reading timestamps
def get_reading_date_range(user_id):
result = (
db.session.query(
func.min(Reading.timestamp).label('first'),
func.max(Reading.timestamp).label('last')
)
.filter(Reading.user_id == user_id)
.first()
)
return result.first, result.last
# Helper function to calculate weekly summary averages
def calculate_weekly_summary(readings):
one_week_ago = datetime.now() - timedelta(days=7)
weekly_readings = [r for r in readings if r.timestamp >= one_week_ago]
if weekly_readings:
systolic_avg = round(sum(r.systolic for r in weekly_readings) / len(weekly_readings), 1)
diastolic_avg = round(sum(r.diastolic for r in weekly_readings) / len(weekly_readings), 1)
heart_rate_avg = round(sum(r.heart_rate for r in weekly_readings) / len(weekly_readings), 1)
else:
systolic_avg = diastolic_avg = heart_rate_avg = 0
return systolic_avg, diastolic_avg, heart_rate_avg
# Helper function to calculate progress badges
def calculate_progress_badges(readings):
"""Calculate badges based on user reading activity."""
badges = []
now = datetime.utcnow().date()
# Prepare sorted readings by timestamp
sorted_readings = sorted(readings, key=lambda r: r.timestamp)
# Incremental milestone badge
def highest_milestone(total_readings, milestones):
"""Determine the highest milestone achieved."""
for milestone in reversed(milestones):
if total_readings >= milestone:
return f"{milestone} Readings Logged"
return None
highest_milestone_badge = highest_milestone(len(readings), [10, 50, 100, 500, 1000, 5000, 10000])
if highest_milestone_badge:
badges.append(highest_milestone_badge)
# Streaks and calendar month badges
if sorted_readings:
streak_count = 1
daily_streak = True
monthly_tracker = defaultdict(int)
# Start with the first reading
previous_date = sorted_readings[0].timestamp.date()
for reading in sorted_readings[1:]:
current_date = reading.timestamp.date()
# Check for consecutive daily streaks
if (current_date - previous_date).days == 1:
streak_count += 1
elif (current_date - previous_date).days > 1:
daily_streak = False
# Track monthly activity
monthly_tracker[current_date.strftime('%Y-%m')] += 1
previous_date = current_date
# Add streak badges
if daily_streak and streak_count >= 1:
badges.append(f"Current Streak: {streak_count} Days")
if daily_streak and streak_count >= 7:
badges.append("Logged Every Day for a Week")
if daily_streak and streak_count >= 30 and previous_date == now:
badges.append("Monthly Streak")
# Add calendar month streak badges
for month, count in monthly_tracker.items():
if count >= 30:
badges.append(f"Full Month of Logging: {month}")
# Time-specific badges (morning/night logging)
def is_morning(reading_time):
return 5 <= reading_time.hour < 12
def is_night(reading_time):
return 18 <= reading_time.hour <= 23
if all(is_morning(r.timestamp) for r in sorted_readings[-7:]):
badges.append("Morning Riser: Logged Readings Every Morning for a Week")
if all(is_night(r.timestamp) for r in sorted_readings[-7:]):
badges.append("Night Owl: Logged Readings Every Night for a Week")
return badges
def generate_monthly_calendar(readings, selected_date, local_timezone):
# Convert selected date to user's timezone and extract the start/end dates
today = datetime.now(local_timezone).date()
date = selected_date.astimezone(local_timezone).date()
first_day_of_month = date.replace(day=1)
days_to_subtract = (first_day_of_month.weekday() + 1) % 7
start_date = first_day_of_month - timedelta(days=days_to_subtract)
end_date = start_date + timedelta(days=6 * 7 - 1)
# Group readings by day
readings_by_day = {}
for reading in readings:
local_date = reading.timestamp.astimezone(local_timezone).date()
readings_by_day.setdefault(local_date, []).append(reading)
# Build calendar days
calendar = []
current_date = start_date
while current_date <= end_date:
calendar.append({
'day': current_date.day,
'is_today': current_date == today,
'is_in_current_month': current_date.month == date.month,
'readings': readings_by_day.get(current_date, []),
})
current_date += timedelta(days=1)
return calendar
# Get the first and last reading timestamps # Get the first and last reading timestamps
first_reading_timestamp, last_reading_timestamp = get_reading_date_range(current_user.id) first_reading_timestamp, last_reading_timestamp = get_reading_date_range(current_user.id)
@@ -221,3 +95,129 @@ def dashboard():
date=date, date=date,
timedelta=timedelta timedelta=timedelta
) )
# Helper function to get first and last reading timestamps
def get_reading_date_range(user_id):
result = (
db.session.query(
func.min(Reading.timestamp).label('first'),
func.max(Reading.timestamp).label('last')
)
.filter(Reading.user_id == user_id)
.first()
)
return result.first, result.last
# Helper function to calculate weekly summary averages
def calculate_weekly_summary(readings):
one_week_ago = datetime.now() - timedelta(days=7)
weekly_readings = [r for r in readings if r.timestamp >= one_week_ago]
if weekly_readings:
systolic_avg = round(sum(r.systolic for r in weekly_readings) / len(weekly_readings), 1)
diastolic_avg = round(sum(r.diastolic for r in weekly_readings) / len(weekly_readings), 1)
heart_rate_avg = round(sum(r.heart_rate for r in weekly_readings) / len(weekly_readings), 1)
else:
systolic_avg = diastolic_avg = heart_rate_avg = 0
return systolic_avg, diastolic_avg, heart_rate_avg
def generate_monthly_calendar(readings, selected_date, local_timezone):
# Convert selected date to user's timezone and extract the start/end dates
today = datetime.now(local_timezone).date()
date = selected_date.astimezone(local_timezone).date()
first_day_of_month = date.replace(day=1)
days_to_subtract = (first_day_of_month.weekday() + 1) % 7
start_date = first_day_of_month - timedelta(days=days_to_subtract)
end_date = start_date + timedelta(days=6 * 7 - 1)
# Group readings by day
readings_by_day = {}
for reading in readings:
local_date = reading.timestamp.astimezone(local_timezone).date()
readings_by_day.setdefault(local_date, []).append(reading)
# Build calendar days
calendar = []
current_date = start_date
while current_date <= end_date:
calendar.append({
'day': current_date.day,
'is_today': current_date == today,
'is_in_current_month': current_date.month == date.month,
'readings': readings_by_day.get(current_date, []),
})
current_date += timedelta(days=1)
return calendar
# Helper function to calculate progress badges
def calculate_progress_badges(readings):
"""Calculate badges based on user reading activity."""
badges = []
now = datetime.utcnow().date()
# Prepare sorted readings by timestamp
sorted_readings = sorted(readings, key=lambda r: r.timestamp)
# Incremental milestone badge
def highest_milestone(total_readings, milestones):
"""Determine the highest milestone achieved."""
for milestone in reversed(milestones):
if total_readings >= milestone:
return f"{milestone} Readings Logged"
return None
highest_milestone_badge = highest_milestone(len(readings), [10, 50, 100, 500, 1000, 5000, 10000])
if highest_milestone_badge:
badges.append(highest_milestone_badge)
# Streaks and calendar month badges
if sorted_readings:
streak_count = 1
daily_streak = True
monthly_tracker = defaultdict(int)
# Start with the first reading
previous_date = sorted_readings[0].timestamp.date()
for reading in sorted_readings[1:]:
current_date = reading.timestamp.date()
# Check for consecutive daily streaks
if (current_date - previous_date).days == 1:
streak_count += 1
elif (current_date - previous_date).days > 1:
daily_streak = False
# Track monthly activity
monthly_tracker[current_date.strftime('%Y-%m')] += 1
previous_date = current_date
# Add streak badges
if daily_streak and streak_count >= 1:
badges.append(f"Current Streak: {streak_count} Days")
if daily_streak and streak_count >= 7:
badges.append("Logged Every Day for a Week")
if daily_streak and streak_count >= 30 and previous_date == now:
badges.append("Monthly Streak")
# Add calendar month streak badges
for month, count in monthly_tracker.items():
if count >= 30:
badges.append(f"Full Month of Logging: {month}")
# Time-specific badges (morning/night logging)
def is_morning(reading_time):
return 5 <= reading_time.hour < 12
def is_night(reading_time):
return 18 <= reading_time.hour <= 23
if all(is_morning(r.timestamp) for r in sorted_readings[-7:]):
badges.append("Morning Riser: Logged Readings Every Morning for a Week")
if all(is_night(r.timestamp) for r in sorted_readings[-7:]):
badges.append("Night Owl: Logged Readings Every Night for a Week")
return badges

View File

@@ -1,12 +1,10 @@
from collections import defaultdict
from flask import Blueprint, render_template, redirect, request, url_for, flash from flask import Blueprint, render_template, redirect, request, url_for, flash
import humanize
from pytz import timezone, utc from pytz import timezone, utc
from sqlalchemy import func
from app.models import Reading, db from app.models import Reading, db
from app.forms import DeleteForm, ReadingForm from app.forms import ReadingForm
from flask_login import login_required, current_user from flask_login import login_required, current_user
from datetime import date, datetime, timedelta from datetime import datetime
reading = Blueprint('reading', __name__) reading = Blueprint('reading', __name__)
@reading.route('/add', methods=['GET', 'POST']) @reading.route('/add', methods=['GET', 'POST'])