Compare commits

..

No commits in common. "7bfa16c10a051757dfdc689be419e6a03791e321" and "d31dbfbb542d69149a1d937cb1a6ee4f039869b4" have entirely different histories.

31 changed files with 79 additions and 776 deletions

3
fitnotes/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -26,24 +26,30 @@ def import_fitnotes_db(filename, user, fitnotes_to_lift=DEFAULT_MAPPING):
# lift name => id # lift name => id
lift_ids = {_clean_name(l.name): l.id for l in Lift.objects.all()} lift_ids = {_clean_name(l.name): l.id for l in Lift.objects.all()}
# build mapping FitNotes exercise id => our lift id
lift_id_mapping = {}
conn = sqlite3.connect(filename) conn = sqlite3.connect(filename)
cur = conn.cursor() cur = conn.cursor()
for fnid, ename in cur.execute('SELECT _id, name FROM exercise WHERE exercise_type_id=0'):
cleaned = _clean_name(ename)
if cleaned not in fitnotes_to_lift:
lift_id_mapping[fnid] = cleaned
else:
lift_id_mapping[fnid] = lift_ids[fitnotes_to_lift[cleaned]]
with transaction.atomic(): with transaction.atomic():
Set.objects.filter(source='fitnotes').delete() Set.objects.filter(source='fitnotes').delete()
count = 0 for fnid, date, weight_kg, reps in cur.execute(
for fname, date, weight_kg, reps in cur.execute( 'SELECT exercise_id, date, metric_weight, reps FROM training_log'):
'SELECT name, date, metric_weight, reps FROM training_log, exercise '
'WHERE exercise_type_id=0 and exercise_id=exercise._id'
):
try: # error if mapping wasn't found and there's a workout using it
lift_id = lift_ids[fitnotes_to_lift[_clean_name(fname)]] if isinstance(lift_id_mapping[fnid], str):
except KeyError: raise ValueError('no known conversion for fitnotes exercise "{}"'.format(
raise ValueError('no known conversion for fitnotes exercise "{}"'.format(fname)) lift_id_mapping[fnid]))
lift_id = lift_id_mapping[fnid]
Set.objects.create(lift_id=lift_id, date=date, weight_kg=weight_kg, reps=reps, Set.objects.create(lift_id=lift_id, date=date, weight_kg=weight_kg, reps=reps,
source='fitnotes', user=user) source='fitnotes', user=user)
count += 1
return count

View File

3
fitnotes/models.py Normal file
View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

BIN
fitnotes/testdata/baddata.fitnotes vendored Normal file

Binary file not shown.

View File

@ -31,8 +31,7 @@ class TestFitnotesImport(TestCase):
def test_basic_import(self): def test_basic_import(self):
# ensure that the data comes in # ensure that the data comes in
num = import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.good_mapping) import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.good_mapping)
assert num == 9
assert Set.objects.filter(lift=self.bench).count() == 4 assert Set.objects.filter(lift=self.bench).count() == 4
assert Set.objects.filter(lift=self.squat).count() == 5 assert Set.objects.filter(lift=self.squat).count() == 5
@ -54,9 +53,10 @@ class TestFitnotesImport(TestCase):
import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.bad_mapping) import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.bad_mapping)
assert Set.objects.filter(lift=self.bench).count() == 0 assert Set.objects.filter(lift=self.bench).count() == 0
def test_bad_data_doesnt_overwrite(self): def test_bad_data_import(self):
# good db then bad db, should fail without screwing up existing data # good db then bad db, should fail without screwing up existing data
import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.good_mapping) import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.good_mapping)
with self.assertRaises(ValueError): with self.assertRaises(Exception):
import_fitnotes_db('fitnotes/testdata/example.fitnotes', self.user, self.bad_mapping) # baddata.fitnotes has all lift ids set to 9999
import_fitnotes_db('fitnotes/testdata/baddata.fitnotes', self.user, self.good_mapping)
assert Set.objects.count() == 9 assert Set.objects.count() == 9

View File

@ -3,5 +3,5 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.fitnotes_upload), url(r'^upload/$', views.fitnotes_upload),
] ]

View File

@ -16,7 +16,6 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)), ('id', models.AutoField(verbose_name='ID', auto_created=True, serialize=False, primary_key=True)),
('name', models.CharField(max_length=100)), ('name', models.CharField(max_length=100)),
('weight_kg', models.DecimalField(max_digits=7, decimal_places=3)), ('weight_kg', models.DecimalField(max_digits=7, decimal_places=3)),
('weight_lb', models.DecimalField(max_digits=7, decimal_places=3)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(

View File

@ -7,8 +7,8 @@ from django.db import models, migrations
def make_bars(apps, schema_editor): def make_bars(apps, schema_editor):
Bar = apps.get_model('inventory', 'Bar') Bar = apps.get_model('inventory', 'Bar')
Bar.objects.bulk_create([ Bar.objects.bulk_create([
Bar(id=1, name="Men's Olympic", weight_kg='20', weight_lb='45'), Bar(name="Women's Olympic", weight_kg='15'),
Bar(id=2, name="Women's Olympic", weight_kg='15', weight_lb='35'), Bar(name="Men's Olympic", weight_kg='20'),
]) ])

View File

@ -1,24 +1,22 @@
from django.db import models from django.db import models
from common import remove_exponent, to_lb from common import to_lb
class Bar(models.Model): class Bar(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
weight_kg = models.DecimalField(max_digits=7, decimal_places=3) weight_kg = models.DecimalField(max_digits=7, decimal_places=3)
weight_lb = models.DecimalField(max_digits=7, decimal_places=3)
def __str__(self): def __str__(self):
return '{} ({}kg / {}lb)'.format(self.name, remove_exponent(self.weight_kg), return '{} ({}lb / {}kg)'.format(self.name, self.weight_kg, self.weight_lb)
self.weight_lb)
@property
def weight_lb(self):
return to_lb(self.weight_kg)
class Lift(models.Model): class Lift(models.Model):
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
@property
def display_name(self):
return self.name
def __str__(self): def __str__(self):
return self.name return self.name

3
inventory/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('inventory', '3000_initial_data'),
('lifting', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='liftingoptions',
name='default_bar',
field=models.ForeignKey(default=1, to='inventory.Bar'),
preserve_default=False,
),
]

View File

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('lifting', '0002_liftingoptions_default_bar'),
]
operations = [
migrations.AlterField(
model_name='liftingoptions',
name='default_bar',
field=models.ForeignKey(default=1, to='inventory.Bar'),
),
]

View File

@ -1,8 +1,7 @@
from decimal import Decimal
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from inventory.models import Lift, Bar from inventory.models import Lift
SET_TYPES = ( SET_TYPES = (
('warmup', 'Warmup'), ('warmup', 'Warmup'),
@ -19,37 +18,9 @@ class LiftingOptions(models.Model):
user = models.OneToOneField(User, related_name='lifting_options') user = models.OneToOneField(User, related_name='lifting_options')
lifting_units = models.CharField(max_length=1, choices=UNITS, default='i') lifting_units = models.CharField(max_length=1, choices=UNITS, default='i')
default_bar = models.ForeignKey(Bar, default=1)
plate_pairs = ArrayField(models.DecimalField(max_digits=7, decimal_places=3), plate_pairs = ArrayField(models.DecimalField(max_digits=7, decimal_places=3),
default=['45','45','25','10','5','5','2.5','1.25']) default=['45','45','25','10','5','5','2.5','1.25'])
def plates_for_weight(self, weight):
side = []
w = Decimal(weight)
if self.lifting_units == 'i':
w -= self.default_bar.weight_lb
else:
w -= self.default_bar.weight_kg
initial_weight = w
available = sorted(self.plate_pairs, reverse=True)
while w and available:
plate = available.pop(0)
if plate * 2 <= w:
w -= plate * 2
side.append(plate)
if sum(side) * 2 != initial_weight:
raise ValueError('remaining weight {}'.format(initial_weight - sum(side) * 2))
return side
class LiftOptions(models.Model):
user = models.ForeignKey(User, related_name='lift_options')
lift = models.ForeignKey(Lift, related_name='options')
bar = models.ForeignKey(Bar, null=True)
extra_start_weight = models.DecimalField(max_digits=7, decimal_places=3, default=0)
increment = models.DecimalField(max_digits=5, decimal_places=3, default=5)
class Set(models.Model): class Set(models.Model):
user = models.ForeignKey(User, related_name='sets') user = models.ForeignKey(User, related_name='sets')

View File

@ -1,13 +1,10 @@
from django import template from django import template
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from common import to_lb, remove_exponent from common import to_lb
register = template.Library() register = template.Library()
register.filter('decimal', remove_exponent)
class MassNode(template.Node): class MassNode(template.Node):
def __init__(self, weight): def __init__(self, weight):
self.weight = template.Variable(weight) self.weight = template.Variable(weight)

View File

@ -1,4 +1,3 @@
from decimal import Decimal as D
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import User from django.contrib.auth.models import User
from lifting.models import LiftingOptions from lifting.models import LiftingOptions
@ -6,55 +5,6 @@ from lifting.models import LiftingOptions
class TestLiftingOptions(TestCase): class TestLiftingOptions(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='test', email='test@example.com', password='test')
def test_signal(self): def test_signal(self):
assert LiftingOptions.objects.filter(user=self.user).count() == 1 u = User.objects.create_user(username='test', email='test@example.com', password='test')
assert LiftingOptions.objects.filter(user=u).count() == 1
def test_plates_for_weight(self):
opts = self.user.lifting_options
opts.plate_pairs = [D(45), D(45), D(25), D(10), D(5), D(5), D('2.5')]
opts.default_bar_id = 1
opts.lifting_units = 'i'
assert opts.plates_for_weight(45) == []
assert opts.plates_for_weight(50) == [D('2.5')]
assert opts.plates_for_weight(90) == [D(10), D(5), D(5), D('2.5')]
assert opts.plates_for_weight(320) == [D(45), D(45), D(25), D(10), D(5), D(5), D('2.5')]
def test_plates_for_weight_womens_bar(self):
opts = self.user.lifting_options
opts.plate_pairs = [D(45), D(45), D(25), D(10), D(5), D(5), D('2.5')]
opts.default_bar_id = 2
opts.lifting_units = 'i'
assert opts.plates_for_weight(35) == []
assert opts.plates_for_weight(40) == [D('2.5')]
assert opts.plates_for_weight(80) == [D(10), D(5), D(5), D('2.5')]
assert opts.plates_for_weight(310) == [D(45), D(45), D(25), D(10), D(5), D(5), D('2.5')]
def test_plates_for_weight_kg(self):
opts = self.user.lifting_options
opts.plate_pairs = [D(20), D(20), D(10), D(5), D('2.5')]
opts.default_bar_id = 1
opts.lifting_units = 'm'
assert opts.plates_for_weight(20) == []
assert opts.plates_for_weight(25) == [D('2.5')]
assert opts.plates_for_weight(55) == [D(10), D(5), D('2.5')]
assert opts.plates_for_weight(135) == [D(20), D(20), D(10), D(5), D('2.5')]
def test_plates_for_weight_error(self):
opts = self.user.lifting_options
opts.plate_pairs = [D(45), D(45), D(25), D(10), D(5), D(5), D('2.5')]
opts.default_bar_id = 1
opts.lifting_units = 'i'
# TODO: check amounts
with self.assertRaises(ValueError):
opts.plates_for_weight('47.5')
with self.assertRaises(ValueError):
opts.plates_for_weight(325)
with self.assertRaises(ValueError):
opts.plates_for_weight(30)

View File

@ -10,5 +10,5 @@ urlpatterns = [
url(r'^lifts/$', views.lift_list, name='lift-list'), url(r'^lifts/$', views.lift_list, name='lift-list'),
url(r'^lifts/(?P<lift_id>\d+)/$', views.by_lift, name='lift-detail'), url(r'^lifts/(?P<lift_id>\d+)/$', views.by_lift, name='lift-detail'),
url(r'^options/$', views.edit_options, name='edit-options'), url(r'^edit/$', views.edit_profile, name='edit-profile'),
] ]

View File

@ -1,17 +1,17 @@
import calendar
import datetime import datetime
import decimal
import os import os
import tempfile import tempfile
from collections import defaultdict, Counter import calendar
from collections import defaultdict
from django.shortcuts import render from django.shortcuts import render
from django import forms
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.generic import dates from django.views.generic import dates
from django.db.models import Count, Max from django.db.models import Count, Max
from inventory.models import Lift, Bar
from .models import Set from .models import Set
from inventory.models import Lift
@login_required @login_required
@ -83,25 +83,7 @@ def by_lift(request, lift_id):
@login_required @login_required
def edit_options(request): def edit_profile(request):
lifting_options = request.user.lifting_options form = request.user.profile
if request.method == 'POST': return render(request, 'profiles/edit.html', {'form': form})
print(request.POST)
plates = []
for weight, number in zip(request.POST.getlist('plate_weight'),
request.POST.getlist('plate_number')):
if weight and number:
plates += [decimal.Decimal(weight)] * int(number)
lifting_options.plate_pairs = plates
lifting_options.default_bar_id = int(request.POST.get('barbell'))
lifting_options.lifting_units = request.POST.get('lifting_units')
lifting_options.save()
bars = Bar.objects.all()
plates = sorted(Counter(lifting_options.plate_pairs).items())
return render(request, 'profiles/edit.html', {'lifting_options': lifting_options,
'bars': bars, 'plates': plates,
})

View File

@ -1,15 +0,0 @@
from django import template
from django.template.loader import render_to_string
register = template.Library()
@register.filter
def formfield(value, arg):
if ',' in arg:
size, units = arg.split(',')
else:
size = arg
units = None
return render_to_string('lifting/_form-group.html',
{'field': value, 'size': size, 'units': units})

View File

@ -1,82 +0,0 @@
class Plan(models.Model):
name = models.CharField(max_length=100)
tags = models.ManyToManyField(PlanTag, related_name='plans')
public = models.BooleanField(default=False)
owner = models.ForeignKey(User, related_name='plans', null=True)
cloned_from = models.ForeignKey('self', null=True)
objects = ByNameManager()
def __str__(self):
return '{0}'.format(self.name)
def get_absolute_url(self):
return reverse('lifting.views.plan', args=[str(self.id)])
def natural_key(self):
return (self.name,)
def get_days(self, user):
exercise_rules = {}
days = []
for day in self.days.all():
day_sets = []
for exercise in day.exercises.all():
for reps in exercise.get_sets():
rules = exercise_rules.setdefault(exercise.exercise,
exercise.exercise.rules.get(user=user))
day_sets.append(
Set(exercise=exercise.exercise,
weight=round_to(rules.work_weight*exercise.percent, rules.increment),
reps=reps,
type='planned')
)
if exercise.raise_weight:
rules.work_weight += rules.increment
days.append(day_sets)
return days
class PlanDay(models.Model):
plan = models.ForeignKey(Plan, related_name='days')
name = models.CharField(max_length=100)
order = models.PositiveIntegerField()
def __str__(self):
return '{0}: {1}'.format(self.plan, self.name)
class Meta:
ordering = ['order']
class PlanExercise(models.Model):
plan_day = models.ForeignKey(PlanDay, related_name='exercises')
exercise = models.ForeignKey(Exercise)
order = models.PositiveIntegerField()
sets = models.CharField(max_length=100)
percent = models.DecimalField(max_digits=4, decimal_places=3, default=1)
raise_weight = models.BooleanField(default=False)
def get_sets(self):
return [int(s) for s in self.sets.split(',')]
def get_set_display(self):
sets = []
last_reps = None
last_reps_num = 0
for s in self.get_sets():
if last_reps and s != last_reps:
sets.append('{0}x{1}'.format(last_reps_num, last_reps))
last_reps_num = 0
last_reps_num += 1
last_reps = s
sets.append('{0}x{1}'.format(last_reps_num, last_reps))
return ', '.join(sets)
def get_percent_display(self):
return '{0:%}'.format(self.percent)
class Meta:
ordering = ['order']

View File

@ -1,31 +0,0 @@
from decimal import Decimal as D
from .models import ExerciseRules, Set
from .utils import round_to
def warmup_ss(exercise, weight, user):
"""
Starting Strength Warmup
========================
(start)x5 x2
(40%)x5
(60%)x3
(80%)x2
"""
# get relevant rules
rules, _ = ExerciseRules.objects.get_or_create(user=user, exercise=exercise)
start = rules.start_weight
# empty bar sets
sets = [Set(exercise=exercise, weight=start, reps=5, type='warmup')]*2
if D('0.8')*weight < start:
return []
for reps, pct in ((5, D('0.4')), (3, D('0.6')), (2, D('0.8'))):
ww = round_to(weight * pct, D('5'))
if ww > start:
sets.append(Set(exercise=exercise, weight=ww, reps=reps, type='warmup'))
return sets

View File

@ -1,147 +0,0 @@
from decimal import Decimal as D
from django.test import TestCase
from django.contrib.auth.models import User
from .models import Exercise, UserSettings, ExerciseRules, Plan
from .plans import warmup_ss
from .utils import round_to
def _seteq(s1, exercise, weight, reps):
try:
assert s1.exercise == exercise
assert s1.weight == weight
assert s1.reps == reps
except AssertionError:
raise AssertionError('{0} != {1}x{2}'.format(s1, weight, reps))
class PlanTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='user')
self.squat = Exercise.objects.create(name='squat')
self.bench = Exercise.objects.create(name='bench press')
ExerciseRules.objects.create(user=self.user, exercise=self.squat, work_weight=200)
ExerciseRules.objects.create(user=self.user, exercise=self.bench, work_weight=100)
self.tm = Plan.objects.create(name='Texas Method')
a1 = self.tm.days.create(name='A week - Volume day', order=1)
a1.exercises.create(exercise=self.squat, order=1, sets='5,5,5,5,5', percent=D('0.85'))
a1.exercises.create(exercise=self.bench, order=2, sets='5,5,5,5,5', percent=D('0.85'))
a2 = self.tm.days.create(name='A week - Recovery day', order=2)
a2.exercises.create(exercise=self.squat, order=1, sets='5,5', percent=D('0.8'))
# exaggerated raise_weight for tests
a3 = self.tm.days.create(name='A week - Record day', order=3)
a3.exercises.create(exercise=self.squat, order=1, sets='5', percent=D(1),
raise_weight=True)
a3.exercises.create(exercise=self.bench, order=2, sets='5', percent=D(1),
raise_weight=True)
b1 = self.tm.days.create(name='B week - Volume day', order=4)
b1.exercises.create(exercise=self.squat, order=1, sets='5,5,5,5,5', percent=D('0.85'))
b2 = self.tm.days.create(name='B week - Recovery day', order=5)
b2.exercises.create(exercise=self.squat, order=1, sets='5,5', percent=D('0.8'))
b2.exercises.create(exercise=self.bench, order=1, sets='5,5', percent=D('0.8'))
b3 = self.tm.days.create(name='B week - Record day', order=6)
b3.exercises.create(exercise=self.squat, order=2, sets='5', percent=D(1))
def test_get_days(self):
a1, a2, a3, b1, b2, b3 = self.tm.get_days(self.user)
_seteq(a1[0], self.squat, 170, 5)
_seteq(a1[1], self.squat, 170, 5)
_seteq(a1[2], self.squat, 170, 5)
_seteq(a1[3], self.squat, 170, 5)
_seteq(a1[4], self.squat, 170, 5)
_seteq(a1[5], self.bench, 85, 5)
_seteq(a1[6], self.bench, 85, 5)
_seteq(a1[7], self.bench, 85, 5)
_seteq(a1[8], self.bench, 85, 5)
_seteq(a1[9], self.bench, 85, 5)
_seteq(a2[0], self.squat, 160, 5)
_seteq(a2[1], self.squat, 160, 5)
_seteq(a3[0], self.squat, 200, 5)
_seteq(a3[1], self.bench, 100, 5)
# b record day raised by 5
_seteq(b3[0], self.squat, 205, 5)
class WarmupTests(TestCase):
def setUp(self):
self.exercise = Exercise.objects.create(name='bench press')
self.user = User.objects.create_user(username='user')
def test_round_to(self):
assert round_to(D('21'), D('2.5')) == D('20')
assert round_to(D('23'), D('2.5')) == D('22.5')
assert round_to(D('23'), D('5')) == D('20')
assert round_to(D('24.5'), D('2.5')) == D('22.5')
assert round_to(D('24.9'), D('5')) == D('25')
def test_warmup_ss(self):
# <=55: no warmup
assert warmup_ss(self.exercise, D('10'), self.user) == []
assert warmup_ss(self.exercise, D('55'), self.user) == []
# 60: just the bar
sets = warmup_ss(self.exercise, D('60'), self.user)
assert len(sets) == 2, sets
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
sets = warmup_ss(self.exercise, D('70'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 55, 2)
sets = warmup_ss(self.exercise, D('95'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 55, 3)
_seteq(sets[3], self.exercise, 75, 2)
sets = warmup_ss(self.exercise, D('135'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 50, 5)
_seteq(sets[3], self.exercise, 80, 3)
_seteq(sets[4], self.exercise, 105, 2)
sets = warmup_ss(self.exercise, D('170'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 65, 5)
_seteq(sets[3], self.exercise, 100, 3)
_seteq(sets[4], self.exercise, 135, 2)
sets = warmup_ss(self.exercise, D('250'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 100, 5)
_seteq(sets[3], self.exercise, 150, 3)
_seteq(sets[4], self.exercise, 200, 2)
# slightly crazy jump
sets = warmup_ss(self.exercise, D('315'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 125, 5)
_seteq(sets[3], self.exercise, 185, 3)
_seteq(sets[4], self.exercise, 250, 2)
# this is probably crazy & should be fixed
sets = warmup_ss(self.exercise, D('500'), self.user)
_seteq(sets[0], self.exercise, 45, 5)
_seteq(sets[1], self.exercise, 45, 5)
_seteq(sets[2], self.exercise, 200, 5)
_seteq(sets[3], self.exercise, 300, 3)
_seteq(sets[4], self.exercise, 400, 2)

View File

@ -1,56 +0,0 @@
from decimal import Decimal as D
from django.shortcuts import render, get_object_or_404
from django.views.decorators.http import require_http_methods, require_GET
from django.contrib.auth.decorators import login_required
from .models import UserSettings, ExerciseRules, Exercise, Plan
from .forms import UserSettingsForm, PlanForm
@require_http_methods(["GET", "POST"])
@login_required
def plan_edit(request, id):
""" edit details of a plan """
plan = get_object_or_404(Plan, pk=id)
exercises = Exercise.objects.all()
if request.method == 'GET':
pform = PlanForm(instance=plan)
return render(request, 'lifting/plan_edit.html',
{'pform': pform, 'plan': plan, 'exercises': exercises})
@require_http_methods(["GET", "POST"])
@login_required
def rules(request):
""" a view that allows a user to view/edit their list of rules """
gr, _ = UserSettings.objects.get_or_create(user=request.user)
ers = list(ExerciseRules.objects.filter(user=request.user))
exercises = Exercise.objects.exclude(id__in=[er.exercise_id for er in ers])
if request.method == 'GET':
grform = UserSettingsForm(instance=gr)
elif request.method == 'POST':
grform = UserSettingsForm(request.POST, instance=gr)
if grform.is_valid():
grform.save()
for exercise, start, inc, work in zip(request.POST.getlist('er.exercise'),
request.POST.getlist('er.start_weight'),
request.POST.getlist('er.increment'),
request.POST.getlist('er.work_weight')):
exercise = int(exercise)
start = D(start)
inc = D(inc)
work = D(work)
er, _ = ExerciseRules.objects.get_or_create(user=request.user,
exercise_id=int(exercise))
er.start_weight = start
er.increment = inc
er.work_weight = work
er.save()
return render(request, 'lifting/rules.html',
{'grform': grform, 'exercise_rules': ers, 'exercises': exercises, })
def er_row(request, eid):
return render(request, 'lifting/_er-row.html',
{'er': ExerciseRules(user=request.user, exercise=Exercise.objects.get(pk=eid))})

View File

@ -1,24 +0,0 @@
<tr>
<input type="hidden" name="er.exercise" value="{{er.exercise.id}}" />
<td class="col-md-3">
{{er.exercise}}
</td>
<td class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" name="er.start_weight" value="{{er.start_weight}}" />
<span class="input-group-addon">lbs</span>
</div>
</td>
<td class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" name="er.increment" value="{{er.increment}}" />
<span class="input-group-addon">lbs</span>
</div>
</td>
<td class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" name="er.work_weight" value="{{er.work_weight}}" />
<span class="input-group-addon">lbs</span>
</div>
</td>
</tr>

View File

@ -1,7 +0,0 @@
<div class="form-group {% if field.errors %}has-error{% endif %}">
<label class="col-md-2 control-label" for="{{field.id_for_label}}">{{field.label}}: </label>
<div class="col-md-{{size}}{% if units %}input-group{% endif %}">
<input type="text" class="form-control" id="{{field.id_for_label}}" name="{{field.html_name}}" value="{{field.value}}" />
{% if units %}<span class="input-group-addon">{{units}}</span>{% endif %}
</div>
</div>

View File

@ -1,34 +0,0 @@
{% extends "lifting/base.html" %}
{% load lifting %}
{% block content %}
<input type="text" name="plan.name">
<div class="row">
{% for day in plan.days.all %}
<div class="col-md-4">
<input type="day.name">
{{day.name}}
<table class="table">
<thead>
<th>Exercise</th><th>Sets</th><th>Percent</th>
</thead>
<tbody>
{% for e in day.exercises.all %}
<tr>
<td>{{e.exercise}}</td>
<td>{{e.get_set_display}}</td>
<td>{{e.get_percent_display}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
{% endblock %}
{% block script %}
<script>
</script>
{% endblock %}

View File

@ -1,33 +0,0 @@
{% extends "lifting/base.html" %}
{% load lifting %}
{% block content %}
<h2>{{plan}}</h2>
<div class="row">
{% for day in plan.days.all %}
<div class="col-md-4">
<h4>{{day.name}}</h4>
<table class="table">
<thead>
<th>Exercise</th><th>Sets</th><th>Percent</th>
</thead>
<tbody>
{% for e in day.exercises.all %}
<tr>
<td>{{e.exercise}}</td>
<td>{{e.get_set_display}}</td>
<td>{{e.get_percent_display}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
{% endblock %}
{% block script %}
<script>
</script>
{% endblock %}

View File

@ -1,54 +0,0 @@
{% extends "lifting/base.html" %}
{% load lifting %}
{% block content %}
<form class="form-horizontal" method="POST">
{{pform.name|formfield:"3"}}
{{pform.tags|formfield:"5"}}
<hr>
<div class="row">
{% for day in plan.days.all %}
<div class="col-md-6">
<div class="form-group">
<label class="col-md-2 control-label" for="day.name">Day: </label>
<div class="col-md-9">
<input type="text" class="form-control" id="day.name" name="day.name" value="{{day.name}}" />
</div>
</div>
</div>
<div class="col-md-6">
<table class="table">
<thead>
<th>Exercise</th><th>Sets</th><th>Percent</th>
</thead>
<tbody>
{% for e in day.exercises.all %}
<tr>
<td>
<select id="new-exercise" class="form-control">
{% for exercise in exercises %}
<option value="{{exercise.id}}" {% if e.exercise_id == exercise.id %}selected{% endif %}>{{exercise}}</option>
{% endfor %}
</select>
</td>
<td>{{e.get_set_display}}</td>
<td>{{e.get_percent_display}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
</form>
{% endblock %}
{% block script %}
<script>
</script>
{% endblock %}

View File

@ -1,36 +0,0 @@
{% extends "lifting/base.html" %}
{% load lifting %}
{% block content %}
<table class="table">
<thead>
<tr>
<th>Plan</th>
<th>Tags</th>
<th>Popularity</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody id="exercise-rules">
{% for plan in plans %}
<tr>
<td><a href="{{plan.get_absolute_url}}">{{plan}}</a></td>
<td>
{% for tag in plan.tags.all %}
<span style="background-color: #{{tag.color}};" class="label">{{tag.name}}</span>
{% endfor %}
</td>
<td>{{plan.popularity}}</td>
<td>clone</td>
<td>use plan</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}
{% block script %}
<script>
</script>
{% endblock %}

View File

@ -1,56 +0,0 @@
{% extends "lifting/base.html" %}
{% load lifting %}
{% block content %}
<form class="form-horizontal" method="POST">
{% csrf_token %}
<h3>Global Settings</h3>
{{grform.bar|formfield:"2,lbs"}}
{{grform.plates|formfield:"3,lbs"}}
<hr>
<h3>Exercise Settings</h3>
<table class="table">
<thead>
<tr>
<th>Exercise</th>
<th>Start Weight</th>
<th>Increment</th>
<th>Working Weight</th>
</tr>
</thead>
<tbody id="exercise-rules">
{% for er in exercise_rules %}
{% include "lifting/_er-row.html" %}
{% endfor %}
</tbody>
</table>
<hr>
<div class="form-group">
<div class="col-md-2">
<button id="add-exercise" type="button" class="btn">Add Exercise: </button>
</div>
<div class="col-md-5">
<select id="new-exercise" class="form-control">
{% for exercise in exercises %}
<option value="{{exercise.id}}">{{exercise}}</option>
{% endfor %}
</select>
</div>
</div>
<button type="submit" class="btn btn-primary">Save Settings</button>
</form>
{% endblock content %}
{% block script %}
<script>
$(function() {
$('#add-exercise').click(function() {
var val = $('#new-exercise').val();
$.get('/_er-row/' + val + '/', function(data) {
$('#exercise-rules').append(data);
$('#new-exercise > option[value=' + val + ']').remove();
});
});
});
</script>
{% endblock %}

View File

@ -1,11 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load lifting %}
{% block content %} {% block content %}
<form method="post">
{% csrf_token %}
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<section class="panel panel-default"> <section class="panel panel-default">
@ -41,21 +37,22 @@
<label class="col-sm-4 control-label">Lifting Units:</label> <label class="col-sm-4 control-label">Lifting Units:</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="radio"> <div class="radio">
<input type="radio" name="lifting_units" value="i" {% if lifting_options.lifting_units == "i" %}checked{% endif %} >lb</input> <input type="radio" name="lifting_unit" value="i">lbs</input>
</div> </div>
<div class="radio"> <div class="radio">
<input type="radio" name="lifting_units" value="m" {% if lifting_options.lifting_units == "m" %}checked{% endif %}>kg</input> <input type="radio" name="lifting_unit" value="m">kg</input>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">Barbell:</label> <label class="col-sm-4 control-label">Barbell:</label>
<div class="col-sm-8"> <div class="col-sm-8">
{% for bar in bars %}
<div class="radio"> <div class="radio">
<input type="radio" name="barbell" value="{{bar.id}}" {% if lifting_options.default_bar_id == bar.id %}checked{% endif %}>{{bar}}</input> <input type="radio" name="barbell" value="1">Men's Olympic (44lbs / 20kg) </input>
</div>
<div class="radio">
<input type="radio" name="barbell" value="2">Women's Olympic (33lbs / 15kg) </input>
</div> </div>
{% endfor %}
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -66,28 +63,37 @@
<tr><td>Weight</td><td># of Pairs</td></tr> <tr><td>Weight</td><td># of Pairs</td></tr>
</thead> </thead>
<tbody> <tbody>
{% for weight, n in plates %}
<tr> <tr>
<td><input type="text" class="form-control" name="plate_weight" value="{{weight|decimal}}"></input></td> <td><input type="text" class="form-control" name="plate_weight" value="45"></input></td>
<td><input type="text" class="form-control" name="plate_number" value="{{n}}"></input></td> <td><input type="text" class="form-control" name="plate_number" value="2"></input></td>
</tr> </tr>
{% endfor %}
<tr> <tr>
<td><input type="text" class="form-control" name="plate_weight" value=""></input></td> <td><input type="text" class="form-control" name="plate_weight" value="25"></input></td>
<td><input type="text" class="form-control" name="plate_number" value=""></input></td> <td><input type="text" class="form-control" name="plate_number" value="1"></input></td>
</tr>
<tr>
<td><input type="text" class="form-control" name="plate_weight" value="10"></input></td>
<td><input type="text" class="form-control" name="plate_number" value="1"></input></td>
</tr>
<tr>
<td><input type="text" class="form-control" name="plate_weight" value="5"></input></td>
<td><input type="text" class="form-control" name="plate_number" value="2"></input></td>
</tr>
<tr>
<td><input type="text" class="form-control" name="plate_weight" value="2.5"></input></td>
<td><input type="text" class="form-control" name="plate_number" value="1"></input></td>
</tr>
<tr>
<td><input type="text" class="form-control" name="plate_weight" value="1.25"></input></td>
<td><input type="text" class="form-control" name="plate_number" value="1"></input></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
<div class="form-group">
<div class="col-sm-12"><input type="submit" class="form-control" value="Save Changes"></input> </div>
</div>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</div> </div>
</form>
{% endblock %} {% endblock %}