diff --git a/planning.md b/planning.md index 6255aa8..f0d6ad2 100644 --- a/planning.md +++ b/planning.md @@ -5,7 +5,7 @@ The app's target user is a person who struggles with planning what exercises to ## 2. What need or problem will your app solve? How do you know this is really a need for your target user? How does the target user currently deal with the problem? -This solves the problem that my current workout tracking app costs money (or I have to watch annoying ads while I'm trying to log information). Currently, I just turn off my data and internet when I'm in the gym to override the app and keep the ad from loading, but this means I don't get notifications from my other apps and I can only listen to the music I have downloaded. Currently, I just do the same exercises over and over, and it gets really boring, or I waste time searching for new workouts that I don't ever try. Eliminating the mental load of choosing a specific workout will help me (and others) be more likely to actually go to the gym. +Currently, I just do the same exercises over and over, and it gets really boring, or I waste time searching for new workouts that I don't ever try. Eliminating the mental load of choosing a specific workout will help me (and others) be more likely to actually go to the gym. ## 3. How will your app's design meet the need you have identified? I will create a bank of exercises sorted by what muscle group they target and that have attributes for weight, reps, sets, or time. I will have a path that allows the user to add their own exercises as well. I will support returning a random exercise based on the muscle group it works. I will also support updating the recommended weight, reps, time etc for each exercise. diff --git a/workouts/app/database.sqlite b/workouts/app/database.sqlite new file mode 100644 index 0000000..d14166f Binary files /dev/null and b/workouts/app/database.sqlite differ diff --git a/workouts/app/exlist.py b/workouts/app/exlist.py new file mode 100644 index 0000000..96fd269 --- /dev/null +++ b/workouts/app/exlist.py @@ -0,0 +1,24 @@ +from app.models import Exercise +import csv + +starting_exs = { + "Treadmill Walking":{"name":"Treadmill Walking","musclegroup":"cardio","weight":0,"reps":1,"sets":1,"timemins":20,"distance":1}, + "Treadmill Running":{"name":"Treadmill Running","musclegroup":"cardio","weight":0,"reps":1,"sets":1,"timemins":13,"distance":1}, + "Bicep Curls":{"name":"Bicep Curls","musclegroup":"arms","weight":10,"reps":10,"sets":3,"timemins":0,"distance":0}, + "Hammer Curls":{"name":"Hammer Curls","musclegroup":"arms","weight":15,"reps":8,"sets":3,"timemins":0,"distance":0}, + "Leg Press":{"name":"Leg Press","musclegroup":"legs","weight":90,"reps":10,"sets":3,"timemins":0,"distance":0}, + "Calf Raises":{"name":"Calf Raises","musclegroup":"legs","weight":0,"reps":20,"sets":3,"timemins":0,"distance":0}, + "Sit-ups":{"name":"Sit-ups","musclegroup":"abs","weight":0,"reps":15,"sets":3,"timemins":0,"distance":0}, + "Weighted Twists":{"name":"Weighted Twists","musclegroup":"abs","weight":5,"reps":20,"sets":3,"timemins":0,"distance":0}, + "Planks":{"name":"Planks","musclegroup":"abs","weight":0,"reps":1,"sets":3,"timemins":0,"distance":0}, + "Lat Pulldowns":{"name":"Lat Pulldowns","musclegroup":"back","weight":50,"reps":8,"sets":3,"timemins":0,"distance":0}, + "Bench Press":{"name":"Bench Press","musclegroup":"chest","weight":45,"reps":4,"sets":3,"timemins":0,"distance":0}, + "Push-ups":{"name":"Push-ups","musclegroup":"chest","weight":0,"reps":10,"sets":3,"timemins":0,"distance":0}, + "Seated Rows":{"name":"Seated Rows","musclegroup":"back","weight":40,"reps":10,"sets":3,"timemins":0,"distance":0}} + +def init_starting_exs(): + for ex in starting_exs.keys(): + if not (Exercise.objects.filter(name=ex).exists()): + info = starting_exs[ex] + Exercise.from_dict(info).save() + print ("Successfully imported library of exercises.") diff --git a/workouts/app/migrations/0001_initial.py b/workouts/app/migrations/0001_initial.py new file mode 100644 index 0000000..03251ff --- /dev/null +++ b/workouts/app/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# Generated by Django 5.1.4 on 2026-03-08 16:44 + +import banjo.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Exercise', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', banjo.models.StringField(default='')), + ('musclegroup', banjo.models.StringField(default='')), + ('weight', banjo.models.IntegerField(default=0)), + ('reps', banjo.models.IntegerField(default=0)), + ('sets', banjo.models.IntegerField(default=0)), + ('timemins', banjo.models.IntegerField(default=0)), + ('distance', banjo.models.IntegerField(default=0)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/workouts/app/migrations/0002_alter_exercise_distance_alter_exercise_timemins.py b/workouts/app/migrations/0002_alter_exercise_distance_alter_exercise_timemins.py new file mode 100644 index 0000000..ed27f87 --- /dev/null +++ b/workouts/app/migrations/0002_alter_exercise_distance_alter_exercise_timemins.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.4 on 2026-03-09 00:49 + +import banjo.models +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='exercise', + name='distance', + field=banjo.models.FloatField(default=0.0), + ), + migrations.AlterField( + model_name='exercise', + name='timemins', + field=banjo.models.FloatField(default=0.0), + ), + ] diff --git a/workouts/app/migrations/__init__.py b/workouts/app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/workouts/app/models.py b/workouts/app/models.py new file mode 100644 index 0000000..936ed3c --- /dev/null +++ b/workouts/app/models.py @@ -0,0 +1,40 @@ +from banjo.models import Model, StringField, IntegerField, FloatField, ForeignKey +from banjo.http import BadRequest + +class Exercise(Model): + name = StringField() + musclegroup = StringField() + weight = IntegerField() + reps = IntegerField() + sets = IntegerField() + timemins = FloatField() + distance = FloatField() + + + def instructions(self): + instr = '' + if self.musclegroup == "Cardio": + timemins = str(self.timemins) + distance = str(self.distance) + instr = "Do exercise for "+timemins+" minute(s) or until "+distance+" mile(s) has been completed." + else: + weight = str(self.weight) + reps = str(self.reps) + sets = str(self.sets) + if self.weight == 0: + instr = "Do exercise with bodyweight for "+reps+" rep(s). Repeat for "+sets+" set(s)" + else: + instr = "Do exercise with "+weight+" lb(s) for "+reps+" rep(s). Repeat for "+sets+" set(s)" + if self.timemins != 0: + timemins = str(self.timemins) + instr += " or for "+timemins+" minute(s)" + instr += "." + return instr + + def __repr__(self): + name = self.name + musclegroup = self.musclegroup + instr = self.instructions() + return name+": This is a(n) "+musclegroup+" exercise. Instructions: "+instr + + diff --git a/workouts/app/views.py b/workouts/app/views.py new file mode 100644 index 0000000..02a9858 --- /dev/null +++ b/workouts/app/views.py @@ -0,0 +1,61 @@ +from banjo.urls import route_get, route_post +from banjo.http import BadRequest, NotFound +from app.models import Exercise +from random import choice, sample +from app.exlist import init_starting_exs + +init_starting_exs() + +#Done +@route_get("all", args = {}) +def list_all_exercises_sorted(params): + exercises = Exercise.objects.all() + all_ex = {'cardio':[],'legs':[],'arms':[],'back':[],'chest':[],"abs":[]} + musclegroups = all_ex.keys() + for mg in musclegroups: + for ex in exercises: + if ex.musclegroup == mg: + all_ex[mg].append(ex.__repr__()) + return all_ex + +#Done +@route_get("workout_length", args= {"length": int}) #Returns n many exercises & instructions at random +def workout_with_length(params): + if Exercise.objects.all().count() >= params["length"]: + workout = [] + xlist = sample(list(Exercise.objects.all()),params["length"]) + for ex in xlist: + xinfo = ex.__repr__() + workout.append(xinfo) + return workout + else: + raise BadRequest("There are not enough exercises to pick that many.") + +@route_get("full_body", args={}) #Returns one random exercise from each muscle group +def workout_full_body(params): + return "in progress" + +@route_post("edit_exercise", args={"name":str,"category to edit":str,"new value":int}) #Allows a change to an exercise weight, reps, sets, time, or distance (numbers) +def edit_exercise(params): + return "in progress" + +#Done +@route_post("new_exercise",args={"name":str,"musclegroup":str,"weight":int,"reps":int,"sets":int,"timemins":int,"distance":int}) +def add_new_exercise(params): + if Exercise.objects.filter(name=params["name"]).exists(): + return "This exercise already exists." + else: + exercise = Exercise.from_dict(params) + exercise.save() + return exercise.__repr__() + +#Done +@route_get("delete_exercise", args ={"name":str}) #Done +def delete_exercise(params): + try: + ex = Exercise.objects.get(name=params["name"]) + ex.delete() + return "Successfully deleted!" + except Exercise.DoesNotExist: + raise NotFound("No such exercise exists.") +