Fixed estimate FG calculation during recipes import. Added estimate FG calculation in the recipe editor but do not yet update the recipe. Added SVG calculation to the recipes editor. Added calculations for hop aroma and flavour contribution.

Mon, 10 Dec 2018 22:20:19 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 10 Dec 2018 22:20:19 +0100
changeset 136
bcc4583fd013
parent 135
cd1403633e96
child 137
dfbf43b2797e

Fixed estimate FG calculation during recipes import. Added estimate FG calculation in the recipe editor but do not yet update the recipe. Added SVG calculation to the recipes editor. Added calculations for hop aroma and flavour contribution.

www/import/from_brouwhulp.php file | annotate | diff | comparison | revisions
www/js/global.js file | annotate | diff | comparison | revisions
www/js/rec_edit.js file | annotate | diff | comparison | revisions
--- a/www/import/from_brouwhulp.php	Sun Dec 09 22:27:38 2018 +0100
+++ b/www/import/from_brouwhulp.php	Mon Dec 10 22:20:19 2018 +0100
@@ -18,6 +18,7 @@
 $brouwhulp = '/home/mbroek/Documents/brouwhulp';
 $pCara = 0;
 $pSugar = 0;
+$svg = 77;
 $efficiency = 75;
 $batch_size = 20;
 $colorw = 0;
@@ -676,6 +677,7 @@
 function recipe_yeasts($recipe)
 {
 	global	$db;
+	global	$svg;
 
 	$yeasts = "[";
 	$comma = FALSE;
@@ -782,7 +784,7 @@
 
 function do_recipes()
 {
-	global $brouwhulp, $db, $efficiency, $batch_size, $pCara, $pSugar, $colorw, $f_sugars;
+	global $brouwhulp, $db, $efficiency, $batch_size, $pCara, $pSugar, $svg, $colorw, $f_sugars;
 	$len_fermentables = 0;
 	$len_hops = 0;
 	$len_miscs = 0;
--- a/www/js/global.js	Sun Dec 09 22:27:38 2018 +0100
+++ b/www/js/global.js	Mon Dec 10 22:20:19 2018 +0100
@@ -235,6 +235,36 @@
 }
 
 
+
+function estimate_fg(percSugar, percCara, WGratio, TotTme, Temp, attenuation, og) {
+
+	var	BD;
+
+	console.log("estimate_fg("+percSugar+","+percCara+","+WGratio+","+TotTme+","+Temp+","+attenuation+","+og+")");
+
+	if (percSugar > 40)
+		percSugar = 0;
+	if (percCara > 50)
+		percCara = 0;
+	if ((WGratio > 0) && (TotTme > 0)) {
+		BD = WGratio;
+		BD = max(2, min(5.5, BD));
+		Temp = max(60, min(72, Temp));
+	} else {
+		BD = 3.5;
+		Temp = 67;
+		TotTme = 75;
+	}
+	if (attenuation < 30)
+		attenuation = 77;
+
+	var AttBeer = 0.00825 * attenuation + 0.00817 * BD - 0.00684 * Temp + 0.00026 * TotTme - 0.00356 * percCara + 0.00553 * percSugar + 0.547;
+	var fg = Math.round((1 + (1 - AttBeer) * (og - 1)) * 1000) / 1000;
+	console.log("fg:"+fg);
+	return fg;
+}
+
+
 /*
  * Steinie:
  *
--- a/www/js/rec_edit.js	Sun Dec 09 22:27:38 2018 +0100
+++ b/www/js/rec_edit.js	Mon Dec 10 22:20:19 2018 +0100
@@ -51,6 +51,7 @@
 	var	sugarsf = 0;	// Sugars after boil
 	var     psugar = 0;     // Percentage real sugars
 	var     pcara = 0;      // Percentage cara/crystal malts
+	var	svg = 77;	// Default attenuation
 
 	console.log("record:" + my_record + "  return:" + my_return + "  theme:" + theme);
 	$("#jqxLoader").jqxLoader({
@@ -77,7 +78,7 @@
 				my_100 = true;
 			if (row.f_type == "Sugar")
 				psugar += row.f_percentage;
-			if (row.f_type == "Crystal")
+			if (row.f_graintype == "Crystal")
 				pcara += row.f_percentage;
 			var d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
 			if (row.f_added == "Mash") {
@@ -95,6 +96,42 @@
 		$('#est_color').val(kw_to_ebc($("#color_method").val(), colorw));
 	};
 
+	function hopFlavourContribution(bt, vol, use, amount) {
+		var result;
+
+		if ((use == "First Wort") || (use == "First wort")) {
+			result = 0.15 * amount * 1000;		// assume 15% flavourcontribution for fwh
+		} else if (bt > 50) {
+			result = 0.10 * amount * 1000;		// assume 10% flavourcontribution as a minimum
+		} else {
+			result = 15.25 / (6 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 21) /6, 2)) * amount * 1000;
+			if (result < (0.10 * amount * 1000))
+				result = 0.10 * amount * 1000;	// assume 10% flavourcontribution as a minimum
+		}
+		console.log("hopFlavourContribution("+bt+","+vol+","+use+","+amount+"): "+(result / vol));
+		return result / vol;
+	}
+
+	function hopAromaContribution(bt, vol, use, amount) {
+		var result = 0;
+
+		if (bt > 20) {
+			result = 0;
+		} else if (bt > 7.5) {
+			result = 10.03 / (4 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 7.5) /4, 2)) * amount * 1000;
+		} else if (use == "Boil") {
+			result = amount * 1000;
+		} else if (use == "Aroma") {
+			result = 1.2 * amount * 1000;
+		} else if (use == "Whirlpool") {
+			result = 1.2 * amount * 1000;
+		} else if ((use == "Dry Hop") || (use == "Dry hop")) {
+			result = 1.33 * amount * 1000;
+		}
+		console.log("hopAromaContribution("+bt+","+vol+","+use+","+amount+"): "+(result / vol));
+		return result / vol;
+	}
+
 	function calcIBUs() {
 		var total_ibus = 0;
 		var rows = $('#hopGrid').jqxGrid('getrows');
@@ -102,11 +139,24 @@
 			var row = rows[i];
 			total_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, parseFloat($("#batch_size").jqxNumberInput('decimal')),
 					parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), $("#ibu_method").val());
+			hopFlavourContribution(parseFloat(row.h_time), parseFloat($("#batch_size").jqxNumberInput('decimal')),
+						row.h_useat, parseFloat(row.h_amount));
+			hopAromaContribution(parseFloat(row.h_time), parseFloat($("#batch_size").jqxNumberInput('decimal')),
+					                                                row.h_useat, parseFloat(row.h_amount));
 		}
 		console.log("calcIBUs(): " + total_ibus);
 		$('#est_ibu').val(total_ibus);
 	};
 
+	function calcSVG() {
+		var rows = $('#yeastGrid').jqxGrid('getrows');
+		for (var i = 0; i < rows.length; i++) {
+			var row = rows[i];
+			if (row.y_use == "Primary")
+				svg = parseFloat(row.y_attenuation);
+		}
+	}
+
 	function calcFermentablesFromOG(OG) {
 
 		console.log("calcFermentablesFromOG("+OG+")");
@@ -157,6 +207,7 @@
 			dataRecord.batch_size = parseFloat(event.args.value);
 			calcFermentablesFromOG(parseFloat($("#est_og").jqxNumberInput('decimal')));     // Keep the OG
 			calcFermentables();
+			calcSVG();
 			calcABV();
 			// TODO: adjust the hops, miscs, yeast, water.
 			calcIBUs();
@@ -171,6 +222,7 @@
 			dataRecord.boil_size = new_boil;
 			$("#boil_size").val(Math.round(new_boil * 100) / 100);
 			calcFermentables();
+			calcSVG();
 			calcABV();
 			// TODO: adjust the hops, miscs, yeast, water.
 			calcIBUs();
@@ -178,6 +230,7 @@
 		$('#efficiency').on('change', function (event) {
 			console.log("efficiency change:"+event.args.value);
 			calcFermentables();
+			calcSVG();
 			calcABV();
 			calcIBUs();
 		});
@@ -185,6 +238,7 @@
 			console.log("est_og change:"+event.args.value);
 			calcFermentablesFromOG(event.args.value);       // Adjust fermentables amounts
 			calcFermentables();                             // Update the recipe details
+			calcSVG();
 			calcABV();                                      // and ABV
 			calcIBUs();                                     // and the IBU's.
 		});
@@ -583,6 +637,7 @@
 						$("#fermentableGrid").jqxGrid('setcellvalue', 0, "f_percentage", 100);
 					}
 					calcFermentables();
+					calcSVG();
 					calcABV();
 					calcIBUs();
 				});
@@ -719,6 +774,7 @@
 			};
 			$('#fermentableGrid').jqxGrid('sortby', 'f_amount', 'desc');	// TODO: not reliable
 			calcFermentables();
+			calcSVG();
 			calcABV();
 			calcIBUs();	// Depends on gravity, so recalculate.
 		});
@@ -1160,6 +1216,7 @@
                                 });
                         },
 			ready: function() {
+				calcSVG();
 				$('#jqxTabs').jqxTabs('next');
 			},
                         columns: [
@@ -1395,6 +1452,7 @@
                                 });
                         },
 			ready: function() {
+				var fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, parseFloat(parseFloat($("#est_og").jqxNumberInput('decimal'))));
 				calcInit();
 				$('#jqxLoader').jqxLoader('close');
 				$('#jqxTabs').jqxTabs('first');

mercurial