Commit e67c7c8

mo khan <mo@mokhan.ca>
2016-06-28 19:28:47
increment weight for squat.
1 parent ce0a432
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