Added Tinseth IBU calculation.

Fri, 21 Sep 2018 17:10:41 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 21 Sep 2018 17:10:41 +0200
changeset 59
ad28e09e3abd
parent 58
83ccc36df675
child 60
dbbe408108ea

Added Tinseth IBU calculation.

www/import/from_brouwhulp.php file | annotate | diff | comparison | revisions
www/js/global.js file | annotate | diff | comparison | revisions
www/js/recipes.js file | annotate | diff | comparison | revisions
--- a/www/import/from_brouwhulp.php	Thu Sep 20 17:50:30 2018 +0200
+++ b/www/import/from_brouwhulp.php	Fri Sep 21 17:10:41 2018 +0200
@@ -601,6 +601,8 @@
 				$hops .= ',"h_useat":"' . mysqli_real_escape_string($db, $hop->USE) . '"';
 				if ($hop->TIME)
 					$hops .= ',"h_time":' . floatval($hop->TIME);
+				else
+					$hops .= ',"h_time":0';
 				$hops .= ',"h_alpha":' . floatval($hop->ALPHA);
 				$hops .= ',"h_beta":' . floatval($hop->BETA);
 				$hops .= ',"h_hsi":' . floatval($hop->HSI);
--- a/www/js/global.js	Thu Sep 20 17:50:30 2018 +0200
+++ b/www/js/global.js	Fri Sep 21 17:10:41 2018 +0200
@@ -90,3 +90,74 @@
 	$("#jqxWidget").css('visibility', 'visible');
 });
 
+
+
+/*
+ * Berekeningen uit https://www.hobbybrouwen.nl/forum/index.php/topic,6079.msg69464.html#msg69464
+ */
+function toIBU_Tinseth(Use, Form, SG, Volume, Amount, Boiltime, Alpha) {
+	var gravity = parseFloat(SG);
+	var liters  = parseFloat(Volume);
+	var alpha   = parseFloat(Alpha)/100;
+	var mass    = parseFloat(Amount) * 1000;
+	var time    = parseFloat(Boiltime);
+	var fmoment = 1.0;
+	var pfactor = 1.0;
+
+	if ((Use == "Dry Hop") || (Use == "Dry hop")) {
+		fmoment = 0.0;
+	} else if (Use == "Whirlpool") {
+		fmoment = 0.0;
+	} else if (Use == "Mash") {
+		fmoment = 0.7;		// Brouwhulp
+	} else if ((Use == "First Wort") || (Use == "First wort"))  {
+		fmoment = 1.1;		// Brouwhulp, Louis, Ozzie
+	} else if (Use == "Aroma") {
+		fmoment = 0.0;
+	}
+
+	if (Form == "Pellet") {
+		pfactor = 1.1;
+	}
+
+	// TODO:  sg = (postBoilGravity - 1.0) * batchSize / boilSize;
+
+	/*
+	 * http://realbeer.com/hops/research.html
+	 *
+	 *                             decimal AA rating * grams hops * 1000
+	 * mg/l of added alpha acids = -------------------------------------
+	 *			         volume of finished beer in liters
+	 *
+	 * Bigness factor = 1.65 * 0.000125^(wort gravity - 1)
+	 *
+	 *                    1 - e^(-0.04 * time in mins)
+	 * Boil Time factor = ----------------------------
+	 *                               4.15
+	 *
+	 * decimal alpha acid utilization = Bigness factor * Boil Time factor
+	 *
+	 * IBUs = decimal alpha acid utilization * mg/l of added alpha acids
+	 */
+	var AddedAlphaAcids = (alpha * mass * 1000) / liters;
+	var Bigness_factor = 1.65 * Math.pow( 0.000125, gravity - 1);
+	var BoilTime_factor = ((1 - Math.exp(-0.04 * time)) / 4.15);		// Glen Tinseth
+	var utiisation = Bigness_factor * BoilTime_factor;
+
+	console.log(" AddedAlphaAcids:"+AddedAlphaAcids+"  Bigness_factor:"+Bigness_factor+"  BoilTime_factor:"+BoilTime_factor+"  utilisation:"+utiisation);
+	console.log(" fmoment:"+fmoment+"  pfactor:"+pfactor);
+
+	var ibu = (Math.round(utiisation * AddedAlphaAcids * fmoment * pfactor * 10) / 10.0);
+	return ibu;
+}
+
+
+
+function toIBU(Use, Form, SG, Volume, Amount, Boiltime, Alpha, Method) {
+
+	console.log("toIBU_Tinseth("+Use+"," + Form + "," + SG + "," + Volume + "," + Amount + "," + Boiltime + "," + Alpha + "," + Method + ")");
+	return toIBU_Tinseth(Use, Form, SG, Volume, Amount, Boiltime, Alpha);
+}
+
+
+
--- a/www/js/recipes.js	Thu Sep 20 17:50:30 2018 +0200
+++ b/www/js/recipes.js	Fri Sep 21 17:10:41 2018 +0200
@@ -314,6 +314,7 @@
                 var hopSource = {
                         localdata: data.hops,
                         datatype: "local",
+			cache: false,
                         datafields: [
                                 { name: 'h_name', type: 'string' },
                                 { name: 'h_origin', type: 'string' },
@@ -430,9 +431,9 @@
                         },
                         columns: [
                                 { text: 'Hop', editable: false, datafield: 'h_name' },
-                                { text: 'Type', editable: false, width: 100, datafield: 'h_type' },
+                                { text: 'Type', editable: false, width: 90, align: 'center', cellsalign: 'center', datafield: 'h_type' },
+				{ text: 'Vorm', editable: false, width: 90, align: 'center', cellsalign: 'center', datafield: 'h_form' },
                                 { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
-				{ text: 'Beta', datafield: 'h_beta', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
                                 { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f3',
                                   columntype: 'numberinput',
                                   validation: function (cell, value) {
@@ -442,13 +443,28 @@
                                         return true;
                                   }
                                 },
-				{ text: 'Tijd', datafield: 'h_time', width: 110, align: 'right', cellsalign: 'right', cellsformat: 'f0',
+				{ text: 'Gebruik', width: 110, align: 'center', cellsalign: 'center', datafield: 'h_useat' },
+				{ text: 'Tijd', datafield: 'h_time', width: 70, align: 'right', cellsalign: 'right', cellsformat: 'f0',
 				  columntype: 'numberinput',
 				  validation: function (cell, value) {
 				  	if (value < 0 || value > 100000000000 ) {
 						return { result: false, message: "De tijd moet  0-~ zijn" };
 					}
 					return true;
+				  } // TODO: Only enable editing if Boil, else use fixed values.
+				},
+				{ text: 'IBU', editable: false, datafield: 'ibu', width: 80, align: 'right',
+				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
+					  var ibu = toIBU(rowdata.h_useat,
+							  rowdata.h_form,
+							  parseFloat($("#est_og").jqxNumberInput('decimal')),
+							  parseFloat($("#batch_size").jqxNumberInput('decimal')),
+							  parseFloat(rowdata.h_amount),
+							  parseFloat(rowdata.h_time),
+							  parseFloat(rowdata.h_alpha),
+							  $("#ibu_method").val()
+							 );
+					  return "<div style='margin: 4px;' class='jqx-right-align'>" + dataAdapter.formatNumber(ibu, "f1") + "</div>";
 				  }
 				}
                         ]
@@ -788,7 +804,7 @@
 				mash_ph: parseFloat($("#mash_ph").jqxNumberInput('decimal')),
 				mash_sparge_temp: parseFloat($("#mash_sparge_temp").jqxNumberInput('decimal')),
 				fermentables: fermentablerow,
-				hops: hopwor,
+				hops: hoprow,
 				waters: waterrow
 			};
 			$('#jqxgrid').jqxGrid('updaterow', rowID, row);

mercurial