Mon, 02 Mar 2020 17:15:38 +0100
Implemented yeast viability calculation from the yeast production date. Changed the pitchrate logic and added Ale above 1.076 rate of 1.25.
README.design | file | annotate | diff | comparison | revisions | |
www/includes/db_product.php | file | annotate | diff | comparison | revisions | |
www/js/prod_edit.js | file | annotate | diff | comparison | revisions | |
www/prod_edit.php | file | annotate | diff | comparison | revisions |
--- a/README.design Sun Mar 01 12:48:09 2020 +0100 +++ b/README.design Mon Mar 02 17:15:38 2020 +0100 @@ -13,7 +13,6 @@ NOOT: experimentele wijziging is toegevoegd op 5-dec-2019. New Cubic van seanterrill. Wish: - Giststarter bereken gist viability. Viability zelf wordt al gebruikt. Giststarter automatisch aantal regels aanpassen bij wijzigen van de hoeveelheden. Extra:
--- a/www/includes/db_product.php Sun Mar 01 12:48:09 2020 +0100 +++ b/www/includes/db_product.php Mon Mar 02 17:15:38 2020 +0100 @@ -265,7 +265,11 @@ $sql .= "', prop4_type='" . $_POST['prop4_type']; $sql .= "', prop4_volume='" . $_POST['prop4_volume']; } - $sql .= "', divide_type='" . $_POST['divide_type']; + if ($_POST['yeast_prod_date'] == '') + $sql .= "', yeast_prod_date=NULL"; + else + $sql .= "', yeast_prod_date='" . $_POST['yeast_prod_date'] . "'"; + $sql .= ", divide_type='" . $_POST['divide_type']; $sql .= "', divide_size='" . floatval($_POST['divide_size']); $sql .= "', divide_factor='" . floatval($_POST['divide_factor']); $sql .= "', divide_parts='" . $_POST['divide_parts']; @@ -869,7 +873,8 @@ $brew .= ',"starter_type":' . $row['starter_type']; $brew .= ',"starter_sg":' . $row['starter_sg']; $brew .= ',"starter_viability":' . $row['starter_viability']; - $brew .= ',"prop1_type":' . $row['prop1_type']; + $brew .= ',"yeast_prod_date":"' . $row['yeast_prod_date']; + $brew .= '","prop1_type":' . $row['prop1_type']; $brew .= ',"prop1_volume":' . $row['prop1_volume']; $brew .= ',"prop2_type":' . $row['prop2_type']; $brew .= ',"prop2_volume":' . $row['prop2_volume'];
--- a/www/js/prod_edit.js Sun Mar 01 12:48:09 2020 +0100 +++ b/www/js/prod_edit.js Mon Mar 02 17:15:38 2020 +0100 @@ -300,6 +300,7 @@ { name: 'starter_type', type: 'int' }, { name: 'starter_sg', type: 'float' }, { name: 'starter_viability', type: 'int' }, + { name: 'yeast_prod_date', type: 'string' }, { name: 'prop1_type', type: 'int' }, { name: 'prop1_volume', type: 'float' }, { name: 'prop2_type', type: 'int' }, @@ -530,6 +531,7 @@ $('#starter_type').val(dataRecord.starter_type); $('#starter_sg').val(dataRecord.starter_sg); $('#starter_viability').val(dataRecord.starter_viability); + $('#yeast_prod_date').val(dataRecord.yeast_prod_date); $('#prop1_type').val(dataRecord.prop1_type); $('#prop1_volume').val(dataRecord.prop1_volume); $('#prop2_type').val(dataRecord.prop2_type); @@ -1310,7 +1312,7 @@ $('#yeastGrid').jqxGrid({ width: 1240, - height: 350, + height: 325, source: yeastAdapter, theme: theme, selectionmode: 'singlerow', @@ -1367,6 +1369,7 @@ row['y_zymocide'] = datarecord.zymocide; $('#yeastGrid').jqxGrid('addrow', null, row); } + calcViability(); calcYeast(); $('#yaddrowbutton').jqxDropDownList('clearSelection'); }); @@ -1383,6 +1386,7 @@ if (selectedrowindex >= 0 && selectedrowindex < rowscount) { id = $('#yeastGrid').jqxGrid('getrowid', selectedrowindex); $('#yeastGrid').jqxGrid('deleterow', id); + calcViability(); calcYeast(); } }); @@ -1627,6 +1631,63 @@ /* * Generic functions */ + function calcViability() { + var vpm = 1.00; + var max = 100; + var rowscount = $('#yeastGrid').jqxGrid('getdatainformation').rowscount; + if (rowscount) { + for (i = 0; i < rowscount; i++) { + row = $('#yeastGrid').jqxGrid('getrowdata', i); + if (row.y_use == 0) { + if (row.y_form == 0) { // Liquid + vpm = 0.80; + max = 97; + if (row.y_laboratory == 'White Labs') + vpm = 0.95; + } else if (row.y_form == 1) { // dry yeast + vpm = 0.98; + max = 100; + } else if (row.y_form == 6) { // Dried kveik + vpm = 1.00; + max = 100; + } else { // Slant, Culture, Frozen, Bottle + vpm = 0.99; + max = 97; + } + } + } + } + var base = max; + var days = 0; + + if (parseFloat($('#yeast_prod_date').val()) > 2000) { + console.log('calculate viability'); + var d = new Date(); + var date2 = $('#yeast_prod_date').val(); + date2 = date2.split('-'); + // Now we convert the array to a Date object + var date1 = new Date(d.getFullYear(), d.getMonth(), d.getDate()); + date2 = new Date(date2[0], date2[1] - 1, date2[2]); + var diff = parseInt(date1.getTime()) - parseInt(date2.getTime()); + days = Math.floor(diff/1000/60/60/24); + + var degrade = 1 - ((1 - vpm) / 30.41); // viability degradation per day. + for (i = 0; i < days; i++) { + base = base * degrade; + } + if (base > max) { + base = max; + } + base = Math.round(base); + } + console.log('age:' + days + ' max:' + max + ' vpm:' + vpm + ' base:' + base); + + if (dataRecord.starter_viability != base) { + dataRecord.starter_viability = base; + $('#starter_viability').val(dataRecord.starter_viability); + } + } + function calcSupplies() { if (dataRecord.inventory_reduced > 6) { $('#ok_pmpt').hide(); @@ -1884,7 +1945,7 @@ if (row.y_form == 0) initcells += (parseFloat(row.y_cells) / 1000000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); else - initcells += (parseFloat(row.y_cells) / 1000000) * parseFloat(row.y_amount); + initcells += (parseFloat(row.y_cells) / 1000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100); } // TODO: brett in secondary ?? if ((((dataRecord.inventory_reduced <= 3) && (row.y_use == 0)) || // Primary @@ -2368,17 +2429,19 @@ if (row.y_use == 0) { // primary // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/ // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/ - pitchrate = 0.75; - if (dataRecord.est_og > 1.060) - pitchrate = 1.0; -// if (dataRecord.est_og > 1.076) -// pitchrate = 1.25; // Wyeast labs. http://www.wyeastlab.com/hb_pitchrates.cfm - if (row.y_type == 0) // lager yeast - pitchrate *= 2; - if (row.y_type == 6) // Kveik - pitchrate /= 10; // http://suigenerisbrewing.com/index.php/2019/08/28/drying-kveik-the-grand-finale/ -// pitchrate = 0.25; // Who knows. - + if (row.y_type == 0) { // lager yeast + pitchrate = 1.5; + if (dataRecord.est_og > 1.060) + pitchrate = 2.0; + } else if (row.y_type == 6) { // Kveik + pitchrate = 0.075; + } else { + pitchrate = 0.75; + if (dataRecord.est_og > 1.060) + pitchrate = 1.0; + if (dataRecord.est_og > 1.076) + pitchrate = 1.25; // Wyeast labs. http://www.wyeastlab.com/hb_pitchrates.cfm + } // if (row.y_form == 1) { // dry yeast // } else { // possible starter needed // } @@ -3558,7 +3621,7 @@ $('#starter_type').jqxDropDownList({ disabled: true }); $('#starter_try').jqxButton({ disabled: true }); $('#starter_sg').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); - $('#starter_viability').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); + $('#yeast_prod_date').jqxDateTimeInput({ disabled: true }); } if (dataRecord.stage > 3) { // Primary fermentation done $('#brew_date_start').jqxDateTimeInput({ disabled: true }); @@ -3652,13 +3715,11 @@ $('#starter_type').jqxDropDownList({ disabled: false }); $('#starter_try').jqxButton({ disabled: false }); $('#starter_sg').jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 }); - $('#starter_viability').jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 }); } else { $('#propagator').hide(); $('#starter_type').jqxDropDownList({ disabled: true }); $('#starter_try').jqxButton({ disabled: true }); $('#starter_sg').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); - $('#starter_viability').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); } } @@ -3698,13 +3759,6 @@ calcYeast(); } }); - $('#starter_viability').on('change', function(event) { - if (event.args) { - dataRecord.starter_viability = event.args.value; - calcFermentables(); - calcYeast(); - } - }); $('#prop1_type').on('change', function(event) { if (event.args) { dataRecord.prop1_type = event.args.index; @@ -4436,6 +4490,7 @@ starter_type: $('#starter_type').val(), starter_sg: parseFloat($('#starter_sg').jqxNumberInput('decimal')), starter_viability: parseFloat($('#starter_viability').jqxNumberInput('decimal')), + yeast_prod_date: $('#yeast_prod_date').val(), prop1_type: $('#prop1_type').val(), prop1_volume: parseFloat($('#prop1_volume').jqxNumberInput('decimal')), prop2_type: $('#prop2_type').val(), @@ -5224,6 +5279,13 @@ $('#need_cells').jqxNumberInput(Show1dec); $('#plato_cells').jqxTooltip({ content: 'De berekende hoeveelheid gistcellen in miljard per ml per graad Plato. Dit is de zogenaamde pitchrate.' }); $('#plato_cells').jqxNumberInput(Show2dec); + $('#yeast_prod_date').jqxTooltip({ content: 'Bij korrelgisten is meestal "best voor" datum op het zakje gedrukt.<br>Gebruik die datum maar dan twee jaar eerder als productie datum.<br>Bij White Labs is de productie datum vier maanden voor de "Best by" datum die geprint op het buisje.<br>Bij Wyeast is dit de "manufacture date" die op het pak geprint is.<br>Voor schuine buis, slurry, opkweek en gedroogd is dit de datum dat je de gist geoogst hebt.' }); + $('#yeast_prod_date').jqxDateTimeInput(Dateopts); + $('#yeast_prod_date').on('close', function(event) { + calcViability(); + calcFermentables(); + calcYeast(); + }); $('#popupYeast').jqxWindow({ width: 800, height: 300, @@ -5265,6 +5327,7 @@ y_avail: yeastData.y_avail }; $('#yeastGrid').jqxGrid('updaterow', rowID, row); + calcViability(); calcFermentables(); calcYeast(); }); @@ -5321,6 +5384,7 @@ } else { $('#wy_pmpt_amount').html('Volume ml:'); } + calcViability(); calcFermentables(); calcYeast(); } @@ -5348,6 +5412,7 @@ if (event.args) { var index = event.args.index; yeastData.y_use = index; + calcViability(); calcFermentables(); calcYeast(); } @@ -5389,12 +5454,11 @@ }); $('#starter_sg').jqxTooltip({ content: 'Het ideale starter SG moet tussen de 1.030 en 1.040 zijn. Optimaal is 1.037.' }); $('#starter_sg').jqxNumberInput(SGopts); - $('#starter_viability').jqxTooltip({ - content: 'De gist conditie te berekenen vanaf de productie datum. Vloeibare gist verlist iedere maand ongeveer 20% active cellen.' - }); - $('#starter_viability').jqxNumberInput(Perc0); + $('#starter_viability').jqxTooltip({ content: 'De gist conditie.' }); + $('#starter_viability').jqxNumberInput(Smal0dec); $('#starter_try').jqxButton({ template: 'primary', width: '100px', height: 23, theme: theme }); + // Tab 7, Mashing $('#mash_name').jqxTooltip({ content: 'De omschrijving van dit maisch profiel.' }); $('#mash_name').jqxInput({ theme: theme, width: 320, height: 23 });
--- a/www/prod_edit.php Sun Mar 01 12:48:09 2020 +0100 +++ b/www/prod_edit.php Mon Mar 02 17:15:38 2020 +0100 @@ -325,6 +325,10 @@ <td style="padding: 3px;"><div id="yeast_cells"></div></td> </tr> <tr> + <td align="right" style="vertical-align: top;">Gist productie datum:</td> + <td style="padding: 3px;"><input readonly="1" id="yeast_prod_date" /></div></td> + </tr> + <tr> <td style="vertical-align: top; float: right; padding: 3px;">Cellen nodig miljard:</td> <td style="padding: 3px;"><div id="need_cells"></div></td> </tr>