gravitheque 0.1.0 → 0.2.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/.gitignore CHANGED
@@ -4,5 +4,7 @@
4
4
  .rbx
5
5
  .rvmrc
6
6
  .yardoc
7
+ coverage
8
+ doc
7
9
  Gemfile.lock
8
10
  *.gem
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
- gem "rb-fsevent", :group => :mac
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
@@ -3,3 +3,7 @@ guard "minitest" do
3
3
  watch(%r|^lib/(.*)\/(.*)\.rb|) { |m| "test/#{m[1]}/test_#{m[2]}.rb" }
4
4
  watch(%r|^test/test_helper\.rb|) { "test" }
5
5
  end
6
+
7
+ guard "yard" do
8
+ watch(%r{lib/.+\.rb})
9
+ end
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, 5.25
48
- Calculate.yeast_cells_required 15.75, 19, { :batch_size => :liters }
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, 10.75, { :type => :hybrid }
51
- Calculate.yeast_cells_required 21.5, 100, { :batch_size => :liters, :extract => :brix, :type => :lager }
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/blob/master/LICENSE
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
@@ -11,5 +11,5 @@ Gem::Specification.new do |gem|
11
11
  gem.test_files = `git ls-files -- test/*`.split("\n")
12
12
  gem.name = "gravitheque"
13
13
  gem.require_paths = ["lib"]
14
- gem.version = "0.1.0"
14
+ gem.version = "0.2.0"
15
15
  end
@@ -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
@@ -1,3 +1,5 @@
1
+ require "conversions/temperature"
2
+
1
3
  module Convert
2
4
 
3
5
  # Convert specific gravity to degrees Plato.
@@ -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-23 00:00:00.000000000 Z
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