Refactor dashboard
This commit is contained in:
270
features/dashboard.py
Normal file
270
features/dashboard.py
Normal file
@@ -0,0 +1,270 @@
|
||||
from utils import calculate_estimated_1rm, get_exercise_graph_model
|
||||
|
||||
|
||||
class Dashboard:
|
||||
def __init__(self, db_connection_method):
|
||||
self.execute = db_connection_method
|
||||
|
||||
def get_people_ids(self):
|
||||
query = """
|
||||
SELECT person_id
|
||||
FROM Person
|
||||
ORDER BY person_id
|
||||
"""
|
||||
result = self.execute(query)
|
||||
# Extract and return the list of IDs
|
||||
return [row["person_id"] for row in result]
|
||||
|
||||
def get_earliest_and_latest_workout_dates(self, selected_people_ids):
|
||||
# Create placeholders for the person IDs
|
||||
placeholders = ", ".join(["%s"] * len(selected_people_ids))
|
||||
|
||||
sql_query = f"""
|
||||
SELECT
|
||||
MIN(w.start_date) AS earliest_date,
|
||||
MAX(w.start_date) AS latest_date
|
||||
FROM workout w
|
||||
INNER JOIN topset t ON w.workout_id = t.workout_id
|
||||
WHERE w.person_id IN ({placeholders});
|
||||
"""
|
||||
result = self.execute(sql_query, selected_people_ids)
|
||||
|
||||
if not result or not result[0]:
|
||||
return None, None
|
||||
|
||||
return result[0]['earliest_date'], result[0]['latest_date']
|
||||
|
||||
def list_of_performed_exercise_ids(self, selected_people_ids, min_date, max_date):
|
||||
# Create placeholders for the person IDs
|
||||
placeholders = ", ".join(["%s"] * len(selected_people_ids))
|
||||
|
||||
sql_query = f"""
|
||||
SELECT
|
||||
ARRAY_AGG(DISTINCT e.exercise_id) AS exercise_ids
|
||||
FROM workout w
|
||||
LEFT JOIN topset t ON w.workout_id = t.workout_id
|
||||
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
|
||||
WHERE w.start_date BETWEEN %s AND %s
|
||||
AND w.person_id IN ({placeholders})
|
||||
"""
|
||||
# Add min_date, max_date, and selected_people_ids to the parameters
|
||||
params = [min_date, max_date] + selected_people_ids
|
||||
|
||||
result = self.execute(sql_query, params)
|
||||
|
||||
if not result or not result[0]:
|
||||
return []
|
||||
|
||||
return result[0]['exercise_ids']
|
||||
|
||||
def get_exercises_with_selection(self, selected_people_ids, start_date, end_date, selected_exercise_ids):
|
||||
# Create placeholders for the person IDs
|
||||
placeholders = ", ".join(["%s"] * len(selected_people_ids))
|
||||
|
||||
# SQL query to fetch all exercises performed by the selected people in the given time range
|
||||
sql_query = f"""
|
||||
SELECT DISTINCT
|
||||
e.exercise_id,
|
||||
e.name AS exercise_name
|
||||
FROM
|
||||
workout w
|
||||
JOIN
|
||||
topset t ON w.workout_id = t.workout_id
|
||||
JOIN
|
||||
exercise e ON t.exercise_id = e.exercise_id
|
||||
WHERE
|
||||
w.person_id IN ({placeholders})
|
||||
AND w.start_date BETWEEN %s AND %s
|
||||
ORDER BY
|
||||
e.name ASC;
|
||||
"""
|
||||
|
||||
# Add parameters for the query
|
||||
params = selected_people_ids + [start_date, end_date]
|
||||
|
||||
# Execute the query with parameters
|
||||
result = self.execute(sql_query, params)
|
||||
|
||||
if not result:
|
||||
return [] # No exercises found in the given time range
|
||||
|
||||
# Add the "selected" property to each exercise
|
||||
exercises = []
|
||||
for row in result:
|
||||
exercises.append({
|
||||
"id": row["exercise_id"],
|
||||
"name": row["exercise_name"],
|
||||
"selected": row["exercise_id"] in selected_exercise_ids
|
||||
})
|
||||
|
||||
return exercises
|
||||
|
||||
def get_people_with_selection(self, selected_people_ids):
|
||||
# SQL query to fetch all people
|
||||
sql_query = """
|
||||
SELECT DISTINCT
|
||||
p.person_id AS id,
|
||||
p.name AS name
|
||||
FROM
|
||||
person p
|
||||
ORDER BY
|
||||
p.name ASC;
|
||||
"""
|
||||
|
||||
# Execute the query (no parameters required since we're fetching all people)
|
||||
result = self.execute(sql_query)
|
||||
|
||||
if not result:
|
||||
return [] # No people found
|
||||
|
||||
# Add the "selected" property to each person
|
||||
people = []
|
||||
for row in result:
|
||||
people.append({
|
||||
"id": row["id"],
|
||||
"name": row["name"],
|
||||
"selected": row["id"] in selected_people_ids
|
||||
})
|
||||
|
||||
return people
|
||||
|
||||
def generate_exercise_progress_graphs(self, person_id, exercise_id, exercise_name, exercise_sets):
|
||||
# Extract the required data
|
||||
estimated_1rm = [t["estimated_1rm"] for t in exercise_sets]
|
||||
repetitions = [t["reps"] for t in exercise_sets]
|
||||
weight = [t["weight"] for t in exercise_sets]
|
||||
start_dates = [t["workout_start_date"] for t in exercise_sets]
|
||||
messages = [
|
||||
f'{t["reps"]} x {t["weight"]}kg ({t["estimated_1rm"]}kg E1RM) on {t["workout_start_date"].strftime("%d %b %y")}'
|
||||
for t in exercise_sets
|
||||
]
|
||||
epoch = "All"
|
||||
|
||||
# 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,
|
||||
)
|
||||
|
||||
return exercise_progress
|
||||
|
||||
|
||||
def get(self, selected_people_ids, start_date, end_date, selected_exercise_ids):
|
||||
# Create placeholders for selected_people_ids and selected_exercise_ids
|
||||
people_placeholders = ", ".join(["%s"] * len(selected_people_ids))
|
||||
exercise_placeholders = ", ".join(["%s"] * len(selected_exercise_ids))
|
||||
|
||||
# SQL query to fetch data
|
||||
sql_query = f"""
|
||||
SELECT
|
||||
p.person_id,
|
||||
p.name AS person_name,
|
||||
e.exercise_id,
|
||||
e.name AS exercise_name,
|
||||
t.topset_id,
|
||||
t.repetitions,
|
||||
t.weight,
|
||||
w.start_date AS workout_date,
|
||||
w.workout_id
|
||||
FROM
|
||||
person p
|
||||
JOIN
|
||||
workout w ON p.person_id = w.person_id
|
||||
JOIN
|
||||
topset t ON w.workout_id = t.workout_id
|
||||
JOIN
|
||||
exercise e ON t.exercise_id = e.exercise_id
|
||||
WHERE
|
||||
p.person_id IN ({people_placeholders})
|
||||
AND w.start_date BETWEEN %s AND %s
|
||||
AND e.exercise_id IN ({exercise_placeholders})
|
||||
ORDER BY
|
||||
p.person_id ASC, e.exercise_id ASC, t.topset_id DESC;
|
||||
"""
|
||||
|
||||
# Add parameters for the query
|
||||
params = selected_people_ids + [start_date, end_date] + selected_exercise_ids
|
||||
|
||||
# Execute the query
|
||||
result = self.execute(sql_query, params)
|
||||
|
||||
# Handle empty result
|
||||
if not result:
|
||||
return {"people": []}
|
||||
|
||||
# Organize data into the desired structure
|
||||
people_map = {}
|
||||
|
||||
for row in result:
|
||||
# Person level
|
||||
person_id = row["person_id"]
|
||||
if person_id not in people_map:
|
||||
people_map[person_id] = {
|
||||
"id": person_id,
|
||||
"name": row["person_name"],
|
||||
"exercises": {}
|
||||
}
|
||||
|
||||
# Exercise level
|
||||
exercise_id = row["exercise_id"]
|
||||
person_exercises = people_map[person_id]["exercises"]
|
||||
if exercise_id not in person_exercises:
|
||||
person_exercises[exercise_id] = {
|
||||
"id": exercise_id,
|
||||
"name": row["exercise_name"],
|
||||
"sets": []
|
||||
}
|
||||
|
||||
# Set level
|
||||
person_exercises[exercise_id]["sets"].append({
|
||||
"id": row["topset_id"],
|
||||
"reps": row["repetitions"],
|
||||
"weight": row["weight"],
|
||||
"exercise_id": row["exercise_id"],
|
||||
"exercise_name": row["exercise_name"],
|
||||
"workout_id": row["workout_id"],
|
||||
"workout_start_date": row["workout_date"],
|
||||
"estimated_1rm": calculate_estimated_1rm(row["weight"], row["repetitions"])
|
||||
})
|
||||
|
||||
# Convert the map into a list of people, generate graphs, and organize exercises
|
||||
people = []
|
||||
for person_id, person_data in people_map.items():
|
||||
exercises = []
|
||||
for exercise_id, exercise_data in person_data["exercises"].items():
|
||||
# Sort sets by timestamp (descending)
|
||||
exercise_data["sets"] = sorted(
|
||||
exercise_data["sets"], key=lambda x: x["id"], reverse=True
|
||||
)
|
||||
|
||||
# Generate the graph for the exercise
|
||||
graph = self.generate_exercise_progress_graphs(
|
||||
person_id=person_id,
|
||||
exercise_id=exercise_id,
|
||||
exercise_name=exercise_data["name"],
|
||||
exercise_sets=exercise_data["sets"]
|
||||
)
|
||||
|
||||
# Add the graph to the exercise data
|
||||
exercises.append({
|
||||
"id": exercise_data["id"],
|
||||
"name": exercise_data["name"],
|
||||
"graph": graph,
|
||||
"sets": exercise_data["sets"]
|
||||
})
|
||||
person_data["exercises"] = exercises
|
||||
people.append(person_data)
|
||||
|
||||
return {"dashboard": people}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user