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 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