Refactor workout graph generation endpoint

This commit is contained in:
Peter Stockings
2023-10-20 19:15:47 +11:00
parent 18ac5d3fbc
commit ec9ec443e4

127
app.py
View File

@@ -211,116 +211,35 @@ def create_workout(user_id):
return f'Added {humanize.naturaldelta(workout.duration)} session.', 201
"""
@app.route('/user/<int:user_id>/workouts', methods=['GET', 'POST'])
def workouts(user_id):
user = User.query.get(user_id)
if request.method == 'GET':
workouts_data = get_workouts_for_user_view_data(user)
return render_template('workouts_list.html', workouts=workouts_data)
elif request.method == 'POST':
app.logger.info(f'Creating workout for user {user.name} ({user.id})')
data = request.json
cadence_readings = data['cadence_readings'] or []
heart_rate_readings = data['heart_rate_readings'] or []
# create a new workout
workout = Workout(user_id=user_id, bike_id=user.bike_id)
db.session.add(workout)
db.session.commit()
app.logger.info(
f'Workout({workout.id}) created for user {user.name} ({user.id}) with {len(cadence_readings)} cadence readings and {len(heart_rate_readings)} heart rate readings')
# add cadence readings to the workout
for c in cadence_readings:
cadence_reading = CadenceReading(
workout_id=workout.id, created_at=c['timestamp'], rpm=c['rpm'], distance=c['distance'], speed=c['speed'], calories=c['calories'], power=c['power'])
db.session.add(cadence_reading)
for h in heart_rate_readings:
heart_rate_reading = HeartRateReading(
workout_id=workout.id, created_at=h['timestamp'], bpm=h['bpm'])
db.session.add(heart_rate_reading)
if cadence_readings:
timestamps = [isoparse(
c['timestamp']) for c in cadence_readings]
start_time = min(timestamps)
end_time = max(timestamps)
duration = end_time - start_time
duration = duration.total_seconds()
average_rpm = sum(
c['rpm'] for c in cadence_readings) / len(cadence_readings)
min_rpm = min(
c['rpm'] for c in cadence_readings)
max_rpm = max(
c['rpm'] for c in cadence_readings)
calories = cadence_readings[-1]['calories']
distance = cadence_readings[-1]['distance']
workout.is_cadence_available = True
workout.started_at = start_time
workout.duration = duration
workout.average_rpm = average_rpm
workout.min_rpm = min_rpm
workout.max_rpm = max_rpm
workout.calories = calories
workout.distance = distance
if heart_rate_readings:
bpm = [h['bpm'] for h in heart_rate_readings]
average_bpm = sum(bpm) / len(bpm)
min_bpm = min(bpm)
max_bpm = max(bpm)
workout.is_heart_rate_available = True
workout.average_bpm = average_bpm
workout.min_bpm = min_bpm
workout.max_bpm = max_bpm
db.session.commit()
return jsonify({'message': 'Workout created successfully.'}), 201
"""
@app.route('/user/<int:user_id>/workout/<int:workout_id>/<string:graph_type>', methods=['GET'])
def workout(user_id, workout_id, graph_type):
workout = Workout.query.filter_by(user_id=user_id, id=workout_id).join(
Workout.cadence_readings).join(Workout.heart_rate_readings).first()
workout = Workout.query.filter_by(user_id=user_id, id=workout_id) \
.join(Workout.cadence_readings) \
.join(Workout.heart_rate_readings) \
.first()
if not workout:
return jsonify({'message': 'Workout {} not found for user {}.'.format(workout_id, user_id)}), 404
return jsonify({'message': f'Workout {workout_id} not found for user {user_id}.'}), 404
if workout.is_cadence_available:
x_values = [reading.created_at for reading in workout.cadence_readings]
if graph_type == 'cadence':
y_values = [reading.rpm for reading in workout.cadence_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Cadence (RPM)', filename='cadence'), 200
elif graph_type == 'speed':
y_values = [reading.speed for reading in workout.cadence_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Speed (KPH)', filename='speed'), 200
elif graph_type == 'distance':
y_values = [
reading.distance for reading in workout.cadence_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Distance (KM)', filename='distance'), 200
elif graph_type == 'calories':
y_values = [
reading.calories for reading in workout.cadence_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Calories (KCAL)', filename='calories'), 200
elif graph_type == 'power':
y_values = [reading.power for reading in workout.cadence_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Power (WATTS)', filename='power'), 200
if workout.is_heart_rate_available:
x_values = [
reading.created_at for reading in workout.heart_rate_readings]
y_values = [reading.bpm for reading in workout.heart_rate_readings]
return create_graph(x_values=x_values, y_values=y_values, y_label='Heart Rate (BPM)', filename='heart_rate'), 200
graph_mappings = {
'cadence': ('cadence_readings', 'rpm', 'Cadence (RPM)', 'cadence'),
'speed': ('cadence_readings', 'speed', 'Speed (KPH)', 'speed'),
'distance': ('cadence_readings', 'distance', 'Distance (KM)', 'distance'),
'calories': ('cadence_readings', 'calories', 'Calories (KCAL)', 'calories'),
'power': ('cadence_readings', 'power', 'Power (WATTS)', 'power'),
'heart_rate': ('heart_rate_readings', 'bpm', 'Heart Rate (BPM)', 'heart_rate')
}
return jsonify({'message': 'Unable to generate {} for workout {}.'.format(graph_type, workout_id)}), 409
readings_attr, y_attr, y_label, filename = graph_mappings.get(
graph_type, (None, None, None, None))
readings = getattr(workout, readings_attr, [])
if readings:
x_values = [reading.created_at for reading in readings]
y_values = [getattr(reading, y_attr) for reading in readings]
return create_graph(x_values=x_values, y_values=y_values, y_label=y_label, filename=filename), 200
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'])