gravitheque 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -3
- data/README.md +210 -43
- data/bin/test +2 -0
- data/gravitheque.gemspec +1 -1
- data/lib/calculators/alcohol.rb +41 -28
- data/lib/calculators/calories.rb +63 -45
- data/lib/calculators/hops.rb +146 -76
- data/lib/calculators/mash.rb +54 -23
- data/lib/calculators/yeast.rb +46 -22
- data/test/calculators/test_alcohol.rb +31 -8
- data/test/calculators/test_calories.rb +53 -12
- data/test/calculators/test_hops.rb +46 -27
- data/test/calculators/test_mash.rb +52 -8
- data/test/calculators/test_yeast.rb +89 -18
- data/test/test_helper.rb +2 -2
- metadata +54 -98
data/lib/calculators/hops.rb
CHANGED
@@ -4,64 +4,87 @@ require "conversions/volume"
|
|
4
4
|
|
5
5
|
module Calculate
|
6
6
|
|
7
|
-
#
|
7
|
+
# Calculates hop utilization.
|
8
|
+
# Supported extract units are `:brix`, `:plato` and `:specific_gravity`. Default: `:plato`
|
8
9
|
#
|
9
10
|
# @example
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# Calculate.hop_utilization({ at: 20, extract: 12 })
|
12
|
+
# Calculate.hop_utilization({ at: 20, extract: 12 }, :brix)
|
13
|
+
# Calculate.hop_utilization({ at: 20, extract: 12 }, :specific_gravity)
|
13
14
|
#
|
14
|
-
# @param [
|
15
|
-
# @param [
|
16
|
-
# @param [Symbol] unit used to change default settings for `extract`
|
15
|
+
# @param [Hash] data the extract level and time added
|
16
|
+
# @param [Symbol] unit the unit used to measure extract
|
17
17
|
# @return [Float] hop utilization
|
18
|
-
def self.hop_utilization
|
19
|
-
unless
|
20
|
-
extract = case
|
21
|
-
when :brix then Convert.brix_to_specific_gravity extract
|
22
|
-
when :plato then Convert.plato_to_specific_gravity extract
|
23
|
-
else raise ArgumentError, "#{
|
18
|
+
def self.hop_utilization data, units = :plato
|
19
|
+
unless units == :specific_gravity
|
20
|
+
data[:extract] = case units
|
21
|
+
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
22
|
+
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
23
|
+
else raise ArgumentError, "#{units} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
((hop_extract_adjustment extract, :specific_gravity) *
|
28
|
-
((hop_boil_time_adjustment at) / 4.15)).round 2
|
27
|
+
((hop_extract_adjustment data[:extract], :specific_gravity) *
|
28
|
+
((hop_boil_time_adjustment data[:at]) / 4.15)).round 2
|
29
29
|
end
|
30
30
|
|
31
|
-
#
|
31
|
+
# Calculates IBUs for hop addition.
|
32
|
+
# Supported extract units are `:brix`, `:plato` and `:specific_gravity`. Default: `:plato`
|
33
|
+
# Supported mass units are `:grams` and `:ounces`. Default: `:grams`
|
34
|
+
# Supported volume units are `:gallons` and `:liters`. Default: `:liters`
|
32
35
|
#
|
33
36
|
# @example
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
+
# Calculate.ibus({
|
38
|
+
# alpha: 12.4,
|
39
|
+
# at: 90,
|
40
|
+
# extract: 15,
|
41
|
+
# mass: 56,
|
42
|
+
# volume: 20
|
43
|
+
# })
|
37
44
|
#
|
38
|
-
#
|
39
|
-
#
|
45
|
+
# Calculate.ibus({
|
46
|
+
# alpha: 6.5,
|
47
|
+
# at: 60,
|
48
|
+
# extract: 18.5,
|
49
|
+
# mass: 30,
|
50
|
+
# volume: 40
|
51
|
+
# }, { extract: :brix })
|
52
|
+
#
|
53
|
+
# Calculate.ibus({
|
54
|
+
# alpha: 8,
|
55
|
+
# at: 30,
|
56
|
+
# extract: 1.055,
|
57
|
+
# mass: 3,
|
58
|
+
# volume: 5
|
59
|
+
# }, { extract: :specific_gravity, mass: :ounces, volume: :gallons })
|
60
|
+
#
|
61
|
+
# @param [Hash] data data required to calculate IBUs; `extract`, `alpha`, `at`, `mass`, `volume`
|
62
|
+
# @param [Hash] units used to change default units for `extract`, `volume` and `mass`
|
40
63
|
# @return [Fixnum] IBUs from hop addition
|
41
|
-
def self.ibus data,
|
42
|
-
|
43
|
-
|
44
|
-
|
64
|
+
def self.ibus data, units = {}
|
65
|
+
units.merge!(extract: :plato) unless units[:extract]
|
66
|
+
units.merge!(mass: :grams) unless units[:mass]
|
67
|
+
units.merge!(volume: :liters) unless units[:volume]
|
45
68
|
|
46
|
-
unless
|
47
|
-
data[:extract] = case
|
69
|
+
unless units[:extract] == :specific_gravity
|
70
|
+
data[:extract] = case units[:extract]
|
48
71
|
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
49
72
|
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
50
|
-
else raise ArgumentError, "#{
|
73
|
+
else raise ArgumentError, "#{units[:extract]} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
51
74
|
end
|
52
75
|
end
|
53
76
|
|
54
|
-
unless
|
55
|
-
data[:mass] = case
|
77
|
+
unless units[:mass] == :grams
|
78
|
+
data[:mass] = case units[:mass]
|
56
79
|
when :ounces then Convert.ounces_to_grams data[:mass]
|
57
|
-
else raise ArgumentError, "#{
|
80
|
+
else raise ArgumentError, "#{units[:mass]} is an unknown unit of mass. Use :grams or :ounces"
|
58
81
|
end
|
59
82
|
end
|
60
83
|
|
61
|
-
unless
|
62
|
-
data[:volume] = case
|
84
|
+
unless units[:volume] == :liters
|
85
|
+
data[:volume] = case units[:volume]
|
63
86
|
when :gallons then Convert.gallons_to_liters data[:volume]
|
64
|
-
else raise ArgumentError, "#{
|
87
|
+
else raise ArgumentError, "#{units[:volume]} is an unknown unit of volume. Use :gallons or :liters"
|
65
88
|
end
|
66
89
|
end
|
67
90
|
|
@@ -70,66 +93,113 @@ module Calculate
|
|
70
93
|
data[:mass] * 1000 / (data[:volume] * 4.15)).round
|
71
94
|
end
|
72
95
|
|
73
|
-
#
|
96
|
+
# Calculates hop mass required to achieve specific IBUs.
|
97
|
+
# Supported extract units are `:brix`, `:plato` and `:specific_gravity`. Default: `:plato`
|
98
|
+
# Supported volume units are `:gallons` and `:liters`. Default: `:liters`
|
74
99
|
#
|
75
100
|
# @example
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
101
|
+
# Calculate.hop_mass_required({
|
102
|
+
# alpha: 13.5,
|
103
|
+
# at: 60,
|
104
|
+
# extract: 16,
|
105
|
+
# ibus: 25,
|
106
|
+
# volume: 20
|
107
|
+
# })
|
108
|
+
#
|
109
|
+
# Calculate.hop_mass_required({
|
110
|
+
# alpha: 3.2,
|
111
|
+
# at: 15,
|
112
|
+
# extract: 14.5,
|
113
|
+
# ibus: 15,
|
114
|
+
# volume: 20
|
115
|
+
# }, { extract: :brix })
|
116
|
+
#
|
117
|
+
# Calculate.hop_mass_required({
|
118
|
+
# alpha: 12.4,
|
119
|
+
# at: 90,
|
120
|
+
# extract: 1.05,
|
121
|
+
# ibus: 100,
|
122
|
+
# volume: 10
|
123
|
+
# }, { extract: :specific_gravity, volume: :gallons })
|
124
|
+
#
|
125
|
+
# @param [Hash] data data required to calculate hop mass required; `extract`, `ibus`, `alpha`, `at`, `volume`
|
126
|
+
# @param [Hash] units used to change default units for `extract` and `volume`
|
127
|
+
# @return [Float] hop mass required to achieve specific IBUs
|
128
|
+
def self.hop_mass_required data, units = {}
|
129
|
+
units.merge!(extract: :plato) unless units[:extract]
|
130
|
+
units.merge!(mass: :grams) unless units[:mass]
|
131
|
+
units.merge!(volume: :liters) unless units[:volume]
|
132
|
+
|
133
|
+
unless units[:extract] == :specific_gravity
|
134
|
+
data[:extract] = case units[:extract]
|
89
135
|
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
90
136
|
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
91
|
-
else raise ArgumentError, "#{
|
137
|
+
else raise ArgumentError, "#{units[:extract]} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
92
138
|
end
|
93
139
|
end
|
94
140
|
|
95
|
-
unless
|
96
|
-
data[:volume] = case
|
141
|
+
unless units[:volume] == :liters
|
142
|
+
data[:volume] = case units[:volume]
|
97
143
|
when :gallons then Convert.gallons_to_liters data[:volume]
|
98
|
-
else raise ArgumentError, "#{
|
144
|
+
else raise ArgumentError, "#{units[:volume]} is an unknown unit of volume. Use :gallons or :liters"
|
99
145
|
end
|
100
146
|
end
|
101
147
|
|
102
|
-
((data[:volume] * data[:ibus]) /
|
103
|
-
|
104
|
-
|
148
|
+
mass = ((data[:volume] * data[:ibus]) /
|
149
|
+
(hop_utilization({extract: data[:extract], at: data[:at]}, :specific_gravity) *
|
150
|
+
data[:alpha] * 10))
|
151
|
+
|
152
|
+
units[:mass] == :grams ? mass.round : Convert.grams_to_ounces(mass).round(1)
|
105
153
|
end
|
106
154
|
|
107
155
|
# Calculate milliliters of HopShot required to achieve specific IBUs.
|
156
|
+
# Supported extract units are `:brix`, `:plato` and `:specific_gravity`. Default: `:plato`
|
157
|
+
# Supported volume units are `:gallons` and `:liters`. Default: `:liters`
|
108
158
|
#
|
109
159
|
# @example
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
160
|
+
# Calculate.hopshot_required({
|
161
|
+
# alpha: 13.5,
|
162
|
+
# at: 60,
|
163
|
+
# extract: 16,
|
164
|
+
# ibus: 25,
|
165
|
+
# volume: 20
|
166
|
+
# })
|
167
|
+
#
|
168
|
+
# Calculate.hopshot_required({
|
169
|
+
# alpha: 3.2,
|
170
|
+
# at: 15,
|
171
|
+
# extract: 14.5,
|
172
|
+
# ibus: 15,
|
173
|
+
# volume: 20
|
174
|
+
# }, { extract: :brix })
|
175
|
+
#
|
176
|
+
# Calculate.hopshot_required({
|
177
|
+
# alpha: 12.4,
|
178
|
+
# at: 90,
|
179
|
+
# extract: 1.05,
|
180
|
+
# ibus: 100,
|
181
|
+
# volume: 10
|
182
|
+
# }, { extract: :specific_gravity, volume: :gallons })
|
183
|
+
#
|
184
|
+
# @param [Hash] data data required to calculate hop mass required; `extract`, `ibus`, `at`, `volume`
|
185
|
+
# @param [Hash] units used to change default units for `extract` and `volume`
|
186
|
+
# @return [Float] milliliters of HopShot required to achieve specific IBUs
|
187
|
+
def self.hopshot_required data, units = {}
|
188
|
+
units.merge!(extract: :plato) unless units[:extract]
|
189
|
+
units.merge!(volume: :liters) unless units[:volume]
|
190
|
+
|
191
|
+
unless units[:extract] == :specific_gravity
|
192
|
+
data[:extract] = case units[:extract]
|
123
193
|
when :brix then Convert.brix_to_specific_gravity data[:extract]
|
124
194
|
when :plato then Convert.plato_to_specific_gravity data[:extract]
|
125
|
-
else raise ArgumentError, "#{
|
195
|
+
else raise ArgumentError, "#{units[:extract]} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
126
196
|
end
|
127
197
|
end
|
128
198
|
|
129
|
-
unless
|
130
|
-
data[:volume] = case
|
199
|
+
unless units[:volume] == :liters
|
200
|
+
data[:volume] = case units[:volume]
|
131
201
|
when :gallons then Convert.gallons_to_liters data[:volume]
|
132
|
-
else raise ArgumentError, "#{
|
202
|
+
else raise ArgumentError, "#{units[:volume]} is an unknown unit of volume. Use :liters or :gallons"
|
133
203
|
end
|
134
204
|
end
|
135
205
|
|
@@ -172,12 +242,12 @@ module Calculate
|
|
172
242
|
#
|
173
243
|
# @param [Float] extract extract level when hop addition is made
|
174
244
|
# @return [Float] extract adjustment
|
175
|
-
def self.hop_extract_adjustment extract,
|
176
|
-
unless
|
177
|
-
extract = case
|
245
|
+
def self.hop_extract_adjustment extract, units = :plato
|
246
|
+
unless units == :specific_gravity
|
247
|
+
extract = case units
|
178
248
|
when :brix then Convert.brix_to_specific_gravity extract
|
179
249
|
when :plato then Convert.plato_to_specific_gravity extract
|
180
|
-
else raise ArgumentError, "#{
|
250
|
+
else raise ArgumentError, "#{units} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
181
251
|
end
|
182
252
|
end
|
183
253
|
|
data/lib/calculators/mash.rb
CHANGED
@@ -1,40 +1,69 @@
|
|
1
1
|
module Calculate
|
2
2
|
|
3
|
-
#
|
3
|
+
# Calculates temperature of strike water for dough in.
|
4
|
+
# Supported units are `:metric` and `:us`. Default: `:metric`
|
4
5
|
#
|
5
6
|
# @example
|
6
|
-
# Calculate.strike_temperature
|
7
|
-
#
|
7
|
+
# Calculate.strike_temperature({
|
8
|
+
# ratio: 1.5,
|
9
|
+
# initial: 20,
|
10
|
+
# target: 75
|
11
|
+
# })
|
8
12
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
+
# Calculate.strike_temperature({
|
14
|
+
# ratio: 1.25,
|
15
|
+
# initial: 65,
|
16
|
+
# target: 154
|
17
|
+
# }, :us)
|
18
|
+
#
|
19
|
+
# Calculate.strike_temperature({
|
20
|
+
# ratio: 1.5,
|
21
|
+
# initial: 60,
|
22
|
+
# target: 150,
|
23
|
+
# loss: 1.015
|
24
|
+
# }, :us)
|
25
|
+
#
|
26
|
+
# @param [Hash] data data required to calculate hop mass required; `ratio`, `initial`, `target`
|
27
|
+
# @param [Symbol] units the unit used to measure temperature
|
13
28
|
# @return [Fixnum] strike water temperature
|
14
|
-
def self.strike_temperature
|
29
|
+
def self.strike_temperature data, units = :metric
|
15
30
|
constant = case units
|
16
31
|
when :metric then 0.41
|
17
32
|
when :us then 0.2
|
18
|
-
else raise ArgumentError, "
|
33
|
+
else raise ArgumentError, "#{units} is an unknown unit of measures. Use :metric or :us"
|
19
34
|
end
|
20
35
|
|
21
|
-
(
|
36
|
+
data.merge!(loss: 1) unless data[:loss]
|
37
|
+
|
38
|
+
(((constant / data[:ratio]) *
|
39
|
+
(data[:target] - data[:initial]) +
|
40
|
+
data[:target]) * data[:loss]).round
|
22
41
|
end
|
23
42
|
|
24
|
-
#
|
43
|
+
# Calculates volume of boiling infusion water needed to increase mash temperature.
|
44
|
+
# Supported units are `:metric` and `:us`. Default: `:metric`
|
25
45
|
#
|
26
46
|
# @example
|
27
|
-
# Calculate.infusion_volume
|
28
|
-
#
|
47
|
+
# Calculate.infusion_volume({
|
48
|
+
# ratio: 1,
|
49
|
+
# initial: 40,
|
50
|
+
# target: 60,
|
51
|
+
# mass: 3.6,
|
52
|
+
# volume: 3.6
|
53
|
+
# })
|
54
|
+
#
|
55
|
+
# Calculate.infusion_volume({
|
56
|
+
# ratio: 1,
|
57
|
+
# initial: 104,
|
58
|
+
# target: 140,
|
59
|
+
# mass: 8,
|
60
|
+
# volume: 8
|
61
|
+
# }, :us)
|
29
62
|
#
|
30
|
-
# @param [
|
31
|
-
# @param [
|
32
|
-
# @param [Fixnum] target mash temperature
|
33
|
-
# @param [Float] mass weight of grain in the mash
|
34
|
-
# @param [Float] volume amount of water already in the mash
|
35
|
-
# @param [Symbol] units change units of measure to U.S. customary
|
63
|
+
# @param [Hash] data data required to calculate infusion volume; `ratio`, `initial`, `target`, `mass`, `volume`
|
64
|
+
# @param [Symbol] units the unit used for measurements
|
36
65
|
# @return [Fixnum] infusion water volume
|
37
|
-
def self.infusion_volume
|
66
|
+
def self.infusion_volume data, units = :metric
|
38
67
|
case units
|
39
68
|
when :metric
|
40
69
|
boiling = 100
|
@@ -42,10 +71,12 @@ module Calculate
|
|
42
71
|
when :us
|
43
72
|
boiling = 212
|
44
73
|
constant = 0.2
|
45
|
-
else raise ArgumentError, "
|
74
|
+
else raise ArgumentError, "#{units} is an unknown unit of measures. Use :metric or :us"
|
46
75
|
end
|
47
76
|
|
48
|
-
((target - initial) *
|
77
|
+
((data[:target] - data[:initial]) *
|
78
|
+
((constant * data[:mass]) + data[:volume]) /
|
79
|
+
(boiling - data[:target])).round 1
|
49
80
|
end
|
50
81
|
|
51
|
-
end
|
82
|
+
end
|
data/lib/calculators/yeast.rb
CHANGED
@@ -3,42 +3,66 @@ require "conversions/volume"
|
|
3
3
|
|
4
4
|
module Calculate
|
5
5
|
|
6
|
-
#
|
6
|
+
# Calculates the number of yeast cells needed to properly ferment a batch.
|
7
|
+
# Supported extract units are `:brix`, `:plato` and `:specific_gravity`. Default: `:plato`
|
8
|
+
# Supported beers types are `:ale`, `:hybrid` and `:lager`. Default: `:ale`
|
9
|
+
# Supported volume units are `:gallons` and `:liters`. Default: `:liters`
|
7
10
|
#
|
8
11
|
# @example
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# Calculate.yeast_cells_needed 1.065, 10.5, { :extract => :specific_gravity, :type => :hybrid, :volume => :gallons }
|
12
|
+
# Calculate.yeast_cells_required({
|
13
|
+
# extract: 16.5,
|
14
|
+
# volume: 19
|
15
|
+
# })
|
14
16
|
#
|
15
|
-
#
|
17
|
+
# Calculate.yeast_cells_required({
|
18
|
+
# extract: 15.75,
|
19
|
+
# volume: 5.25
|
20
|
+
# }, { volume: :gallons })
|
21
|
+
#
|
22
|
+
# Calculate.yeast_cells_required({
|
23
|
+
# extract: 1.055,
|
24
|
+
# volume: 55
|
25
|
+
# }, { extract: :specific_gravity })
|
26
|
+
#
|
27
|
+
# Calculate.yeast_cells_required({
|
28
|
+
# extract: 18,
|
29
|
+
# volume: 20,
|
30
|
+
# type: :hybrid
|
31
|
+
# })
|
32
|
+
#
|
33
|
+
# Calculate.yeast_cells_required({
|
34
|
+
# extract: 21.5,
|
35
|
+
# volume: 10.5,
|
36
|
+
# type: :lager
|
37
|
+
# }, { volume: :gallons, extract: :brix })
|
38
|
+
#
|
39
|
+
# @param [Hash] data data required to calculate yeast cells required; `extract`, `volume`, `type`
|
16
40
|
# @param [Float] volume liters of wort being pitched
|
17
41
|
# @param [Hash] options used to change default settings for `extract`, `volume` and `type`
|
18
42
|
# @return [Fixnum] yeast cells needed to ferment the batch
|
19
|
-
def self.yeast_cells_required
|
20
|
-
|
21
|
-
|
22
|
-
|
43
|
+
def self.yeast_cells_required data, units = {}
|
44
|
+
data.merge!(:type => :ale) unless data[:type]
|
45
|
+
units.merge!(:extract => :plato) unless units[:extract]
|
46
|
+
units.merge!(:volume => :liters) unless units[:volume]
|
23
47
|
|
24
|
-
cells_per_milliliter = case
|
48
|
+
cells_per_milliliter = case data[:type]
|
25
49
|
when :ale then 750_000
|
26
50
|
when :hybrid then 1_125_000
|
27
51
|
when :lager then 1_500_000
|
28
|
-
else raise ArgumentError, "#{
|
52
|
+
else raise ArgumentError, "#{data[:type]} is an unknown type of beer. Use :ale, :hybrid or :lager"
|
29
53
|
end
|
30
54
|
|
31
|
-
volume = case
|
32
|
-
when :liters then volume
|
33
|
-
when :gallons then Convert.gallons_to_liters volume
|
34
|
-
else raise ArgumentError, "#{
|
55
|
+
volume = case units[:volume]
|
56
|
+
when :liters then data[:volume]
|
57
|
+
when :gallons then Convert.gallons_to_liters data[:volume]
|
58
|
+
else raise ArgumentError, "#{units[:volume]} is an unknown unit of volume. Use :gallons or :liters"
|
35
59
|
end
|
36
60
|
|
37
|
-
extract = case
|
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, "#{
|
61
|
+
extract = case units[:extract]
|
62
|
+
when :plato then data[:extract]
|
63
|
+
when :brix then Convert.specific_gravity_to_plato(Convert.brix_to_specific_gravity data[:extract])
|
64
|
+
when :specific_gravity then Convert.specific_gravity_to_plato data[:extract]
|
65
|
+
else raise ArgumentError, "#{units[:extract]} is an unknown unit of extract. Use :brix, :plato or :specific_gravity"
|
42
66
|
end
|
43
67
|
|
44
68
|
(cells_per_milliliter * (volume * 1000) * extract).round
|