feat: assign tags to exercises and show muscle distribution of workout
This commit is contained in:
@@ -5,25 +5,116 @@ class Exercises:
|
||||
def get(self, query):
|
||||
# Add wildcards to the query
|
||||
search_query = f"%{query}%"
|
||||
# We need to fetch exercises with their attributes.
|
||||
# Since an exercise can have many attributes, we'll fetch basic info first or use a join.
|
||||
# But wait, the settings page just lists names. We can fetch attributes separately for each row or do a group_concat-like join.
|
||||
# However, for the settings list, we want to show the tags.
|
||||
|
||||
# Let's use a simpler approach: fetch exercises and then for each one (or via a single join) get attributes.
|
||||
exercises = self.execute("SELECT exercise_id, name FROM exercise WHERE LOWER(name) LIKE LOWER(%s) ORDER BY name ASC;", [search_query])
|
||||
|
||||
for ex in exercises:
|
||||
ex['attributes'] = self.get_exercise_attributes(ex['exercise_id'])
|
||||
|
||||
return exercises
|
||||
|
||||
def get_exercise(self, exercise_id):
|
||||
exercise = self.execute("SELECT exercise_id, name FROM exercise WHERE exercise_id=%s;", [exercise_id], one=True)
|
||||
if exercise:
|
||||
exercise['attributes'] = self.get_exercise_attributes(exercise_id)
|
||||
return exercise
|
||||
|
||||
def update_exercise_name(self, exercise_id, updated_name):
|
||||
self.execute("UPDATE exercise SET name = %s WHERE exercise_id = %s;", [updated_name, exercise_id], commit=True)
|
||||
updated_exercise = self.get_exercise(exercise_id)
|
||||
return updated_exercise
|
||||
def get_exercise_attributes(self, exercise_id):
|
||||
query = """
|
||||
SELECT cat.name as category_name, attr.attribute_id, attr.name as attribute_name
|
||||
FROM exercise_to_attribute eta
|
||||
JOIN exercise_attribute attr ON eta.attribute_id = attr.attribute_id
|
||||
JOIN exercise_attribute_category cat ON attr.category_id = cat.category_id
|
||||
WHERE eta.exercise_id = %s
|
||||
ORDER BY cat.name, attr.name
|
||||
"""
|
||||
return self.execute(query, [exercise_id])
|
||||
|
||||
def get_all_attribute_categories(self):
|
||||
return self.execute("SELECT category_id, name FROM exercise_attribute_category ORDER BY name")
|
||||
|
||||
def get_attributes_by_category(self):
|
||||
# Returns a dict: { category_name: [ {id, name}, ... ] }
|
||||
categories = self.get_all_attribute_categories()
|
||||
all_attrs = self.execute("SELECT attribute_id, name, category_id FROM exercise_attribute ORDER BY name")
|
||||
|
||||
result = {}
|
||||
for cat in categories:
|
||||
result[cat['name']] = [a for a in all_attrs if a['category_id'] == cat['category_id']]
|
||||
return result
|
||||
|
||||
def update_exercise(self, exercise_id, name, attribute_ids=None):
|
||||
self.execute("UPDATE exercise SET name = %s WHERE exercise_id = %s;", [name, exercise_id], commit=True)
|
||||
|
||||
# Update attributes: simple delete and re-insert for now
|
||||
self.execute("DELETE FROM exercise_to_attribute WHERE exercise_id = %s", [exercise_id], commit=True)
|
||||
|
||||
if attribute_ids:
|
||||
for attr_id in attribute_ids:
|
||||
if attr_id:
|
||||
self.execute("INSERT INTO exercise_to_attribute (exercise_id, attribute_id) VALUES (%s, %s)",
|
||||
[exercise_id, attr_id], commit=True)
|
||||
|
||||
return self.get_exercise(exercise_id)
|
||||
|
||||
def delete_exercise(self, exercise_id):
|
||||
self.execute('DELETE FROM exercise WHERE exercise_id=%s', [
|
||||
exercise_id], commit=True)
|
||||
|
||||
def add_exercise(self, name):
|
||||
def add_exercise(self, name, attribute_ids=None):
|
||||
result = self.execute('INSERT INTO exercise (name) VALUES (%s) RETURNING exercise_id', [name], commit=True, one=True)
|
||||
exercise_id = result['exercise_id']
|
||||
new_exercise = self.get_exercise(exercise_id)
|
||||
return new_exercise
|
||||
|
||||
if attribute_ids:
|
||||
for attr_id in attribute_ids:
|
||||
if attr_id:
|
||||
self.execute("INSERT INTO exercise_to_attribute (exercise_id, attribute_id) VALUES (%s, %s)",
|
||||
[exercise_id, attr_id], commit=True)
|
||||
|
||||
return self.get_exercise(exercise_id)
|
||||
|
||||
def get_workout_muscle_group_distribution(self, workout_id):
|
||||
query = """
|
||||
SELECT attr.name as muscle_group, COUNT(*) as count
|
||||
FROM topset t
|
||||
JOIN exercise_to_attribute eta ON t.exercise_id = eta.exercise_id
|
||||
JOIN exercise_attribute attr ON eta.attribute_id = attr.attribute_id
|
||||
JOIN exercise_attribute_category cat ON attr.category_id = cat.category_id
|
||||
WHERE t.workout_id = %s AND cat.name = 'Muscle Group'
|
||||
GROUP BY attr.name
|
||||
ORDER BY count DESC
|
||||
"""
|
||||
distribution = self.execute(query, [workout_id])
|
||||
|
||||
# Calculate percentages and SVG parameters
|
||||
total_counts = sum(item['count'] for item in distribution)
|
||||
accumulated_percentage = 0
|
||||
|
||||
# Color palette for segments
|
||||
colors = [
|
||||
"#3b82f6", # blue-500
|
||||
"#06b6d4", # cyan-500
|
||||
"#8b5cf6", # violet-500
|
||||
"#ec4899", # pink-500
|
||||
"#f59e0b", # amber-500
|
||||
"#10b981", # emerald-500
|
||||
"#6366f1", # indigo-500
|
||||
"#f43f5e", # rose-500
|
||||
]
|
||||
|
||||
if total_counts > 0:
|
||||
for i, item in enumerate(distribution):
|
||||
percentage = (item['count'] / total_counts) * 100
|
||||
item['percentage'] = round(percentage)
|
||||
item['dasharray'] = f"{percentage} 100"
|
||||
item['dashoffset'] = -accumulated_percentage
|
||||
item['color'] = colors[i % len(colors)]
|
||||
accumulated_percentage += percentage
|
||||
|
||||
return distribution
|
||||
|
||||
|
||||
Reference in New Issue
Block a user