nutrition_calculator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +33 -0
- data/Rakefile +23 -0
- data/features/calorie_budgeter.feature +181 -0
- data/features/step_definitions/.keep +0 -0
- data/features/step_definitions/calorie_budgeter_steps.rb +39 -0
- data/features/support/.keep +0 -0
- data/features/support/helper_methods.rb +18 -0
- data/lib/nutrition_calculator/cached_outputs_with_recalculation.rb +126 -0
- data/lib/nutrition_calculator/calorie_budgeter.rb +158 -0
- data/lib/nutrition_calculator/has_logging.rb +40 -0
- data/lib/nutrition_calculator/version.rb +3 -0
- data/lib/nutrition_calculator.rb +5 -0
- data/nutrition_calculator.gemspec +31 -0
- data/spec/nutrition_calculator/cached_outputs_with_recalculation_spec.rb +51 -0
- data/spec/nutrition_calculator/calorie_budgeter_spec.rb +236 -0
- data/spec/nutrition_calculator_spec.rb +7 -0
- data/spec/spec_helper.rb +7 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb7c8df58d699d0f69ba05ba196c2ffe55f1976e
|
4
|
+
data.tar.gz: d3185d82f8c2dd202a37a6e17e5ce4a05978840b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b1e6934c01fe8b9586d8b6e2bb88d9d7400f2fe8f1993eac742f19beb7014ea17ef694cb91705c6ddac4280f64306cc2fc2abca551e44b3d3dd2a5c8b7c8409a
|
7
|
+
data.tar.gz: e195e994cb4700b66cbb827ab32f6578b88f113a3884c6e4f120139fc92de83f0f6d5ba2994cd08f57bc523d6cb5cbdccd22c90a49d2e6cd714673a6780ea3fc
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.5
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 John Wilger
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# NutritionCalculator
|
2
|
+
|
3
|
+
NutritionCalculator provides a set of core libraries to help track a
|
4
|
+
person's individual nutritional goals. It is meant to aid in both
|
5
|
+
weight-management and monitoring the nutritional balance of a diet.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'nutrition_calculator'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install nutrition_calculator
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
See {NutritionCalculator::CalorieBudgeter}
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
1. Fork it ( https://github.com/[my-github-username]/nutrition_calculator/fork )
|
30
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
33
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "cucumber/rake/task"
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
desc "Run all cucumber features"
|
8
|
+
task :features => 'features:default'
|
9
|
+
|
10
|
+
namespace :features do
|
11
|
+
task :default => %w(wip ok)
|
12
|
+
|
13
|
+
Cucumber::Rake::Task.new(:wip) do |t|
|
14
|
+
t.cucumber_opts = "-t @wip"
|
15
|
+
end
|
16
|
+
|
17
|
+
Cucumber::Rake::Task.new(:ok) do |t|
|
18
|
+
t.cucumber_opts = "-t ~@wip -t ~@pending -q --format progress"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => %w(spec features)
|
23
|
+
|
@@ -0,0 +1,181 @@
|
|
1
|
+
Feature: Calculate Remaining Daily Calories
|
2
|
+
|
3
|
+
So that I know how much more I should eat today in order to hit my weekly calorie goal,
|
4
|
+
As a dieter,
|
5
|
+
I want to see my remaining calories for the day, taking into account what I have already consumed this week
|
6
|
+
|
7
|
+
Scenario Outline: Maintain Weight
|
8
|
+
Given my RMR is <daily_rmr> calories per day
|
9
|
+
And my weekly calorie goal is <weekly_goal> calories
|
10
|
+
And I have consumed <prev_days_cal> net calories on prior days this week
|
11
|
+
And it is the <day> day of the week
|
12
|
+
And I have consumed <consumed> calories today
|
13
|
+
And I have burned <burned> calories with exercise today
|
14
|
+
|
15
|
+
When I calculate my remaining calories for the day
|
16
|
+
|
17
|
+
Then I see that my net calorie consumption for the day is <net>
|
18
|
+
And I see that I should consume <remaining> more calories today
|
19
|
+
And I see that I should burn <to_burn> more calories by exercising today
|
20
|
+
|
21
|
+
Examples: RMR 1500
|
22
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
23
|
+
| 1500 | 10500 | 0 | 1st | 0 | 0 | 0 | 1500 | 0 |
|
24
|
+
| 1500 | 10500 | 0 | 1st | 500 | 0 | 500 | 1000 | 0 |
|
25
|
+
| 1500 | 10500 | 0 | 1st | 1500 | 0 | 1500 | 0 | 0 |
|
26
|
+
| 1500 | 10500 | 0 | 1st | 1501 | 0 | 1501 | 0 | 1 |
|
27
|
+
|
28
|
+
Examples: RMR 1500 - with exercise
|
29
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
30
|
+
| 1500 | 10500 | 0 | 1st | 0 | 100 | -100 | 1600 | 0 |
|
31
|
+
| 1500 | 10500 | 0 | 1st | 500 | 100 | 400 | 1100 | 0 |
|
32
|
+
| 1500 | 10500 | 0 | 1st | 1600 | 100 | 1500 | 0 | 0 |
|
33
|
+
| 1500 | 10500 | 0 | 1st | 1601 | 100 | 1501 | 0 | 1 |
|
34
|
+
|
35
|
+
Examples: RMR 1500 - 2nd day of week
|
36
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
37
|
+
| 1500 | 10500 | 1500 | 2nd | 0 | 0 | 0 | 1500 | 0 |
|
38
|
+
| 1500 | 10500 | 1503 | 2nd | 0 | 0 | 0 | 1500 | 0 |
|
39
|
+
| 1500 | 10500 | 1504 | 2nd | 0 | 0 | 0 | 1500 | 1 |
|
40
|
+
| 1500 | 10500 | 1504 | 2nd | 500 | 100 | 400 | 1099 | 0 |
|
41
|
+
| 1500 | 10500 | 1504 | 2nd | 1500 | 0 | 1500 | 0 | 1 |
|
42
|
+
| 1500 | 10500 | 1504 | 2nd | 1600 | 100 | 1500 | 0 | 1 |
|
43
|
+
|
44
|
+
Examples: RMR 2000
|
45
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
46
|
+
| 2000 | 14000 | 0 | 1st | 0 | 0 | 0 | 2000 | 0 |
|
47
|
+
| 2000 | 14000 | 0 | 1st | 500 | 0 | 500 | 1500 | 0 |
|
48
|
+
| 2000 | 14000 | 0 | 1st | 2000 | 0 | 2000 | 0 | 0 |
|
49
|
+
| 2000 | 14000 | 0 | 1st | 2001 | 0 | 2001 | 0 | 1 |
|
50
|
+
|
51
|
+
Examples: RMR 2000 - with exercise
|
52
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
53
|
+
| 2000 | 14000 | 0 | 1st | 0 | 100 | -100 | 2100 | 0 |
|
54
|
+
| 2000 | 14000 | 0 | 1st | 500 | 100 | 400 | 1600 | 0 |
|
55
|
+
| 2000 | 14000 | 0 | 1st | 2100 | 100 | 2000 | 0 | 0 |
|
56
|
+
| 2000 | 14000 | 0 | 1st | 2101 | 100 | 2001 | 0 | 1 |
|
57
|
+
|
58
|
+
Examples: RMR 2000 - 2nd day of week
|
59
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
60
|
+
| 2000 | 14000 | 1997 | 2nd | 0 | 0 | 0 | 2001 | 0 |
|
61
|
+
| 2000 | 14000 | 1998 | 2nd | 0 | 0 | 0 | 2000 | 0 |
|
62
|
+
| 2000 | 14000 | 2000 | 2nd | 0 | 0 | 0 | 2000 | 0 |
|
63
|
+
| 2000 | 14000 | 2003 | 2nd | 0 | 0 | 0 | 2000 | 0 |
|
64
|
+
# must consume at lease RMR every day and you should exercise off the overage
|
65
|
+
| 2000 | 14000 | 2004 | 2nd | 0 | 0 | 0 | 2000 | 1 |
|
66
|
+
| 2000 | 14000 | 2004 | 2nd | 500 | 100 | 400 | 1599 | 0 |
|
67
|
+
| 2000 | 14000 | 2004 | 2nd | 2000 | 0 | 2000 | 0 | 1 |
|
68
|
+
| 2000 | 14000 | 2004 | 2nd | 2100 | 100 | 2000 | 0 | 1 |
|
69
|
+
|
70
|
+
Examples: 3rd day of week
|
71
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
72
|
+
| 2000 | 14000 | 3997 | 3rd | 0 | 0 | 0 | 2001 | 0 |
|
73
|
+
| 2000 | 14000 | 3998 | 3rd | 0 | 0 | 0 | 2000 | 0 |
|
74
|
+
| 2000 | 14000 | 4000 | 3rd | 0 | 0 | 0 | 2000 | 0 |
|
75
|
+
| 2000 | 14000 | 4002 | 3rd | 0 | 0 | 0 | 2000 | 0 |
|
76
|
+
| 2000 | 14000 | 4003 | 3rd | 0 | 0 | 0 | 2000 | 1 |
|
77
|
+
|
78
|
+
Examples: 4th day of week
|
79
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
80
|
+
| 2000 | 14000 | 5998 | 4th | 0 | 0 | 0 | 2001 | 0 |
|
81
|
+
| 2000 | 14000 | 5999 | 4th | 0 | 0 | 0 | 2000 | 0 |
|
82
|
+
| 2000 | 14000 | 6000 | 4th | 0 | 0 | 0 | 2000 | 0 |
|
83
|
+
| 2000 | 14000 | 6002 | 4th | 0 | 0 | 0 | 2000 | 0 |
|
84
|
+
| 2000 | 14000 | 6003 | 4th | 0 | 0 | 0 | 2000 | 1 |
|
85
|
+
|
86
|
+
Examples: 5th day of week
|
87
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
88
|
+
| 2000 | 14000 | 7998 | 5th | 0 | 0 | 0 | 2001 | 0 |
|
89
|
+
| 2000 | 14000 | 7999 | 5th | 0 | 0 | 0 | 2000 | 0 |
|
90
|
+
| 2000 | 14000 | 8000 | 5th | 0 | 0 | 0 | 2000 | 0 |
|
91
|
+
| 2000 | 14000 | 8001 | 5th | 0 | 0 | 0 | 2000 | 0 |
|
92
|
+
| 2000 | 14000 | 8002 | 5th | 0 | 0 | 0 | 2000 | 1 |
|
93
|
+
|
94
|
+
Examples: 6th day of week
|
95
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
96
|
+
| 2000 | 14000 | 9997 | 6th | 0 | 0 | 0 | 2002 | 0 |
|
97
|
+
| 2000 | 14000 | 9998 | 6th | 0 | 0 | 0 | 2001 | 0 |
|
98
|
+
| 2000 | 14000 | 9999 | 6th | 0 | 0 | 0 | 2001 | 0 |
|
99
|
+
| 2000 | 14000 | 10000 | 6th | 0 | 0 | 0 | 2000 | 0 |
|
100
|
+
| 2000 | 14000 | 10001 | 6th | 0 | 0 | 0 | 2000 | 0 |
|
101
|
+
| 2000 | 14000 | 10002 | 6th | 0 | 0 | 0 | 2000 | 1 |
|
102
|
+
|
103
|
+
Examples: 7th day of week
|
104
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
105
|
+
| 2000 | 14000 | 11999 | 7th | 0 | 0 | 0 | 2001 | 0 |
|
106
|
+
| 2000 | 14000 | 12000 | 7th | 0 | 0 | 0 | 2000 | 0 |
|
107
|
+
| 2000 | 14000 | 12001 | 7th | 0 | 0 | 0 | 2000 | 1 |
|
108
|
+
|
109
|
+
Scenario Outline: Lose Weight - must consume at least RMR daily
|
110
|
+
Given my RMR is <daily_rmr> calories per day
|
111
|
+
And my weekly calorie goal is <weekly_goal> calories
|
112
|
+
And I have consumed <prev_days_cal> net calories on prior days this week
|
113
|
+
And it is the <day> day of the week
|
114
|
+
And I have consumed <consumed> calories today
|
115
|
+
And I have burned <burned> calories with exercise today
|
116
|
+
|
117
|
+
When I calculate my remaining calories for the day
|
118
|
+
|
119
|
+
Then I see that my net calorie consumption for the day is <net>
|
120
|
+
And I see that I should consume <remaining> more calories today
|
121
|
+
And I see that I should burn <to_burn> more calories by exercising today
|
122
|
+
|
123
|
+
Examples: RMR 2000
|
124
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
125
|
+
| 2000 | 10500 | 0 | 1st | 0 | 0 | 0 | 2000 | 500 |
|
126
|
+
| 2000 | 10500 | 0 | 1st | 500 | 0 | 500 | 1500 | 500 |
|
127
|
+
| 2000 | 10500 | 0 | 1st | 2000 | 0 | 2000 | 0 | 500 |
|
128
|
+
| 2000 | 10500 | 0 | 1st | 2001 | 0 | 2001 | 0 | 501 |
|
129
|
+
|
130
|
+
Examples: RMR 2000 - with exercise
|
131
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
132
|
+
| 2000 | 10500 | 0 | 1st | 0 | 100 | -100 | 2000 | 400 |
|
133
|
+
| 2000 | 10500 | 0 | 1st | 500 | 100 | 400 | 1500 | 400 |
|
134
|
+
| 2000 | 10500 | 0 | 1st | 2100 | 100 | 2000 | 0 | 500 |
|
135
|
+
| 2000 | 10500 | 0 | 1st | 2101 | 100 | 2001 | 0 | 501 |
|
136
|
+
| 2000 | 10500 | 0 | 1st | 2000 | 500 | 1500 | 0 | 0 |
|
137
|
+
| 2000 | 10500 | 0 | 1st | 0 | 500 | -500 | 2000 | 0 |
|
138
|
+
|
139
|
+
Examples: 3rd day of week
|
140
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
141
|
+
| 2000 | 10500 | 3000 | 3rd | 0 | 0 | 0 | 2000 | 500 |
|
142
|
+
| 2000 | 10500 | 3997 | 3rd | 0 | 0 | 0 | 2000 | 699 |
|
143
|
+
| 2000 | 10500 | 3998 | 3rd | 0 | 0 | 0 | 2000 | 700 |
|
144
|
+
| 2000 | 10500 | 4000 | 3rd | 0 | 0 | 0 | 2000 | 700 |
|
145
|
+
| 2000 | 10500 | 4002 | 3rd | 0 | 0 | 0 | 2000 | 700 |
|
146
|
+
| 2000 | 10500 | 4003 | 3rd | 0 | 0 | 0 | 2000 | 701 |
|
147
|
+
| 2000 | 10500 | 4000 | 3rd | 2000 | 0 | 2000 | 0 | 700 |
|
148
|
+
| 2000 | 10500 | 4000 | 3rd | 2000 | 700 | 1300 | 0 | 0 |
|
149
|
+
|
150
|
+
Scenario Outline: Gain Weight
|
151
|
+
Given my RMR is <daily_rmr> calories per day
|
152
|
+
And my weekly calorie goal is <weekly_goal> calories
|
153
|
+
And I have consumed <prev_days_cal> net calories on prior days this week
|
154
|
+
And it is the <day> day of the week
|
155
|
+
And I have consumed <consumed> calories today
|
156
|
+
And I have burned <burned> calories with exercise today
|
157
|
+
|
158
|
+
When I calculate my remaining calories for the day
|
159
|
+
|
160
|
+
Then I see that my net calorie consumption for the day is <net>
|
161
|
+
And I see that I should consume <remaining> more calories today
|
162
|
+
And I see that I should burn <to_burn> more calories by exercising today
|
163
|
+
|
164
|
+
Examples: RMR 2000
|
165
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
166
|
+
| 2000 | 17500 | 0 | 1st | 0 | 0 | 0 | 2500 | 0 |
|
167
|
+
| 2000 | 17500 | 0 | 1st | 500 | 0 | 500 | 2000 | 0 |
|
168
|
+
| 2000 | 17500 | 0 | 1st | 2500 | 0 | 2500 | 0 | 0 |
|
169
|
+
| 2000 | 17500 | 0 | 1st | 2501 | 0 | 2501 | 0 | 1 |
|
170
|
+
|
171
|
+
Examples: RMR 2000 - with exercise
|
172
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
173
|
+
| 2000 | 17500 | 0 | 1st | 0 | 500 | -500 | 3000 | 0 |
|
174
|
+
| 2000 | 17500 | 0 | 1st | 2500 | 500 | 2000 | 500 | 0 |
|
175
|
+
| 2000 | 17500 | 0 | 1st | 3001 | 500 | 2501 | 0 | 1 |
|
176
|
+
|
177
|
+
Examples: 3rd day of week
|
178
|
+
| daily_rmr | weekly_goal | prev_days_cal | day | consumed | burned | net | remaining | to_burn |
|
179
|
+
| 2000 | 17500 | 4997 | 3rd | 0 | 0 | 0 | 2501 | 0 |
|
180
|
+
| 2000 | 17500 | 5000 | 3rd | 0 | 0 | 0 | 2500 | 0 |
|
181
|
+
| 2000 | 17500 | 5003 | 3rd | 0 | 0 | 0 | 2499 | 0 |
|
File without changes
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Given(/^my RMR is (\d+) calories per day$/) do |rmr|
|
2
|
+
inputs.resting_metabolic_rate = rmr.to_i
|
3
|
+
end
|
4
|
+
|
5
|
+
Given(/^my weekly calorie goal is (\d+) calories$/) do |cals|
|
6
|
+
inputs.weekly_calorie_goal = cals.to_i
|
7
|
+
end
|
8
|
+
|
9
|
+
Given(/^I have consumed (\d+) net calories on prior days this week$/) do |cals|
|
10
|
+
inputs.prior_days_calories = cals.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
Given(/^it is the (\d+)(st|nd|rd|th) day of the week$/) do |day, _|
|
14
|
+
inputs.current_day_of_week = day.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
Given(/^I have consumed (\d+) calories today$/) do |cals|
|
18
|
+
inputs.calories_consumed = cals.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
Given(/^I have burned (\d+) calories with exercise today$/) do |cals|
|
22
|
+
inputs.calories_burned = cals.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
When(/^I calculate my remaining calories for the day$/) do
|
26
|
+
calculate_remaining_calories
|
27
|
+
end
|
28
|
+
|
29
|
+
Then(/^I see that my net calorie consumption for the day is (\-?\d+)$/) do |cals|
|
30
|
+
expect(outputs.net_calorie_consumption).to eq cals.to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
Then(/^I see that I should consume (\d+) more calories today$/) do |cals|
|
34
|
+
expect(outputs.calories_remaining).to eq cals.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
Then(/^I see that I should burn (\d+) more calories by exercising today$/) do |cals|
|
38
|
+
expect(outputs.exercise_calories_remaining).to eq cals.to_i
|
39
|
+
end
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'nutrition_calculator/calorie_budgeter'
|
2
|
+
|
3
|
+
def inputs
|
4
|
+
@inputs ||= NutritionCalculator::CalorieBudgeter.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def calculate_remaining_calories
|
8
|
+
# Uncomment the following line if you need debugging output
|
9
|
+
# inputs.logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def outputs
|
13
|
+
inputs
|
14
|
+
end
|
15
|
+
|
16
|
+
def logger
|
17
|
+
Logger.new(STDERR)
|
18
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'nutrition_calculator/has_logging'
|
2
|
+
|
3
|
+
module NutritionCalculator
|
4
|
+
|
5
|
+
# Define an object that turns inputs into outputs. With Caching! And Logging!
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class Foo
|
9
|
+
# extend NutritionCalculator::CachedOutputsWithRecalculation
|
10
|
+
#
|
11
|
+
# def_input :bar
|
12
|
+
#
|
13
|
+
# def_output :baz do
|
14
|
+
# bar.expensive_operation
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# x = Foo.new
|
19
|
+
#
|
20
|
+
# x.baz
|
21
|
+
# #=> Raises a RuntimeError because input bar was not set
|
22
|
+
#
|
23
|
+
# a_thing = ExpensiveObject.new
|
24
|
+
#
|
25
|
+
# x.bar = a_thing
|
26
|
+
# x.baz
|
27
|
+
# #=> result of `a_thing.expensive_operation`
|
28
|
+
#
|
29
|
+
# # `a_thing.expensive_operation` will not be called again
|
30
|
+
# x.baz
|
31
|
+
# #=> cached result of `a_thing.expensive_operation`
|
32
|
+
#
|
33
|
+
# # `a_thing.expensive_operation` will be called again since input is
|
34
|
+
# # reassigned
|
35
|
+
# x.bar = a_thing
|
36
|
+
# x.baz
|
37
|
+
# #=> result of `a_thing.expensive_operation`
|
38
|
+
#
|
39
|
+
module CachedOutputsWithRecalculation
|
40
|
+
# @private
|
41
|
+
def self.extended(other)
|
42
|
+
other.include(InstanceMethods)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Defines accessors for the named attribute
|
46
|
+
#
|
47
|
+
# Assignment to the named accessor will cause all cached results to be
|
48
|
+
# recalculated the next time they are called.
|
49
|
+
#
|
50
|
+
# @param name [Symbol]
|
51
|
+
def def_input(name)
|
52
|
+
def_input_writer name
|
53
|
+
def_input_reader name
|
54
|
+
end
|
55
|
+
|
56
|
+
# Defines attribute reader methods for the specified calculation
|
57
|
+
#
|
58
|
+
# The result of the block is cached as long as no inputs are re-assigned
|
59
|
+
# after the attribute reader is called. Additionaly, if `#logger` is set,
|
60
|
+
# the result of the calculation will be sent to the DEBUG log when the block
|
61
|
+
# is run.
|
62
|
+
#
|
63
|
+
# @param name [Symbol]
|
64
|
+
# @param block [Proc] will be `instance_eval`ed in the Object as though it
|
65
|
+
# were the body of a regular method
|
66
|
+
def def_output(name, &block)
|
67
|
+
define_method(name) do
|
68
|
+
cache_and_debug(name, &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def def_input_writer(name)
|
75
|
+
define_method("#{name}=") do |value|
|
76
|
+
recalculate!
|
77
|
+
instance_variable_set("@#{name}", value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def def_input_reader(name)
|
82
|
+
define_method(name) do
|
83
|
+
require_input name
|
84
|
+
instance_variable_get("@#{name}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module InstanceMethods
|
89
|
+
include HasLogging
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def cached_values
|
94
|
+
@cached_values ||= {}
|
95
|
+
end
|
96
|
+
|
97
|
+
def recalculate!
|
98
|
+
logger.debug "Input received; clearing cached calculations."
|
99
|
+
@cached_values = {}
|
100
|
+
end
|
101
|
+
|
102
|
+
def cache(name, &block)
|
103
|
+
cached_values.fetch(name) do
|
104
|
+
cached_values[name] = block.call
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def require_input(name)
|
109
|
+
unless instance_variable_defined?("@#{name}")
|
110
|
+
raise RuntimeError, "Required input missing: `#{name}`."
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def cache_and_debug(name, &block)
|
115
|
+
cache(name) do
|
116
|
+
run_and_debug(name, &block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def run_and_debug(name, &block)
|
121
|
+
debug_value(name) { instance_eval &block }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
private_constant :InstanceMethods
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'nutrition_calculator/cached_outputs_with_recalculation'
|
2
|
+
|
3
|
+
module NutritionCalculator
|
4
|
+
# Calculates Calorie Budget Per Day in Weekly Context
|
5
|
+
#
|
6
|
+
# The `NutritionCalculator::CalorieBudgeter` is used to determine how many
|
7
|
+
# calories you need to consume and how many calories you need to burn via
|
8
|
+
# exercise for a given day in order to stay on target with your diet. In
|
9
|
+
# particular, it ensures that you consume at least enough to satisfy your
|
10
|
+
# resting metabolic rate each day, even if that means you need to burn off
|
11
|
+
# calories via exercise to keep on track. It operates on a weekly basis,
|
12
|
+
# so if you are over-/under-budget on a given day, the goals for the
|
13
|
+
# remainder of the week will be adjusted accordingly.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# cb = NutritionCalculator::CalorieBudgeter.new
|
17
|
+
#
|
18
|
+
# cb.resting_metabolic_rate = 2_000 # calories per day
|
19
|
+
# cb.weekly_calorie_goal = 10_500 # creates an average deficit of 500 calories/day
|
20
|
+
# cb.current_day_of_week = 3 # if your week starts on Monday, this would be Wednesday
|
21
|
+
# cb.prior_days_calories = 3_524 # net calories from Monday and Tuesday
|
22
|
+
#
|
23
|
+
# cb.calories_consumed = 0
|
24
|
+
# cb.calories_burned = 0
|
25
|
+
#
|
26
|
+
# cb.calories_remaining
|
27
|
+
# #=> 2_000
|
28
|
+
#
|
29
|
+
# cb.exercise_calories_remaining
|
30
|
+
# #=> 605
|
31
|
+
#
|
32
|
+
# cb.calories_consumed = 681 # total calories consumed today
|
33
|
+
# cb.calories_burned = 1752
|
34
|
+
#
|
35
|
+
# cb.calories_remaining
|
36
|
+
# #=> 2_466
|
37
|
+
#
|
38
|
+
# cb.exercise_calories_remaining
|
39
|
+
# #=> 0
|
40
|
+
class CalorieBudgeter
|
41
|
+
extend CachedOutputsWithRecalculation
|
42
|
+
|
43
|
+
# @!group Inputs
|
44
|
+
|
45
|
+
# @!attribute
|
46
|
+
# @return [Integer] The daily resting metabolic rate in calories
|
47
|
+
def_input :resting_metabolic_rate
|
48
|
+
|
49
|
+
# @!attribute
|
50
|
+
# @return [Integer] The total net calories (consumed - burned) planned for
|
51
|
+
# the week
|
52
|
+
def_input :weekly_calorie_goal
|
53
|
+
|
54
|
+
# @!attribute
|
55
|
+
# @return [Integer] The total net calories from all days this week prior
|
56
|
+
# to the current day
|
57
|
+
# @example
|
58
|
+
# If it is currently Wednesday
|
59
|
+
# And on Monday you consumed 100 calories and burned 75 for a net of 25
|
60
|
+
# And on Tuesday you consumed 200 calories and burned 100 for a net of 100
|
61
|
+
# Then you don't care about today's calories
|
62
|
+
# And the value for this input should be 125 (Monday + Tuesday)
|
63
|
+
def_input :prior_days_calories
|
64
|
+
|
65
|
+
# @!attribute
|
66
|
+
# @return [Integer] The number of the day of the week
|
67
|
+
# @example If you start your week on Monday
|
68
|
+
# 1 - Monday
|
69
|
+
# 2 - Tuesday
|
70
|
+
# 3 - Wednesday
|
71
|
+
# 4 - Thursday
|
72
|
+
# 5 - Friday
|
73
|
+
# 6 - Saturday
|
74
|
+
# 7 - Sunday
|
75
|
+
def_input :current_day_of_week
|
76
|
+
|
77
|
+
# @!attribute
|
78
|
+
# @return [Integer] The total number of calories consumed today
|
79
|
+
def_input :calories_consumed
|
80
|
+
|
81
|
+
# @!attribute
|
82
|
+
# @return [Integer] The total number of calories burned via exercise today
|
83
|
+
def_input :calories_burned
|
84
|
+
|
85
|
+
# @!group Outputs
|
86
|
+
|
87
|
+
# @!attribute [r]
|
88
|
+
# @return [Integer] The net calories for the day (consumed - burned via
|
89
|
+
# exercise)
|
90
|
+
def_output :net_calorie_consumption do
|
91
|
+
calories_consumed - calories_burned
|
92
|
+
end
|
93
|
+
|
94
|
+
# @!attribute [r]
|
95
|
+
# @return [Integer] The number of calories remaining to consume today
|
96
|
+
def_output :calories_remaining do
|
97
|
+
[0, remaining_to_target].max
|
98
|
+
end
|
99
|
+
|
100
|
+
# @!attribute [r]
|
101
|
+
# @return [Integer] The number of calories that must still be burned today
|
102
|
+
# in order to meet the daily calorie goal
|
103
|
+
def_output :exercise_calories_remaining do
|
104
|
+
[0, predicted_overage].max
|
105
|
+
end
|
106
|
+
|
107
|
+
# @!attribute [r]
|
108
|
+
# @return [Integer] The number of calories that will likely be consumed
|
109
|
+
# today (the greater of actual consumption or target
|
110
|
+
# consumption).
|
111
|
+
def_output :predicted_calorie_consumption do
|
112
|
+
[target_daily_calorie_consumption, calories_consumed].max
|
113
|
+
end
|
114
|
+
|
115
|
+
# @!attribute [r]
|
116
|
+
# @return [Integer] The number of calories consumed (or predicted to be
|
117
|
+
# consumed) that is greater than the daily calorie goal
|
118
|
+
# and not yet burned off via exercise
|
119
|
+
def_output :predicted_overage do
|
120
|
+
predicted_calorie_consumption - daily_calorie_goal - calories_burned
|
121
|
+
end
|
122
|
+
|
123
|
+
# @!attribute [r]
|
124
|
+
# @return [Integer] The number of calories that must still be consumed to
|
125
|
+
# hit the day's target
|
126
|
+
def_output :remaining_to_target do
|
127
|
+
target_daily_calorie_consumption - calories_consumed
|
128
|
+
end
|
129
|
+
|
130
|
+
# @!attribute [r]
|
131
|
+
# @return [Integer] The number of calories that should be consumed today
|
132
|
+
def_output :target_daily_calorie_consumption do
|
133
|
+
[(daily_calorie_goal + calories_burned), resting_metabolic_rate].max
|
134
|
+
end
|
135
|
+
|
136
|
+
# @!attribute [r]
|
137
|
+
# @return [Integer] The number of net calories that should be consumed today
|
138
|
+
# to meet the weekly calorie goal
|
139
|
+
def_output :daily_calorie_goal do
|
140
|
+
(remaining_calories_this_week.to_f / remaining_days_of_week).round
|
141
|
+
end
|
142
|
+
|
143
|
+
# @!attribute [r]
|
144
|
+
# @return [Integer] The number of calories left in the calorie budget for
|
145
|
+
# the current week (does not include calories consumed
|
146
|
+
# today)
|
147
|
+
def_output :remaining_calories_this_week do
|
148
|
+
weekly_calorie_goal - prior_days_calories
|
149
|
+
end
|
150
|
+
|
151
|
+
# @!attribute [r]
|
152
|
+
# @return [Integer] The number of days remaining in the week, including the
|
153
|
+
# current day
|
154
|
+
def_output :remaining_days_of_week do
|
155
|
+
8 - current_day_of_week
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module NutritionCalculator
|
4
|
+
# Provides a few logging utilities to the including class/module
|
5
|
+
module HasLogging
|
6
|
+
module NullLogger
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def noop(*args); args; end
|
10
|
+
alias_method :error, :noop
|
11
|
+
alias_method :warn, :noop
|
12
|
+
alias_method :info, :noop
|
13
|
+
alias_method :debug, :noop
|
14
|
+
end
|
15
|
+
private_constant :NullLogger
|
16
|
+
|
17
|
+
attr_writer :logger
|
18
|
+
|
19
|
+
# The logger to which the including class/module should write
|
20
|
+
#
|
21
|
+
# Defaults to a NullLogger, which simply discards all logging attempts as
|
22
|
+
# noops.
|
23
|
+
#
|
24
|
+
# @return [Logger] an object adhering to the Logger interface
|
25
|
+
def logger
|
26
|
+
@logger ||= NullLogger
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
# Executes the block and both logs and returns the result
|
32
|
+
#
|
33
|
+
# @return [block.call] The result of calling the block provided
|
34
|
+
def debug_value(name, &block)
|
35
|
+
block.call.tap do |value|
|
36
|
+
logger.debug("#{name}: #{value}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nutrition_calculator/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "nutrition_calculator"
|
8
|
+
spec.version = NutritionCalculator::VERSION
|
9
|
+
spec.authors = ["John Wilger"]
|
10
|
+
spec.email = ["johnwilger@gmail.com"]
|
11
|
+
spec.summary = %q{Nutrition calculators for diet management}
|
12
|
+
spec.description = %q{
|
13
|
+
NutritionCalculator provides a set of core libraries to help track a
|
14
|
+
person's individual nutritional goals. It is meant to aid in both
|
15
|
+
weight-management and monitoring the nutritional balance of a diet.
|
16
|
+
}
|
17
|
+
spec.homepage = ""
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0")
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.2.0"
|
28
|
+
spec.add_development_dependency "cucumber", "~> 1.3.0"
|
29
|
+
spec.add_development_dependency "reek"
|
30
|
+
spec.add_development_dependency "yard"
|
31
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nutrition_calculator/cached_outputs_with_recalculation'
|
3
|
+
|
4
|
+
describe NutritionCalculator::CachedOutputsWithRecalculation do
|
5
|
+
subject {
|
6
|
+
klass = Class.new do
|
7
|
+
extend NutritionCalculator::CachedOutputsWithRecalculation
|
8
|
+
|
9
|
+
def_input :foo
|
10
|
+
|
11
|
+
def_output :baz do
|
12
|
+
foo.bar
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
klass.new
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:foo_value) { double('FooValue', bar: 'baz') }
|
20
|
+
|
21
|
+
it 'creates attr_accessors for inputs' do
|
22
|
+
subject.foo = :bar
|
23
|
+
expect(subject.foo).to eq :bar
|
24
|
+
end
|
25
|
+
|
26
|
+
it "complains when asked for the value of an input that was not provided" do
|
27
|
+
expect{subject.foo}.to \
|
28
|
+
raise_error(RuntimeError, "Required input missing: `foo`.")
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates attr_readers for outputs' do
|
32
|
+
subject.foo = foo_value
|
33
|
+
expect(subject.baz).to eq 'baz'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'caches the calculated values for output' do
|
37
|
+
subject.foo = foo_value
|
38
|
+
expect(foo_value).to receive(:bar).once.and_return('baz')
|
39
|
+
2.times do
|
40
|
+
subject.baz
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'clears cached calculations when inputs are changed' do
|
45
|
+
expect(foo_value).to receive(:bar).twice.and_return('baz')
|
46
|
+
2.times do
|
47
|
+
subject.foo = foo_value
|
48
|
+
subject.baz
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'logger'
|
3
|
+
require 'nutrition_calculator/calorie_budgeter'
|
4
|
+
|
5
|
+
describe NutritionCalculator::CalorieBudgeter do
|
6
|
+
# Uncomment the following line if you need debugging output
|
7
|
+
# before(:each) { subject.logger = Logger.new(STDERR) }
|
8
|
+
|
9
|
+
describe '#net_calorie_consumption' do
|
10
|
+
it 'is the number of calories consumed less any calories burned via exercise' do
|
11
|
+
subject.calories_consumed = 100
|
12
|
+
subject.calories_burned = 10
|
13
|
+
expect(subject.net_calorie_consumption).to eq 90
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#remaining_calories_this_week' do
|
18
|
+
it 'is the weekly calorie goal less net calories from previous days' do
|
19
|
+
subject.weekly_calorie_goal = 10_000
|
20
|
+
subject.prior_days_calories = 1_000
|
21
|
+
expect(subject.remaining_calories_this_week).to eq 9000
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#daily_calorie_goal' do
|
26
|
+
let(:days_left) { 8 - day }
|
27
|
+
let(:weekly_goal) { 10_000 }
|
28
|
+
|
29
|
+
before(:each) do
|
30
|
+
subject.current_day_of_week = day
|
31
|
+
subject.weekly_calorie_goal = weekly_goal
|
32
|
+
subject.prior_days_calories = weekly_consumed
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples_for 'it calculates the daily calorie goal' do
|
36
|
+
it 'is the number of calories remaining for the week divided by the remaining days in the week' do
|
37
|
+
expected = ((weekly_goal - weekly_consumed).to_f / days_left).round
|
38
|
+
expect(subject.daily_calorie_goal).to eq expected
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
(1..7).each do |day_num|
|
43
|
+
context "on day #{day_num}" do
|
44
|
+
let(:day) { day_num }
|
45
|
+
let(:weekly_consumed) { day_num * 10 }
|
46
|
+
it_behaves_like 'it calculates the daily calorie goal'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#target_daily_calorie_consumption' do
|
52
|
+
before(:each) do
|
53
|
+
subject.current_day_of_week = 1
|
54
|
+
subject.prior_days_calories = 0
|
55
|
+
subject.resting_metabolic_rate = 2_000
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when the daily calorie goal is the same as the RMR' do
|
59
|
+
before(:each) do
|
60
|
+
subject.weekly_calorie_goal = 14_000
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when no calories have been burned via exercise' do
|
64
|
+
before(:each) do
|
65
|
+
subject.calories_burned = 0
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'is equal to the resting metabolic rate' do
|
69
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_000
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when calories have been burned via exercise' do
|
74
|
+
before(:each) do
|
75
|
+
subject.calories_burned = 100
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'is equal to the resting metabolic rate plus exercise calories' do
|
79
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_100
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when the daily calorie goal is lower than the RMR' do
|
85
|
+
before(:each) do
|
86
|
+
subject.weekly_calorie_goal = 10_500
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when no calories have been burned via exercise' do
|
90
|
+
before(:each) do
|
91
|
+
subject.calories_burned = 0
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'is equal to the resting metabolic rate' do
|
95
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_000
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when calories burned are less than difference between goal and RMR' do
|
100
|
+
before(:each) do
|
101
|
+
subject.calories_burned = 100
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'is equal to the resting metabolic rate' do
|
105
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_000
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'when calories burned are equal to the difference between goal and RMR' do
|
110
|
+
before(:each) do
|
111
|
+
subject.calories_burned = 500
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is equal to the resting metabolic rate' do
|
115
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_000
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when calories burned are greater than the difference between goal and RMR' do
|
120
|
+
before(:each) do
|
121
|
+
subject.calories_burned = 501
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'is equal to the daily goal plus calories burned' do
|
125
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_001
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'when the daily calorie goal is higher than the RMR' do
|
131
|
+
before(:each) do
|
132
|
+
subject.weekly_calorie_goal = 17_500
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when no calories have been burned via exercise' do
|
136
|
+
before(:each) do
|
137
|
+
subject.calories_burned = 0
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'is equal to the daily calorie goal rate' do
|
141
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_500
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when any calories have been burned via exercise' do
|
146
|
+
before(:each) do
|
147
|
+
subject.calories_burned = 1
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'is equal to the daily goal plus calories burned' do
|
151
|
+
expect(subject.target_daily_calorie_consumption).to eq 2_501
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#remaining_to_target' do
|
158
|
+
before(:each) do
|
159
|
+
subject.resting_metabolic_rate = 2_000
|
160
|
+
subject.weekly_calorie_goal = 14_000
|
161
|
+
subject.current_day_of_week = 1
|
162
|
+
subject.prior_days_calories = 0
|
163
|
+
subject.calories_burned = 0
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'is equal to the target daily calorie consumption less any calories already consumed' do
|
167
|
+
subject.calories_consumed = 500
|
168
|
+
expect(subject.remaining_to_target).to eq 1_500
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'can be negative' do
|
172
|
+
subject.calories_consumed = 2_001
|
173
|
+
expect(subject.remaining_to_target).to eq -1
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'calories_remaining' do
|
178
|
+
before(:each) do
|
179
|
+
subject.resting_metabolic_rate = 2_000
|
180
|
+
subject.weekly_calorie_goal = 14_000
|
181
|
+
subject.current_day_of_week = 1
|
182
|
+
subject.prior_days_calories = 0
|
183
|
+
subject.calories_burned = 0
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'is usually equal to the calories remaining to target' do
|
187
|
+
subject.calories_consumed = 500
|
188
|
+
expect(subject.calories_remaining).to eq 1_500
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'will not be less than zero' do
|
192
|
+
subject.calories_consumed = 2_001
|
193
|
+
expect(subject.calories_remaining).to eq 0
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe '#predicted_calorie_consumption' do
|
198
|
+
before(:each) do
|
199
|
+
subject.current_day_of_week = 1
|
200
|
+
subject.prior_days_calories = 0
|
201
|
+
subject.resting_metabolic_rate = 2_000
|
202
|
+
subject.weekly_calorie_goal = 14_000
|
203
|
+
subject.calories_burned = 0
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'when net calorie consumption is less than the target daily consumption' do
|
207
|
+
before(:each) do
|
208
|
+
subject.calories_consumed = 1_999
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'is equal to the target daily consumption' do
|
212
|
+
expect(subject.predicted_calorie_consumption).to eq 2_000
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'when net calorie consumption is equal to the target daily consumption' do
|
217
|
+
before(:each) do
|
218
|
+
subject.calories_consumed = 2_000
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'is equal to the target daily consumption' do
|
222
|
+
expect(subject.predicted_calorie_consumption).to eq 2_000
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'when net calorie consumption is greater than the target daily consumption' do
|
227
|
+
before(:each) do
|
228
|
+
subject.calories_consumed = 2_001
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'is equal to the net consumption' do
|
232
|
+
expect(subject.predicted_calorie_consumption).to eq 2_001
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nutrition_calculator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Wilger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.2.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.2.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cucumber
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: reek
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: "\n NutritionCalculator provides a set of core libraries to help track
|
98
|
+
a\n person's individual nutritional goals. It is meant to aid in both\n weight-management
|
99
|
+
and monitoring the nutritional balance of a diet.\n "
|
100
|
+
email:
|
101
|
+
- johnwilger@gmail.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".gitignore"
|
107
|
+
- ".rspec"
|
108
|
+
- ".ruby-version"
|
109
|
+
- ".travis.yml"
|
110
|
+
- Gemfile
|
111
|
+
- LICENSE.txt
|
112
|
+
- README.md
|
113
|
+
- Rakefile
|
114
|
+
- features/calorie_budgeter.feature
|
115
|
+
- features/step_definitions/.keep
|
116
|
+
- features/step_definitions/calorie_budgeter_steps.rb
|
117
|
+
- features/support/.keep
|
118
|
+
- features/support/helper_methods.rb
|
119
|
+
- lib/nutrition_calculator.rb
|
120
|
+
- lib/nutrition_calculator/cached_outputs_with_recalculation.rb
|
121
|
+
- lib/nutrition_calculator/calorie_budgeter.rb
|
122
|
+
- lib/nutrition_calculator/has_logging.rb
|
123
|
+
- lib/nutrition_calculator/version.rb
|
124
|
+
- nutrition_calculator.gemspec
|
125
|
+
- spec/nutrition_calculator/cached_outputs_with_recalculation_spec.rb
|
126
|
+
- spec/nutrition_calculator/calorie_budgeter_spec.rb
|
127
|
+
- spec/nutrition_calculator_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
homepage: ''
|
130
|
+
licenses:
|
131
|
+
- MIT
|
132
|
+
metadata: {}
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 2.2.2
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Nutrition calculators for diet management
|
153
|
+
test_files:
|
154
|
+
- features/calorie_budgeter.feature
|
155
|
+
- features/step_definitions/.keep
|
156
|
+
- features/step_definitions/calorie_budgeter_steps.rb
|
157
|
+
- features/support/.keep
|
158
|
+
- features/support/helper_methods.rb
|
159
|
+
- spec/nutrition_calculator/cached_outputs_with_recalculation_spec.rb
|
160
|
+
- spec/nutrition_calculator/calorie_budgeter_spec.rb
|
161
|
+
- spec/nutrition_calculator_spec.rb
|
162
|
+
- spec/spec_helper.rb
|
163
|
+
has_rdoc:
|