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
Get SQL for database & data (Mysql)
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(); } ?>
I quit ATITD a few months back, but have been maintaining the beer calculator a bit since then. It seems best to give to tool to the people, and release the source for it and the SQL to build the db. If anyone wants to get this running somewhere else, let me know and I can help and also provide a link to a new and improved calc.

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.

Please contribute to the yeast DB. I'll update the SQL periodically to account for new data going in. Here is a quick run down on how to find the info you'll 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.

email to shakey % so-sad.com (substitute a @ for the %, o'course) - 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