Skip to content
This repository has been archived by the owner on Mar 4, 2022. It is now read-only.

Commit

Permalink
tinseth ibu calculations for entire recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
codekitchen committed Mar 8, 2011
1 parent 7ec531f commit 0ae77a8
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 14 deletions.
4 changes: 2 additions & 2 deletions lib/beerxml/hop.rb
Expand Up @@ -21,11 +21,11 @@ class Beerxml::Hop < Beerxml::Model
property :id, Serial
belongs_to :recipe, :required => false

def tinseth(post_boil_og, batch_size) # batch size is gallons for now
def tinseth(post_boil_og, batch_size) # batch size is gallons or Unit
bigness = 1.65 * 0.000125**(post_boil_og - 1)
boil_factor = (1 - 2.72 ** (-0.04 * time.in_minutes.to_f)) / 4.15
utilization = bigness * boil_factor
ibus = utilization * (aau * 0.01 * 7490) / batch_size
ibus = utilization * (aau * 0.01 * 7490) / U(batch_size, 'gallons').to_f
ibus.round
end
alias_method :ibus, :tinseth
Expand Down
5 changes: 5 additions & 0 deletions lib/beerxml/recipe.rb
Expand Up @@ -45,4 +45,9 @@ class Beerxml::Recipe < Beerxml::Model

# these are not used in the xml
property :id, Serial

def tinseth
hops.inject(0) { |v, h| v + h.tinseth(og, batch_size) }.round
end
alias_method :ibus, :tinseth
end
14 changes: 12 additions & 2 deletions lib/beerxml/unit.rb
@@ -1,6 +1,7 @@
module Beerxml
# Unit system with conversions between units of the same type. Very much
# a work in progress.
class Beerxml::Unit
class Unit
attr_reader :type, :unit

Units = {}
Expand All @@ -22,6 +23,7 @@ def in!(new_unit, *args)
@unit = new_unit
self
end
alias_method :to!, :in!
alias_method :unit=, :in!

def base_unit
Expand All @@ -33,7 +35,13 @@ def to_f
end

def initialize(amount, unit = nil)
if !unit
if amount.is_a?(Unit)
if unit
amount = amount.to(unit).to_f
else
amount, unit = amount.to_f, amount.unit
end
elsif !unit
amount, unit = amount.to_s.split(/\s+/, 2)
end
unit = unit.to_s
Expand Down Expand Up @@ -117,6 +125,7 @@ def self.included(k)
module Volume
def self.included(k)
k.add_type('volume', 'liters', 'l', 'liter')
k.add('volume', 0.26417, 'gallons', 'gallon')
end
end
include Volume
Expand All @@ -138,6 +147,7 @@ def self.included(k)
end
include Temperature
end
end

def U(*a)
Beerxml::Unit.new(*a)
Expand Down
10 changes: 0 additions & 10 deletions spec/parsing_spec.rb
@@ -1,16 +1,6 @@
require "#{File.dirname(__FILE__)}/spec_helper"

describe "beerxml.com examples" do
def filename(example)
"examples/beerxml.com/#{example}.xml"
end
def read_file(example)
File.read(filename(example))
end
def read_xml(example)
Nokogiri::XML(read_file(example))
end

it "should parse the first recipe and its hops" do
recipe = Beerxml::Recipe.new.from_xml(read_xml("recipes").root.children[1])

Expand Down
9 changes: 9 additions & 0 deletions spec/recipes_spec.rb
@@ -0,0 +1,9 @@
require "#{File.dirname(__FILE__)}/spec_helper"

describe Beerxml::Recipe do
it "should calculate IBUs using the tinseth method" do
recipe = Beerxml::Recipe.new.from_xml(read_xml("recipes").root.children[1])
recipe.should be_valid
recipe.ibus.should == 44
end
end
9 changes: 9 additions & 0 deletions spec/spec_helper.rb
Expand Up @@ -3,4 +3,13 @@
require 'rspec'

RSpec.configure do |c|
def filename(example)
"examples/beerxml.com/#{example}.xml"
end
def read_file(example)
File.read(filename(example))
end
def read_xml(example)
Nokogiri::XML(read_file(example))
end
end
11 changes: 11 additions & 0 deletions spec/units_spec.rb
Expand Up @@ -41,6 +41,17 @@ def near?(rhs, prec = 0.01)
w.should == U('53.97 oz')
end

it "should allow constructing from another compatible Unit object" do
w = U(53.97, 'oz')
w2 = U(w) # defaults to oz, same units as copying object
w3 = U(w, 'kg')
w.should == w2
w.should == w3
w2.should == w3
w2.should == 53.97
w3.should == 1.53
end

describe "equality" do
it "should compare between units" do
w = U(3.5, 'kg')
Expand Down

0 comments on commit 0ae77a8

Please sign in to comment.