mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-08 07:43:49 -04:00
Moving the planting predictions to own service
This commit is contained in:
1
Gemfile
1
Gemfile
@@ -136,6 +136,7 @@ end
|
||||
|
||||
group :test do
|
||||
gem 'codeclimate-test-reporter', require: false
|
||||
gem 'timecop'
|
||||
end
|
||||
|
||||
group :travis do
|
||||
|
||||
@@ -482,6 +482,7 @@ GEM
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.7)
|
||||
timecop (0.8.1)
|
||||
tins (1.14.0)
|
||||
trollop (1.16.2)
|
||||
tzinfo (1.2.3)
|
||||
@@ -589,12 +590,12 @@ DEPENDENCIES
|
||||
selenium-webdriver
|
||||
sidekiq
|
||||
sparkpost_rails
|
||||
timecop
|
||||
uglifier (~> 2.7.2)
|
||||
unicorn
|
||||
webrat
|
||||
will_paginate (~> 3.0)
|
||||
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.3.4p301
|
||||
|
||||
|
||||
@@ -91,59 +91,27 @@ class Planting < ActiveRecord::Base
|
||||
photos.first
|
||||
end
|
||||
|
||||
def planted?(current_date = Date.current)
|
||||
planted_at.present? && current_date.to_date >= planted_at
|
||||
def planted?
|
||||
planted_at.present? && planted_at < Date.current
|
||||
end
|
||||
|
||||
def days_until_finished
|
||||
return 0 if finished?
|
||||
days = (finished_at - Date.current).to_i
|
||||
days.positive? ? days : 0
|
||||
PlantingPredictions.new(self).days_until_finished
|
||||
end
|
||||
|
||||
def days_until_mature
|
||||
days = ((planted_at + days_before_maturity) - Date.current).to_i
|
||||
days.positive? ? days : 0
|
||||
PlantingPredictions.new(self).days_until_mature
|
||||
end
|
||||
|
||||
def percentage_grown(current_date = Date.current)
|
||||
return nil unless days_before_maturity && planted?(current_date)
|
||||
|
||||
days = (current_date.to_date - planted_at.to_date).to_i
|
||||
|
||||
return 0 if current_date < planted_at
|
||||
return 100 if days > days_before_maturity
|
||||
percent = (days / days_before_maturity * 100).to_i
|
||||
|
||||
if percent >= 100
|
||||
percent = 100
|
||||
end
|
||||
|
||||
percent
|
||||
def percentage_grown
|
||||
PlantingPredictions.new(self).percentage_grown
|
||||
end
|
||||
|
||||
def start_to_finish_diff
|
||||
(finished_at - planted_at).to_i if finished_at && planted_at
|
||||
end
|
||||
|
||||
def self.mean_days_until_maturity(plantings)
|
||||
## Given a set of finished plantings, calculate the average/mean time from start to finish
|
||||
differences = plantings.collect(&:start_to_finish_diff)
|
||||
differences.compact.sum / differences.compact.size unless differences.compact.empty?
|
||||
PlantingPredictions.new(self).start_to_finish_diff
|
||||
end
|
||||
|
||||
def calc_and_set_days_before_maturity
|
||||
# calculate the number of days, from planted_at, until maturity
|
||||
if planted_at && finished_at
|
||||
self.days_before_maturity = start_to_finish_diff
|
||||
else
|
||||
self.days_before_maturity = Planting.mean_days_until_maturity other_finished_plantings_same_crop
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def other_finished_plantings_same_crop
|
||||
Planting.where(crop_id: crop).where.not(id: id).where.not(finished_at: nil)
|
||||
PlantingPredictions.new(self).calc_and_set_days_before_maturity
|
||||
end
|
||||
end
|
||||
|
||||
59
app/services/planting_predictions.rb
Normal file
59
app/services/planting_predictions.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
class PlantingPredictions
|
||||
def initialize(planting)
|
||||
@planting = planting
|
||||
end
|
||||
|
||||
def days_until_finished
|
||||
return 0 if @planting.finished?
|
||||
days = (@planting.finished_at - Date.current).to_i
|
||||
days.positive? ? days : 0
|
||||
end
|
||||
|
||||
def days_until_mature
|
||||
days = ((@planting.planted_at + @planting.days_before_maturity) - Date.current).to_i
|
||||
days.positive? ? days : 0
|
||||
end
|
||||
|
||||
def percentage_grown
|
||||
current_date = Date.current
|
||||
return nil unless @planting.days_before_maturity && @planting.planted?
|
||||
|
||||
days = (current_date.to_date - @planting.planted_at.to_date).to_i
|
||||
|
||||
return 0 if current_date < @planting.planted_at
|
||||
return 100 if days > @planting.days_before_maturity
|
||||
percent = (days / @planting.days_before_maturity * 100).to_i
|
||||
|
||||
percent = 100 if percent >= 100
|
||||
|
||||
percent
|
||||
end
|
||||
|
||||
def start_to_finish_diff
|
||||
(@planting.finished_at - @planting.planted_at).to_i if @planting.finished_at && @planting.planted_at
|
||||
end
|
||||
|
||||
def calc_and_set_days_before_maturity
|
||||
# calculate the number of days, from planted_at, until maturity
|
||||
if @planting.planted_at && @planting.finished_at
|
||||
@planting.days_before_maturity = start_to_finish_diff
|
||||
else
|
||||
plantings = other_finished_plantings_same_crop
|
||||
@planting.days_before_maturity = PlantingPredictions.mean_days_until_maturity(plantings)
|
||||
end
|
||||
end
|
||||
|
||||
def self.mean_days_until_maturity(plantings)
|
||||
## Given a set of finished plantings, calculate the average/mean time from start to finish
|
||||
differences = plantings.collect(&:start_to_finish_diff)
|
||||
differences.compact.sum / differences.compact.size unless differences.compact.empty?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def other_finished_plantings_same_crop
|
||||
Planting.where(crop_id: @planting.crop.id)
|
||||
.where.not(id: @planting.id)
|
||||
.where.not(finished_at: nil)
|
||||
end
|
||||
end
|
||||
@@ -20,9 +20,13 @@ describe Planting do
|
||||
8.times { FactoryGirl.create :planting, crop: crop, finished_at: nil }
|
||||
end
|
||||
let!(:planting_with_diff_crop) { FactoryGirl.create :planting, planted_at: 10.days.ago, finished_at: 2.days.ago }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop).size).to eq(8) }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop)).not_to include(planting) }
|
||||
it { expect(planting.send(:other_finished_plantings_same_crop)).not_to include(planting_with_diff_crop) }
|
||||
let(:planting_predictions) { PlantingPredictions.new(planting) }
|
||||
it { expect(planting_predictions.send(:other_finished_plantings_same_crop).size).to eq(8) }
|
||||
it { expect(planting_predictions.send(:other_finished_plantings_same_crop)).not_to include(planting) }
|
||||
it do
|
||||
expect(planting_predictions.send(:other_finished_plantings_same_crop))
|
||||
.not_to include(planting_with_diff_crop)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'mean_days_until_maturity' do
|
||||
@@ -30,7 +34,7 @@ describe Planting do
|
||||
FactoryGirl.create_list(:planting, 10, crop: crop, planted_at: 12.days.ago, finished_at: 2.days.ago)
|
||||
end
|
||||
it { expect(plantings.size).to eq(10) }
|
||||
it { expect(Planting.mean_days_until_maturity(plantings)).to eq(10) }
|
||||
it { expect(PlantingPredictions.mean_days_until_maturity(plantings)).to eq(10) }
|
||||
end
|
||||
|
||||
describe 'saving planting calculates days_before_maturity' do
|
||||
@@ -88,23 +92,22 @@ describe Planting do
|
||||
it 'should not be more than 100%' do
|
||||
@planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago)
|
||||
|
||||
now_later_than_planting = 2.days.from_now
|
||||
|
||||
@planting.percentage_grown(now_later_than_planting).should be 100
|
||||
Timecop.freeze(2.days.from_now) do
|
||||
@planting.percentage_grown.should be 100
|
||||
end
|
||||
end
|
||||
|
||||
it 'should not be less than 0%' do
|
||||
@planting = FactoryGirl.build(:planting, days_before_maturity: 1, planted_at: 1.day.ago)
|
||||
|
||||
now_earlier_than_planting = 2.days.ago
|
||||
|
||||
@planting.percentage_grown(now_earlier_than_planting).should be nil
|
||||
Timecop.freeze(2.days.ago) do
|
||||
@planting.percentage_grown.should be nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'should reflect the current growth' do
|
||||
@planting = FactoryGirl.build(:planting, days_before_maturity: 10, planted_at: 4.days.ago)
|
||||
|
||||
expect(@planting.percentage_grown(Date.current)).to eq 40
|
||||
expect(@planting.percentage_grown).to eq 40
|
||||
end
|
||||
|
||||
it 'should not be calculated for unplanted plantings' do
|
||||
@@ -116,7 +119,6 @@ describe Planting do
|
||||
|
||||
it 'should not be calculated for plantings with an unknown days before maturity' do
|
||||
@planting = FactoryGirl.build(:planting, days_before_maturity: nil)
|
||||
|
||||
@planting.percentage_grown.should be nil
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user