Add exercise progress graphs to new person overview page
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
from utils import calculate_estimated_1rm, get_exercise_graph_model
|
||||||
|
|
||||||
|
|
||||||
class PersonOverview:
|
class PersonOverview:
|
||||||
def __init__(self, db_connection_method):
|
def __init__(self, db_connection_method):
|
||||||
self.execute = db_connection_method
|
self.execute = db_connection_method
|
||||||
@@ -111,7 +114,7 @@ class PersonOverview:
|
|||||||
result = self.execute(sql_query, params)
|
result = self.execute(sql_query, params)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return {"person_id": person_id, "person_name": None, "workouts": [], "selected_exercises": []}
|
return {"person_id": person_id, "person_name": None, "workouts": [], "selected_exercises": [], "exercise_progress_graphs": []}
|
||||||
|
|
||||||
# Extract person info from the first row
|
# Extract person info from the first row
|
||||||
person_info = {"person_id": result[0]["person_id"], "person_name": result[0]["person_name"]}
|
person_info = {"person_id": result[0]["person_id"], "person_name": result[0]["person_name"]}
|
||||||
@@ -131,6 +134,9 @@ class PersonOverview:
|
|||||||
workouts = []
|
workouts = []
|
||||||
workout_map = {} # Map to track workouts
|
workout_map = {} # Map to track workouts
|
||||||
|
|
||||||
|
# Initialize the exercise sets dictionary
|
||||||
|
exercise_sets = {exercise["id"]: {"exercise_id": exercise["id"], "name": exercise["name"], "sets": []} for exercise in exercises}
|
||||||
|
|
||||||
for row in result:
|
for row in result:
|
||||||
workout_id = row["workout_id"]
|
workout_id = row["workout_id"]
|
||||||
|
|
||||||
@@ -145,16 +151,77 @@ class PersonOverview:
|
|||||||
|
|
||||||
# Add topset to the corresponding exercise
|
# Add topset to the corresponding exercise
|
||||||
if row["exercise_id"] and row["topset_id"]:
|
if row["exercise_id"] and row["topset_id"]:
|
||||||
|
# Add to workout exercises
|
||||||
workout_map[workout_id]["exercises"][row["exercise_id"]].append({
|
workout_map[workout_id]["exercises"][row["exercise_id"]].append({
|
||||||
"repetitions": row["repetitions"],
|
"repetitions": row["repetitions"],
|
||||||
"weight": row["weight"]
|
"weight": row["weight"]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Add to the exercise sets dictionary with workout start date
|
||||||
|
exercise_sets[row["exercise_id"]]["sets"].append({
|
||||||
|
"repetitions": row["repetitions"],
|
||||||
|
"weight": row["weight"],
|
||||||
|
"estimated_1rm": calculate_estimated_1rm(row["weight"], row["repetitions"]),
|
||||||
|
"workout_start_date": row["start_date"],
|
||||||
|
"exercise_name": row["exercise_name"]
|
||||||
|
})
|
||||||
|
|
||||||
# Transform into a list of rows
|
# Transform into a list of rows
|
||||||
for workout_id, workout in workout_map.items():
|
for workout_id, workout in workout_map.items():
|
||||||
workouts.append(workout)
|
workouts.append(workout)
|
||||||
|
|
||||||
return {**person_info, "workouts": workouts, "selected_exercises": exercises}
|
exercise_progress_graphs = self.generate_exercise_progress_graphs(person_info["person_id"], exercise_sets)
|
||||||
|
|
||||||
|
return {
|
||||||
|
**person_info,
|
||||||
|
"workouts": workouts,
|
||||||
|
"selected_exercises": exercises,
|
||||||
|
"exercise_progress_graphs": exercise_progress_graphs
|
||||||
|
}
|
||||||
|
|
||||||
|
def generate_exercise_progress_graphs(self, person_id, exercise_sets):
|
||||||
|
exercise_progress_graphs = []
|
||||||
|
|
||||||
|
for exercise_id, exercise_data in exercise_sets.items():
|
||||||
|
# Sort the sets by start date in descending order
|
||||||
|
sorted_exercise_sets = sorted(exercise_data["sets"], key=lambda t: t["workout_start_date"], reverse=True)
|
||||||
|
|
||||||
|
# Extract the required data
|
||||||
|
estimated_1rm = [t["estimated_1rm"] for t in sorted_exercise_sets]
|
||||||
|
repetitions = [t["repetitions"] for t in sorted_exercise_sets]
|
||||||
|
weight = [t["weight"] for t in sorted_exercise_sets]
|
||||||
|
start_dates = [t["workout_start_date"] for t in sorted_exercise_sets]
|
||||||
|
messages = [
|
||||||
|
f'{t["repetitions"]} x {t["weight"]}kg ({t["estimated_1rm"]}kg E1RM) on {t["workout_start_date"].strftime("%d %b %y")}'
|
||||||
|
for t in sorted_exercise_sets
|
||||||
|
]
|
||||||
|
epoch = "All"
|
||||||
|
exercise_name = sorted_exercise_sets[0]["exercise_name"]
|
||||||
|
|
||||||
|
# Check for valid data before generating the graph
|
||||||
|
if exercise_name and estimated_1rm and repetitions and weight and start_dates and messages:
|
||||||
|
exercise_progress = get_exercise_graph_model(
|
||||||
|
title=exercise_name,
|
||||||
|
estimated_1rm=estimated_1rm,
|
||||||
|
repetitions=repetitions,
|
||||||
|
weight=weight,
|
||||||
|
start_dates=start_dates,
|
||||||
|
messages=messages,
|
||||||
|
epoch=epoch,
|
||||||
|
person_id=person_id,
|
||||||
|
exercise_id=exercise_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Append the generated graph model to the list
|
||||||
|
exercise_progress_graphs.append({
|
||||||
|
"exercise_id": exercise_id,
|
||||||
|
"exercise_name": exercise_name,
|
||||||
|
"progress_graph": exercise_progress
|
||||||
|
})
|
||||||
|
|
||||||
|
return exercise_progress_graphs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,12 @@
|
|||||||
|
|
||||||
{{ render_partial('partials/tags.html',person_id=person_id, tags=tags) }}
|
{{ render_partial('partials/tags.html',person_id=person_id, tags=tags) }}
|
||||||
|
|
||||||
|
<div class="mt-4 mb-4 w-full grid grid-cols-1 2xl:grid-cols-2 gap-4">
|
||||||
|
{% for graph in exercise_progress_graphs %}
|
||||||
|
{{ render_partial('partials/sparkline.html', **graph.progress_graph) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col mt-3 w-screen sm:w-full overflow-auto">
|
<div class="flex flex-col mt-3 w-screen sm:w-full overflow-auto">
|
||||||
<div class="overflow-x-auto rounded-lg">
|
<div class="overflow-x-auto rounded-lg">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
|
|||||||
7
utils.py
7
utils.py
@@ -469,3 +469,10 @@ def generate_plot(df, title):
|
|||||||
# Convert Plotly figure to HTML div
|
# Convert Plotly figure to HTML div
|
||||||
plot_div = pio.to_html(fig, full_html=False)
|
plot_div = pio.to_html(fig, full_html=False)
|
||||||
return plot_div
|
return plot_div
|
||||||
|
|
||||||
|
def calculate_estimated_1rm(weight, repetitions):
|
||||||
|
# Ensure the inputs are numeric
|
||||||
|
if repetitions == 0: # Avoid division by zero
|
||||||
|
return 0
|
||||||
|
estimated_1rm = round((100 * int(weight)) / (101.3 - 2.67123 * repetitions), 0)
|
||||||
|
return int(estimated_1rm)
|
||||||
Reference in New Issue
Block a user