diff -r 029e65ca3678 -r 1246550451ca www/js/rec_edit.js
--- a/www/js/rec_edit.js Fri May 01 21:37:23 2020 +0200
+++ b/www/js/rec_edit.js Wed May 06 14:14:14 2020 +0200
@@ -48,7 +48,12 @@
MMNaHCO3 = 84.007,
MMNa2CO3 = 105.996,
MMNaCl = 58.443,
- MMCaOH2 = 74.06268;
+ MMCaOH2 = 74.06268,
+ SpecificHeatWater = 1.0,
+ SpecificHeatMalt = 0.399, //cal/g.°C
+ SlakingHeat = 10.318, //cal/g.°C
+ eq_tun_weight = 2.0, // 2 Kg pot
+ eq_tun_specific_heat = 0.110, // Stainless Steel
data_loaded = 0;
function createDelElements() {
@@ -348,18 +353,90 @@
}
+function swapMash(r1, r2) {
+
+ console.log('swap mash rows ' + r1 + ' ' + r2);
+ var row1 = $('#mashGrid').jqxGrid('getrowdata', r1);
+ var row2 = $('#mashGrid').jqxGrid('getrowdata', r2);
+ var obj1 = { step_name: row1.step_name, step_type: row1.step_type, step_volume: row1.step_volume, step_infuse_amount: row1.step_infuse_amount,
+ step_infuse_temp: row1.step_infuse_temp, step_temp: row1.step_temp, step_time: row1.step_time,
+ ramp_time: row1.ramp_time, end_temp: row1.end_temp, step_wg_ratio: row1.step_wg_ratio };
+ var obj2 = { step_name: row2.step_name, step_type: row2.step_type, step_volume: row2.step_volume, step_infuse_amount: row2.step_infuse_amount,
+ step_infuse_temp: row2.step_infuse_temp, step_temp: row2.step_temp, step_time: row2.step_time,
+ ramp_time: row2.ramp_time, end_temp: row2.end_temp, step_wg_ratio: row2.step_wg_ratio };
+ $("#mashGrid").jqxGrid('updaterow', r1, obj2);
+ $("#mashGrid").jqxGrid('updaterow', r2, obj1);
+}
+
+
+function infusionVol(step_infused, step_mashkg, infuse_temp, step_temp, last_temp) {
+ var a = last_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
+ var b = step_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
+ var vol = Round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)), 2);
+ console.log('infusionVol(' + step_infused + ', ' + step_mashkg + ', ' + infuse_temp + ', ' + step_temp + ', ' + last_temp + '): ' + vol);
+ return vol;
+}
+
+
+function decoctionVol(step_volume, step_temp, prev_temp) {
+ var a = (eq_tun_weight * eq_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp);
+ var b = SpecificHeatWater * (99 - step_temp);
+ var vol = 0;
+ if (b > 0)
+ vol = Round(a / b, 6);
+ console.log('decoctionVol(' + step_volume + ', ' + step_temp + ', ' + prev_temp + '): ' + vol);
+ return vol;
+}
+
+
function calcMash() {
- var infused = 0, i, row, rows;
- if (!(rows = $('#mashGrid').jqxGrid('getrows')))
- return;
- if (mashkg == 0)
- return;
+ var infused = 0, vol, i, j, n, a, b, row, rows, temp;
+ var lasttemp = 18.0;
+ var graintemp = 18.0;
+ var tuntemp = 18.0;
- for (i = 0; i < rows.length; i++) {
- row = $('#mashGrid').jqxGrid('getrowdata', i);
- if (row.step_type == 0) // Infusion
- infused += row.step_infuse_amount;
- $('#mashGrid').jqxGrid('setcellvalue', i, 'step_thickness', infused / mashkg);
+ if ((rows = $('#mashGrid').jqxGrid('getrows')) && (mashkg > 0)) {
+ console.log('calcMash()');
+ for (i = 0; i < rows.length; i++) {
+ row = $('#mashGrid').jqxGrid('getrowdata', i);
+ if (row.step_type == 0) { // Infusion
+ if (i == 0) {
+ // First mash step, temperature from the mashtun and malt.
+ n = 20; // tun is preheated.
+ tuntemp = row.step_temp;
+ for (j = 0; j < n; j++) {
+ a = mashkg * graintemp * SpecificHeatMalt + eq_tun_weight * tuntemp * eq_tun_specific_heat;
+ b = row.step_temp * (eq_tun_weight * eq_tun_specific_heat + row.step_infuse_amount * SpecificHeatWater + mashkg * SpecificHeatMalt) - SlakingHeat * mashkg;
+ if (row.step_infuse_amount > 0) {
+ temp = (b - a) / (row.step_infuse_amount * SpecificHeatWater);
+ } else {
+ temp = 99;
+ }
+ tuntemp += (temp - tuntemp) / 2;
+ row.step_infuse_temp = Round(temp, 6);
+ }
+ console.log('init infuse temp: ' + row.step_infuse_temp);
+ } else {
+ // Calculate amount of infusion water.
+ row.step_infuse_amount = infusionVol(infused, mashkg, row.step_infuse_temp, row.step_temp, lasttemp);
+ //console.log('vol: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
+ }
+ infused += row.step_infuse_amount;
+ } else if (row.step_type == 1) { // Temperature
+ if (i > 0)
+ row.step_infuse_amount = 0;
+ row.step_infuse_temp = 0;
+ } else if (row.step_type == 2) { // Decoction
+ row.step_infuse_amount = decoctionVol(infused, row.step_temp, lasttemp);
+ row.step_infuse_temp = 99;
+ }
+ row.step_volume = infused;
+ //console.log(i + ' type: ' + row.step_type + ' volume: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
+ lasttemp = row.step_temp;
+ mashtime += row.step_time + row.ramp_time;
+ row.step_wg_ratio = Round(infused / mashkg, 6);
+ $('#mashGrid').jqxGrid('updaterow', i, row);
+ }
}
}
@@ -1685,18 +1762,6 @@
// inline mash editor
var editMash = function(data) {
- var generaterow = function() {
- var row = {};
- row['step_name'] = 'Stap 1';
- row['step_type'] = 0;
- row['step_infuse_amount'] = 15;
- row['step_temp'] = 62.0;
- row['step_time'] = 20.0;
- row['step_thickness'] = 0;
- row['ramp_time'] = 1.0;
- row['end_temp'] = 62.0;
- return row;
- };
var mashSource = {
localdata: data.mashs,
datatype: 'local',
@@ -1705,19 +1770,17 @@
datafields: [
{ name: 'step_name', type: 'string' },
{ name: 'step_type', type: 'int' },
+ { name: 'step_volume', type: 'float' },
{ name: 'step_infuse_amount', type: 'float' },
+ { name: 'step_infuse_temp', type: 'float' },
{ name: 'step_temp', type: 'float' },
{ name: 'step_time', type: 'float' },
- { name: 'step_thickness', type: 'float' },
+ { name: 'step_wg_ratio', type: 'float' },
{ name: 'ramp_time', type: 'float' },
{ name: 'end_temp', type: 'float' }
],
- addrow: function(rowid, rowdata, position, commit) {
- commit(true);
- },
- deleterow: function(rowid, commit) {
- commit(true);
- }
+ addrow: function(rowid, rowdata, position, commit) { commit(true); },
+ deleterow: function(rowid, commit) { commit(true); }
},
mashAdapter = new $.jqx.dataAdapter(mashSource, {
beforeLoadComplete: function(records) {
@@ -1727,7 +1790,7 @@
row = records[i];
if (row.step_type == 0) // Infusion
mash_infuse += parseFloat(row.step_infuse_amount);
- row.step_thickness = 0; // Init this field.
+ row.step_wg_ratio = 0; // Init this field.
data.push(row);
}
},
@@ -1747,8 +1810,25 @@
container.append('');
$('#saddrowbutton').jqxButton({ template: 'primary', theme: theme, height: 27, width: 150 });
$('#saddrowbutton').on('click', function() {
- var datarow = generaterow();
+ var row = {}, rowscount = $('#mashGrid').jqxGrid('getdatainformation').rowscount;
+ row['step_name'] = 'Stap ' + (rowscount + 1);
+ if (rowscount > 0) {
+ row['step_type'] = 1;
+ row['step_infuse_amount'] = 0;
+ row['step_volume'] = mash_infuse;
+ } else {
+ row['step_type'] = 0;
+ row['step_infuse_amount'] = 15;
+ row['step_volume'] = 15;
+ }
+ row['step_infuse_temp'] = 0;
+ row['step_temp'] = 62.0;
+ row['step_time'] = 20.0;
+ row['step_wg_ratio'] = 0;
+ row['ramp_time'] = 1.0;
+ row['end_temp'] = 62.0;
$('#mashGrid').jqxGrid('addrow', null, datarow);
+ calcMash();
});
// delete selected yeast.
$('#sdeleterowbutton').jqxButton({ template: 'danger', theme: theme, height: 27, width: 150 });
@@ -1758,6 +1838,7 @@
if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
id = $('#mashGrid').jqxGrid('getrowid', selectedrowindex);
$('#mashGrid').jqxGrid('deleterow', id);
+ calcMash();
}
});
},
@@ -1779,27 +1860,82 @@
{ text: 'Eind °C', datafield: 'end_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
{ text: 'Rust min.', datafield: 'step_time', width: 90, align: 'right', cellsalign: 'right' },
{ text: 'Stap min.', datafield: 'ramp_time', width: 90, align: 'right', cellsalign: 'right' },
- { text: 'Infuse L.', datafield: 'step_infuse_amount', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
- { text: 'L/Kg.', datafield: 'step_thickness', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f2' },
- { text: '', datafield: 'Edit', columntype: 'button', width: 100, align: 'center',
+ { text: 'Inf/dec L.', datafield: 'step_infuse_amount', width: 90, align: 'right',
+ cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+ if (rowdata.step_type == 1)
+ return '';
+ return '' + dataAdapter.formatNumber(value, 'f1') + '';
+ }
+ },
+ { text: 'Inf/dec °C', datafield: 'step_infuse_temp', width: 90, align: 'right',
+ cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+ if (rowdata.step_type == 1)
+ return '';
+ return '' + dataAdapter.formatNumber(value, 'f2') + '';
+ }
+ },
+ { text: 'L/Kg.', datafield: 'step_wg_ratio', width: 90, align: 'right',
+ cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+ var color = '#ffffff';
+ if (value < 2.0 || value > 6.0)
+ color = '#ff4040';
+ return '' + dataAdapter.formatNumber(value, 'f2') + '';
+ }
+ },
+ { text: '', columntype: 'button', width: 15, align: 'center',
+ cellsrenderer: function(row) {
+ if (row < 2)
+ return ' ';
+ return '▴';
+ }, buttonclick: function(row) {
+ if (row >= 2) {
+ swapMash(row, row-1);
+ }
+ }
+ },
+ { text: '', columntype: 'button', width: 15, align: 'center',
+ cellsrenderer: function(row) {
+ rowscount = $('#mashGrid').jqxGrid('getdatainformation').rowscount;
+ if (row < 1 || row > (rowscount -2))
+ return ' ';
+ return '▾';
+ }, buttonclick: function(row) {
+ rowscount = $('#mashGrid').jqxGrid('getdatainformation').rowscount;
+ if (row >= 1 && row <= (rowscount -2)) {
+ swapMash(row, row+1);
+ }
+ }
+ },
+ { text: '', datafield: 'Edit', columntype: 'button', width: 80, align: 'center',
cellsrenderer: function() {
return 'Wijzig';
}, buttonclick: function(row) {
mashRow = row;
mashData = $('#mashGrid').jqxGrid('getrowdata', mashRow);
+ if (mashRow == 0)
+ $("#wstep_type").jqxDropDownList('disableAt', 2);
+ else
+ $("#wstep_type").jqxDropDownList('enableAt', 2);
$('#wstep_name').val(mashData.step_name);
$('#wstep_type').val(mashData.step_type);
$('#wstep_infuse_amount').val(mashData.step_infuse_amount);
+ $('#wstep_infuse_temp').val(mashData.step_infuse_temp);
$('#wstep_temp').val(mashData.step_temp);
$('#wend_temp').val(mashData.end_temp);
$('#wstep_time').val(mashData.step_time);
$('#wramp_time').val(mashData.ramp_time);
+ $('#wstep_infuse_amount').hide(); // Hide all untile we need it.
+ $('#wstep_infuse_temp').hide();
+ $('#wstep_pmpt_amount').hide();
+ $('#wstep_pmpt_temp').hide();
if (mashData.step_type == 0) {
- $('#wstep_infuse_amount').show();
- $('#wstep_pmpt').show();
- } else {
- $('#wstep_infuse_amount').hide();
- $('#wstep_pmpt').hide();
+ if (mashRow == 0) {
+ $('#wstep_infuse_amount').show();
+ $('#wstep_pmpt_amount').show();
+ } else {
+ $('#wstep_infuse_temp').show();
+ $('#wstep_pmpt_temp').show();
+ }
}
// show the popup window.
$('#popupMash').jqxWindow('open');
@@ -1826,7 +1962,6 @@
theme: theme
});
-
function setWaterAgent(name, amount) {
var record, records, miscs, i, id, row, found = false, rows = $('#miscGrid').jqxGrid('getrows');
@@ -3582,7 +3717,7 @@
});
$('#mash_select').on('select', function(event) {
if (event.args) {
- var data, datarecord, i, row, rows, rowIDs, index = event.args.index;
+ var infused = 0, data, datarecord, i, row, rows, rowIDs, index = event.args.index;
// First delete all current steps
rowIDs = new Array();
rows = $('#mashGrid').jqxGrid('getdisplayrows');
@@ -3598,29 +3733,37 @@
data = datarecord.steps[i];
row = {};
row['step_name'] = data.step_name;
- row['step_type'] = data.step_type;
- // For now, but this must be smarter.
- if (mash_infuse == 0 && dataRecord.w1_amount > 0)
- mash_infuse = dataRecord.w1_amount;
- if (i == 0)
- row['step_infuse_amount'] = mash_infuse;
+ row['step_type'] = parseInt(data.step_type);
+ row['step_temp'] = parseFloat(data.step_temp);
+ row['end_temp'] = parseFloat(data.end_temp);
+ row['step_time'] = parseFloat(data.step_time);
+ row['ramp_time'] = parseFloat(data.ramp_time);
+ row['step_infuse_temp'] = 0.0;
+ row['step_infuse_amount'] = 0.0;
+ if (mash_infuse == 0 && dataRecord.wg_amount > 0)
+ mash_infuse = dataRecord.wg_amount;
+ if (data.step_type == 0) { // Infusion
+ if (i == 0) {
+ row['step_infuse_amount'] = parseFloat(mash_infuse);
+ } else {
+ row['step_infuse_temp'] = 99.0;
+ }
+ }
+ //console.log(i + ' type: ' + row['step_type'] + ' start infusion: ' + parseFloat(row['step_infuse_amount']) + ' mash_infuse: ' + mash_infuse);
+ infused += parseFloat(row['step_infuse_amount']);
+ row['step_volume'] = infused;
+ if (mashkg > 0)
+ row['step_wg_ratio'] = Round(parseFloat(mash_infuse / mashkg), 2);
else
- row['step_infuse_amount'] = 0;
- row['step_temp'] = data.step_temp;
- if (mashkg > 0)
- row['step_thickness'] = parseFloat(mash_infuse / mashkg);
- else
- row['step_thickness'] = 0;
- row['end_temp'] = data.end_temp;
- row['step_time'] = data.step_time;
- row['ramp_time'] = data.ramp_time;
+ row['step_wg_ratio'] = 0;
$('#mashGrid').jqxGrid('addrow', null, row);
}
+ calcMash();
}
});
$('#popupMash').jqxWindow({
width: 800,
- height: 350,
+ height: 375,
position: { x: 230, y: 100 },
resizable: false,
theme: theme,
@@ -3636,7 +3779,7 @@
$('#wstep_name').jqxInput({ theme: theme, width: 320, height: 23 });
$('#wstep_name').on('change', function(event) {
var rowdata = $('#mashGrid').jqxGrid('getrowdata', mashRow);
- rowdata.step_name = event.args.value;
+ rowdata.step_name = $('#wstep_name').val();
});
$('#wstep_type').jqxDropDownList({
theme: theme,
@@ -3651,28 +3794,61 @@
if (event.args) {
var rowdata, rows, i, row, index = event.args.index;
rowdata = $('#mashGrid').jqxGrid('getrowdata', mashRow);
- rowdata.step_type = index;
- if (index == 0) {
- $('#wstep_infuse_amount').show();
- $('#wstep_pmpt').show();
- } else {
- rowdata.step_infuse_amount = 0;
+ if (rowdata.step_type != index) {
+ rowdata.step_type = index;
$('#wstep_infuse_amount').hide();
- $('#wstep_pmpt').hide();
- }
- mash_infuse = 0;
- rows = $('#mashGrid').jqxGrid('getrows');
- for (i = 0; i < rows.length; i++) {
- row = rows[i];
- if (row.step_type == 0) // Infusion
- mash_infuse += parseFloat(row.step_infuse_amount);
+ $('#wstep_infuse_temp').hide();
+ $('#wstep_pmpt_amount').hide();
+ $('#wstep_pmpt_temp').hide();
+ if (index == 0) { // Infusion
+ if (mashRow == 0) {
+ $('#wstep_infuse_amount').show();
+ $('#wstep_pmpt_amount').show();
+ } else {
+ $('#wstep_infuse_temp').show();
+ $('#wstep_pmpt_temp').show();
+ }
+ }
+ if (index == 1) { // Temperature
+ if (mashRow > 0)
+ rowdata.step_infuse_amount = 0;
+ rowdata.step_infuse_temp = 0;
+ }
+ if (index == 2) { // Decoction
+ var rowprev = $('#mashGrid').jqxGrid('getrowdata', mashRow-1);
+ rowdata.step_infuse_temp = 99;
+ rowdata.step_infuse_amount = decoctionVol(rowdata.step_volume, rowdata.step_temp, rowprev.end_temp);
+ console.log('decoction: ' + rowdata.step_infuse_amount + '/' + rowdata.step_infuse_temp);
+ }
+ $('#mashGrid').jqxGrid('updaterow', mashRow, rowdata);
+ mash_infuse = 0;
+ rows = $('#mashGrid').jqxGrid('getrows');
+ for (i = 0; i < rows.length; i++) {
+ row = rows[i];
+ if (row.step_type == 0) // Infusion
+ mash_infuse += parseFloat(row.step_infuse_amount);
+ }
+ calcMash();
}
}
});
$('#wstep_temp').jqxNumberInput(Spin1dec);
$('#wstep_temp').on('change', function(event) {
var rowdata = $('#mashGrid').jqxGrid('getrowdata', mashRow);
- rowdata.step_temp = parseFloat(event.args.value);
+ if (rowdata.step_type == 2) { // Decoction
+ var rowprev = $('#mashGrid').jqxGrid('getrowdata', mashRow-1);
+ var a = (eq_tun_weight * eq_tun_specific_heat + rowdata.step_volume * SpecificHeatWater) *
+ (parseFloat(event.args.value) - rowprev.end_temp);
+ var b = SpecificHeatWater * (99 - parseFloat(event.args.value));
+ if (b > 0) {
+ rowdata.step_temp = parseFloat(event.args.value);
+ rowdata.step_infuse_amount = Round(a / b, 2);
+ } else
+ rowdata.step_infuse_amount = 0;
+ console.log('change temp ' + rowdata.step_temp + ' decoction: ' + rowdata.step_infuse_amount + '/' + rowdata.step_infuse_temp);
+ } else {
+ rowdata.step_temp = parseFloat(event.args.value);
+ }
});
$('#wend_temp').jqxNumberInput(Spin1dec);
$('#wend_temp').on('change', function(event) {
@@ -3693,23 +3869,40 @@
$('#wstep_infuse_amount').on('change', function(event) {
var i, rows, row, rowdata = $('#mashGrid').jqxGrid('getrowdata', mashRow);
rowdata.step_infuse_amount = parseFloat(event.args.value);
- mash_infuse = 0;
- rows = $('#mashGrid').jqxGrid('getrows');
- for (i = 0; i < rows.length; i++) {
- row = rows[i];
- if (row.step_type == 0) // Infusion
- mash_infuse += parseFloat(row.step_infuse_amount);
+ if (mashRow == 0) {
+ rowdata.step_infuse_amount = parseFloat(event.args.value);
+ mash_infuse = 0;
+ rows = $('#mashGrid').jqxGrid('getrows');
+ for (i = 0; i < rows.length; i++) {
+ row = rows[i];
+ if (row.step_type == 0) // Infusion
+ mash_infuse += parseFloat(row.step_infuse_amount);
+ }
+ if (dataRecord.w2_amount == 0) {
+ dataRecord.w1_amount = mash_infuse;
+ $('#w1_amount').val(mash_infuse);
+ } else {
+ var w1_amount = (dataRecord.w1_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
+ var w2_amount = (dataRecord.w2_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
+ dataRecord.w1_amount = Round(w1_amount, 3);
+ dataRecord.w2_amount = Round(w2_amount, 3);
+ $('#w1_amount').val(dataRecord.w1_amount);
+ $('#w2_amount').val(dataRecord.w2_amount);
+ }
+ $('#wg_amount').val(mash_infuse);
+ console.log('new infuse amount: ' + mash_infuse);
+ calcWater();
}
- if (dataRecord.w2_amount == 0) {
- dataRecord.w1_amount = mash_infuse;
- $('#w1_amount').val(mash_infuse);
- } else {
- dataRecord.w1_amount = (dataRecord.w1_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
- dataRecord.w2_amount = (dataRecord.w2_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
- $('#w1_amount').val(dataRecord.w1_amount);
- $('#w2_amount').val(dataRecord.w2_amount);
- }
- $('#wg_amount').val(mash_infuse);
+ });
+ $('#wstep_infuse_temp').jqxNumberInput(Spin1dec);
+ $('#wstep_infuse_temp').on('change', function(event) {
+ var prevdata = $('#mashGrid').jqxGrid('getrowdata', mashRow-1);
+ var rowdata = $('#mashGrid').jqxGrid('getrowdata', mashRow);
+ rowdata.step_infuse_temp = parseFloat(event.args.value);
+ var vol = infusionVol(prevdata.step_volume, mashkg, rowdata.step_infuse_temp, rowdata.step_temp, prevdata.end_temp);
+ console.log('new vol: ' + vol);
+ rowdata.step_infuse_amount = vol;
+ $('#wstep_infuse_amount').val(vol);
});
// Tab 7, Water