Commit e67c7c8
Changed files (8)
spec
app/models/program.rb
@@ -27,7 +27,7 @@ class Program < ActiveRecord::Base
ExerciseSet.new(
exercise: exercise,
target_repetitions: recommended_reps_for(user, exercise),
- target_weight: user.next_weight_for(exercise)
+ target_weight: recommendation_for(user, exercise).next_weight
)
end
end
app/models/quantity.rb
@@ -14,15 +14,28 @@ class Quantity
@amount.to_f
end
+ def +(other)
+ Quantity.new(amount + amount_from(other), unit)
+ end
+
def eql?(other, delta = 0.1)
- converted = other.respond_to?(:to) ? other.to(unit).amount : other
- (self.amount - converted).abs <= delta
+ (self.amount - amount_from(other)).abs <= delta
+ end
+
+ def ==(other)
+ eql?(other)
end
def to_s
to_f.to_s
end
+ private
+
+ def amount_from(quantity)
+ quantity.respond_to?(:to) ? quantity.to(unit).amount : quantity
+ end
+
class UnitOfMeasure
def self.for(unit)
case unit
app/models/training_history.rb
@@ -26,10 +26,6 @@ class TrainingHistory
last_successful_set.try(:target_weight).to_i
end
- def next_weight
- 5 + last_weight
- end
-
def to_line_chart
user.workouts.inject({}) do |memo, workout|
memo[workout.occurred_at] =
app/models/user.rb
@@ -60,10 +60,6 @@ class User < ActiveRecord::Base
TrainingHistory.new(self, exercise)
end
- def next_weight_for(exercise)
- history_for(exercise).next_weight
- end
-
def begin_workout(routine, date, body_weight)
matching_workouts = workouts.where(occurred_at: date)
if matching_workouts.any?
app/models/user_recommendation.rb
@@ -16,6 +16,15 @@ class UserRecommendation
recommended_sets > 0 ? recommended_sets : recommendation.sets
end
+ def next_weight
+ last_weight = user.history_for(exercise).last_weight
+ if last_weight > 0
+ 5.lbs + last_weight
+ else
+ 45.lbs
+ end
+ end
+
private
def recommendation
spec/models/program_spec.rb
@@ -13,4 +13,37 @@ describe Program do
expect(Program.stronglifts).to eql(program)
end
end
+
+ describe "#prepare_sets_for" do
+ include_context "stronglifts_program"
+ subject { Program.stronglifts }
+
+ describe "squat" do
+ let(:user) { build(:user) }
+
+ it 'returns 5 sets of 5 repetitions' do
+ sets = subject.prepare_sets_for(user, squat)
+ expect(sets.length).to eql(5)
+ expect(sets.map(&:target_repetitions)).to match_array([5, 5, 5, 5, 5])
+ end
+
+ it 'returns the correct exercise for each set' do
+ sets = subject.prepare_sets_for(user, squat)
+ expect(sets.map(&:exercise).uniq).to match_array([squat])
+ end
+
+ it 'returns 45 lbs for the first workout' do
+ sets = subject.prepare_sets_for(user, squat)
+ expect(sets.map(&:target_weight).uniq).to match_array([45.lbs])
+ end
+
+ it 'returns 50 lbs for the second workout' do
+ workout = create(:workout, user: user, routine: routine_a)
+ 5.times { workout.train(squat, 45, repetitions: 5) }
+
+ sets = subject.prepare_sets_for(user, squat)
+ expect(sets.map(&:target_weight).uniq).to match_array([50.lbs])
+ end
+ end
+ end
end
spec/models/quantity_spec.rb
@@ -53,4 +53,30 @@ describe Quantity do
expect(quantity).to_not eql(other)
end
end
+
+ describe "#+" do
+ it 'adds lbs to lbs' do
+ quantity = Quantity.new(135.0, :lbs)
+ other = Quantity.new(135.0, :lbs)
+ expect(quantity + other).to eql(Quantity.new(270.0, :lbs))
+ end
+
+ it 'adds kgs to lbs' do
+ quantity = Quantity.new(135.0, :lbs)
+ other = Quantity.new(61.2, :kg)
+ expect(quantity + other).to eql(Quantity.new(270.0, :lbs))
+ end
+
+ it 'adds lbs to kgs' do
+ quantity = Quantity.new(61.2, :kg)
+ other = Quantity.new(135.0, :lbs)
+ expect(quantity + other).to eql(Quantity.new(122.4, :kg))
+ end
+
+ it 'adds a float to lbs' do
+ quantity = Quantity.new(135.0, :lbs)
+ other = 135.0
+ expect(quantity + other).to eql(Quantity.new(270.0, :lbs))
+ end
+ end
end
spec/models/user_spec.rb
@@ -227,4 +227,73 @@ describe User do
expect(received_email.body).to eql(email.body)
end
end
+
+ describe "#next_workout_for" do
+ subject { create(:user) }
+ let(:routine) { create(:routine) }
+ let(:body_weight) { rand(300) }
+
+ it 'includes the body weight from the previous workout' do
+ create(:workout, user: subject, body_weight: body_weight)
+
+ workout = subject.next_workout_for(routine)
+ expect(workout.body_weight).to eql(body_weight)
+ end
+
+ it 'uses the correct routine' do
+ workout = subject.next_workout_for(routine)
+ expect(workout.routine).to eql(routine)
+ end
+
+ it 'prepares the correct number of sets' do
+ squat = create(:exercise)
+ routine.add_exercise(squat, sets: 3)
+ workout = subject.next_workout_for(routine)
+ expect(workout.exercise_sets.length).to eql(3)
+ end
+ end
+
+ describe "#next_routine" do
+ include_context "stronglifts_program"
+ subject { create(:user) }
+
+ it 'routines the next workout' do
+ create(:workout, routine: routine_a, user: subject)
+ expect(subject.next_routine).to eql(routine_b)
+ end
+
+ it 'returns the first routine in the program' do
+ expect(subject.next_routine).to eql(routine_a)
+ end
+ end
+
+ describe "#last_workout" do
+ include_context "stronglifts_program"
+ subject { create(:user) }
+
+ it 'returns the last workout' do
+ workout = create(:workout, user: subject, routine: routine_a)
+ expect(subject.last_workout).to eql(workout)
+ end
+
+ it 'returns the last workout that included a specific exercise' do
+ deadlift_workout = create(:workout, user: subject, routine: routine_b)
+ deadlift_workout.train(deadlift, 315.lbs, repetitions: 5)
+ bench_workout = create(:workout, user: subject, routine: routine_a)
+ bench_workout.train(bench_press, 195.lbs, repetitions: 5)
+
+ expect(subject.last_workout(deadlift)).to eql(deadlift_workout)
+ end
+
+ it 'returns nil when no workouts have been completed' do
+ expect(subject.last_workout).to be_nil
+ end
+
+ it 'returns nil when the exercise has not been performed' do
+ bench_workout = create(:workout, user: subject, routine: routine_a)
+ bench_workout.train(bench_press, 195.lbs, repetitions: 5)
+
+ expect(subject.last_workout(deadlift)).to be_nil
+ end
+ end
end