www/includes/formulas.php

Mon, 12 Nov 2018 16:34:43 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 12 Nov 2018 16:34:43 +0100
changeset 89
082c23b26055
parent 88
0a39cbdcf085
child 90
d4246abee34e
permissions
-rw-r--r--

Missing Water agent costs from Brouwhulp import are now added from the imported miscs database. The printed recipe report now calculates the beer color from the ingredients. Also set during recipes import. This will later allow to set the color method for each recipe individually.

<?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);
	return $fg;
}



function abvol($og, $fg) {
	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 == "Morey")
		return 1.49 * pow($c, 0.69);
	if ($colormethod == "Mosher")
		return 0.3 * $c + 4.7;
	if ($colormethod == "Daniels")
		return 0.2 * $c + 8.4;
}



function kw_to_ebc($colormethod, $c) {
	return srm_to_ebc(kw_to_srm($colormethod, $c));
}



/*

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;


  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;




*/

?>

mercurial