gravitheque 0.3.0 → 0.4.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.
- 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
|