gravitheque 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +9 -2
- data/Guardfile +4 -0
- data/README.md +65 -6
- data/gravitheque.gemspec +1 -1
- data/lib/calculators/hops.rb +187 -0
- data/lib/calculators/yeast.rb +47 -0
- data/lib/conversions/extract.rb +2 -0
- data/test/calculators/test_hops.rb +238 -0
- data/test/calculators/test_yeast.rb +78 -0
- data/test/conversions/test_extract.rb +6 -0
- data/test/test_helper.rb +15 -0
- metadata +10 -4
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
3
|
group :development do
|
4
|
-
gem "growl"
|
5
4
|
gem "guard-minitest"
|
5
|
+
gem "guard-yard"
|
6
6
|
end
|
7
7
|
|
8
8
|
group :documentation do
|
@@ -11,4 +11,11 @@ group :documentation do
|
|
11
11
|
gem "yard"
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
group :mac do
|
15
|
+
gem "growl"
|
16
|
+
gem "rb-fsevent"
|
17
|
+
end
|
18
|
+
|
19
|
+
group :test do
|
20
|
+
gem "simplecov"
|
21
|
+
end
|
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,45 @@
|
|
1
1
|
# Gravitheque [![Build Status](https://secure.travis-ci.org/johnmuhl/gravitheque.png)](http://travis-ci.org/johnmuhl/gravitheque)
|
2
2
|
|
3
|
+
**This is still a work in progress; as such neither the library nor web
|
4
|
+
application are particularly useful right now.**
|
5
|
+
|
3
6
|
A collection of [open source][oss] tools for brewers. It can be used as
|
4
7
|
a [web application][web], interactively through IRB or as a [library][lib] to
|
5
|
-
build your own brewing application. For use as a library refer the full
|
8
|
+
build your own brewing application. For use as a library refer to the full
|
6
9
|
[documentation][doc].
|
7
10
|
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
```bash
|
14
|
+
gem install gravitheque
|
15
|
+
```
|
16
|
+
|
17
|
+
To use the Gravitheque library nothing more than a compatible Ruby 1.9.3
|
18
|
+
implementation is required. It may work on older and newer versions but only by
|
19
|
+
coincidence; refer to the [build logs][trv] to see which Rubies are supported.
|
20
|
+
|
21
|
+
### Development
|
22
|
+
|
23
|
+
```bash
|
24
|
+
git clone git://github.com/johnmuhl/gravitheque.git
|
25
|
+
cd gravitheque
|
26
|
+
bin/test
|
27
|
+
```
|
28
|
+
|
29
|
+
Handy (non-essential) development dependencies can be installed with Bundler.
|
30
|
+
|
31
|
+
```bash
|
32
|
+
bundle install
|
33
|
+
# if you're on Linux or Windows
|
34
|
+
# bundle install --without mac
|
35
|
+
```
|
36
|
+
|
37
|
+
Now use [Guard][grd] to run tests and update documentation automatically.
|
38
|
+
|
39
|
+
```bash
|
40
|
+
guard start --clear
|
41
|
+
```
|
42
|
+
|
8
43
|
## Calculators
|
9
44
|
|
10
45
|
### Alcohol
|
@@ -39,16 +74,38 @@ Calculate.calories_per_serving 1.055, 1.012, :specific_gravity
|
|
39
74
|
Calculate.calories_per_serving 16.4, 8.2, :brix
|
40
75
|
```
|
41
76
|
|
77
|
+
### Hops
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
require "calculators/hops"
|
81
|
+
|
82
|
+
Calculate.hop_utilization 15, 45
|
83
|
+
Calculate.hop_utilization 1.055, 60, :specific_gravity
|
84
|
+
Calculate.hop_utilization 12, 15, :brix
|
85
|
+
|
86
|
+
Calculate.hop_mass_required({ :ibus => 50, :extract => 12, :at => 30, :alpha => 10, :volume => 20 })
|
87
|
+
Calculate.hop_mass_required({ :ibus => 15, :extract => 14.5, :at => 15, :alpha => 3.2, :volume => 20 }, { :extract => :brix })
|
88
|
+
Calculate.hop_mass_required({ :ibus => 100, :extract => 1.05, :at => 90, :alpha => 12.4, :volume => 10 }, { :extract => :specific_gravity, :volume => :gallons })
|
89
|
+
|
90
|
+
Calculate.hopshot_required({ :ibus => 40, :extract => 18, :at => 60, :volume => 20 })
|
91
|
+
Calculate.hopshot_required({ :ibus => 40, :extract => 14.5, :at => 60, :volume => 20 }, { :extract => :brix })
|
92
|
+
Calculate.hopshot_required({ :ibus => 40, :extract => 1.085, :at => 60, :volume => 10.5 }, { :extract => :specific_gravity, :volume => :gallons })
|
93
|
+
|
94
|
+
Calculate.ibus({ :extract => 15, :at => 60, :alpha => 6.5, :mass => 56, :volume => 20 })
|
95
|
+
Calculate.ibus({ :extract => 18.5, :at => 60, :alpha => 6.5, :mass => 56, :volume => 20 }, { :extract => :brix })
|
96
|
+
Calculate.ibus({ :extract => 1.055, :at => 60, :alpha => 6.5, :mass => 2, :volume => 5 }, { :extract => :specific_gravity, :mass => :ounces, :volume => :gallons })
|
97
|
+
```
|
98
|
+
|
42
99
|
### Yeast
|
43
100
|
|
44
101
|
```ruby
|
45
102
|
require "calculators/yeast"
|
46
103
|
|
47
|
-
Calculate.yeast_cells_required 16.5,
|
48
|
-
Calculate.yeast_cells_required 15.75,
|
104
|
+
Calculate.yeast_cells_required 16.5, 19
|
105
|
+
Calculate.yeast_cells_required 15.75, 5.25, { :volume => :gallons }
|
49
106
|
Calculate.yeast_cells_required 1.055, 55, { :extract => :specific_gravity }
|
50
|
-
Calculate.yeast_cells_required 18,
|
51
|
-
Calculate.yeast_cells_required 21.5,
|
107
|
+
Calculate.yeast_cells_required 18, 20, { :type => :hybrid }
|
108
|
+
Calculate.yeast_cells_required 21.5, 10.5, { :volume => :gallons, :extract => :brix, :type => :lager }
|
52
109
|
```
|
53
110
|
|
54
111
|
## Conversions
|
@@ -106,6 +163,8 @@ Convert.quarts_to_liters 11
|
|
106
163
|
```
|
107
164
|
|
108
165
|
[doc]: http://rubydoc.info/gems/gravitheque
|
166
|
+
[grd]: https://github.com/guard/guard
|
109
167
|
[lib]: http://rubygems.org/gems/gravitheque
|
110
|
-
[oss]: https://github.com/johnmuhl/gravitheque
|
168
|
+
[oss]: https://github.com/johnmuhl/gravitheque
|
169
|
+
[trv]: http://travis-ci.org/johnmuhl/gravitheque
|
111
170
|
[web]: http://gravitheque.herokuapp.com/
|
data/gravitheque.gemspec
CHANGED
@@ -0,0 +1,187 @@
|
|
1
|
+
require "conversions/extract"
|
2
|
+
require "conversions/mass"
|
3
|
+
require "conversions/volume"
|
4
|
+
|
5
|
+
module Calculate
|
6
|
+
|
7
|
+
# Calculate hop utilization.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# Calculate.hop_utilization 12, 20
|
11
|
+
# Calculate.hop_utilization 16.3, 45, :brix
|
12
|
+
# Calculate.hop_utilization 1.089, 60, :specific_gravity
|
13
|
+
#
|
14
|
+
# @param [Float] extract degrees Plato of wort being pitched
|
15
|
+
# @param [Float] at boil time remaining when hop addition is made
|
16
|
+
# @param [Symbol] unit used to change default settings for `extract`
|
17
|
+
# @return [Float] hop utilization
|
18
|
+
def self.hop_utilization extract, at, unit = :plato
|
19
|
+
unless unit == :specific_gravity
|
20
|
+
extract = case unit
|
21
|
+
when :brix then Convert.brix_to_specific_gravity extract
|
22
|
+
when :plato then Convert.plato_to_specific_gravity extract
|
23
|
+
else raise ArgumentError, "#{unit} is not recognized as a unit of extract"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
((hop_extract_adjustment extract, :specific_gravity) *
|
28
|
+
((hop_boil_time_adjustment at) / 4.15)).round 2
|
29
|
+
end
|
30
|
+
|
31
|
+
# Calculate IBUs for hop addition.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# Calculate.ibus({ :extract => 15, :at => 60, :alpha => 6.5, :mass => 56, :volume => 20 })
|
35
|
+
# Calculate.ibus({ :extract => 18.5, :at => 60, :alpha => 6.5, :mass => 56, :volume => 20 }, { :extract => :brix })
|
36
|
+
# Calculate.ibus({ :extract => 1.055, :at => 60, :alpha => 6.5, :mass => 2, :volume => 5 }, { :extract => :specific_gravity, :mass => :ounces, :volume => :gallons })
|
37
|
+
#
|
38
|
+
# @param [Hash] data data required to calculate IBUs; `:extract`, `:alpha`, `:at`, `:mass`, `:volume`
|
39
|
+
# @param [Hash] options used to change default settings for `extract`, `volume` and `mass`
|
40
|
+
# @return [Fixnum] IBUs from hop addition
|
41
|
+
def self.ibus data, options = {}
|
42
|
+
options.merge!(:extract => :plato) unless options[:extract]
|
43
|
+
options.merge!(:mass => :grams) unless options[:mass]
|
44
|
+
options.merge!(:volume => :liters) unless options[:volume]
|
45
|
+
|
46
|
+
unless options[:extract] == :specific_gravity
|
47
|
+
data[:extract] = case options[:extract]
|
48
|
+
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
49
|
+
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
50
|
+
else raise ArgumentError, "#{options[:extract]} is not recognized as a unit of extract"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
unless options[:mass] == :grams
|
55
|
+
data[:mass] = case options[:mass]
|
56
|
+
when :ounces then Convert.ounces_to_grams data[:mass]
|
57
|
+
else raise ArgumentError, "#{options[:mass]} is not recognized as a unit of mass"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
unless options[:volume] == :liters
|
62
|
+
data[:volume] = case options[:volume]
|
63
|
+
when :gallons then Convert.gallons_to_liters data[:volume]
|
64
|
+
else raise ArgumentError, "#{options[:volume]} is not recognized as a unit of volume"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
(hop_extract_adjustment(data[:extract], :specific_gravity) *
|
69
|
+
hop_boil_time_adjustment(data[:at]) * (data[:alpha] / 100) *
|
70
|
+
data[:mass] * 1000 / (data[:volume] * 4.15)).round
|
71
|
+
end
|
72
|
+
|
73
|
+
# Calculate hop mass required to achieve specific IBUs.
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# Calculate.hop_mass_required({ :ibu => 50, :extract => 12, :at => 30, :alpha => 10, :volume => 20 })
|
77
|
+
# Calculate.hop_mass_required({ :ibu => 15, :extract => 14.5, :at => 15, :alpha => 3.2, :volume => 20 }, { :extract => :brix })
|
78
|
+
# Calculate.hop_mass_required({ :ibu => 100, :extract => 1.05, :at => 90, :alpha => 12.4, :volume => 10 }, { :extract => :specific_gravity, :volume => :gallons })
|
79
|
+
#
|
80
|
+
# @param [Hash] data data required to calculate hop mass required; `:extract`, `:alpha`, `:at`, `:volume`, `:ibus`
|
81
|
+
# @param [Hash] options used to change default settings for `extract` and `volume`
|
82
|
+
# @return [Fixnum] hop mass required to achieve specific IBUs
|
83
|
+
def self.hop_mass_required data, options = {}
|
84
|
+
options.merge!(:extract => :plato) unless options[:extract]
|
85
|
+
options.merge!(:volume => :liters) unless options[:volume]
|
86
|
+
|
87
|
+
unless options[:extract] == :specific_gravity
|
88
|
+
data[:extract] = case options[:extract]
|
89
|
+
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
90
|
+
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
91
|
+
else raise ArgumentError, "#{options[:extract]} is not recognized as a unit of extract"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
unless options[:volume] == :liters
|
96
|
+
data[:volume] = case options[:volume]
|
97
|
+
when :gallons then Convert.gallons_to_liters data[:volume]
|
98
|
+
else raise ArgumentError, "#{options[:volume]} is not recognized as a unit of volume"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
((data[:volume] * data[:ibus]) /
|
103
|
+
(hop_utilization(data[:extract], data[:at], :specific_gravity) *
|
104
|
+
data[:alpha] * 10)).round
|
105
|
+
end
|
106
|
+
|
107
|
+
# Calculate milliliters of HopShot required to achieve specific IBUs.
|
108
|
+
#
|
109
|
+
# @example
|
110
|
+
# Calculate.hopshot_required({ :ibus => 40, :extract => 18, :at => 60, :volume => 20 })
|
111
|
+
# Calculate.hopshot_required({ :ibus => 40, :extract => 14.5, :at => 60, :volume => 20 }, { :extract => :brix })
|
112
|
+
# Calculate.hopshot_required({ :ibus => 40, :extract => 1.085, :at => 60, :volume => 10.5 }, { :extract => :specific_gravity, :volume => :gallons })
|
113
|
+
#
|
114
|
+
# @param [Hash] data data required to calculate HopShot required; `:extract`, `:at`, `:volume`, `:ibus`
|
115
|
+
# @param [Hash] options used to change default settings for `extract` and `volume`
|
116
|
+
# @return [Fixnum] HopShot required to achieve specific IBUs
|
117
|
+
def self.hopshot_required data, options = {}
|
118
|
+
options.merge!(:extract => :plato) unless options[:extract]
|
119
|
+
options.merge!(:volume => :liters) unless options[:volume]
|
120
|
+
|
121
|
+
unless options[:extract] == :specific_gravity
|
122
|
+
data[:extract] = case options[:extract]
|
123
|
+
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
124
|
+
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
125
|
+
else raise ArgumentError, "#{options[:extract]} is not recognized as a unit of extract"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
unless options[:volume] == :liters
|
130
|
+
data[:volume] = case options[:volume]
|
131
|
+
when :gallons then Convert.gallons_to_liters data[:volume]
|
132
|
+
else raise ArgumentError, "#{options[:volume]} is not recognized as a unit of volume"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
unadjusted_amount = (data[:ibus] / 10.0) * (data[:volume] / 19.0)
|
137
|
+
hopshot_required = unadjusted_amount
|
138
|
+
|
139
|
+
if data[:extract] >= 1.08 && data[:extract] < 1.1
|
140
|
+
hopshot_required = unadjusted_amount + (unadjusted_amount * 0.1)
|
141
|
+
elsif data[:extract] >= 1.1 && data[:extract] < 1.15
|
142
|
+
hopshot_required = unadjusted_amount + (unadjusted_amount * 0.2)
|
143
|
+
elsif data[:extract] >= 1.15
|
144
|
+
hopshot_required = unadjusted_amount + (unadjusted_amount * 0.3)
|
145
|
+
end
|
146
|
+
|
147
|
+
if data[:at] >= 90
|
148
|
+
hopshot_required = hopshot_required - (unadjusted_amount * 0.1)
|
149
|
+
end
|
150
|
+
|
151
|
+
hopshot_required.round 1
|
152
|
+
end
|
153
|
+
|
154
|
+
# Calculate hop boil time adjustment.
|
155
|
+
#
|
156
|
+
# @example
|
157
|
+
# Calculate.hop_boil_time_adjustment 60
|
158
|
+
# Calculate.hop_boil_time_adjustment 15
|
159
|
+
#
|
160
|
+
# @param [Fixnum] at boil time remaining when hop addition is made
|
161
|
+
# @return [Float] boil time adjustment
|
162
|
+
def self.hop_boil_time_adjustment at
|
163
|
+
(1 - Math.exp(-0.04 * at)).round 2
|
164
|
+
end
|
165
|
+
|
166
|
+
# Calculate hop extract adjustment.
|
167
|
+
#
|
168
|
+
# @example
|
169
|
+
# Calculate.hop_extract_adjustment 12
|
170
|
+
# Calculate.hop_extract_adjustment 14.2, :brix
|
171
|
+
# Calculate.hop_extract_adjustment 1.065, :specific_gravity
|
172
|
+
#
|
173
|
+
# @param [Float] extract extract level when hop addition is made
|
174
|
+
# @return [Float] extract adjustment
|
175
|
+
def self.hop_extract_adjustment extract, unit = :plato
|
176
|
+
unless unit == :specific_gravity
|
177
|
+
extract = case unit
|
178
|
+
when :brix then Convert.brix_to_specific_gravity extract
|
179
|
+
when :plato then Convert.plato_to_specific_gravity extract
|
180
|
+
else raise ArgumentError, "#{unit} is not recognized as a unit of extract"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
(1.65 * 0.000125 ** (extract - 1)).round 2
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "conversions/extract"
|
2
|
+
require "conversions/volume"
|
3
|
+
|
4
|
+
module Calculate
|
5
|
+
|
6
|
+
# Calculate the number of yeast cells needed to properly ferment a batch.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# Calculate.yeast_cells_needed 12, 20
|
10
|
+
# Calculate.yeast_cells_needed 12, 20, { :type => :lager }
|
11
|
+
# Calculate.yeast_cells_needed 12, 50, { :volume => :gallons }
|
12
|
+
# Calculate.yeast_cells_needed 1.048, 20, { :extract => :specific_gravity }
|
13
|
+
# Calculate.yeast_cells_needed 1.065, 10.5, { :extract => :specific_gravity, :type => :hybrid, :volume => :gallons }
|
14
|
+
#
|
15
|
+
# @param [Float] extract degrees Plato of wort being pitched
|
16
|
+
# @param [Float] volume liters of wort being pitched
|
17
|
+
# @param [Hash] options used to change default settings for `extract`, `volume` and `type`
|
18
|
+
# @return [Fixnum] yeast cells needed to ferment the batch
|
19
|
+
def self.yeast_cells_required extract, volume, options = {}
|
20
|
+
options.merge!(:volume => :liters) unless options[:volume]
|
21
|
+
options.merge!(:extract => :plato) unless options[:extract]
|
22
|
+
options.merge!(:type => :ale) unless options[:type]
|
23
|
+
|
24
|
+
cells_per_milliliter = case options[:type]
|
25
|
+
when :ale then 750_000
|
26
|
+
when :hybrid then 1_125_000
|
27
|
+
when :lager then 1_500_000
|
28
|
+
else raise ArgumentError, "#{options[:type]} is not recognized as a beer type"
|
29
|
+
end
|
30
|
+
|
31
|
+
volume = case options[:volume]
|
32
|
+
when :liters then volume
|
33
|
+
when :gallons then Convert.gallons_to_liters volume
|
34
|
+
else raise ArgumentError, "#{options[:volume]} is not recognized as measure of volume"
|
35
|
+
end
|
36
|
+
|
37
|
+
extract = case options[:extract]
|
38
|
+
when :plato then extract
|
39
|
+
when :brix then Convert.specific_gravity_to_plato(Convert.brix_to_specific_gravity extract)
|
40
|
+
when :specific_gravity then Convert.specific_gravity_to_plato extract
|
41
|
+
else raise ArgumentError, "#{options[:extract]} is not recognized as measure of extract"
|
42
|
+
end
|
43
|
+
|
44
|
+
(cells_per_milliliter * (volume * 1000) * extract).round
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/conversions/extract.rb
CHANGED
@@ -0,0 +1,238 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "calculators/hops"
|
3
|
+
|
4
|
+
describe Calculate do
|
5
|
+
|
6
|
+
it "must calculate the boil time adjustment" do
|
7
|
+
(Calculate.hop_boil_time_adjustment 60).must_equal 0.91
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must calculate the extract adjustment from Plato" do
|
11
|
+
(Calculate.hop_extract_adjustment 14).must_equal 0.99
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must calculate the extract adjustment from Brix" do
|
15
|
+
(Calculate.hop_extract_adjustment 16, :brix).must_equal 0.91
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must calculate the extract adjustment from specific gravity" do
|
19
|
+
(Calculate.hop_extract_adjustment 1.055, :specific_gravity).must_equal 1.01
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must calculate hop utilization from Plato" do
|
23
|
+
(Calculate.hop_utilization 15, 60).must_equal 0.21
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must calculate hop utilization from Brix" do
|
27
|
+
(Calculate.hop_utilization 12, 30, :brix).must_equal 0.18
|
28
|
+
end
|
29
|
+
|
30
|
+
it "must calculate hop utilization from specific gravity" do
|
31
|
+
(Calculate.hop_utilization 1.065, 10, :specific_gravity).must_equal 0.07
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must calculate IBUs from hop addition using Plato" do
|
35
|
+
Calculate.ibus({
|
36
|
+
extract: 12.3,
|
37
|
+
at: 60,
|
38
|
+
alpha: 5.0,
|
39
|
+
mass: 56,
|
40
|
+
volume: 19
|
41
|
+
}).must_equal 34
|
42
|
+
end
|
43
|
+
|
44
|
+
it "must calculate IBUs from hop addition using ounces" do
|
45
|
+
Calculate.ibus({
|
46
|
+
extract: 12.3,
|
47
|
+
at: 60,
|
48
|
+
alpha: 5.0,
|
49
|
+
mass: 2,
|
50
|
+
volume: 19
|
51
|
+
}, { :mass => :ounces }).must_equal 34
|
52
|
+
end
|
53
|
+
|
54
|
+
it "must calculate IBUs from hop addition using gallons" do
|
55
|
+
Calculate.ibus({
|
56
|
+
extract: 12.3,
|
57
|
+
at: 60,
|
58
|
+
alpha: 5.0,
|
59
|
+
mass: 56,
|
60
|
+
volume: 5
|
61
|
+
}, { :volume => :gallons }).must_equal 34
|
62
|
+
end
|
63
|
+
|
64
|
+
it "must calculate IBUs from hop addition using Brix" do
|
65
|
+
Calculate.ibus({
|
66
|
+
extract: 12.2,
|
67
|
+
at: 60,
|
68
|
+
alpha: 5.0,
|
69
|
+
mass: 56,
|
70
|
+
volume: 19
|
71
|
+
}, { :extract => :brix }).must_equal 34
|
72
|
+
end
|
73
|
+
|
74
|
+
it "must calculate IBUs from hop addition using specific gravity" do
|
75
|
+
Calculate.ibus({
|
76
|
+
extract: 1.05,
|
77
|
+
at: 60,
|
78
|
+
alpha: 5.0,
|
79
|
+
mass: 56,
|
80
|
+
volume: 19
|
81
|
+
}, { :extract => :specific_gravity }).must_equal 34
|
82
|
+
end
|
83
|
+
|
84
|
+
it "must calculate hop mass required for a specific IBU contribution using specific gravity" do
|
85
|
+
Calculate.hop_mass_required({
|
86
|
+
extract: 1.05,
|
87
|
+
at: 60,
|
88
|
+
alpha: 5.0,
|
89
|
+
ibus: 34,
|
90
|
+
volume: 19
|
91
|
+
}, { :extract => :specific_gravity }).must_equal 56
|
92
|
+
end
|
93
|
+
|
94
|
+
it "must calculate hop mass required for a specific IBU contribution using Plato" do
|
95
|
+
Calculate.hop_mass_required({
|
96
|
+
extract: 12.3,
|
97
|
+
at: 60,
|
98
|
+
alpha: 5.0,
|
99
|
+
ibus: 34,
|
100
|
+
volume: 19
|
101
|
+
}).must_equal 56
|
102
|
+
end
|
103
|
+
|
104
|
+
it "must calculate hop mass required for a specific IBU contribution using Brix" do
|
105
|
+
Calculate.hop_mass_required({
|
106
|
+
extract: 12.2,
|
107
|
+
at: 60,
|
108
|
+
alpha: 5.0,
|
109
|
+
ibus: 34,
|
110
|
+
volume: 19
|
111
|
+
}, { :extract => :brix }).must_equal 56
|
112
|
+
end
|
113
|
+
|
114
|
+
it "must calculate hop mass required for a specific IBU contribution using gallons" do
|
115
|
+
Calculate.hop_mass_required({
|
116
|
+
extract: 12.3,
|
117
|
+
at: 60,
|
118
|
+
alpha: 5.0,
|
119
|
+
ibus: 34,
|
120
|
+
volume: 5
|
121
|
+
}, { :volume => :gallons }).must_equal 56
|
122
|
+
end
|
123
|
+
|
124
|
+
it "must calculate milliliters of HopShot required for a specific IBU contribution using specific gravity" do
|
125
|
+
Calculate.hopshot_required({
|
126
|
+
ibus: 35,
|
127
|
+
at: 60,
|
128
|
+
volume: 19,
|
129
|
+
extract: 1.045
|
130
|
+
}, { :extract => :specific_gravity }).must_equal 3.5
|
131
|
+
|
132
|
+
Calculate.hopshot_required({
|
133
|
+
ibus: 80,
|
134
|
+
at: 60,
|
135
|
+
volume: 38,
|
136
|
+
extract: 1.085
|
137
|
+
}, { :extract => :specific_gravity }).must_equal 17.6
|
138
|
+
|
139
|
+
Calculate.hopshot_required({
|
140
|
+
ibus: 80,
|
141
|
+
at: 60,
|
142
|
+
volume: 38,
|
143
|
+
extract: 1.1
|
144
|
+
}, { :extract => :specific_gravity }).must_equal 19.2
|
145
|
+
|
146
|
+
Calculate.hopshot_required({
|
147
|
+
ibus: 60,
|
148
|
+
at: 90,
|
149
|
+
volume: 19,
|
150
|
+
extract: 1.15
|
151
|
+
}, { :extract => :specific_gravity }).must_equal 7.2
|
152
|
+
end
|
153
|
+
|
154
|
+
it "must calculate milliliters of HopShot required for a specific IBU contribution using Plato" do
|
155
|
+
Calculate.hopshot_required({
|
156
|
+
ibus: 35,
|
157
|
+
at: 60,
|
158
|
+
volume: 19,
|
159
|
+
extract: 12.3
|
160
|
+
}).must_equal 3.5
|
161
|
+
|
162
|
+
Calculate.hopshot_required({
|
163
|
+
ibus: 80,
|
164
|
+
at: 60,
|
165
|
+
volume: 38,
|
166
|
+
extract: 20.4
|
167
|
+
}).must_equal 17.6
|
168
|
+
|
169
|
+
Calculate.hopshot_required({
|
170
|
+
ibus: 80,
|
171
|
+
at: 60,
|
172
|
+
volume: 38,
|
173
|
+
extract: 23.7
|
174
|
+
}).must_equal 19.2
|
175
|
+
|
176
|
+
Calculate.hopshot_required({
|
177
|
+
ibus: 60,
|
178
|
+
at: 90,
|
179
|
+
volume: 19,
|
180
|
+
extract: 34.2
|
181
|
+
}).must_equal 7.2
|
182
|
+
end
|
183
|
+
|
184
|
+
it "must calculate milliliters of HopShot required for a specific IBU contribution using Brix" do
|
185
|
+
Calculate.hopshot_required({
|
186
|
+
ibus: 35,
|
187
|
+
at: 60,
|
188
|
+
volume: 19,
|
189
|
+
extract: 12.2
|
190
|
+
}, { :extract => :brix }).must_equal 3.5
|
191
|
+
|
192
|
+
Calculate.hopshot_required({
|
193
|
+
ibus: 80,
|
194
|
+
at: 60,
|
195
|
+
volume: 38,
|
196
|
+
extract: 20.3
|
197
|
+
}, { :extract => :brix }).must_equal 17.6
|
198
|
+
|
199
|
+
Calculate.hopshot_required({
|
200
|
+
ibus: 80,
|
201
|
+
at: 60,
|
202
|
+
volume: 38,
|
203
|
+
extract: 23.6
|
204
|
+
}, { :extract => :brix }).must_equal 19.2
|
205
|
+
|
206
|
+
Calculate.hopshot_required({
|
207
|
+
ibus: 60,
|
208
|
+
at: 90,
|
209
|
+
volume: 19,
|
210
|
+
extract: 34.1
|
211
|
+
}, { :extract => :brix }).must_equal 7.2
|
212
|
+
end
|
213
|
+
|
214
|
+
it "must calculate milliliters of HopShot required for a specific IBU contribution using gallons" do
|
215
|
+
Calculate.hopshot_required({
|
216
|
+
ibus: 35,
|
217
|
+
at: 60,
|
218
|
+
volume: 5,
|
219
|
+
extract: 11.2
|
220
|
+
}, { :volume => :gallons }).must_equal 3.5
|
221
|
+
end
|
222
|
+
|
223
|
+
it "must raise an exception for unrecognized units of measure" do
|
224
|
+
lambda { Calculate.hop_extract_adjustment 99, :razor_blades }.must_raise ArgumentError
|
225
|
+
lambda { Calculate.hop_utilization 18, 90, :razor_blades }.must_raise ArgumentError
|
226
|
+
|
227
|
+
lambda { Calculate.ibus({ extract: 1.05, at: 60, alpha: 5.0, mass: 56, volume: 19 }, { :extract => :razor_blades }) }.must_raise ArgumentError
|
228
|
+
lambda { Calculate.ibus({ extract: 1.05, at: 60, alpha: 5.0, mass: 56, volume: 19 }, { :mass => :razor_blades }) }.must_raise ArgumentError
|
229
|
+
lambda { Calculate.ibus({ extract: 1.05, at: 60, alpha: 5.0, mass: 56, volume: 19 }, { :volume => :razor_blades }) }.must_raise ArgumentError
|
230
|
+
|
231
|
+
lambda { Calculate.hop_mass_required({ extract: 1.05, at: 60, alpha: 5.0, ibus: 56, volume: 19 }, { :extract => :razor_blades }) }.must_raise ArgumentError
|
232
|
+
lambda { Calculate.hop_mass_required({ extract: 1.05, at: 60, alpha: 5.0, ibus: 56, volume: 19 }, { :volume => :razor_blades }) }.must_raise ArgumentError
|
233
|
+
|
234
|
+
lambda { Calculate.hopshot_required({ extract: 1.05, at: 60, alpha: 5.0, ibus: 56, volume: 19 }, { :extract => :razor_blades }) }.must_raise ArgumentError
|
235
|
+
lambda { Calculate.hopshot_required({ extract: 1.05, at: 60, alpha: 5.0, ibus: 56, volume: 19 }, { :volume => :razor_blades }) }.must_raise ArgumentError
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "./test/test_helper"
|
2
|
+
require "calculators/yeast"
|
3
|
+
|
4
|
+
describe Calculate do
|
5
|
+
|
6
|
+
it "must calculate yeast cells needed for an ale" do
|
7
|
+
(Calculate.yeast_cells_required 12, 20).must_equal 180_000_000_000
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must calculate yeast cells needed for a hybrid" do
|
11
|
+
(Calculate.yeast_cells_required 12, 20, { :type => :hybrid }).must_equal 270_000_000_000
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must calculate yeast cells needed for a lager" do
|
15
|
+
(Calculate.yeast_cells_required 12, 20, { :type => :lager }).must_equal 360_000_000_000
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must calculate yeast cells needed for an ale using gallons" do
|
19
|
+
(Calculate.yeast_cells_required 12, 5.3, { :volume => :gallons }).must_equal 180_900_000_000
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must calculate yeast cells needed for an ale using specific gravity" do
|
23
|
+
(Calculate.yeast_cells_required 1.048, 20, { :extract => :specific_gravity }).must_equal 178_500_000_000
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must calculate yeast cells needed for an ale using Brix" do
|
27
|
+
(Calculate.yeast_cells_required 18.5, 20, { :extract => :brix }).must_equal 279_000_000_000
|
28
|
+
end
|
29
|
+
|
30
|
+
it "must calculate yeast cells needed for an ale using gallons and specific gravity" do
|
31
|
+
(Calculate.yeast_cells_required 1.048, 5.3, { :volume => :gallons, :extract => :specific_gravity }).must_equal 179_392_500_000
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must calculate yeast cells needed for an hybrid using gallons" do
|
35
|
+
(Calculate.yeast_cells_required 12, 5.3, { :volume => :gallons, :type => :hybrid }).must_equal 271_350_000_000
|
36
|
+
end
|
37
|
+
|
38
|
+
it "must calculate yeast cells needed for an hybrid using specific gravity" do
|
39
|
+
(Calculate.yeast_cells_required 1.048, 20, { :extract => :specific_gravity, :type => :hybrid }).must_equal 267_750_000_000
|
40
|
+
end
|
41
|
+
|
42
|
+
it "must calculate yeast cells needed for an hybrid using Brix" do
|
43
|
+
(Calculate.yeast_cells_required 18.5, 20, { :extract => :brix, :type => :hybrid }).must_equal 418_500_000_000
|
44
|
+
end
|
45
|
+
|
46
|
+
it "must calculate yeast cells needed for an hybrid using gallons and specific gravity" do
|
47
|
+
(Calculate.yeast_cells_required 1.048, 5.3, { :volume => :gallons, :extract => :specific_gravity, :type => :hybrid }).must_equal 269_088_750_000
|
48
|
+
end
|
49
|
+
|
50
|
+
it "must calculate yeast cells needed for an lager using gallons" do
|
51
|
+
(Calculate.yeast_cells_required 12, 5.3, { :volume => :gallons, :type => :lager }).must_equal 361_800_000_000
|
52
|
+
end
|
53
|
+
|
54
|
+
it "must calculate yeast cells needed for an lager using specific gravity" do
|
55
|
+
(Calculate.yeast_cells_required 1.048, 20, { :extract => :specific_gravity, :type => :lager }).must_equal 357_000_000_000
|
56
|
+
end
|
57
|
+
|
58
|
+
it "must calculate yeast cells needed for an lager using Brix" do
|
59
|
+
(Calculate.yeast_cells_required 18.5, 20, { :extract => :brix, :type => :lager }).must_equal 558_000_000_000
|
60
|
+
end
|
61
|
+
|
62
|
+
it "must calculate yeast cells needed for an lager using gallons and specific gravity" do
|
63
|
+
(Calculate.yeast_cells_required 1.048, 5.3, { :volume => :gallons, :extract => :specific_gravity, :type => :lager }).must_equal 358_785_000_000
|
64
|
+
end
|
65
|
+
|
66
|
+
it "must raise an exception when the beer type is unrecognized" do
|
67
|
+
lambda { Calculate.yeast_cells_required 15, 20, { :type => :wine } }.must_raise ArgumentError
|
68
|
+
end
|
69
|
+
|
70
|
+
it "must raise an exception when the extract unit is unrecognized" do
|
71
|
+
lambda { Calculate.yeast_cells_required 15, 20, { :extract => :squeeze } }.must_raise ArgumentError
|
72
|
+
end
|
73
|
+
|
74
|
+
it "must raise an exception when the volume unit is unrecognized" do
|
75
|
+
lambda { Calculate.yeast_cells_required 15, 20, { :volume => :barrels } }.must_raise ArgumentError
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -20,7 +20,13 @@ describe Convert do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "must convert specific gravity to temperature corrected specific gravity" do
|
23
|
+
(Convert.specific_gravity_to_temperature_corrected_gravity 1.064, 2).must_equal 1.063
|
23
24
|
(Convert.specific_gravity_to_temperature_corrected_gravity 1.064, 42).must_equal 1.072
|
25
|
+
(Convert.specific_gravity_to_temperature_corrected_gravity 1.055, 12, :celsius).must_equal 1.068
|
26
|
+
end
|
27
|
+
|
28
|
+
it "must raise an exception when the temperature unit for specific gravity to temperature corrected specific gravity is not recognized" do
|
29
|
+
lambda { Convert.specific_gravity_to_temperature_corrected_gravity 1.055, 12, :kelvin }.must_raise ArgumentError
|
24
30
|
end
|
25
31
|
|
26
32
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# Rubinius does not (yet?) have the 1.9 Coverage module
|
2
|
+
unless RUBY_DESCRIPTION =~ /rubinius/i
|
3
|
+
require "simplecov"
|
4
|
+
|
5
|
+
class SimpleCov::Formatter::NoHTMLFormatter
|
6
|
+
def format result
|
7
|
+
puts "\n#{result.covered_lines} of #{result.total_lines} LOC tested (#{result.covered_percent.round(2)}%)"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
SimpleCov.start do
|
12
|
+
@formatter = SimpleCov::Formatter::NoHTMLFormatter
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
1
16
|
$:.push File.expand_path "../../lib", __FILE__
|
2
17
|
|
3
18
|
require "minitest/autorun"
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gravitheque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- john muhl
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-24 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Tools for brewers.
|
15
15
|
email:
|
@@ -30,6 +30,8 @@ files:
|
|
30
30
|
- lib/calculators.rb
|
31
31
|
- lib/calculators/alcohol.rb
|
32
32
|
- lib/calculators/calories.rb
|
33
|
+
- lib/calculators/hops.rb
|
34
|
+
- lib/calculators/yeast.rb
|
33
35
|
- lib/conversions.rb
|
34
36
|
- lib/conversions/extract.rb
|
35
37
|
- lib/conversions/mass.rb
|
@@ -38,6 +40,8 @@ files:
|
|
38
40
|
- lib/gravitheque.rb
|
39
41
|
- test/calculators/test_alcohol.rb
|
40
42
|
- test/calculators/test_calories.rb
|
43
|
+
- test/calculators/test_hops.rb
|
44
|
+
- test/calculators/test_yeast.rb
|
41
45
|
- test/conversions/test_extract.rb
|
42
46
|
- test/conversions/test_mass.rb
|
43
47
|
- test/conversions/test_temperature.rb
|
@@ -50,17 +54,17 @@ rdoc_options: []
|
|
50
54
|
require_paths:
|
51
55
|
- lib
|
52
56
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
53
58
|
requirements:
|
54
59
|
- - ! '>='
|
55
60
|
- !ruby/object:Gem::Version
|
56
61
|
version: '0'
|
57
|
-
none: false
|
58
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
59
64
|
requirements:
|
60
65
|
- - ! '>='
|
61
66
|
- !ruby/object:Gem::Version
|
62
67
|
version: '0'
|
63
|
-
none: false
|
64
68
|
requirements: []
|
65
69
|
rubyforge_project:
|
66
70
|
rubygems_version: 1.8.15
|
@@ -70,6 +74,8 @@ summary: The library that will eventually power the web application of the same
|
|
70
74
|
test_files:
|
71
75
|
- test/calculators/test_alcohol.rb
|
72
76
|
- test/calculators/test_calories.rb
|
77
|
+
- test/calculators/test_hops.rb
|
78
|
+
- test/calculators/test_yeast.rb
|
73
79
|
- test/conversions/test_extract.rb
|
74
80
|
- test/conversions/test_mass.rb
|
75
81
|
- test/conversions/test_temperature.rb
|