www/js/rec_edit.js

changeset 149
ff45488d480e
parent 148
c0f0bbfefd63
child 150
159d7a89fcef
--- a/www/js/rec_edit.js	Wed Dec 19 21:58:21 2018 +0100
+++ b/www/js/rec_edit.js	Sun Dec 23 20:13:36 2018 +0100
@@ -44,16 +44,35 @@
 
 $(document).ready(function () {
 
-	var	to_100 = false;	// Fermentables adjust to 100%
+	var	to_100 = false;		// Fermentables adjust to 100%
 	var	preboil_sg = 0;
-	var	sugarsm = 0;	// Sugars after mash
-	var	sugarsf = 0;	// Sugars after boil
-	var     psugar = 0;     // Percentage real sugars
-	var     pcara = 0;      // Percentage cara/crystal malts
-	var	svg = 77;	// Default attenuation
+	var	sugarsm = 0;		// Sugars after mash
+	var	sugarsf = 0;		// Sugars after boil
+	var     psugar = 0;     	// Percentage real sugars
+	var     pcara = 0;      	// Percentage cara/crystal malts
+	var	svg = 77;		// Default attenuation
+	var	mashkg = 0;		// Malt in mash weight
 	var	hop_flavour = 0;
 	var	hop_aroma = 0;
 	var	mash_infuse = 0;
+	var	last_base = '';
+	var	last_acid = '';
+
+	var     MMCa = 40.048;
+	var     MMMg = 24.305;
+	var     MMNa = 22.98976928;
+	var     MMCl = 35.453;
+	var     MMSO4 = 96.0626;
+	var     MMCO3 = 60.01684;
+	var     MMHCO3 = 61.01684;
+	var     MMCaSO4 = 172.171;
+	var     MMCaCl2 = 147.015;
+	var     MMCaCO3 = 100.087;
+	var     MMMgSO4 = 246.475;
+	var     MMNaHCO3 = 84.007;
+	var     MMNa2CO3 = 105.996;
+	var     MMNaCl = 58.443;
+	var     MMCaOH2 = 74.06268;
 
 	console.log("record:" + my_record + "  return:" + my_return + "  theme:" + theme);
 	$("#jqxLoader").jqxLoader({
@@ -70,6 +89,7 @@
 		sugarsm = 0;
 		psugar = 0;
 		pcara = 0;
+		mashkg = 0;
 		var colorw = 0;	// Colors working
 		var my_100 = false;
 
@@ -84,25 +104,29 @@
 				pcara += row.f_percentage;
 			var d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
 			if (row.f_added == "Mash") {
-				d = parseFloat($("#efficiency").jqxNumberInput('decimal')) / 100 * d;
+				d = parseFloat(dataRecord.efficiency) / 100 * d;
 				sugarsm += d;
+				mashkg += row.f_amount;
 			}
 			sugarsf += d;
-			colorw += row.f_amount * ebc_to_srm(row.f_color) / parseFloat($("#batch_size").jqxNumberInput('decimal')) * 8.34436;
+			colorw += row.f_amount * ebc_to_srm(row.f_color) / parseFloat(dataRecord.batch_size) * 8.34436;
 		}
-		if (to_100 != my_100)
-			console.log("change to_100 to:"+my_100);
 		to_100 = my_100;
-		var est_og = estimate_sg(sugarsf, parseFloat($("#batch_size").jqxNumberInput('decimal')));
+		var est_og = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size));
 		$('#est_og').val(est_og);
 		$('#est_og2').val(est_og);
-		preboil_sg = estimate_sg(sugarsm, parseFloat($("#boil_size").jqxNumberInput('decimal')));
-		var color = kw_to_ebc($("#color_method").val(), colorw);
+		preboil_sg = estimate_sg(sugarsm, dataRecord.boil_size);
+		var color = kw_to_ebc(dataRecord.color_method, colorw);
 		$('#est_color').val(color);
 		$('#est_color2').val(color);
 		var scolor = ebc_to_color(color);
 		document.getElementById("bcolor").style.background= scolor;
 		document.getElementById("bcolor2").style.background= scolor;
+		// Use boil_size instead of mash_max from equipment.
+		pmalts = mashkg / (dataRecord.boil_size / 3) * 100;
+		$("#perc_malts").jqxProgressBar('val', pmalts);
+		$("#perc_sugars").jqxProgressBar('val', psugar);
+		$("#perc_cara").jqxProgressBar('val', pcara);
 	};
 
 	function hopFlavourContribution(bt, vol, use, amount) {
@@ -149,11 +173,11 @@
 		var rows = $('#hopGrid').jqxGrid('getrows');
 		for (var i = 0; i < rows.length; i++) {
 			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());
-			hop_flavour += hopFlavourContribution(parseFloat(row.h_time), parseFloat($("#batch_size").jqxNumberInput('decimal')),
+			total_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, parseFloat(dataRecord.batch_size),
+					parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method);
+			hop_flavour += hopFlavourContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size),
 						row.h_useat, parseFloat(row.h_amount));
-			hop_aroma += hopAromaContribution(parseFloat(row.h_time), parseFloat($("#batch_size").jqxNumberInput('decimal')),
+			hop_aroma += hopAromaContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size),
 					        row.h_useat, parseFloat(row.h_amount));
 		}
 		total_ibus = Math.round(total_ibus);
@@ -174,6 +198,59 @@
 		}
 	}
 
+	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) {
+//				console.log("need to add this misc");
+				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);
+//								console.log("result: "+commit);
+							}
+						}
+					}
+				});
+				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>");
@@ -186,6 +263,49 @@
 		return 0;
 	}
 
+	var Ka1 = 0.0000004445;
+	var Ka2 = 0.0000000000468;
+
+	function PartCO3(pH) {
+		var H = Math.pow(10, -pH);
+		return 100 * Ka1 * Ka2 / (H*H + H * Ka1 + Ka1 * Ka2);
+	}
+
+	function PartHCO3(pH) {
+		var H = Math.pow(10, -pH);
+		return 100 * Ka1 * H / (H*H + H * Ka1 + Ka1 * Ka2);
+	}
+
+	function Charge(pH) {
+		return (-2 * PartCO3(pH) - PartHCO3(pH));
+	}
+
+	//Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH)
+	function ZAlkalinity(pHZ) {
+		var C43 = Charge(4.3);
+		var Cw = Charge(parseFloat(dataRecord.mash_ph));
+		var Cz = Charge(pHZ);
+		var DeltaCNaught = -C43+Cw;
+		var CT = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')) / 50 / DeltaCNaught;
+		var DeltaCZ = -Cz+Cw;
+		return CT * DeltaCZ;
+	}
+
+	function ZRA(pHZ) {
+
+		var Calc = parseFloat($("#wg_calcium").jqxNumberInput('decimal')) / (MMCa / 2);
+		var Magn = parseFloat($("#wg_magnesium").jqxNumberInput('decimal')) / (MMMg / 2);
+		var Z = ZAlkalinity(pHZ);
+		return Z - (Calc / 3.5 + Magn / 7);
+	}
+
+	function ProtonDeficit(pHZ) {
+
+		var Result = ZRA(pHZ) * parseFloat($("#wg_amount").jqxNumberInput('decimal'));
+
+		return Result;
+	}
+
 	function calcWater() {
 
 		console.log("calcWater()");
@@ -197,18 +317,29 @@
 		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;
 
 //		console.log((dataRecord.w1_name != "") + " " + (dataRecord.w2_name != ""));
 		if (dataRecord.w1_name != "") {
 			if (dataRecord.w2_name != "") {
 				liters = dataRecord.w1_amount + dataRecord.w2_amount;
-				calcium = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium) * 10) / 10;
-				magnesium = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium) * 10) / 10;
-				sodium = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium) * 10) / 10;
-				chloride = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride) * 10) / 10;
-				sulfate = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate) * 10) / 10;
-				total_alkalinity = Math.round(mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity) * 10) / 10;
-				ph = Math.round(-Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount))  / liters) * 10) / 10;
+				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;
@@ -216,47 +347,140 @@
 				sodium = dataRecord.w1_sodium;
 				chloride = dataRecord.w1_chloride;
 				sulfate = dataRecord.w1_sulfate;
-				total_alkalinity = dataRecord.total_alkalinity;
+				total_alkalinity = dataRecord.w1_total_alkalinity;
 				ph = dataRecord.w1_ph;
 			}
 		}
 		$('#wg_amount').val(liters);
-		$('#wg_calcium').val(calcium);
-		$('#wg_magnesium').val(magnesium);
-		$('#wg_sodium').val(sodium);
-		$('#wg_total_alkalinity').val(total_alkalinity);
-		$('#wg_chloride').val(chloride);
-		$('#wg_sulfate').val(sulfate);
+		$('#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(ph);
+		$('#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'));
 
-		// Brouwhulp < 40 || > 200
-		if (calcium < 50) { setRangeIndicator("calcium", "low"); }
-		if (calcium >= 50 && calcium <= 150) { setRangeIndicator("calcium", "normal"); }
-		if (calcium > 150) { setRangeIndicator("calcium", "high"); }
-		if (calcium > 250) { setRangeIndicator("calcium", "harmful"); }
+		// 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;
 
-		// Brouwhulp > 40
-		if (magnesium >= 0 && magnesium <= 30) { setRangeIndicator("magnesium", "normal"); }
-		if (magnesium > 30) { setRangeIndicator("magnesium", "high"); }
-		if (magnesium > 50) { setRangeIndicator("magnesium", "harmful"); }
+			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;
 
-		// Brouwhulp > 100
-		if (sodium <= 150) { setRangeIndicator("sodium", "normal"); }
-		if (sodium > 150) { setRangeIndicator("sodium", "high"); }
-		if (sodium > 200) { setRangeIndicator("sodium", "harmful"); }
+			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;
 
-		// Brouwhulp > 200
-		if (chloride <= 250) { setRangeIndicator("chloride", "normal"); }
-		if (chloride > 250) { setRangeIndicator("chloride", "high"); }
-		if (chloride > 300) { setRangeIndicator("chloride", "harmful"); }
+			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);
 
-		// Brouwhulp > 600
-		if (sulfate < 50) { setRangeIndicator("sulfate", "low"); }
-		if (sulfate >= 50 && sulfate <= 350) { setRangeIndicator("sulfate", "normal"); }
-		if (sulfate > 350) { setRangeIndicator("sulfate", "high"); }
-		if (sulfate > 750) { setRangeIndicator("sulfate", "harmful"); }
-
+                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 calcFermentablesFromOG(OG) {
@@ -298,6 +522,14 @@
 
 		$("#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);
@@ -312,6 +544,43 @@
 			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) {
@@ -362,6 +631,7 @@
 			calcIBUs();                                     // and the IBU's.
 		});
 		$('#mash_ph').on('change', function (event) {
+			dataRecord.mash_ph = parseFloat(event.args.value);
 			$("#tgt_mash_ph").val(parseFloat(event.args.value));
 			calcWater();
 		});
@@ -445,6 +715,11 @@
 	$("#st_abv_max").jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'});
 	$("#st_carb_min").jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'});
 	$("#st_carb_max").jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'});
+	$("#wa_cacl2").jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.'});
+	$("#wa_caso4").jqxTooltip({ content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.'});
+	$("#wa_mgso4").jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!'});
+	$("#wa_nacl").jqxTooltip({ content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.'});
+	$("#w2_amount").jqxTooltip({ content: 'De verdeling van het hoofd en meng water. Het totale maisch water volume blijft gelijk.'});
 
 	// prepare the data
 	var source = {
@@ -1158,14 +1433,52 @@
 					row.m_weight = row.m_amount * 1000;
 					data.push(row);
 					// Initial set water agent values.
-					if (row.m_name == 'CaCl2')
-						$("#wa_cacl2").val(row.m_weight);
-					if (row.m_name == 'CaSO4')
-						$("#wa_caso4").val(row.m_weight);
-					if (row.m_name == 'MgSO4')
-						$("#wa_mgso4").val(row.m_weight);
-					if (row.m_name == 'NaCl')
-						$("#wa_nacl").val(row.m_weight);
+					switch (row.m_name) {
+						case 'CaCl2':		$("#wa_cacl2").val(row.m_weight);
+									break;
+						case 'CaSO4':		$("#wa_caso4").val(row.m_weight);
+									break;
+						case 'MgSO4':		$("#wa_mgso4").val(row.m_weight);
+									break;
+						case 'NaCl':		$("#wa_nacl").val(row.m_weight);
+									break;
+						case 'Melkzuur':	$("#wa_acid_name").val('Melkzuur');
+									$("#wa_acid").val(row.m_weight);
+									$("#wa_acid_perc").val(80);
+									last_acid = 'Melkzuur';
+									break;
+						case 'Zoutzuur':	$("#wa_acid_name").val('Zoutzuur');
+									$("#wa_acid").val(row.m_weight);
+									$("#wa_acid_perc").val(80);
+									last_acid = 'Zoutzuur';
+									break;
+						case 'Fosforzuur':	$("#wa_acid_name").val('Fosforzuur');
+									$("#wa_acid").val(row.m_weight);
+									$("#wa_acid_perc").val(80);
+									last_acid = 'Fosforzuur';
+									break;
+						case 'Zwavelzuur':	$("#wa_acid_name").val('Zwavelzuur');
+									$("#wa_acid").val(row.m_weight);
+									$("#wa_acid_perc").val(80);
+									last_acid = 'Zwavelzuur';
+									break;
+						case 'NaHCO3':		$("#wa_base_name").val('NaHCO3');
+									$("#wa_base").val(row.m_weight);
+									last_base = 'NaHCO3';
+									break;
+						case 'Na2CO3':		$("#wa_base_name").val('Na2CO3');
+									$("#wa_base").val(row.m_weight);
+									last_base = 'Na2CO3';
+									break;
+						case 'CaCO3':		$("#wa_base_name").val('CaCO3');
+									$("#wa_base").val(row.m_weight);
+									last_base = 'CaCO3';
+									break;
+						case 'Ca(OH)2':		$("#wa_base_name").val('Ca(OH)2');
+									$("#wa_base").val(row.m_weight);
+									last_base = 'Ca(OH)2';
+									break;
+					}
 				}
 				return data;
 			},
@@ -1645,7 +1958,7 @@
 	var srcColor = [ "Morey", "Mosher", "Daniels" ];
 	//var srcIBU = [ "Tinseth", "Rager", "Garetz", "Daniels", "Mosher", "Noonan" ];
 	var srcIBU = [ "Tinseth", "Rager", "Daniels" ];	// Only these are supported at this time.
-	var srcDeAcid = [ "NaHCO3", "Na2CO3", "CaCO3", "Ca(OH)2" ];
+	var srcBase = [ "NaHCO3", "Na2CO3", "CaCO3", "Ca(OH)2" ];
 	var srcAcid = [ "Melkzuur", "Zoutzuur", "Fosforzuur", "Zwavelzuur" ];
 	$("#name").jqxInput({ theme: theme, width: 640, height: 23 });
 	$("#notes").jqxInput({ theme: theme, width: 960, height: 200 });
@@ -1693,9 +2006,12 @@
 	$("#mash_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 4, max: 8, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 });
 	$("#tgt_mash_ph").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, readOnly: true });
 	$("#sparge_temp").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 70, max: 98, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.5 });
-	// Hop flavour and aroma gauges
+	// Several gauges
 	$("#hop_flavour").jqxProgressBar({ width: 300, height: 23, theme: theme, showText: true });
 	$("#hop_aroma").jqxProgressBar({ width: 300, height: 23, theme: theme, showText: true });
+	$("#perc_malts").jqxProgressBar({ width: 300, height: 23, theme: theme, showText: true });
+	$("#perc_sugars").jqxProgressBar({ width: 300, height: 23, theme: theme, showText: true });
+	$("#perc_cara").jqxProgressBar({ width: 300, height: 23, theme: theme, showText: true });
 
 	// Water treatment
 	$("#w1_name").jqxDropDownList({
@@ -1802,13 +2118,34 @@
 	$("#wb_sulfate").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#wb_ph").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 
+	$("#pr_name").jqxDropDownList({
+		placeHolder: "Kies doel profiel:",
+		theme: theme,
+		source: waterprofiles,
+		displayMember: "name",
+		width: 250,
+		height: 27,
+		dropDownWidth: 400,
+		dropDownHeight: 300
+	});
+	$("#pr_name").on('select', function (event) {
+		if (event.args) {
+			var index = event.args.index;
+			var datarecord = waterprofiles.records[index];
+			$("#pr_calcium").val(datarecord.calcium);
+			$("#pr_sulfate").val(datarecord.sulfate);
+			$("#pr_chloride").val(datarecord.chloride);
+			$("#pr_sodium").val(datarecord.sodium);
+			$("#pr_magnesium").val(datarecord.magnesium);
+			$("#pr_total_alkalinity").val(datarecord.total_alkalinity);
+		}
+        });
 	$("#pr_calcium").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#pr_magnesium").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#pr_sodium").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#pr_total_alkalinity").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#pr_chloride").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 	$("#pr_sulfate").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
-	$("#pr_ph").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 74, height: 23, decimalDigits: 1, readOnly: true });
 
 	$("#wa_cacl2").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' });
 	$("#wa_caso4").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' });
@@ -1816,10 +2153,11 @@
 	$("#wa_nacl").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, symbol: ' gr', symbolPosition: 'right' });
 
 	$("#calc_acid").jqxCheckBox({ theme: theme, width: 120, height: 23 });
-	$("#wa_ph_up").jqxDropDownList({ theme: theme, source: srcDeAcid, width: 125, height: 23, dropDownHeight: 128 });
-	$("#wa_ph_up").val('NaHCO3');
-	$("#wa_ph_down").jqxDropDownList({ theme: theme, source: srcAcid, width: 125, height: 23, dropDownHeight: 128 })
-	$("#wa_ph_down").val('Melkzuur');
+	$("#wa_base_name").jqxDropDownList({ theme: theme, source: srcBase, width: 125, height: 23, dropDownHeight: 128 });
+	$("#wa_base").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 2, spinButtons: true, spinButtonsStep: 0.05, symbol: ' gr', symbolPosition: 'right' });
+	$("#wa_acid_name").jqxDropDownList({ theme: theme, source: srcAcid, width: 125, height: 23, dropDownHeight: 128 })
+	$("#wa_acid").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, min: 0, decimalDigits: 2, spinButtons: true, spinButtonsStep: 0.05, symbol: ' ml', symbolPosition: 'right' });
+	$("#wa_acid_perc").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 80, height: 23, min: 0, max: 100, decimalDigits: 0, spinButtons: true, symbol: '%', symbolPosition: 'right' });
 
 	$("#sparge_volume").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 });
 	$("#sparge_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 100, height: 23, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1 });

mercurial