Commit 4fe3b12

mo khan <mo@mokhan.ca>
2016-06-30 03:40:32
start to add warmup sets.
1 parent a2a4ad1
app/models/exercise_set.rb
@@ -3,4 +3,15 @@ class ExerciseSet < ActiveRecord::Base
   belongs_to :workout
   scope :for, ->(exercise) { where(exercise: exercise).order(:created_at) }
   scope :successful, -> { where('actual_repetitions = target_repetitions') }
+
+  attr_accessor :type
+  enum type: { work: 'WorkSet', warm_up: 'WarmUpSet' }
+
+  def work?
+    type == :work
+  end
+
+  def warm_up?
+    !work?
+  end
 end
app/models/program.rb
@@ -23,21 +23,8 @@ class Program < ActiveRecord::Base
   end
 
   def prepare_sets_for(user, exercise)
-    recommended_sets_for(user, exercise).times.map do
-      ExerciseSet.new(
-        exercise: exercise,
-        target_repetitions: recommended_reps_for(user, exercise),
-        target_weight: recommendation_for(user, exercise).next_weight
-      )
-    end
-  end
-
-  def recommended_sets_for(user, exercise)
-    recommendation_for(user, exercise).sets
-  end
-
-  def recommended_reps_for(user, exercise)
-    recommendation_for(user, exercise).repetitions
+    recommendation = recommendation_for(user, exercise)
+    recommendation.prepare_sets_for(user, exercise)
   end
 
   def recommendation_for(user, exercise)
app/models/quantity.rb
@@ -18,6 +18,18 @@ class Quantity
     Quantity.new(amount + amount_from(other), unit)
   end
 
+  def >(other)
+    self.amount > amount_from(other)
+  end
+
+  def >=(other)
+    self.>(other) || eql?(other)
+  end
+
+  def <(other)
+    self.amount < amount_from(other)
+  end
+
   def eql?(other, delta = 0.1)
     (self.amount - amount_from(other)).abs <= delta
   end
app/models/user_recommendation.rb
@@ -7,10 +7,37 @@ class UserRecommendation
     @program = program
   end
 
+  def prepare_sets_for(user, exercise)
+    target_weight = next_weight
+    warm_up_sets = []
+    if target_weight >= 65.lbs
+       2.times.map do
+        warm_up_sets << ExerciseSet.new(
+          type: :warm_up,
+          exercise: exercise,
+          target_weight: 45.lbs,
+          #target_repetitions: repetitions,
+        )
+      end
+    end
+    work_sets = sets.times.map do
+      ExerciseSet.new(
+        type: :work,
+        exercise: exercise,
+        target_repetitions: repetitions,
+        target_weight: target_weight
+      )
+    end
+    (warm_up_sets + work_sets).compact
+  end
+
+
   def repetitions
     recommendation.repetitions
   end
 
+  private
+
   def sets
     recommended_sets = user.history_for(exercise).last_target_sets
     recommended_sets > 0 ? recommended_sets : recommendation.sets
@@ -25,8 +52,6 @@ class UserRecommendation
     end
   end
 
-  private
-
   def recommendation
     @recommendation ||= program.recommendations.find_by(exercise: exercise)
   end
app/models/workout.rb
@@ -22,7 +22,7 @@ class Workout < ActiveRecord::Base
       else
         sets.build(
           exercise: exercise,
-          target_repetitions: program.recommended_reps_for(user, exercise)
+          target_repetitions: program.recommendation_for(user, exercise).repetitions
         )
       end
     set.update!(actual_repetitions: repetitions, target_weight: target_weight)
spec/models/program_spec.rb
@@ -21,10 +21,21 @@ describe Program do
     describe "squat" do
       let(:user) { build(:user) }
 
-      it 'returns 5 sets of 5 repetitions' do
+      it 'returns 5 work 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])
+        worksets = sets.find_all { |x| x.work? }
+        expect(worksets.length).to eql(5)
+        expect(worksets.map(&:target_repetitions)).to match_array([5, 5, 5, 5, 5])
+      end
+
+      it 'returns 3 sets of 5 repetitions when the last workout was 3x5' do
+        workout = create(:workout, user: user, routine: routine_a)
+        3.times { workout.train(squat, 45, repetitions: 5) }
+
+        sets = subject.prepare_sets_for(user, squat)
+        worksets = sets.find_all { |x| x.work? }
+        expect(worksets.length).to eql(3)
+        expect(worksets.map(&:target_repetitions)).to match_array([5, 5, 5])
       end
 
       it 'returns the correct exercise for each set' do
@@ -33,7 +44,7 @@ describe Program do
       end
 
       it 'returns 45 lbs for the first workout' do
-        sets = subject.prepare_sets_for(user, squat)
+        sets = subject.prepare_sets_for(user, squat).find_all { |x| x.work? }
         expect(sets.map(&:target_weight).uniq).to match_array([45.lbs])
       end
 
@@ -41,7 +52,7 @@ describe Program do
         workout = create(:workout, user: user, routine: routine_a)
         5.times { workout.train(squat, 45, repetitions: 5) }
 
-        sets = subject.prepare_sets_for(user, squat)
+        sets = subject.prepare_sets_for(user, squat).find_all { |x| x.work? }
         expect(sets.map(&:target_weight).uniq).to match_array([50.lbs])
       end
 
@@ -49,9 +60,43 @@ describe Program do
         workout = create(:workout, user: user, routine: routine_a)
         5.times { |n| workout.train(squat, 45, repetitions: n) }
 
-        sets = subject.prepare_sets_for(user, squat)
+        sets = subject.prepare_sets_for(user, squat).find_all { |x| x.work? }
         expect(sets.map(&:target_weight).uniq).to match_array([45.lbs])
       end
+
+      describe "warmup" do
+        describe "when the workset is less than 65 lbs" do
+          it 'returns zero warmup sets' do
+            sets = subject.prepare_sets_for(user, squat)
+            warmup_sets = sets.find_all { |x| x.warm_up? }
+            expect(warmup_sets.length).to eql(0)
+          end
+        end
+
+        describe "when the work set is between 65 lbs an 95 lbs" do
+          it 'returns two warmup sets' do
+            workout = create(:workout, user: user, routine: routine_a)
+            5.times { |n| workout.train(squat, 65, repetitions: 5) }
+
+            sets = subject.prepare_sets_for(user, squat)
+            warmup_sets = sets.find_all { |x| x.warm_up? }
+            expect(warmup_sets.length).to eql(2)
+            expect(warmup_sets.at(0).target_weight.lbs).to eql(45.lbs)
+            expect(warmup_sets.at(1).target_weight.lbs).to eql(45.lbs)
+          end
+        end
+      end
+    end
+
+    describe "deadlift" do
+      let(:user) { build(:user) }
+
+      it 'returns 1 work set with 5 repetitions' do
+        sets = subject.prepare_sets_for(user, deadlift)
+        worksets = sets.find_all { |x| x.work? }
+        expect(worksets.length).to eql(1)
+        expect(worksets.map(&:target_repetitions)).to match_array([5])
+      end
     end
   end
 end
spec/models/quantity_spec.rb
@@ -79,4 +79,32 @@ describe Quantity do
       expect(quantity + other).to eql(Quantity.new(270.0, :lbs))
     end
   end
+
+  describe "#>" do
+    it 'compares lbs with lbs' do
+      quantity = Quantity.new(135.1, :lbs)
+      other = Quantity.new(135.0, :lbs)
+      expect(quantity).to be > other
+      expect(other).to_not be > quantity
+    end
+  end
+
+  describe "#>=" do
+    it 'compares lbs with lbs' do
+      quantity = Quantity.new(135.2, :lbs)
+      other = Quantity.new(135.0, :lbs)
+      expect(quantity).to be >= quantity
+      expect(quantity).to be >= other
+      expect(other).to_not be >= quantity
+    end
+  end
+
+  describe "#<" do
+    it 'compares lbs with lbs' do
+      quantity = Quantity.new(135.1, :lbs)
+      other = Quantity.new(135.0, :lbs)
+      expect(quantity).to_not be < other
+      expect(other).to be < quantity
+    end
+  end
 end