# HG changeset patch # User Michiel Broek # Date 1557666995 -7200 # Node ID 98354ef399cde8a4af9479cca5953b074590d225 # Parent 3be8c2278fd7f5df7f633156c819187297072fda Lot's of improvements for recipes and products database load and save. Insert missing yeast tolerance field for old products and recipes. Recipe locked and calc_acid fields coverted to integer. In recipe edit screen removed the Print button. It is now included in the export screen. Added recipe export to forum screen. diff -r 3be8c2278fd7 -r 98354ef399cd README.design --- a/README.design Sat May 11 23:13:40 2019 +0200 +++ b/README.design Sun May 12 15:16:35 2019 +0200 @@ -123,8 +123,5 @@ Extra: Gisten diastaticus bit toevoegen. -Waarschuwing voor overschrijden moutstort. Gist typen: kveik en brett? Apart of niet. -Controle ingredienten voor het brouwen. - diff -r 3be8c2278fd7 -r 98354ef399cd www/includes/db_product.php --- a/www/includes/db_product.php Sat May 11 23:13:40 2019 +0200 +++ b/www/includes/db_product.php Sun May 12 15:16:35 2019 +0200 @@ -688,29 +688,29 @@ $brew .= ',"sparge_acid_type":' . $row['sparge_acid_type']; $brew .= ',"sparge_acid_perc":' . floatval($row['sparge_acid_perc']); $brew .= ',"sparge_acid_amount":' . floatval($row['sparge_acid_amount']); - $brew .= ',"mash_ph":' . $row['mash_ph']; - $brew .= ',"mash_name":"' . $row['mash_name']; + $brew .= ',"mash_ph":' . floatval($row['mash_ph']); + $brew .= ',"mash_name":"' . str_replace($escapers, $replacements, $row['mash_name']); $brew .= '","calc_acid":' . $row['calc_acid']; $brew .= ',"w1_name":"' . str_replace($escapers, $replacements, $row['w1_name']); - $brew .= '","w1_amount":' . $row['w1_amount']; - $brew .= ',"w1_calcium":' . $row['w1_calcium']; - $brew .= ',"w1_sulfate":' . $row['w1_sulfate']; - $brew .= ',"w1_chloride":' . $row['w1_chloride']; - $brew .= ',"w1_sodium":' . $row['w1_sodium']; - $brew .= ',"w1_magnesium":' . $row['w1_magnesium']; - $brew .= ',"w1_total_alkalinity":' . $row['w1_total_alkalinity']; - $brew .= ',"w1_ph":' . $row['w1_ph']; - $brew .= ',"w1_cost":' . $row['w1_cost']; + $brew .= '","w1_amount":' . floatval($row['w1_amount']); + $brew .= ',"w1_calcium":' . floatval($row['w1_calcium']); + $brew .= ',"w1_sulfate":' . floatval($row['w1_sulfate']); + $brew .= ',"w1_chloride":' . floatval($row['w1_chloride']); + $brew .= ',"w1_sodium":' . floatval($row['w1_sodium']); + $brew .= ',"w1_magnesium":' . floatval($row['w1_magnesium']); + $brew .= ',"w1_total_alkalinity":' . floatval($row['w1_total_alkalinity']); + $brew .= ',"w1_ph":' . floatval($row['w1_ph']); + $brew .= ',"w1_cost":' . floatval($row['w1_cost']); $brew .= ',"w2_name":"' . str_replace($escapers, $replacements, $row['w2_name']); - $brew .= '","w2_amount":' . $row['w2_amount']; - $brew .= ',"w2_calcium":' . $row['w2_calcium']; - $brew .= ',"w2_sulfate":' . $row['w2_sulfate']; - $brew .= ',"w2_chloride":' . $row['w2_chloride']; - $brew .= ',"w2_sodium":' . $row['w2_sodium']; - $brew .= ',"w2_magnesium":' . $row['w2_magnesium']; - $brew .= ',"w2_total_alkalinity":' . $row['w2_total_alkalinity']; - $brew .= ',"w2_ph":' . $row['w2_ph']; - $brew .= ',"w2_cost":' . $row['w2_cost']; + $brew .= '","w2_amount":' . floatval($row['w2_amount']); + $brew .= ',"w2_calcium":' . floatval($row['w2_calcium']); + $brew .= ',"w2_sulfate":' . floatval($row['w2_sulfate']); + $brew .= ',"w2_chloride":' . floatval($row['w2_chloride']); + $brew .= ',"w2_sodium":' . floatval($row['w2_sodium']); + $brew .= ',"w2_magnesium":' . floatval($row['w2_magnesium']); + $brew .= ',"w2_total_alkalinity":' . floatval($row['w2_total_alkalinity']); + $brew .= ',"w2_ph":' . floatval($row['w2_ph']); + $brew .= ',"w2_cost":' . floatval($row['w2_cost']); $brew .= ',"wa_acid_name":' . $row['wa_acid_name']; $brew .= ',"wa_acid_perc":' . $row['wa_acid_perc']; $brew .= ',"wa_base_name":' . $row['wa_base_name']; @@ -784,6 +784,8 @@ for ($i = 0; $i < count($yeasts); $i++) { $yeasts[$i]['y_inventory'] = 0; // Not in stock $yeasts[$i]['y_avail'] = 0; // Ingredient not in db + if (! isset($yeasts[$i]['y_tolerance'])) + $yeasts[$i]['y_tolerance'] = 0; $sql2 = "SELECT inventory,tolerance FROM inventory_yeasts "; $sql2 .= "WHERE name='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_name'])."' AND"; $sql2 .= " form='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_form'])."' AND"; diff -r 3be8c2278fd7 -r 98354ef399cd www/includes/db_recipes.php --- a/www/includes/db_recipes.php Sat May 11 23:13:40 2019 +0200 +++ b/www/includes/db_recipes.php Sun May 12 15:16:35 2019 +0200 @@ -32,7 +32,7 @@ $uuid = str_replace("\n", "", file_get_contents('/proc/sys/kernel/random/uuid')); $sql .= "uuid='" . $uuid; } - ($_POST['locked'] == 'true') ? $sql .= "', locked='1" : $sql .= "', locked='0"; + $sql .= "', locked='" . $_POST['locked']; $sql .= "', st_name='" . mysqli_real_escape_string($connect, $_POST['st_name']); $sql .= "', st_letter='" . mysqli_real_escape_string($connect, $_POST['st_letter']); $sql .= "', st_guide='" . mysqli_real_escape_string($connect, $_POST['st_guide']); @@ -75,7 +75,7 @@ $sql .= "', sparge_acid_amount='" . $_POST['sparge_acid_amount']; $sql .= "', mash_ph='" . $_POST['mash_ph']; $sql .= "', mash_name='" . $_POST['mash_name']; - ($_POST['calc_acid'] == 'true') ? $sql .= "', calc_acid='1" : $sql .= "', calc_acid='0"; + $sql .= "', calc_acid='" . $_POST['calc_acid']; if (isset($_POST['w1_name'])) { $sql .= "', w1_name='" . mysqli_real_escape_string($connect, $_POST['w1_name']); $sql .= "', w1_amount='" . $_POST['w1_amount']; @@ -103,7 +103,7 @@ $sql .= "', wa_acid_name='" . $_POST['wa_acid_name']; $sql .= "', wa_acid_perc='" . $_POST['wa_acid_perc']; $sql .= "', wa_base_name='" . $_POST['wa_base_name']; - syslog(LOG_NOTICE, $sql); + //syslog(LOG_NOTICE, $sql); $fermentables = '['; $comma = FALSE; @@ -202,6 +202,7 @@ $comma = FALSE; if (isset($_POST['yeasts'])) { $array = $_POST['yeasts']; +syslog(LOG_NOTICE, $_POST['yeasts']); foreach($array as $key => $item) { if ($comma) $yeasts .= ','; @@ -221,7 +222,7 @@ $yeast .= ',"y_inventory":' . $item['y_inventory']; $yeast .= ',"y_use":' . $item['y_use']; $yeast .= ',"y_cost":' . $item['y_cost'] . '}'; - //syslog(LOG_NOTICE, $yeast); + syslog(LOG_NOTICE, $yeast); $yeasts .= $yeast; } } @@ -247,7 +248,7 @@ $mash .= ',"ramp_time":' . $item['ramp_time']; $mash .= ',"end_temp":' . $item['end_temp'] . '}'; $mashs .= $mash; - syslog(LOG_NOTICE, $mash); + //syslog(LOG_NOTICE, $mash); } } $mashs .= ']'; @@ -303,7 +304,7 @@ } $comma = TRUE; $recipes .= '{"record":' . $row['record']; - $recipes .= ',"uuid":"' . $row['uuid']; + $recipes .= ',"uuid":"' . str_replace($escapers, $replacements, $row['uuid']); $recipes .= '","locked":' . $row['locked']; $recipes .= ',"st_guide":"' . str_replace($escapers, $replacements, $row['st_guide']); $recipes .= '","st_letter":"' . str_replace($escapers, $replacements, $row['st_letter']); @@ -338,38 +339,38 @@ $recipes .= ',"color_method":' . $row['color_method']; $recipes .= ',"est_ibu":' . floatval($row['est_ibu']); $recipes .= ',"ibu_method":' . $row['ibu_method']; - $recipes .= ',"sparge_temp":' . $row['sparge_temp']; - $recipes .= ',"sparge_ph":' . $row['sparge_ph']; - $recipes .= ',"sparge_volume":' . $row['sparge_volume']; + $recipes .= ',"sparge_temp":' . floatval($row['sparge_temp']); + $recipes .= ',"sparge_ph":' . floatval($row['sparge_ph']); + $recipes .= ',"sparge_volume":' . floatval($row['sparge_volume']); $recipes .= ',"sparge_source":"' . $row['sparge_source']; $recipes .= '","sparge_acid_type":' . $row['sparge_acid_type']; - $recipes .= ',"sparge_acid_perc":' . $row['sparge_acid_perc']; - $recipes .= ',"sparge_acid_amount":' . $row['sparge_acid_amount']; - $recipes .= ',"mash_ph":' . $row['mash_ph']; - $recipes .= ',"mash_name":"' . $row['mash_name']; + $recipes .= ',"sparge_acid_perc":' . floatval($row['sparge_acid_perc']); + $recipes .= ',"sparge_acid_amount":' . floatval($row['sparge_acid_amount']); + $recipes .= ',"mash_ph":' . floatval($row['mash_ph']); + $recipes .= ',"mash_name":"' . str_replace($escapers, $replacements, $row['mash_name']); $recipes .= '","calc_acid":' . $row['calc_acid']; $recipes .= ',"w1_name":"' . str_replace($escapers, $replacements, $row['w1_name']); - $recipes .= '","w1_amount":' . $row['w1_amount']; - $recipes .= ',"w1_calcium":' . $row['w1_calcium']; - $recipes .= ',"w1_sulfate":' . $row['w1_sulfate']; - $recipes .= ',"w1_chloride":' . $row['w1_chloride']; - $recipes .= ',"w1_sodium":' . $row['w1_sodium']; - $recipes .= ',"w1_magnesium":' . $row['w1_magnesium']; - $recipes .= ',"w1_total_alkalinity":' . $row['w1_total_alkalinity']; - $recipes .= ',"w1_ph":' . $row['w1_ph']; - $recipes .= ',"w1_cost":' . $row['w1_cost']; + $recipes .= '","w1_amount":' . floatval($row['w1_amount']); + $recipes .= ',"w1_calcium":' . floatval($row['w1_calcium']); + $recipes .= ',"w1_sulfate":' . floatval($row['w1_sulfate']); + $recipes .= ',"w1_chloride":' . floatval($row['w1_chloride']); + $recipes .= ',"w1_sodium":' . floatval($row['w1_sodium']); + $recipes .= ',"w1_magnesium":' . floatval($row['w1_magnesium']); + $recipes .= ',"w1_total_alkalinity":' . floatval($row['w1_total_alkalinity']); + $recipes .= ',"w1_ph":' . floatval($row['w1_ph']); + $recipes .= ',"w1_cost":' . floatval($row['w1_cost']); $recipes .= ',"w2_name":"' . str_replace($escapers, $replacements, $row['w2_name']); - $recipes .= '","w2_amount":' . $row['w2_amount']; - $recipes .= ',"w2_calcium":' . $row['w2_calcium']; - $recipes .= ',"w2_sulfate":' . $row['w2_sulfate']; - $recipes .= ',"w2_chloride":' . $row['w2_chloride']; - $recipes .= ',"w2_sodium":' . $row['w2_sodium']; - $recipes .= ',"w2_magnesium":' . $row['w2_magnesium']; - $recipes .= ',"w2_total_alkalinity":' . $row['w2_total_alkalinity']; - $recipes .= ',"w2_ph":' . $row['w2_ph']; - $recipes .= ',"w2_cost":' . $row['w2_cost']; + $recipes .= '","w2_amount":' . floatval($row['w2_amount']); + $recipes .= ',"w2_calcium":' . floatval($row['w2_calcium']); + $recipes .= ',"w2_sulfate":' . floatval($row['w2_sulfate']); + $recipes .= ',"w2_chloride":' . floatval($row['w2_chloride']); + $recipes .= ',"w2_sodium":' . floatval($row['w2_sodium']); + $recipes .= ',"w2_magnesium":' . floatval($row['w2_magnesium']); + $recipes .= ',"w2_total_alkalinity":' . floatval($row['w2_total_alkalinity']); + $recipes .= ',"w2_ph":' . floatval($row['w2_ph']); + $recipes .= ',"w2_cost":' . floatval($row['w2_cost']); $recipes .= ',"wa_acid_name":' . $row['wa_acid_name']; - $recipes .= ',"wa_acid_perc":' . $row['wa_acid_perc']; + $recipes .= ',"wa_acid_perc":' . floatval($row['wa_acid_perc']); $recipes .= ',"wa_base_name":' . $row['wa_base_name']; if (isset($_GET['record'])) { // Append stock information. @@ -429,6 +430,8 @@ for ($i = 0; $i < count($yeasts); $i++) { $yeasts[$i]['y_inventory'] = 0; // Not in stock $yeasts[$i]['y_avail'] = 0; // Ingredient not in db + if (! isset($yeasts[$i]['y_tolerance'])) + $yeasts[$i]['y_tolerance'] = 0; $sql2 = "SELECT inventory,tolerance FROM inventory_yeasts "; $sql2 .= "WHERE name='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_name'])."' AND"; $sql2 .= " form='".str_replace($rescapers, $rreplacements, $yeasts[$i]['y_form'])."' AND"; diff -r 3be8c2278fd7 -r 98354ef399cd www/js/rec_edit.js --- a/www/js/rec_edit.js Sat May 11 23:13:40 2019 +0200 +++ b/www/js/rec_edit.js Sun May 12 15:16:35 2019 +0200 @@ -1200,11 +1200,11 @@ console.log("calc.init()"); $("#calc_acid").on('checked', function (event) { - dataRecord.calc_acid = true; + dataRecord.calc_acid = 1; calcWater(); }); $("#calc_acid").on('unchecked', function (event) { - dataRecord.calc_acid = false; + dataRecord.calc_acid = 0; calcWater(); }); $("#w1_name").jqxDropDownList('selectItem', dataRecord.w1_name); @@ -1384,9 +1384,11 @@ calcSparge(); }); $('#locked').on('checked', function (event) { + dataRecord.locked = 1; setReadonly(true); }); $('#locked').on('unchecked', function (event) { + dataRecord.locked = 0; setReadonly(false); }); // setReadonly(false); @@ -1442,7 +1444,7 @@ record: my_record, uuid: dataRecord.uuid, name: $("#name").val(), - locked: $("#locked").val(), + locked: dataRecord.locked, notes: $("#notes").val(), st_name: $('#st_name').val(), st_letter: $('#st_letter').val(), @@ -1484,7 +1486,7 @@ sparge_acid_type: $("#sparge_acid_type").val(), sparge_acid_perc: parseFloat($("#sparge_acid_perc").jqxNumberInput('decimal')), sparge_acid_amount: dataRecord.sparge_acid_amount, - calc_acid: $("#calc_acid").val(), + calc_acid: dataRecord.calc_acid, w1_name: $("#w1_name").val(), w1_amount: parseFloat($("#w1_amount").jqxNumberInput('decimal')), w1_calcium: parseFloat($("#w1_calcium").jqxNumberInput('decimal')), @@ -1541,7 +1543,7 @@ datafields: [ { name: 'record', type: 'number' }, { name: 'uuid', type: 'string' }, - { name: 'locked', type: 'bool' }, + { name: 'locked', type: 'int' }, { name: 'st_name', type: 'string' }, { name: 'st_letter', type: 'string' }, { name: 'st_guide', type: 'string' }, @@ -1584,7 +1586,7 @@ { name: 'sparge_acid_amount', type: 'float' }, { name: 'mash_ph', type: 'float' }, { name: 'mash_name', type: 'string' }, - { name: 'calc_acid', type: 'bool' }, + { name: 'calc_acid', type: 'int' }, { name: 'w1_name', type: 'string' }, { name: 'w1_amount', type: 'float' }, { name: 'w1_calcium', type: 'float' }, @@ -3734,14 +3736,7 @@ position: 'top' }); - $("#Print").jqxButton({ template: "info", width: '80px', theme: theme }); - $("#Print").bind('click', function () { - saveRecord(); - // Open print in a new tab. - var url="rec_print.php?record=" + my_record; - window.open(url); - }); - + // Buttons below $("#Export").jqxButton({ template: "info", width: '80px', theme: theme }); $("#Export").bind('click', function () { saveRecord(); diff -r 3be8c2278fd7 -r 98354ef399cd www/js/rec_export.js --- a/www/js/rec_export.js Sat May 11 23:13:40 2019 +0200 +++ b/www/js/rec_export.js Sun May 12 15:16:35 2019 +0200 @@ -29,6 +29,8 @@ $("#jqxRadioButton1").jqxRadioButton({ theme: theme, width: 250, height: 23 }); $("#jqxRadioButton2").jqxRadioButton({ theme: theme, width: 250, height: 23 }); $("#jqxRadioButton3").jqxRadioButton({ theme: theme, width: 250, height: 23 }); + $("#jqxRadioButton4").jqxRadioButton({ theme: theme, width: 250, height: 23 }); + $("#jqxRadioButton5").jqxRadioButton({ theme: theme, width: 250, height: 23 }); $('#jqxRadioButton1').on('checked', function (event) { $('#Start').jqxButton({ disabled: false }); choice = 1; @@ -41,6 +43,14 @@ $('#Start').jqxButton({ disabled: false }); choice = 3; }); + $('#jqxRadioButton4').on('checked', function (event) { + $('#Start').jqxButton({ disabled: false }); + choice = 4; + }); + $('#jqxRadioButton5').on('checked', function (event) { + $('#Start').jqxButton({ disabled: false }); + choice = 5; + }); $('#Start').jqxButton({ template: "success", width: '100px', theme: theme, disabled: true }); $('#Start').click(function () { @@ -53,8 +63,14 @@ } else if (choice == 3) { var url="rec_toproduct.php?record=" + my_record; window.open(url); - } - // Return to the original product - window.location.href = my_return + "?record=" + my_record; + } else if (choice == 4) { + var url="rec_print.php?record=" + my_record; + window.open(url); + } else if (choice == 5) { + var url="rec_forum.php?record=" + my_record; + window.open(url); + } + // Return to the original recipe + window.location.href = "rec_edit.php?record=" + my_record + "&return=" + my_return; }); }); diff -r 3be8c2278fd7 -r 98354ef399cd www/rec_edit.php --- a/www/rec_edit.php Sat May 11 23:13:40 2019 +0200 +++ b/www/rec_edit.php Sun May 12 15:16:35 2019 +0200 @@ -94,11 +94,10 @@
- - +
diff -r 3be8c2278fd7 -r 98354ef399cd www/rec_export.php --- a/www/rec_export.php Sat May 11 23:13:40 2019 +0200 +++ b/www/rec_export.php Sun May 12 15:16:35 2019 +0200 @@ -24,6 +24,14 @@ Copieer als brouw product:
+ + Print dit recept: +
+ + + Export voor forum: +
+   diff -r 3be8c2278fd7 -r 98354ef399cd www/rec_forum.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/www/rec_forum.php Sun May 12 15:16:35 2019 +0200 @@ -0,0 +1,237 @@ + + + + + + BMS v<?php echo $my_version;?> - Export recipe + + + +
+':
+                                        $strout .= '>';
+                                        break;
+                        case '&':
+                                        $strout .= '&';
+                                        break;
+                        case '"':
+                                        $strout .= '"';
+                                        break;
+                        default:
+                                        $strout .= $strin[$i];
+        	}
+
+		if ($cnt >= $len)
+			break;
+        }
+
+	for ($i = $cnt; $i < $len; $i++)
+		$strout .= " ";
+        return $strout;
+}
+
+
+echo "BMS v" . $my_version . " - Datum export: " . $prdate . PHP_EOL;
+echo "----------------------------------------------------------" . PHP_EOL;
+itemline("Bier naam", $row['name']);
+itemline("Bier stijl", $row['st_name']);
+itemline("Recept type", $recipetype[$row['type']]);
+itemline("Batch grootte", $row['batch_size'].' liter');
+itemline("Kooktijd", $row['boil_time'].' minuten');
+itemline("Brouwzaal rendement", $row['efficiency'].' %');
+itemline("Geschatte begin densiteit", sprintf("%.3f",$row['est_og']).' SG/ '.sprintf("%.1f", sg_to_plato($row['est_og'])).'°P');
+itemline("Geschatte eind densiteit", sprintf("%.3f",$row['est_fg']).' SG/ '.sprintf("%.1f", sg_to_plato($row['est_fg'])).'°P');
+itemline("Geschat alcohol", sprintf("%.1f",$row['est_abv']).'% vol');
+itemline("Kleur (" . $colormethod[$row['color_method']] . ")", $row['est_color'] . ' EBC');
+itemline("Bitterheid (" . $ibumethod[$row['ibu_method']] . ")", $row['est_ibu'] . ' IBU');
+echo PHP_EOL . PHP_EOL;
+
+$sugarsm = 0;
+$grainabsorbtion = 0;
+$mashwater = 0;
+
+$arr = json_decode($row['json_fermentables'], true);
+echo "Mout, granen en suikers                  EBC Gewicht kg     % Gebruik tijdens" . PHP_EOL;
+echo "---------------------------------------- --- ---------- ----- ----------------" . PHP_EOL;
+foreach($arr as $item) {
+	$name = formatstr($item['f_name'] . " (" . $item['f_supplier'] . ")", 40);
+	$amount   = floatval($item['f_amount']);
+	$d = $amount * (floatval($item['f_yield']) / 100) * (1 - floatval($item['f_moisture']) / 100);
+        if ($item['f_added']  == 0) {
+        	$d = floatval($row['efficiency']) / 100 * $d;
+                $sugarsm += $d;
+		$grainabsorbtion += $item['f_amount'];
+        }
+	echo sprintf("%s %3.0f %10.3f %5.1f ", $name, floatval($item['f_color']), $amount, floatval($item['f_percentage']));
+	echo $added[$item['f_added']] . PHP_EOL;
+}
+$preboil_sg = estimate_sg($sugarsm, floatval($row['boil_size']));
+echo PHP_EOL . PHP_EOL;
+
+
+echo "Hop                                      Vorm      α %   IBU   Gram Toevoegen moment" . PHP_EOL;
+echo "---------------------------------------- ------- ----- ----- ------ --------------------" . PHP_EOL;
+$arr = json_decode($row['json_hops'], true);
+foreach($arr as $item) {
+	$name   = formatstr($item['h_name'] . " (" . $item['h_origin'] . ")", 40);
+	$amount = floatval($item['h_amount']) * 1000;
+	$time   = floatval($item['h_time']);
+        $alpha  = floatval($item['h_alpha']);
+	$ibu    = calc_IBU($item['h_useat'], $item['h_form'], $preboil_sg, floatval($row['batch_size']), $amount, $time, $alpha, $row['ibu_method']);
+	$moment = $hopuse[$item['h_useat']];
+        if ($item['h_useat'] == 2) {    // Boil
+        	$moment = "Kook ".$time." minuten";
+        }
+
+	echo sprintf("%s %-7s %5.1f %5.1f %6.1f %-20s", $name, $hopform[$item['h_form']], $alpha, $ibu, $amount, $moment);
+	echo PHP_EOL;
+}
+echo PHP_EOL . PHP_EOL;
+
+echo "Specerij, kruid, brouwzout etc Type grondstof  Gebruik tijdens          Hoeveel" . PHP_EOL;
+echo "------------------------------ --------------- -------------------- -----------" . PHP_EOL;
+$arr = json_decode($row['json_miscs'], true);
+foreach($arr as $item) {
+	$amount  = floatval($item['m_amount']) * 1000;
+	$aiw     = $item['m_amount_is_weight'];
+	$use_use = $item['m_use_use'];
+	$time    = floatval($item['m_time']);
+
+	if ($use_use == 2)      // Boil
+        	$gebruik = sprintf("%s %d min",$miscuse[$use_use],$time);
+        else
+        	$gebruik = $miscuse[$use_use];
+	$hoeveel = sprintf("%.2f %s",$amount,$aiw ? "gr":"ml");
+
+	echo sprintf("%s %-15s %-20s %11s", formatstr($item['m_name'], 30), $misctype[$item['m_type']], $gebruik, $hoeveel) . PHP_EOL;
+}
+echo PHP_EOL . PHP_EOL;
+
+echo "Gistlab en code      Omschrijving                   Gebruik      Vorm            Hoeveel" . PHP_EOL;
+echo "-------------------- ------------------------------ ------------ ------------ ----------" . PHP_EOL;
+$arr = json_decode($row['json_yeasts'], true);
+foreach($arr as $item) {
+	$name    = formatstr($item['y_name'], 30);
+	$product = formatstr($item['y_laboratory']." ".$item['y_product_id'], 20);
+
+	if ($item['y_form'] == 0)       // Liquid
+                $amount = sprintf("%.0f",floatval($item['y_amount']))." pak";
+        else if ($item['y_form'] == 1)  // Dry
+                $amount = sprintf("%.1f",floatval($item['y_amount'])*1000)." gr";
+        else
+                $amount = sprintf("%.0f",floatval($item['y_amount'])*1000)." ml";
+
+	echo sprintf("%s %s %-12s %-12s %10s", $product, $name, $yeastuse[$item['y_use']], $yeastform[$item['y_form']], $amount) . PHP_EOL;
+}
+if ($row['starter_enable'] && $row['prop1_volume']) {
+	$sv = 0;
+	for ($i = 1; $i < 5; $i++) {
+		$pv = "prop".$i."_volume";
+		if (floatval($row[$pv]) && (floatval($row[$pv]) > $sv)) {
+			$sv = floatval($row[$pv]);
+		}
+	}
+	echo PHP_EOL . "Maak een giststarter van " . sprintf("%.1f", $sv) . " liter." . PHP_EOL;
+}
+echo PHP_EOL . PHP_EOL;
+
+if ($row['w1_name'])
+	$mashwater += floatval($row['w1_amount']);
+if ($row['w2_name'])
+	$mashwater += floatval($row['w2_amount']);
+
+echo "Maisch stap          stap type              stap temp    rusten  opwarmen" . PHP_EOL;
+echo "-------------------- ---------------------- --------- --------- ---------" . PHP_EOL;
+$arr = json_decode($row['json_mashs'], true);
+foreach($arr as $item) {
+	
+	if ($item['step_type'] == 1) {
+		$stype = formatstr($steptype[$item['step_type']], 22);
+	} else {
+		$stype = formatstr($steptype[$item['step_type']].' '.sprintf("%.1f", $item['step_infuse_amount']).' liter', 22);
+	}
+	echo sprintf("%s %s %s %s %s", 
+		formatstr($item['step_name'], 20), $stype, sprintf("%6.1f °C", $item['step_temp']),
+		sprintf("%4.0f min.", $item['step_time']), sprintf("%4.0f min.", $item['ramp_time'])) . PHP_EOL;
+}
+echo PHP_EOL;
+if ($row['w1_name'] && $row['w2_name']) {
+	itemline("Maischwater 1", sprintf("%.1f",floatval($row['w1_amount'])).' liter water '.$row['w1_name']);
+	itemline("Maischwater 2", sprintf("%.1f",floatval($row['w2_amount'])).' liter water '.$row['w2_name']);
+} else {
+	itemline("Maischwater", sprintf("%.1f",floatval($row['w1_amount'])).' liter water '.$row['w1_name']);
+}
+itemline("Maischwater aanzuren tot pH", $row['mash_ph'].' pH');
+$spoelw = ($row['boil_size'] - $mashwater + $grainabsorbtion + $row['eq_lauter_deadspace']) * 1.03;     // A small heat correction
+itemline("Spoelwater geschat", sprintf("%.1f", $spoelw)." liter");
+itemline("Spoelwater temperatuur", $row['sparge_temp'].' °C');
+itemline("Spoelwater aanzuren tot pH", sprintf("%.1f",$row['sparge_ph']).' pH');
+echo PHP_EOL . PHP_EOL;
+
+
+?>
+  
+ +