diff --git a/app.py b/app.py index 31469dc..fb21aee 100644 --- a/app.py +++ b/app.py @@ -424,14 +424,45 @@ def get_most_recent_topset_for_exercise(person_id, workout_id): return render_template('partials/new_set_form.html', person_id=person_id, workout_id=workout_id, exercises=exercises, has_value=True, exercise_id=exercise_id, repetitions=repetitions, weight=weight) -# # TODO: Remove me, just for testing -# @ app.route("/sparkline", methods=['GET']) -# def get_sparkline(): -# width = request.args.get('width', 400, type=int) -# height = request.args.get('height', 200, type=int) -# number_of_points = request.args.get('number_of_points', 50, type=int) -# points = [random.randint(1, 100) for _ in range(number_of_points)] -# return render_template('partials/sparkline.html', width=width, height=height, points=points) +def calculate_relative_positions(start_dates): + min_date = min(start_dates) + max_date = max(start_dates) + total_span = (max_date - min_date).days if max_date != min_date else 1 + return [(date - min_date).days / total_span for date in start_dates] + +@ app.route("/person//exercise//sparkline", methods=['GET']) +def get_exercise_progress_for_user(person_id, exercise_id): + width = request.args.get('width', 300, type=int) + height = request.args.get('height', 100, type=int) + (estimated_1rm, start_dates) = db.get_exercise_progress_for_user(person_id, exercise_id) + + # Calculate vb_width + min_date = min(start_dates) + max_date = max(start_dates) + date_range = (max_date - min_date).days # e.g., 30 days + vb_width = date_range # This can be scaled if needed + + # Calculate vb_height + min_value = min(estimated_1rm) + max_value = max(estimated_1rm) + value_range = max_value - min_value # e.g., 100 + vb_height = value_range # This can be scaled if needed + + # Scaling factors (optional, for design) + width_scaling_factor = 200 / vb_width # e.g., if you want 200px width + height_scaling_factor = 75 / vb_height # e.g., if you want 100px height + + # Apply scaling + vb_width *= width_scaling_factor + vb_height *= height_scaling_factor + + # Scale estimated_1rm between 0 and vb_height + estimated_1rm = [((value - min_value) / value_range) * vb_height for value in estimated_1rm] + + relative_positions = calculate_relative_positions(start_dates) + data_points = list(zip(estimated_1rm, relative_positions)) + + return render_template('partials/sparkline.html', title="GHR", vb_width=vb_width, vb_height=vb_height, data_points=data_points) @app.teardown_appcontext diff --git a/db.py b/db.py index 80fd4b1..13f0cee 100644 --- a/db.py +++ b/db.py @@ -462,3 +462,31 @@ class DataBase(): exercises = self.execute( 'SELECT exercise_id, name FROM exercise') return exercises + + def get_exercise_progress_for_user(self, person_id, exercise_id): + topsets = self.execute(""" + SELECT + T.topset_id, + E.name AS exercise_name, + W.person_id, + T.workout_id, + T.repetitions, + T.weight, + ROUND((100 * T.weight::NUMERIC::INTEGER) / (101.3 - 2.67123 * T.repetitions), 0)::NUMERIC::INTEGER AS estimated_1rm, + W.start_date + FROM + topset T + JOIN + exercise E ON T.exercise_id = E.exercise_id + JOIN + workout W ON T.workout_id = W.workout_id + WHERE + W.person_id = %s AND + E.exercise_id = %s + ORDER BY + W.start_date;""", [person_id, exercise_id]) + # Get a list of all estimated_1rm values + estimated_1rm = [t['estimated_1rm'] for t in topsets] + # Get a list of all start_dates + start_dates = [t['start_date'] for t in topsets] + return (estimated_1rm, start_dates) \ No newline at end of file diff --git a/templates/partials/new_set_form.html b/templates/partials/new_set_form.html index 00d1209..76c54db 100644 --- a/templates/partials/new_set_form.html +++ b/templates/partials/new_set_form.html @@ -67,4 +67,11 @@ class="py-2 px-3 mb-3 text-sm font-medium text-center text-gray-900 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 hover:scale-[1.02] transition-transform">Delete workout - \ No newline at end of file + + +{% if has_value==True %} + +{% endif %} \ No newline at end of file diff --git a/templates/partials/sparkline.html b/templates/partials/sparkline.html new file mode 100644 index 0000000..b7be7a2 --- /dev/null +++ b/templates/partials/sparkline.html @@ -0,0 +1,42 @@ +{% set fill = "#dcfce7" %} +{% set stroke = "#bbf7d0" %} +{% set stroke_width = 4 %} +{% set margin = 0 %} {# space allocated for axis labels and ticks #} + +{% macro path(data_points, vb_height) %} + {% for value, position in data_points %} + {% set x = position * vb_width %} + {% set y = vb_height - value %} + {% if loop.first %}M{{ x }} {{ y }}{% else %} L{{ x }} {{ y }}{% endif %} + {% endfor %} +{% endmacro %} + +{% macro circles(data_points, vb_height) %} + {% for value, position in data_points %} + {% set x = position * vb_width %} + {% set y = vb_height - value %} + + + {% endfor %} +{% endmacro %} + +{% macro closed_path(points, vb_width, vb_height) %} + {{ path(points, vb_width, vb_height) }} L {{ vb_width + 2*margin }} {{ vb_height + 2*margin }} L {{ 2*margin }} {{ vb_height + 2*margin }} Z +{% endmacro %} + + + + + + + {{ circles(data_points, vb_height) }} + + + \ No newline at end of file diff --git a/templates/partials/workout_modal.html b/templates/partials/workout_modal.html index d7bba66..2d7b800 100644 --- a/templates/partials/workout_modal.html +++ b/templates/partials/workout_modal.html @@ -100,6 +100,9 @@ exercises=exercises, has_value=False) }} +
+ +