Skip to content

Commit 0805022

Browse files
authored
Merge pull request #2 from abalcobia/build-octofit-app
Build octofit app
2 parents 9b8e7d6 + 7f382c1 commit 0805022

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+19477
-1
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
description: Update Django project files for octofit-tracker app
3+
---
4+
5+
# Django App Updates
6+
7+
- All Django project files are in the `octofit-tracker/backend/octofit_tracker` directory.
8+
9+
1. Update `settings.py` for MongoDB connection and CORS. And make sure `octofit_tracker`, `rest_framework`, and `djongo` are in `INSTALLED_APPS`.
10+
2. Update `models.py`, `serializers.py`, `urls.py`, `views.py`, `tests.py`, and `admin.py` to support users, teams, activities, leaderboard, and workouts collections.
11+
3. Ensure `/` points to the api and `api_root` is present in `urls.py`.

.vscode/launch.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"env": {
1414
"PYTHONPATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin/python",
1515
"VIRTUAL_ENV": "${workspaceFolder}/octofit-tracker/backend/venv",
16-
"PATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin:${env:PATH}"
16+
"PATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin:${env:PATH}",
17+
"CODESPACE_NAME": "${env:CODESPACE_NAME}"
1718
}
1819
},
1920
{

octofit-tracker/backend/db.sqlite3

128 KB
Binary file not shown.

octofit-tracker/backend/manage.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
import os
4+
import sys
5+
6+
7+
def main():
8+
"""Run administrative tasks."""
9+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'octofit_tracker.settings')
10+
try:
11+
from django.core.management import execute_from_command_line
12+
except ImportError as exc:
13+
raise ImportError(
14+
"Couldn't import Django. Are you sure it's installed and "
15+
"available on your PYTHONPATH environment variable? Did you "
16+
"forget to activate a virtual environment?"
17+
) from exc
18+
execute_from_command_line(sys.argv)
19+
20+
21+
if __name__ == '__main__':
22+
main()

octofit-tracker/backend/octofit_tracker/__init__.py

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from django.contrib import admin
2+
from .models import User, Team, Activity, Leaderboard, Workout
3+
4+
5+
@admin.register(User)
6+
class UserAdmin(admin.ModelAdmin):
7+
list_display = ('name', 'email', 'team', 'fitness_level', 'created_at')
8+
list_filter = ('fitness_level', 'team')
9+
search_fields = ('name', 'email')
10+
11+
12+
@admin.register(Team)
13+
class TeamAdmin(admin.ModelAdmin):
14+
list_display = ('name', 'description', 'created_at')
15+
search_fields = ('name',)
16+
17+
18+
@admin.register(Activity)
19+
class ActivityAdmin(admin.ModelAdmin):
20+
list_display = ('user', 'activity_type', 'duration', 'date')
21+
list_filter = ('activity_type',)
22+
search_fields = ('user__name',)
23+
24+
25+
@admin.register(Leaderboard)
26+
class LeaderboardAdmin(admin.ModelAdmin):
27+
list_display = ('user', 'score', 'rank')
28+
ordering = ('rank',)
29+
30+
31+
@admin.register(Workout)
32+
class WorkoutAdmin(admin.ModelAdmin):
33+
list_display = ('name', 'difficulty')
34+
list_filter = ('difficulty',)
35+
search_fields = ('name',)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for octofit_tracker project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'octofit_tracker.settings')
15+
16+
application = get_asgi_application()

octofit-tracker/backend/octofit_tracker/management/__init__.py

Whitespace-only changes.

octofit-tracker/backend/octofit_tracker/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
from django.core.management.base import BaseCommand
2+
from django.utils import timezone
3+
from datetime import timedelta
4+
import random
5+
from pymongo import MongoClient
6+
from octofit_tracker.models import User, Team, Activity, Leaderboard, Workout
7+
8+
9+
class Command(BaseCommand):
10+
help = 'Populate the octofit_db database with test data'
11+
12+
def handle(self, *args, **options):
13+
# Clear existing data directly via pymongo to avoid ORM issues with
14+
# malformed documents that may have non-integer primary keys.
15+
self.stdout.write('Clearing existing data...')
16+
_client = MongoClient('localhost', 27017)
17+
_db = _client['octofit_db']
18+
for col in ['users', 'teams', 'activities', 'leaderboard', 'workouts']:
19+
_db[col].delete_many({})
20+
_client.close()
21+
22+
# Create Teams using Django ORM
23+
self.stdout.write('Inserting teams...')
24+
Team.objects.create(
25+
id=1,
26+
name='Team Marvel',
27+
description="Earth's Mightiest Heroes",
28+
)
29+
Team.objects.create(
30+
id=2,
31+
name='Team DC',
32+
description='Justice League United',
33+
)
34+
# Re-fetch to get clean integer PKs (djongo can return ObjectId on save)
35+
team_marvel = Team.objects.get(pk=1)
36+
team_dc = Team.objects.get(pk=2)
37+
self.stdout.write(self.style.SUCCESS('Inserted 2 teams'))
38+
39+
# Create Users using Django ORM
40+
self.stdout.write('Inserting users...')
41+
users_info = [
42+
# Team Marvel
43+
(1, 'Tony Stark', 'ironman@avengers.com', team_marvel, '🦾', 'advanced'),
44+
(2, 'Steve Rogers', 'captain@avengers.com', team_marvel, '🛡️', 'advanced'),
45+
(3, 'Natasha Romanoff', 'blackwidow@avengers.com', team_marvel, '🕷️', 'advanced'),
46+
(4, 'Bruce Banner', 'hulk@avengers.com', team_marvel, '💚', 'advanced'),
47+
(5, 'Thor Odinson', 'thor@asgard.com', team_marvel, '⚡', 'god-tier'),
48+
# Team DC
49+
(6, 'Clark Kent', 'superman@justiceleague.com', team_dc, '🦸', 'god-tier'),
50+
(7, 'Bruce Wayne', 'batman@gotham.com', team_dc, '🦇', 'advanced'),
51+
(8, 'Diana Prince', 'wonderwoman@themyscira.com', team_dc, '⭐', 'god-tier'),
52+
(9, 'Barry Allen', 'flash@speedforce.com', team_dc, '⚡', 'advanced'),
53+
(10, 'Arthur Curry', 'aquaman@atlantis.com', team_dc, '🔱', 'advanced'),
54+
]
55+
56+
users = []
57+
for uid, name, email, team, avatar, fitness_level in users_info:
58+
User.objects.create(
59+
id=uid,
60+
name=name,
61+
email=email,
62+
team=team,
63+
avatar=avatar,
64+
fitness_level=fitness_level,
65+
)
66+
# Re-fetch users with clean integer PKs
67+
users = list(User.objects.all().order_by('id'))
68+
self.stdout.write(self.style.SUCCESS(f'Inserted {len(users)} users'))
69+
70+
# Create Activities using Django ORM
71+
self.stdout.write('Inserting activities...')
72+
activity_types = ['running', 'cycling', 'swimming', 'strength_training', 'yoga']
73+
activities_created = 0
74+
activity_id = 1
75+
for user in users:
76+
num_activities = random.randint(5, 10)
77+
for j in range(num_activities):
78+
days_ago = random.randint(0, 30)
79+
activity_date = timezone.now() - timedelta(days=days_ago)
80+
Activity.objects.create(
81+
id=activity_id,
82+
user=user,
83+
activity_type=random.choice(activity_types),
84+
duration=random.randint(15, 120),
85+
date=activity_date,
86+
notes=f'Great workout session #{j + 1}',
87+
)
88+
activity_id += 1
89+
activities_created += 1
90+
self.stdout.write(self.style.SUCCESS(f'Inserted {activities_created} activities'))
91+
92+
# Create Leaderboard entries using Django ORM
93+
self.stdout.write('Calculating leaderboard...')
94+
leaderboard_entries = []
95+
for user in users:
96+
total_duration = sum(
97+
a.duration for a in Activity.objects.filter(user=user)
98+
)
99+
leaderboard_entries.append((user, total_duration))
100+
101+
# Sort by total duration descending and assign ranks
102+
leaderboard_entries.sort(key=lambda x: x[1], reverse=True)
103+
for rank, (user, score) in enumerate(leaderboard_entries, start=1):
104+
Leaderboard.objects.create(id=rank, user=user, score=score, rank=rank)
105+
self.stdout.write(self.style.SUCCESS(f'Inserted {len(leaderboard_entries)} leaderboard entries'))
106+
107+
# Create Workout suggestions using Django ORM
108+
self.stdout.write('Inserting workout suggestions...')
109+
workouts_data = [
110+
{
111+
'name': 'Super Soldier Circuit',
112+
'description': "Captain America's legendary training routine",
113+
'difficulty': 'advanced',
114+
'exercises': [
115+
{'name': 'Push-ups', 'reps': 50, 'sets': 4},
116+
{'name': 'Pull-ups', 'reps': 20, 'sets': 4},
117+
{'name': 'Squats', 'reps': 50, 'sets': 4},
118+
{'name': 'Burpees', 'reps': 30, 'sets': 3},
119+
],
120+
},
121+
{
122+
'name': 'Speedster Sprint Training',
123+
'description': "Barry Allen's speed-building workout",
124+
'difficulty': 'intermediate',
125+
'exercises': [
126+
{'name': 'Sprint Intervals', 'duration': '30 sec', 'sets': 10},
127+
{'name': 'High Knees', 'duration': '1 min', 'sets': 5},
128+
{'name': 'Mountain Climbers', 'reps': 40, 'sets': 4},
129+
],
130+
},
131+
{
132+
'name': 'Amazonian Warrior Training',
133+
'description': "Wonder Woman's combat conditioning",
134+
'difficulty': 'advanced',
135+
'exercises': [
136+
{'name': 'Sword Swings (weighted)', 'reps': 30, 'sets': 5},
137+
{'name': 'Shield Holds', 'duration': '2 min', 'sets': 3},
138+
{'name': 'Battle Rope', 'duration': '1 min', 'sets': 5},
139+
{'name': 'Box Jumps', 'reps': 25, 'sets': 4},
140+
],
141+
},
142+
{
143+
'name': 'Atlantean Swim Power',
144+
'description': "Aquaman's underwater endurance training",
145+
'difficulty': 'intermediate',
146+
'exercises': [
147+
{'name': 'Freestyle Swimming', 'distance': '1000m', 'sets': 3},
148+
{'name': 'Underwater Breath Hold', 'duration': '2 min', 'sets': 5},
149+
{'name': 'Treading Water', 'duration': '5 min', 'sets': 3},
150+
],
151+
},
152+
{
153+
'name': 'Zen Master Flow',
154+
'description': "Black Widow's flexibility and balance routine",
155+
'difficulty': 'beginner',
156+
'exercises': [
157+
{'name': 'Sun Salutations', 'reps': 10, 'sets': 3},
158+
{'name': 'Warrior Poses', 'duration': '1 min each', 'sets': 3},
159+
{'name': 'Tree Pose', 'duration': '1 min', 'sets': 3},
160+
{'name': 'Cobra Stretch', 'duration': '30 sec', 'sets': 4},
161+
],
162+
},
163+
{
164+
'name': 'Dark Knight Conditioning',
165+
'description': "Batman's stealth and agility training",
166+
'difficulty': 'advanced',
167+
'exercises': [
168+
{'name': 'Parkour Drills', 'duration': '10 min', 'sets': 1},
169+
{'name': 'Rope Climbing', 'reps': 10, 'sets': 3},
170+
{'name': 'Handstand Push-ups', 'reps': 15, 'sets': 3},
171+
{'name': 'Ninja Rolls', 'reps': 20, 'sets': 4},
172+
],
173+
},
174+
{
175+
'name': 'Arc Reactor Cardio',
176+
'description': "Iron Man's heart-healthy workout",
177+
'difficulty': 'intermediate',
178+
'exercises': [
179+
{'name': 'Cycling', 'duration': '20 min', 'sets': 1},
180+
{'name': 'Jumping Jacks', 'reps': 50, 'sets': 3},
181+
{'name': 'Step-ups', 'reps': 30, 'sets': 4},
182+
],
183+
},
184+
]
185+
186+
for w_id, w in enumerate(workouts_data, start=1):
187+
Workout.objects.create(
188+
id=w_id,
189+
name=w['name'],
190+
description=w['description'],
191+
difficulty=w['difficulty'],
192+
exercises=w['exercises'],
193+
)
194+
self.stdout.write(self.style.SUCCESS(f'Inserted {len(workouts_data)} workout suggestions'))
195+
196+
# Summary
197+
self.stdout.write('\n' + '=' * 50)
198+
self.stdout.write(self.style.SUCCESS('DATABASE POPULATION COMPLETE!'))
199+
self.stdout.write('=' * 50 + '\n')
200+
self.stdout.write('Collection counts:')
201+
self.stdout.write(f' Users: {User.objects.count()}')
202+
self.stdout.write(f' Teams: {Team.objects.count()}')
203+
self.stdout.write(f' Activities: {Activity.objects.count()}')
204+
self.stdout.write(f' Leaderboard: {Leaderboard.objects.count()}')
205+
self.stdout.write(f' Workouts: {Workout.objects.count()}')
206+

0 commit comments

Comments
 (0)