Sun, 11 Nov 2018 23:15:46 +0100
OG and FG are now calculated from the grist. The printed report has a summary an notes section at the end. The formulas are in the global formulas script.
<?php define('EURO', chr(128)); 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*Ebc4-0.00000000291515*Ebc3+0.00000818515*Ebc2+0.372038*Ebc+0.596351 return -1.32303E-12 * pow($ebc, 4) - 0.00000000291515 * pow($ebc, 3) + 0.00000818515 * pow($ebc, 2) + 0.372038 * $ebc + 0.596351; // return $ebc * 0.508; } function srm_to_ebc($srm) { // EBC = 0.000000000176506*Srm4+ 0.000000154529*Srm3-0.000159428*Srm2+2.68837*Srm-1.6004 // // Formule van Adrie Otten. brouwhulp. $ebc = 0.000000000176506 * pow($srm, 4) + 0.000000154529 * pow($srm, 3) - 0.000159428 * pow($srm, 2) + 2.68837 * $srm - 1.6004; return round($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_og($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); // echo $percSugar.' '.$percCara.' '.$attenuation.' attn '.$AttBeer.' FG '.$fg.PHP_EOL; return $fg; } /* Brouwhulp data.pas Function THop.FlavourContribution : double; //in % * concentration in g/l var bt, vol : double; begin bt:= FTime.Value; vol:= 0; if FRecipe <> NIL then vol:= FRecipe.BatchSize.Value; if FUse = huFirstWort then Result:= 0.15 * FAmount.Value * 1000 //assume 15% flavourcontribution for fwh else if bt > 50 then Result:= 0.10 * FAmount.Value * 1000 //assume 10% flavourcontribution as a minimum else begin Result:= 15.25 / (6 * sqrt(2 * PI)) * Exp(-0.5*Power((bt-21)/6, 2)) * FAmount.Value * 1000; if result < 0.10 * FAmount.Value * 1000 then Result:= 0.10 * FAmount.Value * 1000 //assume 10% flavourcontribution as a minimum end; if vol > 0 then Result:= Result / vol; end; Function THop.AromaContribution : double; //in % * concentration in g/l var bt, vol : double; begin bt:= FTime.Value; vol:= 0; if FRecipe <> NIL then vol:= FRecipe.BatchSize.Value; if bt > 20 then Result:= 0 else if bt > 7.5 then Result:= 10.03 / (4 * sqrt(2 * PI)) * Exp(-0.5*Power((bt-7.5)/4, 2)) * FAmount.Value * 1000 else if FUse = huBoil then Result:= FAmount.Value * 1000 else if FUse = huAroma then Result:= 1.2 * FAmount.Value * 1000 else if FUse = huWhirlpool then Result:= 1.2 * FAmount.Value * 1000 else if FUse = huDryHop then Result:= 1.33 * FAmount.Value * 1000; if vol > 0 then Result:= Result / vol; end; 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; Procedure TWater.AddMinerals(Ca, Mg, Na, HCO3, Cl, SO4 : double); begin FCalcium.Add(Ca); FMagnesium.Add(Mg); FSodium.Add(Na); FBicarbonate.Add(HCO3); FChloride.Add(Cl); FSulfate.Add(SO4); end; function TWater.GetResidualAlkalinity: double; begin //Result in mg/l as CaCO3 Result:= FTotalAlkalinity.Value - (FCalcium.Value / 1.4 + FMagnesium.Value / 1.7); end; const Ka1 = 0.0000004445; Ka2 = 0.0000000000468; Function PartCO3(pH : double) : double; var H : double; begin H:= Power(10, -pH); Result:= 100 * Ka1 * Ka2 / (H*H + H * Ka1 + Ka1 * Ka2); end; Function PartHCO3(pH : double) : double; var H : double; begin H:= Power(10, -pH); Result:= 100 * Ka1 * H / (H*H + H * Ka1 + Ka1 * Ka2); end; Function PartH2CO3(pH : double) : double; var H : double; begin H:= Power(10, -pH); Result:= 100 * H * H / (H*H + H * Ka1 + Ka1 * Ka2); end; Function Charge(pH : double) : double; begin Result:= (-2 * PartCO3(pH) - PartHCO3(pH)); end; //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH) Function TWater.ZAlkalinity(pHZ : double) : double; //in mEq/l var CT, DeltaCNaught, DeltaCZ, C43, Cw, Cz : double; begin C43:= Charge(4.3); Cw:= Charge(FpH.Value); Cz:= Charge(pHz); DeltaCNaught:= -C43+Cw; CT:= GetAlkalinity / 50 / DeltaCNaught; DeltaCZ:= -Cz+Cw; Result:= CT * DeltaCZ; end; //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH) Function TWater.ZRA(pHZ : double) : double; //in mEq/l var Calc, Magn, Z : double; begin Calc:= FCalcium.Value / (MMCa / 2); Magn:= FMagnesium.Value / (MMMg / 2); Z:= ZAlkalinity(pHZ); Result:= Z - (Calc / 3.5 + Magn / 7); end; Function TWater.ProtonDeficit(pHZ : double) : double; var i : integer; F : TFermentable; x : double; begin Result:= ZRA(pHZ) * FAmount.Value; //proton deficit for the added malts for i:= 0 to FRecipe.NumFermentables - 1 do begin F:= FRecipe.Fermentable[i]; if (F.AddedType = atMash) and (F.GrainType <> gtNone) then begin x:= F.AcidRequired(pHZ) * F.Amount.Value; Result:= Result + x; end; end; end; Function TWater.MashpH : double; var n : integer; pd : double; pH, deltapH, deltapd : double; begin Result:= 0; n:= 0; pH:= 5.4; deltapH:= 0.001; deltapd:= 0.1; pd:= ProtonDeficit(pH); while ((pd < -deltapd) or (pd > deltapd)) and (n < 1000) do begin inc(n); if pd < -deltapd then ph:= ph - deltapH else if pd > deltapd then pH:= pH + deltapH; pd:= ProtonDeficit(pH); end; Result:= pH; end; Function TWater.MashpH2(PrDef : double) : double; var n : integer; pd : double; pH, deltapH, deltapd : double; begin Result:= 0; n:= 0; pH:= 5.4; deltapH:= 0.001; deltapd:= 0.1; pd:= ProtonDeficit(pH); while ((pd < PrDef-deltapd) or (pd > PrDef + deltapd)) and (n < 1000) do begin inc(n); if pd < PrDef-deltapd then ph:= ph - deltapH else if pd > PrDef+deltapd then pH:= pH + deltapH; pd:= ProtonDeficit(pH); end; Result:= pH; end; function TWater.GetAlkalinity: double; begin Result := FBicarbonate.Value / 1.22; //mEq/l 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; function TBeerStyle.GetBUGUMin: double; var B, G: double; begin Result:= 0; if ((FOGMax.Value + FOGMin.Value) > 0) and ((FIBUMax.Value + FIBUMin.Value) > 0) then begin G := (FOGMax.Value - FOGMin.Value) / ((FOGMax.Value + FOGMin.Value) / 2); B := (FIBUMax.Value - FIBUMin.Value) / ((FIBUMax.Value + FIBUMin.Value) / 2); if G > B then Result := ((FIBUMin.Value + FIBUMax.Value) / 2) / (1000 * (FOGMax.Value - 1)) else Result := FIBUMin.Value / (1000 * (((FOGMax.Value + FOGMin.Value) / 2) - 1)); end; end; function TBeerStyle.GetBUGUMax: double; var B, G: double; begin Result:= 0; if ((FOGMax.Value + FOGMin.Value) > 0) and ((FIBUMax.Value + FIBUMin.Value) > 0) and (FOGMin.Value > 1) then begin G := (FOGMax.Value - FOGMin.Value) / ((FOGMax.Value + FOGMin.Value) / 2); B := (FIBUMax.Value - FIBUMin.Value) / ((FIBUMax.Value + FIBUMin.Value) / 2); if G > B then Result := ((FIBUMin.Value + FIBUMax.Value) / 2) / (1000 * (FOGMin.Value - 1)) else Result := FIBUMax.Value / (1000 * (((FOGMax.Value + FOGMin.Value) / 2) - 1)); end; end; CalcOG; CalcBitterness; // Get concentration of ions in diluted brewwater (1) and target water (2) in mmol/l Ca1 := W.Calcium.Value / MMCa; Ca2 := W2.Calcium.Value / MMCa; Mg1 := W.Magnesium.Value / MMMg; Mg2 := W2.Magnesium.Value / MMMg; Na1 := W.Sodium.Value / MMNa; Na2 := W2.Sodium.Value / MMNa; CO31 := W.Bicarbonate.Value / MMHCO3; CO32 := W2.Bicarbonate.Value / MMHCO3; SO41 := W.Sulfate.Value / MMSO4; SO42 := W2.Sulfate.Value / MMSO4; Cl1 := W.Sulfate.Value / MMSO4; Cl2 := W2.Sulfate.Value / MMSO4; procedure MixWater(W1, W2, Wr: TWater); function Mix(V1, V2, C1, C2: double): double; begin if (V1 + V2) > 0 then Result := (V1 * C1 + V2 * C2) / (V1 + V2) else Result := 0; end; var vol1, vol2: double; phnew: double; begin vol1 := W1.Amount.Value; vol2 := W2.Amount.Value; if (vol1 + vol2) > 0 then begin Wr.Amount.Value := vol1 + vol2; Wr.Calcium.Value := Mix(vol1, vol2, W1.Calcium.Value, W2.Calcium.Value); Wr.Magnesium.Value := Mix(vol1, vol2, W1.Magnesium.Value, W2.Magnesium.Value); Wr.Sodium.Value := Mix(vol1, vol2, W1.Sodium.Value, W2.Sodium.Value); Wr.Bicarbonate.Value := Mix(vol1, vol2, W1.Bicarbonate.Value, W2.Bicarbonate.Value); Wr.Sulfate.Value := Mix(vol1, vol2, W1.Sulfate.Value, W2.Sulfate.Value); Wr.Chloride.Value := Mix(vol1, vol2, W1.Chloride.Value, W2.Chloride.Value); pHnew := -log10((power(10, -W1.pHWater.Value) * vol1 + power(10, -W2.pHWater.Value) * vol2) / (vol1 + vol2)); Wr.pHwater.Value := pHnew; end; end; function TRecipe.CalcColorWort : double; var i: integer; F: TFermentable; c, v: double; begin c := 0; v := FBatchSize.Value; if (v > 0) and (High(FFermentables) >= 0) then begin for i := Low(FFermentables) to High(FFermentables) do begin F := TFermentable(FFermentables[i]); c := c + F.Amount.Value * F.Color.Value / v; end; c := c * 8.34436; case FColorMethod of cmMorey: c := 1.49 * Power(c, 0.69); cmMosher: c := 0.3 * c + 4.7; cmDaniels: c := 0.2 * c + 8.4; end; end; Result:= c; end; procedure TRecipe.CalcWaterBalance; var i: integer; F: TFermentable; begin FAbsorbedByGrain := 0; for i := Low(FFermentables) to High(FFermentables) do begin F := TFermentable(FFermentables[i]); if (F.FermentableType = ftGrain) or (F.FermentableType = ftAdjunct) then FAbsorbedByGrain := FAbsorbedByGrain + F.Amount.Value; end; FAbsorbedByGrain := FAbsorbedByGrain * Settings.GrainAbsorption.Value; if FEquipment.CalcBoilVolume.Value then {FBoilSize.Value := FBatchSize.Value / (1 - (FEquipment.EvapRate.Value / 100) * (FBoilTime.Value / 60));} FBoilSize.Value:= FBatchSize.Value + FEquipment.BoilSize.Value * FEquipment.EvapRate.Value / 100 * (FBoilTime.Value / 60); 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; */ ?>