Estimate OG recalculation now uses the equipment profile. Added basic water calculations.

Tue, 25 Dec 2018 15:06:39 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 25 Dec 2018 15:06:39 +0100
changeset 153
15fe253ffa83
parent 152
2e4249add363
child 154
ef298b5aa994

Estimate OG recalculation now uses the equipment profile. Added basic water calculations.

www/js/prod_edit.js file | annotate | diff | comparison | revisions
--- a/www/js/prod_edit.js	Tue Dec 25 13:42:36 2018 +0100
+++ b/www/js/prod_edit.js	Tue Dec 25 15:06:39 2018 +0100
@@ -152,19 +152,15 @@
 					sug2 += row.f_amount * x;
 				}
 			}
-	//              if FEquipment <> NIL then               /* Use this for prod_edit.js
-	//              begin
-	//              	sug:= SGToPlato(OG) * OG / 100; //kg/l
-	//              	vol1:= FBatchSize.Value - FEquipment.TrubChillerLoss.Value;
-	//              	vol2:= vol1 + FEquipment.TopUpWater.Value + vol;
-	//              	sug:= sug * vol2; //kg in het gistvat
-	//              	sug:= sug - sug2; //kg voor toevoeging in gistvat
-	//              	if vol1 > 0 then
-	//              		sug:= sug * FBatchSize.Value / vol1; //kg in kookketel
-	//              	sug:= sug + sug2;
-	//              end
-	//              else
-				sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100;      //total amount of sugars in kg
+			sug = sg_to_plato(OG) * OG / 100;	// kg/l
+			vol1 = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss;
+			vol2 = vol1 + dataRecord.eq_top_up_water + vol;
+			sug = sug * vol2;	// kg in het gistvat
+			sug = sug - sug2;	// kg voor toevoeging in gistvat
+			if (vol1 > 0)
+				sug = sug * dataRecord.batch_size / vol1;	//kg in kookketel
+			sug = sug + sug2;
+			//	sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100;      //total amount of sugars in kg
 
 			tot = 0;
 			d = 0;
@@ -309,12 +305,321 @@
 			$("#brew_mash_efficiency").val(0);
 	};
 
+	function setWaterAgent(name, amount) {
+		console.log("setWaterAgent(" + name + ", " + amount + ")");
+		var rows = $('#miscGrid').jqxGrid('getrows');
+		if (amount == 0) {
+			for (var i = 0; i < rows.length; i++) {
+				var row = rows[i];
+				if (row.m_name == name) {
+					var id = $("#miscGrid").jqxGrid('getrowid', i);
+					// console.log("name found, erase "+ id);
+					var commit = $("#miscGrid").jqxGrid('deleterow', id);
+					// console.log("result: "+commit);
+				}
+			}
+		} else {
+			var found = false;
+			for (var i = 0; i < rows.length; i++) {
+				var row = rows[i];
+				if (row.m_name == name) {
+					found = true;
+					$("#miscGrid").jqxGrid('setcellvalue', i, 'm_weight', amount);
+					$("#miscGrid").jqxGrid('setcellvalue', i, 'm_amount', amount / 1000);
+					break;
+				}
+			}
+			console.log("set something, found: "+found);
+			if (! found) {
+				var miscs = new $.jqx.dataAdapter(miscInvSource, {
+					loadComplete: function () {
+						var records = miscs.records;
+						for (var i = 0; i < records.length; i++) {
+							var record = records[i];
+							if (record.name == name) {
+								var row = {};
+								row["m_name"] = record.name;
+								row["m_amount"] = amount / 1000;
+								row["m_cost"] = record.cost;
+								row["m_type"] = record.type;
+								row["m_use_use"] = record.use_use;
+								row["m_time"] = 0;
+								row["m_weight"] = amount;
+								row["m_amount_is_weight"] = record.amount_is_weight;
+								var commit = $("#miscGrid").jqxGrid('addrow', null, row);
+							}
+						}
+					}
+				});
+				miscs.dataBind();
+				return;
+			}
+		}
+	}
+
+	function setRangeIndicator(ion, rangeCode) {
+		$("#wr_" + ion).html("<img src='images/checkmark_range_" + rangeCode + ".gif'><span style='font-size: 10px; font-style: italic;'>" + rangeCode + "</span>");
+	}
+
+	function mix(v1, v2, c1, c2) {
+		if ((v1 + v2) > 0) {
+			return ((v1 * c1) + (v2 * c2)) / (v1 + v2);
+		}
+		return 0;
+	}
+
+	// pH calculations
+
+	function calcWater() {
+
+		console.log("calcWater()");
+		var liters = 0;
+		var calcium = 0;
+		var magnesium = 0;
+		var sodium = 0;
+		var total_alkalinity = 0;
+		var chloride = 0;
+		var sulfate = 0;
+		var ph = 0;
+		var RA = 0;
+		var acid = 0;
+		var frac = 0;
+		var MolWt = 0;
+		var pK1 = 0;
+		var pK2 = 0;
+		var pK3 = 0;
+		var TpH = 0;
+		var AcidSG = 0;
+		var AcidPrc = 0;
+		var protonDeficit = 0;
+
+		if (dataRecord.w1_name != "") {
+			if (dataRecord.w2_name != "") {
+				liters = dataRecord.w1_amount + dataRecord.w2_amount;
+				calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium);
+				magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium);
+				sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium);
+				chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride);
+				sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate);
+				total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity);
+				ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount))  / liters);
+			} else {
+				liters = dataRecord.w1_amount;
+				calcium = dataRecord.w1_calcium;
+				magnesium = dataRecord.w1_magnesium;
+				sodium = dataRecord.w1_sodium;
+				chloride = dataRecord.w1_chloride;
+				sulfate = dataRecord.w1_sulfate;
+				total_alkalinity = dataRecord.w1_total_alkalinity;
+				ph = dataRecord.w1_ph;
+			}
+		}
+		$('#wg_amount').val(liters);
+		$('#wg_calcium').val(Math.round(calcium * 10) / 10);
+		$('#wg_magnesium').val(Math.round(magnesium * 10) / 10);
+		$('#wg_sodium').val(Math.round(sodium * 10) / 10);
+		$('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
+		$('#wg_chloride').val(Math.round(chloride * 10) / 10);
+		$('#wg_sulfate').val(Math.round(sulfate * 10) / 10);
+		// Note: brouwhulp has the malts included here in the result.
+		$('#wg_ph').val(Math.round(ph * 10) / 10);
+
+		// Noot: de volgende berekeningen geven bijna gelijke resultaten in Brun'water.
+		// Calculate Ca
+		RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
+		     parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMCa / MMCaSO4;
+		calcium += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+
+		// Calculate Mg
+		RA = parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMMg / MMMgSO4;
+		magnesium += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+
+		// Calculate Na
+		RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
+		     parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
+		sodium += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+
+		// Calculate SO4
+		RA = parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 +
+		     parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMSO4 / MMMgSO4;
+		sulfate += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+
+		// Calculate Cl
+		RA = 2 * parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCl / MMCaCl2 +
+			 parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMCl / MMNaCl;
+		chloride += 1000 * RA / parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+		// Einde noot.
+
+		TpH = parseFloat(dataRecord.mash_ph);
+		if (TpH < 5.0 || TpH > 6.0) {
+			TpH = 5.4;
+			dataRecord.mash_ph = 5.4;
+			$("#mash_ph").val(5.4);
+			$("#tgt_mash_ph").val(5.4);
+		}
+		var acid_amount = parseFloat($("#wa_acid").jqxNumberInput('decimal'));
+		var acid_perc = parseFloat($("#wa_acid_perc").jqxNumberInput('decimal'));
+
+		switch ($("#wa_acid_name").val()) {
+			case 'Melkzuur':        pK1 = 3.08;
+						pK2 = 20;
+						pK3 = 20;
+						MolWt = 90.08;
+						AcidSG = 1214; //@88%
+						AcidPrc = 0.88;
+						//frac = CalcFrac(TpH, pK1, pK2, pK3);
+						acid += acid_amount * acid_perc / 100 * AcidSG / MolWt * frac / liters; //mEq/l
+						break;
+
+			case 'Zoutzuur':        pK1 = -10;
+						pK2 =  20;
+						pK3 =  20;
+						MolWt = 36.46;
+						AcidSG = 1142; //@28%
+						AcidPrc = 0.28;
+						//frac = CalcFrac(TpH, pK1, pK2, pK3);
+						Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters;
+						acid += Acidmg / MolWt * frac; //mEq/l
+						chloride += Acidmg / 1000 * MMCl / (MMCl + 1);
+						break;
+
+			case 'Fosforzuur':      pK1 = 2.12;
+						pK2 = 7.20;
+						pK3 =  12.44;
+						MolWt = 98.00;
+						AcidSG = 1170; //@25%
+						AcidPrc = 0.25;
+						//frac = CalcFrac(TpH, pK1, pK2, pK3);
+						Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters;
+						acid += Acidmg / MolWt * frac; //mEq/l
+						break;
+
+			case 'Zwavelzuur':      pK1 = -10;
+						pK2 = 1.92;
+						pK3 = 20;
+						MolWt = 98.07;
+						AcidSG = 1700; //@93%
+						AcidPrc = 0.93;
+						//frac = CalcFrac(TpH, pK1, pK2, pK3);
+						Acidmg = acid_amount * acid_perc / 100 * AcidSG / liters;
+						acid += Acidmg / MolWt * frac; //mEq/l
+						sulfate += Acidmg / 1000 * MMSO4 / (MMSO4 + 2);
+						break;
+		}
+		//protonDeficit = ProtonDeficit(TpH);
+		//console.log("frac: "+frac+"  acid: "+acid+"  protonDeficit: "+protonDeficit);
+		//total_alkalinity -= 50 / 61 * protonDeficit * frac / liters;
+
+		$('#wb_calcium').val(Math.round(calcium * 10) / 10);
+		$('#wb_magnesium').val(Math.round(magnesium * 10) / 10);
+		$('#wb_sodium').val(Math.round(sodium * 10) / 10);
+		$('#wb_sulfate').val(Math.round(sulfate * 10) / 10);
+		$('#wb_chloride').val(Math.round(chloride * 10) / 10);
+		$('#wb_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
+
+		if (calcium < 40) {
+			setRangeIndicator("calcium", "low");
+		} else if (calcium > 150) {
+			setRangeIndicator("calcium", "high");
+		} else {
+			setRangeIndicator("calcium", "normal");
+		}
+		if (magnesium >= 0 && magnesium <= 30) {
+			setRangeIndicator("magnesium", "normal");
+		} else {
+			setRangeIndicator("magnesium", "high");
+		}
+		if (sodium <= 150) {
+			setRangeIndicator("sodium", "normal");
+		} else {
+			setRangeIndicator("sodium", "high");
+		}
+		if (chloride <= 100) {
+			setRangeIndicator("chloride", "normal");
+		} else {
+			setRangeIndicator("chloride", "high");
+		}
+		if (sulfate <= 350) {
+			setRangeIndicator("sulfate", "normal");
+		} else {
+			setRangeIndicator("sulfate", "high");
+		}
+	}
+
 	function calcInit () {
 		console.log("calc.init()");
 
 		calcSGendMash();
 		calcMashEfficiency();
 
+		$("#w1_name").jqxDropDownList('selectItem', dataRecord.w1_name);
+		$("#w2_name").jqxDropDownList('selectItem', dataRecord.w2_name);
+		// Fix tap water if zero using mash infuse amount.
+		if (parseFloat($("#wg_amount").jqxNumberInput('decimal')) == 0 && mash_infuse > 0) {
+			$("#w1_amount").val(mash_infuse);
+			dataRecord.w1_amount = mash_infuse;
+			$("#wg_amount").val(mash_infuse);
+			$("#w2_amount").val(0);
+			dataRecord.w2_amount = 0;
+		}
+		calcWater();
+		$("#w2_amount").on('change', function (event) {
+			var newval = parseFloat(event.args.value);
+
+			if (newval > mash_infuse) {
+				$("#w2_amount").val(dataRecord.w2_amount);
+				return;
+			}
+			dataRecord.w1_amount = parseFloat($("#wg_amount").jqxNumberInput('decimal')) - newval;
+			$("#w1_amount").val(dataRecord.w1_amount);
+			dataRecord.w2_amount = newval;
+			console.log("new: "+event.args.value+" w1: "+dataRecord.w1_amount+"  w2: "+dataRecord.w2_amount);
+			calcWater();
+		});
+		$('#wa_cacl2').on('change', function (event) {
+			setWaterAgent('CaCl2', event.args.value);
+			calcWater();
+		});
+		$('#wa_caso4').on('change', function (event) {
+			setWaterAgent('CaSO4', event.args.value);
+			calcWater();
+		});
+		$('#wa_mgso4').on('change', function (event) {
+			setWaterAgent('MgSO4', event.args.value);
+			calcWater();
+		});
+		$('#wa_nacl').on('change', function (event) {
+			setWaterAgent('NaCl', event.args.value);
+			calcWater();
+		});
+		$('#wa_base_name').on('change', function (event) {
+			setWaterAgent(last_base, 0);
+			last_base = event.args.item.value;
+			setWaterAgent(last_base, parseFloat($("#wa_base").jqxNumberInput('decimal')));
+			calcWater();
+		});
+		$('#wa_base').on('change', function (event) {
+			setWaterAgent($("#wa_base_name").val(), parseFloat(event.args.value));
+			calcWater();
+		});
+		$('#wa_acid_name').on('change', function (event) {
+			setWaterAgent(last_acid, 0);
+			last_acid = event.args.item.value;
+			setWaterAgent(last_acid, parseFloat($("#wa_acid").jqxNumberInput('decimal')));
+			calcWater();
+		});
+		$('#wa_acid').on('change', function (event) {
+			setWaterAgent($("#wa_acid_name").val(), parseFloat(event.args.value));
+			calcWater();
+		});
+		$('#wa_acid_perc').on('change', function (event) { calcWater(); });
+
+		$('#color_method').on('change', function (event) { calcFermentables(); });
+		$('#ibu_method').on('change', function (event) {
+			calcFermentables();
+			calcIBUs();
+		});
+
 		$('#batch_size').on('change', function (event) {
 			console.log("batch_size change:"+event.args.value+" old:"+dataRecord.batch_size);
 			var new_boil = parseFloat(event.args.value) + dataRecord.boil_size - dataRecord.batch_size;
@@ -360,7 +665,7 @@
 		$('#mash_ph').on('change', function (event) {
 			dataRecord.mash_ph = parseFloat(event.args.value);
 			$("#tgt_mash_ph").val(parseFloat(event.args.value));
-	//		calcWater();
+			calcWater();
 		});
 	};
 

mercurial