Moving the planting predictions to own service

This commit is contained in:
Brenda Wallace
2017-05-29 19:37:32 +12:00
committed by Shiny
parent 479f61b224
commit ff1c835cda
5 changed files with 85 additions and 54 deletions

View File

@@ -136,6 +136,7 @@ end
group :test do
gem 'codeclimate-test-reporter', require: false
gem 'timecop'
end
group :travis do

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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