Sun, 02 Jun 2019 12:48:54 +0200
Added 15 fields to the recipes table. Added 18 fields to the products table. These are calculated values that are now stored in the database so export programs can use these values without calculating them again. Product and recipe print have water and mash schedule added. Product print has brewday results added if the brewday is over. The ingredients layout changed in the product and recipe prints.
<?php define('EURO', chr(128)); define('DEG', chr(176)); define('SUGARDENSITY', '1.611'); define('MMCa', '40.048'); define('MMMg', '24.305'); define('MMNa', '22.98976928'); define('MMCl', '35.453'); define('MMSO4', '96.0626'); define('MMCO3', '60.01684'); define('MMHCO3', '61.01684'); define('MMCaSO4', '172.171'); define('MMCaCl2', '147.015'); define('MMCaCO3', '100.087'); define('MMMgSO4', '246.475'); define('MMNaHCO3', '84.007'); define('MMNa2CO3', '105.996'); define('MMNaCl', '58.443'); define('MMCaOH2', '74.06268'); function ebc_to_srm($ebc) { $srm = -1.32303E-12 * pow($ebc, 4) - 0.00000000291515 * pow($ebc, 3) + 0.00000818515 * pow($ebc, 2) + 0.372038 * $ebc + 0.596351; if (($ebc < 0) || ($srm < 0)) syslog(LOG_NOTICE, "ebc_to_srm(".$ebc.") = ".$srm); return $srm; } function srm_to_ebc($srm) { // Formule van Adrie Otten. brouwhulp. $ebc = round( 0.000000000176506 * pow($srm, 4) + 0.000000154529 * pow($srm, 3) - 0.000159428 * pow($srm, 2) + 2.68837 * $srm - 1.6004 ); if (($ebc < 0) || ($srm < 0)) syslog(LOG_NOTICE, "srm_to_ebc(".$srm.") = ".$ebc); return $ebc; } function ebc_to_color($ebc) { return srm_to_color(ebc_to_srm($ebc)); } function srm_to_color($srm) { $i = abs($srm * 10); if ($i < 0) { $i = 0; } if ($i > 299) { $i = 299; } /* Table copied from Brouwhulp/BrewBuddy */ $R = array( 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, // 0 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, // 2 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, // 4 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 200, 199, 199, 198, 198, // 6 197, 197, 196, 196, 195, 195, 194, 194, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 8 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 10 192, 192, 192, 192, 192, 192, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, // 12 179, 178, 177, 175, 174, 172, 171, 169, 168, 167, 195, 164, 162, 161, 159, 158, 157, 155, 154, 152, // 14 151, 149, 148, 147, 145, 144, 142, 141, 139, 138, 137, 135, 134, 132, 131, 129, 128, 127, 125, 124, // 16 122, 121, 119, 118, 117, 115, 114, 112, 111, 109, 108, 107, 105, 104, 102, 101, 99, 98, 97, 95, // 18 94, 92, 91, 89, 88, 87, 85, 84, 82, 81, 79, 78, 77, 75, 74, 72, 71, 69, 68, 67, // 20 65, 64, 62, 61, 59, 58, 57, 55, 54, 52, 51, 49, 48, 47, 45, 44, 43, 41, 39, 38, // 22 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, // 24 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, // 26 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8 ); $G = array( 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 242, 240, 238, 236, 234, 232, 230, 228, 226, 224, 222, 220, 218, 216, 214, 212, 210, 208, 206, 204, 202, 200, 198, 196, 194, 192, 190, 188, 186, 184, 182, 180, 178, 176, 174, 172, 170, 168, 166, 164, 162, 160, 158, 156, 154, 152, 150, 148, 146, 144, 142, 141, 140, 139, 139, 138, 137, 136, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129, 128, 127, 127, 126, 125, 124, 124, 123, 122, 121, 121, 120, 119, 118, 118, 117, 116, 115, 115, 114, 113, 112, 112, 111, 110, 109, 109, 108, 107, 106, 106, 105, 104, 103, 103, 102, 101, 100, 100, 99, 98, 97, 97, 96, 95, 94, 94, 93, 92, 91, 91, 90, 89, 88, 88, 87, 86, 85, 85, 84, 83, 82, 82, 81, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 72, 71, 70, 69, 69, 68, 67, 66, 66, 65, 64, 63, 63, 62, 61, 60, 60, 59, 58, 57, 57, 56, 55, 54, 54, 53, 52, 51, 51, 50, 49, 48, 48, 47, 46, 45, 45, 44, 43, 42, 42, 41, 40, 39, 39, 38, 37, 36, 36, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28, 27, 27, 26, 25, 24, 24, 23, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3 ); $B = array( 210, 204, 199, 193, 188, 182, 177, 171, 166, 160, 155, 149, 144, 138, 133, 127, 122, 116, 111, 105, 100, 94, 89, 83, 78, 72, 67, 61, 56, 50, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 54, 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 52, 51, 51, 51, 51, 50, 50, 50, 50, 49, 49, 48, 47, 47, 46, 45, 45, 44, 43, 43, 42, 41, 41, 40, 39, 39, 38, 37, 37, 36, 35, 34, 33, 32, 31, 29, 28, 27, 26, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 13, 12, 11, 10, 9, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2 ); return array($R[$i],$G[$i],$B[$i]); } function sg_to_plato($sg) { if ($sg > 0.5) return 259 - 259 / $sg; return 0; } function plato_to_sg($plato) { if ($plato < 259) return 259 / (259 - $plato); return 1.000; } /* * sugars is the total extract weight of sugars. */ function estimate_sg($sugars, $batch_size) { $plato = 100 * $sugars / $batch_size; $sg = plato_to_sg($plato); /* Average loops, HansH 5x. Brouwhulp 20x, about 10x is enough so keep 20. */ for ($i = 0; $i < 20; $i++) { if ($sg > 0) $plato = 100 * $sugars / ($batch_size * $sg); $sg = plato_to_sg($plato); } return $sg; } function estimate_fg($percSugar, $percCara, $WGratio, $TotTme, $Temp, $attenuation, $og) { if ($percSugar > 40) $percSugar = 0; if ($percCara > 50) $percCara = 0; if (($WGratio > 0) && ($TotTme > 0)) { $BD = $WGratio; $BD = max(2, min(5.5, $BD)); $Temp = max(60, min(72, $Temp)); } else { $BD = 3.5; $Temp = 67; $TotTme = 75; } if ($attenuation < 30) $attenuation = 77; $AttBeer = 0.00825 * $attenuation + 0.00817 * $BD - 0.00684 * $Temp + 0.00026 * $TotTme - 0.00356 * $percCara + 0.00553 * $percSugar + 0.547; $fg = 1 + (1 - $AttBeer) * ($og - 1); return $fg; } function abvol($og, $fg) { $factor = $og * 3157 * pow(10, -5) + 9.716 * pow(10, -2); return ($og * 1000 - $fg * 1000) * $factor; //if ((4.749804 - $fg) <> 0) // return 486.8693 * ($og - $fg) / (4.749804 - $fg); //return 0; } /* * Kleurwerking naar SRM */ function kw_to_srm($colormethod, $c) { if ($colormethod == 0) // Morey return 1.4922 * pow($c, 0.6859); if ($colormethod == 1) // Mosher return 0.3 * $c + 4.7; if ($colormethod == 2) // Daniels return 0.2 * $c + 8.4; } function kw_to_ebc($colormethod, $c) { return srm_to_ebc(kw_to_srm($colormethod, $c)); } function calc_IBU($useat, $form, $sg, $volume, $mass, $boiltime, $alpha, $method) { global $my_factor_mashhop; global $my_factor_fwh; global $my_factor_pellet; global $my_factor_plug; $fmoment = 1.0; if (($useat == 5) || ($useat == 4) || ($useat == 3)) { // Dry hop, Whirlpool or Aroma $fmoment = 0.0; } else if ($useat == 0) { // Mash $fmoment += $my_factor_mashhop / 100; // Brouwhulp } else if ($useat == 1) { // First wort $fmoment += $my_factor_fwh / 100; // Brouwhulp, Louis, Ozzie } $pfactor = 1.0; if ($form == 0) { // Pellets $pfactor += $my_factor_pellet / 100; } if ($form == 1) { // Plugs $pfactor += $my_factor_plug / 100; } $ibu = 0; if (($method == 0) || ($method == 3)) { // Tinseth or Garetz // For Garetz, we need the $ibu $AddedAlphaAcids = (($alpha / 100) * $mass * 1000) / $volume; $Bigness_factor = 1.65 * pow( 0.000125, $sg - 1); $BoilTime_factor = ((1 - exp(-0.04 * $boiltime)) / 4.15); $utiisation = $Bigness_factor * $BoilTime_factor; $ibu = (round($utiisation * $AddedAlphaAcids * $fmoment * $pfactor * 10) / 10.0); } if ($method == 2) { // Daniels if ($form == 2) // Leaf $boilfactor = -(0.0041*$boiltime*$boiltime)+(0.6162*$boiltime)+1.5779; else $boilfactor = -(0.0051*$boiltime*$boiltime)+(0.7835*$boiltime)+1.9348; if ($sg < 1.050) $sgfactor = 0; else $sgfactor = (($sg * 1000) - 1050) / 200; $ibu = $fmoment * (($mass * $alpha * $boilfactor * 0.1) / ($volume * (1 + $sgfactor))); } if ($method == 1) { // Rager $boilfactor = $fmoment * 18.11 + 13.86 * tanh(($boiltime * 31.32) / 18.27); if ($sg < 1.050) $sgfactor = 0; else $sgfactor = (($sg * 1000) - 1050) / 200; $ibu = ($mass * $alpha * $boilfactor * 0.1) / ($volume * (1 + $sgfactor)); } if ($method == 3) { // Garetz, not in use. /* Something is wrong, late hops and dryhops give negative results. */ $boilfactor = $fmoment * 6.03253 + 16.5289 * tanh(($boiltime - 19.17323) / 26.8013); $cfactor = $volume / (1.1 * $volume); // ConcentratieFactor = (Volume na koelen) / (Volume bij Koken) $kookdichtheid = ($cfactor * (($sg * 1000) - 1000) / 1000) + 1; $sgfactor = ($kookdichtheid - 1.05) / 0.2 + 1; $hopratefactor = (($cfactor * $ibu) / 260) + 1; // $ibu is Tinseth bitterness. Weird. $tempfactor = (32.8/550)*0.02+1; $ibu = ($boilfactor * $alpha * $mass * 0.1) / ($volume * $sgfactor * $hopratefactor * $tempfactor); } /* TODO: Noonan and Mosher */ return $ibu; } function kettle_cm($vol, $kettle_vol, $kettle_height) { if (($vol > 0) && ($kettle_vol > 0) && ($vol <= $kettle_vol)) return 100 * ((1 - $vol / $kettle_vol) * $kettle_height); return 0; } function density_str($sg) { global $my_brix_correction; $plato = sg_to_plato(floatval($sg)); $brix = $plato * $my_brix_correction; return sprintf("%.3f", floatval($sg))." SG ".sprintf("%.1f",$brix).DEG.'Brix '.sprintf("%.1f",$plato).DEG.'P'; } /* Brouwhulp data.pas Procedure TFermentable.SetpHParameters(force : boolean); var x, ebc : double; begin if Between(FDIpH.Value, -0.01, 0.01) or Between(FAcidTo57.Value, -0.1, 0.1) or force then begin ebc:= SRMtoEBC(FColor.Value); case FGrainType of gtBase, gtKilned: begin FDIpH.Value:= -0.0132 * ebc + 5.7605; x:= 0.4278 * ebc - 1.8106; FAcidTo57.Value:= x; end; gtRoast: begin FDIpH.Value:= 0.00018 * ebc + 4.558; FAcidTo57.Value:= -0.0176 * ebc + 60.04; end; gtCrystal: begin FDIpH.Value:= -0.0019 * ebc + 5.2175; FAcidTo57.Value:= 0.132 * ebc + 14.277; end; gtSour: begin FDIpH.Value:= 3.44; FAcidTo57.Value:= 337; end; gtSpecial: //this could be anything. Assume for now it is a non-acidulated base or kilned malt begin FDIpH.Value:= -0.0132 * ebc + 5.7605; FAcidTo57.Value:= 0.4278 * ebc - 1.8106; end; end; end; //known parameters should be filled in here if FSupplier.Value = 'Weyermann' then begin if FName.Value = 'Vienna mout' then begin FDIpH.Value:= 5.65; FAcidTo57.Value:= 1.6; end; if FName.Value = 'Münchner I' then begin FDIpH.Value:= 5.44; FAcidTo57.Value:= 8.4; end; if FName.Value = 'Münchner II' then begin FDIpH.Value:= 5.54; FAcidTo57.Value:= 5.6; end; if FName.Value = 'Caramunich I' then begin FDIpH.Value:= 5.1; FAcidTo57.Value:= 22.4; end; if FName.Value = 'Caramunich II' then begin FDIpH.Value:= 4.71; FAcidTo57.Value:= 49; end; if FName.Value = 'Caramunich III' then begin FDIpH.Value:= 4.92; FAcidTo57.Value:= 31.2; end; if FName.Value = 'Cara-aroma' then begin FDIpH.Value:= 4.48; FAcidTo57.Value:= 74.4; end; if FName.Value = 'Carafa I' then begin FDIpH.Value:= 4.71; FAcidTo57.Value:= 42; end; if FName.Value = 'Carafa III' then begin FDIpH.Value:= 4.81; FAcidTo57.Value:= 35.4; end; if FName.Value = 'Carafa II' then begin FDIpH.Value:= 4.76; FAcidTo57.Value:= 38.7; end; if FName.Value = 'Carafa Special I' then begin FDIpH.Value:= 4.73; FAcidTo57.Value:= 46.4; end; if FName.Value = 'Carafa Special II' then begin FDIpH.Value:= 4.78; FAcidTo57.Value:= 42.9; end; if FName.Value = 'Carafa Special III' then begin FDIpH.Value:= 4.83; FAcidTo57.Value:= 38.9; end; if IsInString(FName.Value, 'Zuurmout') then begin FDIpH.Value:= 3.44; FAcidTo57.Value:= 358.2; end; end; end; function TFermentable.GetExtract: double; begin Result := 0; if FRecipe <> nil then begin Result := FAmount.Value * FYield.Value / 100 * (1 - FMoisture.Value / 100); if FAdded = atMash then Result := Result * FRecipe.Efficiency / 100; end; end; function TFermentable.GetKolbachIndex: double; begin if FProtein.Value > 0 then Result := FDissolvedProtein.Value / FProtein.Value else Result := 0; end; function TWater.GetResidualAlkalinity: double; begin //Result in mg/l as CaCO3 Result:= FTotalAlkalinity.Value - (FCalcium.Value / 1.4 + FMagnesium.Value / 1.7); end; function TWater.GetHardness: double; begin Result := 0.14 * FCalcium.Value - 0.23 * FMagnesium.Value; end; function TWater.GetEstPhMash: double; {var pHdemi, S: double;} begin Result:= MashpH; { Result := 0; if FRecipe <> nil then begin pHDemi := FRecipe.pHdemi; S := 0.013 * FRecipe.MashThickness + 0.013; Result := pHDemi + ResidualAlkalinity / 50 * S; end;} end; Procedure TRecipe.CalcCalories; var sug, alc, org, fig : double; begin if FOGFermenter.Value > 1.001 then org:= FOGFermenter.Value else if FOG.Value > 1.001 then org:= FOG.Value else org:= 0; if FFG.Value > 0.999 then fig:= FFG.Value else if FEstFG.Value > 1.000 then fig:= FEstFG.Value else if FEstFG2.Value > 1.000 then fig:= FEstFG2.Value else fig:= 0; if (org > 0) and (fig > 0) then begin alc:= 1881.22 * fig * (org - fig) / (1.775 - org); sug:= 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004); FCalories.Value:= (alc + sug) / (12 * 0.0295735296); end else FCalories.Value:= 0; end; */ ?>