array("color"=>12,"vitamins"=>0,"glucose"=>0,"maltose"=>2,"barley"=>0,"tannin"=>0,"grassy"=>0,"honey"=>0), dark=>array("color"=>6,"vitamins"=>4.3,"glucose"=>2,"maltose"=>10,"barley"=>6,"tannin"=>1.5,"grassy"=>0,"honey"=>0), med=>array("color"=>3,"vitamins"=>5.7,"glucose"=>2,"maltose"=>10,"barley"=>6,"tannin"=>2,"grassy"=>0,"honey"=>0), light=>array("color"=>1.5,"vitamins"=>8.5,"glucose"=>2,"maltose"=>10,"barley"=>6,"tannin"=>3,"grassy"=>1.5,"honey"=>0), raw=>array("color"=>1,"vitamins"=>10.8,"glucose"=>1,"maltose"=>5,"barley"=>12,"tannin"=>6,"grassy"=>6,"honey"=>0), honey=>array("color"=>0,"vitamins"=>1,"glucose"=>10,"maltose"=>0,"barley"=>0,"tannin"=>0,"grassy"=>0,"honey"=>1) ); if ($yeast_id) { $flavors=array("barley","orange","banana","cherry","date","honey","nutmeg","cinnamon","tannin","grassy","nasty"); } else { $flavors=array("barley","honey","tannin","grassy"); } $total = $_SESSION["total"]; $addedIngr = $_SESSION["addedIngr"]; $tick = ceil($_POST['time']/36); foreach($b as $ingr => $data) { if ($_POST[$ingr]) { //echo "

" . $ingr . ":
"; foreach ($data as $attr => $baseValue) { if ($attr != "vitamins" && $attr != "glucose" && $attr != "maltose" && $attr !="honey") { $value = ($baseValue*$_POST[$ingr]) * ((1/6) + ((5/6)*($tick/100))); } elseif ($attr == "vitamins") { $temp = pow(((100 - $tick) / 10 ),2); $value = ($baseValue*$_POST[$ingr])*(1+ ((3/36) * $temp)); } elseif ($attr == "honey") { //$value = ($baseValue*$_POST[$ingr]) * ((2/3) + ((1/3)*(100/$tick))); $value = ($baseValue*$_POST[$ingr]) * (100/(5+$tick)); } else { $value = $baseValue * $_POST[$ingr]; } $total[$attr] += round($value); } } } $yeast = mysql_fetch_array($res); if ($yeast_id > 0) { // figure alcohol if ($yeast['max_alcohol'] < 1) $yeast['max_alcohol'] = 10000; $glucoseToConsume=MAX(($total['glucose']-$yeast['min_glucose']),0); $maltoseToConsume=MAX(($total['maltose']-$yeast['min_maltose']),0); $glucose = $total['glucose'] - MIN($glucoseToConsume,$yeast['max_alcohol']); $maltose = $total['maltose'] - MIN($maltoseToConsume,($yeast['max_alcohol']-($total['glucose']-$glucose))); $alcohol = min($total['glucose'] - $glucose + $total['maltose'] - $maltose,$yeast['max_alcohol']) ; // figure vitamins $vitamins = round($total['vitamins'] - ($alcohol * $yeast['vit_consume'])); if ($vitamins < $yeast['min_vit']) { $alcohol = round(($total['vitamins']-$yeast['min_vit'])/$yeast['vit_consume']); $vitamins = $yeast['min_vit']; } } else { $alcohol = "n/a"; $glucose = $total['glucose']; $maltose = $total['maltose']; } // figure flavors $res = mysql_query("SELECT * from yeast_flavor WHERE yeast_id=" . $yeast_id); $flavorData = mysql_fetch_array($res); foreach ($flavors as $flav) { $flavor[$flav] = round(($alcohol/$flavorData[$flav])) + $total[$flav]; } } else { //if form hasn't yet been submitted, pull all available yeasts $res = mysql_query("SELECT yeast_id from yeast"); } ?> Beer Calc

Beer Calculator v.1.0

View Source
Add yeast Data
See current yeast data

TIME ADDED: YEAST: Y-
IngredientAmount
Burnt Malt
Dark Roast Malt
Medium Roast Malt
Light Roast Malt
Raw Malt
Honey

900) $descriptor = "Potent "; if ($alcohol > 1200) $descriptor = "Very Potent "; if ($total['color'] > 500) $descriptor .= "Black "; elseif ($total['color'] > 200) $descriptor .= "Brown "; if ($flavor['orange'] + $flavor['banana'] + $flavor['cherry'] + $flavor['date'] + $flavor['honey'] > 500) $descriptor .= "Fruity "; if ($flavor['nutmeg'] + $flavor['cinnamon'] > 300) $descriptor .= "Spicy "; // dry or sweet? if (($alcohol/$sugar) < 5) $descriptor .= "Sweet (?) "; elseif (($alcohol/$sugar) > 7) $descriptor .="Dry (?) "; $descriptor .= "Beer. "; foreach ($flavor as $attr=>$value) { $flavorOutput .= "" . $attr . ": " . $value . "
"; if ($value > 1000 ) { $tempFlavorDesc = "Bold " . $attr . " flavor. "; $f++; } elseif ($value > 500) { $tempFlavorDesc = "Noticible " . $attr . " flavor. "; $f++; } elseif ($value > 200) { $tempFlavorDesc = "Hint of " . $attr . " flavor. "; $f++; } else $tempFlavorDesc = ""; $flavorDesc .= $tempFlavorDesc; } if ($f > 2) $flavorDesc = "Muddled flavors."; $descriptor .= $flavorDesc; //if (($alcohol/$sugar) > 17 && $alcohol > 1000) $descriptor = "Caustic Beer.(?)"; // Cloying & Bitter use the formulae provided by Tamutnefret in this post: // http://www.atitdportal.com/phpBB2/posting.php?mode=quote&p=125863 if (($sugar/2) > ($flavor['tannin'] + $spices)) $descriptor .= " (Cloying Beer.(?))"; if ($sugar < ($flavor['tannin'] + ($spices/5))) $descriptor .= " (Bitter Beer.(?))"; if ($flavor['grassy'] > 100) $descriptor = "Grassy Beer."; if ($alcohol < 100) $descriptor = "Nonalcoholic Soup."; if (!$yeast_id) $descriptor = ""; // show totals echo "

TOTALS"; if ($yeast_id) echo " for Y-" . $yeast_id; echo ":

"; ?>

Alcohol:
Color:
Vitamins: (started at )

Glucose: (started at )
Maltose: (started at ) $value) { if ($flavors[$attr]) next; echo "" . $attr . ": " . $value . "
"; } */ echo "

Flavors:

"; echo $flavorOutput; echo "

"; // show all ingredients added thus far $addedIngr .="At time " . $_POST['time'] . ", added:"; foreach ($b as $ingr => $data) { if ($_POST[$ingr]) $addedIngr .= $_POST[$ingr] ." " . $ingr .", "; } $addedIngr .= "
"; echo "

$addedIngr
"; // remember totals/ingredients for next time $_SESSION["total"] = $total; $_SESSION["addedIngr"] = $addedIngr; } elseif ($_POST['reset']) { // Unset all of the session variables. $_SESSION = array(); // Finally, destroy the session. session_destroy(); } ?>
This is a work in progress.... Many thanks to fellow brewers Kem, Huldo, Anax, Temander, Varen, and everyone else who contributes to this line of research. Especially Huldo, whose beer research project has been a great boon to this project.

Obviously, we need to know more about how the different yeasts work. If you have a yeast not represented here, please send me info about it and I'll add it to the database this runs off of, so you can use the calculator for it. This is what I need:

  1. The Glucose floor. (The amount of glucose left at which a yeast "thinks" the glucose has run out, and will process no more.) You will notice that your number for glucose is often the same -- this is your glucose floor. (note that if you are hitting the "alcohol ceiling" (oh my god it's spinning! ), this number won't be apparent, b/c the yeast is dying off before consuming all the sugars. In this case, you'll need to lower your starting sugar values until you get a result below your max alcohol level -- at which point the sugar floors will reveal themselves to you.
  2. The Maltose floor. Same as above, but substitute maltose for glucose. This is usually a significantly higher number.
  3. The alcohol ceiling. The alcohol value above which the yeast will not go despite the presence of *more* than the values of either 1 or 2 above. You'll know you've hit this when your maltose level is higher than the maltose floor.
  4. Rate of conversion to flavors. To find this, take: Alcohol level of beer/flavor level. This works for the following flavors: Orange, Banana, Cherry, Date, Nutmeg, Cinnamon, and Nasty. If your yeast produces barley, grassy, honey, or tannin flavors, first subtract the expected level of those flavors for your ingredient mix (using my online calculator, for instance ), then calculate the ratio.

Send me this data, and I'll add it to the calc. If it's too complicated, you could also just send me some ingredient lists (including times addeD), and screenshots of the final results. Make sure you have isolated a single yeast, though!

email to shakey(at)so-sad.com - shakey

changelog:

.1: initial release
.2: fixed vitamin calculation
.21: fixed glucose and maltose calculation, not dependent on time
.5b: added yeast interaction
.6: fixed honey flavor computation (not perfect yet, but closer), added beer descriptors (very very rough)
.61: fixed maltose computation
.9: Merged non-yeast and yeast beer calculators
.91: Fixed grassy flavor computation for light malt
.95: Added vitamin consumption, still experimental...
1.0: Open sourced, improved honey calculation (?), changed to "tick"-based time computation