Add duration in minutes option to user overview graph, this section needs a refactor - too many layers of abstraction thanks to chatgpt
This commit is contained in:
46
app.py
46
app.py
@@ -227,12 +227,14 @@ def graph_user_workouts(user_id):
|
|||||||
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
||||||
"""
|
"""
|
||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
workouts = user.workouts
|
# workouts = user.workouts
|
||||||
|
|
||||||
earliest_workout_date = min([workout.created_at.date()
|
workouts = get_workouts_for_user_view_data(user)
|
||||||
|
|
||||||
|
earliest_workout_date = min([workout['start_time_date']
|
||||||
for workout in workouts])
|
for workout in workouts])
|
||||||
most_recent_workout_date = max(
|
most_recent_workout_date = max(
|
||||||
[workout.created_at.date() for workout in workouts])
|
[workout['start_time_date'] for workout in workouts])
|
||||||
|
|
||||||
start_date = request.args.get(
|
start_date = request.args.get(
|
||||||
'start_date', default=earliest_workout_date, type=toDate)
|
'start_date', default=earliest_workout_date, type=toDate)
|
||||||
@@ -283,17 +285,16 @@ def average_workout_attributes_per_period(workouts, start_date, end_date, period
|
|||||||
for start_period in daterange(start_date, end_date, delta):
|
for start_period in daterange(start_date, end_date, delta):
|
||||||
end_period = start_period + delta
|
end_period = start_period + delta
|
||||||
filtered_workouts = [
|
filtered_workouts = [
|
||||||
w for w in workouts if start_period <= w.created_at.date() < end_period]
|
w for w in workouts if start_period <= w['start_time_date'] < end_period]
|
||||||
|
|
||||||
for attribute in attributes:
|
for attribute in attributes:
|
||||||
if hasattr(Workout, attribute):
|
valid_values = [w.get(attribute) for w in filtered_workouts if w.get(
|
||||||
valid_values = [getattr(w, attribute) for w in filtered_workouts if getattr(
|
attribute) is not None]
|
||||||
w, attribute) is not None]
|
if valid_values:
|
||||||
if valid_values:
|
average = sum(valid_values) / len(valid_values)
|
||||||
average = sum(valid_values) / len(valid_values)
|
results[start_period][attribute] = average
|
||||||
results[start_period][attribute] = average
|
else:
|
||||||
else:
|
results[start_period][attribute] = 0 # None
|
||||||
results[start_period][attribute] = 0 # None
|
|
||||||
|
|
||||||
results[start_period]['workout_count'] = len(
|
results[start_period]['workout_count'] = len(
|
||||||
filtered_workouts)
|
filtered_workouts)
|
||||||
@@ -331,7 +332,8 @@ def create_user_graph(x_values, y_data, filename, x_label='Time', title=None):
|
|||||||
|
|
||||||
# Save the graph to a bytes buffer
|
# Save the graph to a bytes buffer
|
||||||
buffer = io.BytesIO()
|
buffer = io.BytesIO()
|
||||||
plt.savefig(buffer, format='png', transparent=True, bbox_inches='tight')
|
plt.savefig(buffer, format='png',
|
||||||
|
transparent=True, bbox_inches='tight')
|
||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
|
|
||||||
# Create a response object with the graph image
|
# Create a response object with the graph image
|
||||||
@@ -372,7 +374,7 @@ def plot_averaged_attributes(workouts_list, user, start_date, end_date, period,
|
|||||||
return create_user_graph(x_values, y_data, filename=f"average_attributes_over_{period}", title=title)
|
return create_user_graph(x_values, y_data, filename=f"average_attributes_over_{period}", title=title)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/<int:user_id>/workout/<int:workout_id>/<string:graph_type>', methods=['GET'])
|
@ app.route('/user/<int:user_id>/workout/<int:workout_id>/<string:graph_type>', methods=['GET'])
|
||||||
def workout(user_id, workout_id, graph_type):
|
def workout(user_id, workout_id, graph_type):
|
||||||
workout = Workout.query.filter_by(user_id=user_id, id=workout_id) \
|
workout = Workout.query.filter_by(user_id=user_id, id=workout_id) \
|
||||||
.join(Workout.cadence_readings) \
|
.join(Workout.cadence_readings) \
|
||||||
@@ -403,15 +405,15 @@ def workout(user_id, workout_id, graph_type):
|
|||||||
return jsonify({'message': f'Unable to generate {graph_type} for workout {workout_id}.'}), 409
|
return jsonify({'message': f'Unable to generate {graph_type} for workout {workout_id}.'}), 409
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/<int:user_id>/workout/<int:workout_id>/view', methods=['GET'])
|
@ app.route('/user/<int:user_id>/workout/<int:workout_id>/view', methods=['GET'])
|
||||||
def view_workout(user_id, workout_id):
|
def view_workout(user_id, workout_id):
|
||||||
workout = Workout.query.filter_by(user_id=user_id, id=workout_id).first()
|
workout = Workout.query.filter_by(user_id=user_id, id=workout_id).first()
|
||||||
graph_types = request.args.getlist('graph_types')
|
graph_types = request.args.getlist('graph_types')
|
||||||
return render_template('workout_view.html', workout=workout, graph_types=graph_types)
|
return render_template('workout_view.html', workout=workout, graph_types=graph_types)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/<int:user_id>/workout/<int:workout_id>/delete', methods=['DELETE'])
|
@ app.route('/user/<int:user_id>/workout/<int:workout_id>/delete', methods=['DELETE'])
|
||||||
@basic_auth.required
|
@ basic_auth.required
|
||||||
def delete_workout(user_id, workout_id):
|
def delete_workout(user_id, workout_id):
|
||||||
# Delete the workout and its associated cadence readings
|
# Delete the workout and its associated cadence readings
|
||||||
CadenceReading.query.filter_by(workout_id=workout_id).delete()
|
CadenceReading.query.filter_by(workout_id=workout_id).delete()
|
||||||
@@ -421,7 +423,7 @@ def delete_workout(user_id, workout_id):
|
|||||||
return render_users_and_workouts()
|
return render_users_and_workouts()
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/<int:user_id>/bike', methods=['GET'])
|
@ app.route('/user/<int:user_id>/bike', methods=['GET'])
|
||||||
def update_users_bike(user_id):
|
def update_users_bike(user_id):
|
||||||
bike_id = request.args.get('bike_id')
|
bike_id = request.args.get('bike_id')
|
||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
@@ -438,7 +440,8 @@ def update_users_bike(user_id):
|
|||||||
def calendar_view(user_id):
|
def calendar_view(user_id):
|
||||||
user = User.query.get(user_id)
|
user = User.query.get(user_id)
|
||||||
workouts = get_workouts_for_user_view_data(user)
|
workouts = get_workouts_for_user_view_data(user)
|
||||||
date = request.args.get('date', default=datetime.now().date(), type=toDate)
|
date = request.args.get(
|
||||||
|
'date', default=datetime.now().date(), type=toDate)
|
||||||
calendar_month = generate_calendar_monthly_view(workouts, date)
|
calendar_month = generate_calendar_monthly_view(workouts, date)
|
||||||
return render_template('partials/calendar.html', calendar_month=calendar_month, user_id=user_id)
|
return render_template('partials/calendar.html', calendar_month=calendar_month, user_id=user_id)
|
||||||
|
|
||||||
@@ -480,7 +483,7 @@ def generate_user_data(user, workouts=[]):
|
|||||||
'workouts': workouts,
|
'workouts': workouts,
|
||||||
'daily_duration_sparkline': generate_daily_duration_sparkline(workouts),
|
'daily_duration_sparkline': generate_daily_duration_sparkline(workouts),
|
||||||
'calendar_month': generate_calendar_monthly_view(workouts, datetime.now().date()),
|
'calendar_month': generate_calendar_monthly_view(workouts, datetime.now().date()),
|
||||||
'attributes': [('workout_count', 'Workout count'), ('duration', 'Duration'), ('average_rpm', 'Average RPM'), ('max_rpm', 'Max RPM'), ('average_bpm', 'Average BPM'), ('max_bpm', 'Max BPM'), ('distance', 'Distance'), ('calories', 'Calories')],
|
'attributes': [('workout_count', 'Workout count'), ('duration', 'Duration (sec)'), ('duration_minutes', 'Duration (min)'), ('average_rpm', 'Average RPM'), ('max_rpm', 'Max RPM'), ('average_bpm', 'Average BPM'), ('max_bpm', 'Max BPM'), ('distance', 'Distance'), ('calories', 'Calories')],
|
||||||
'periods': [('day', 'Day'), ('week', 'Week'), ('month', 'Month')],
|
'periods': [('day', 'Day'), ('week', 'Week'), ('month', 'Month')],
|
||||||
'first_workout_date': workouts[-1]['start_time_date'] if workouts else None,
|
'first_workout_date': workouts[-1]['start_time_date'] if workouts else None,
|
||||||
'last_workout_date': workouts[0]['start_time_date'] if workouts else None,
|
'last_workout_date': workouts[0]['start_time_date'] if workouts else None,
|
||||||
@@ -632,7 +635,8 @@ def generate_calendar_monthly_view(workouts, selected_date):
|
|||||||
start_date, end_date = get_month_bounds(selected_date)
|
start_date, end_date = get_month_bounds(selected_date)
|
||||||
|
|
||||||
# Build a lookup dictionary for faster access
|
# Build a lookup dictionary for faster access
|
||||||
workout_lookup = {w['start_time_date']: w for w in workouts if start_date <= w['start_time_date'] <= end_date}
|
workout_lookup = {w['start_time_date']
|
||||||
|
: w for w in workouts if start_date <= w['start_time_date'] <= end_date}
|
||||||
|
|
||||||
current_date = datetime.now().date()
|
current_date = datetime.now().date()
|
||||||
days_of_month = [
|
days_of_month = [
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
<div id="user-workouts-overview-graphs-{{ user.id }}">
|
<div id="user-workouts-overview-graphs-{{ user.id }}">
|
||||||
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='week', attributes=['workout_count']) }}"
|
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='week', attributes=['workout_count']) }}"
|
||||||
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
||||||
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='month', attributes=['duration']) }}"
|
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='month', attributes=['duration_minutes']) }}"
|
||||||
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
||||||
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='week', attributes=['average_rpm','average_bpm']) }}"
|
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period='week', attributes=['average_rpm','average_bpm']) }}"
|
||||||
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
||||||
|
|||||||
Reference in New Issue
Block a user