-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #919 from matty0ung/usability
Fix places where we are using old ABV formulae
- Loading branch information
Showing
3 changed files
with
34 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ | ||
* Algorithms.cpp is part of Brewtarget, and is copyright the following authors 2009-2023: | ||
* Algorithms.cpp is part of Brewtarget, and is copyright the following authors 2009-2025: | ||
* • Eric Tamme <[email protected]> | ||
* • Matt Young <[email protected]> | ||
* • Philip Greggory Lee <[email protected]> | ||
|
@@ -247,7 +247,7 @@ double Polynomial::rootFind( double x0, double x1 ) const { | |
return newGuess; | ||
} | ||
|
||
//╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ | ||
//====================================================================================================================== | ||
|
||
bool Algorithms::isNan(double d) { | ||
// If using IEEE floating points, all comparisons with a NaN | ||
|
@@ -475,6 +475,12 @@ double Algorithms::abvFromOgAndFg(double og, double fg) { | |
// Assert the parameters were supplied in the right order by checking that FG cannot by higher than OG | ||
Q_ASSERT(og >= fg); | ||
|
||
// | ||
// Previously, in different places in the code, we either used a very rough rule of thumb: | ||
// | ||
// double calculatedABV_pct = (og - fg) * 130 | ||
// | ||
// or we used the FALLBACK METHOD described below. | ||
// | ||
// The current calculation method we use comes from the UK Laboratory of the Government Chemist. It is what HM | ||
// Revenue and Customs (HMRC) encourage UK microbreweries to use to calculate ABV if they have "no or minimal | ||
|
@@ -526,7 +532,7 @@ double Algorithms::abvFromOgAndFg(double og, double fg) { | |
); | ||
|
||
// | ||
// OLD METHOD, which is also the fallback | ||
// FALLBACK METHOD | ||
// | ||
// From http://www.brewersfriend.com/2011/06/16/alcohol-by-volume-calculator-updated/: | ||
// "[This] formula, and variations on it, comes from Ritchie Products Ltd, (Zymurgy, Summer 1995, vol. 18, no. 2) | ||
|
@@ -536,31 +542,31 @@ double Algorithms::abvFromOgAndFg(double og, double fg) { | |
// The relationship between the change in gravity, and the change in ABV is not linear. All these equations are | ||
// approximations." | ||
// | ||
double abvByOldMethod = (76.08 * (og - fg) / (1.775 - og)) * (fg / 0.794); | ||
double const abvByFallbackMethod = (76.08 * (og - fg) / (1.775 - og)) * (fg / 0.794); | ||
|
||
if (matchingGravityDifferenceRec == gravityDifferenceFactors.cend()) { | ||
qCritical() << | ||
Q_FUNC_INFO << "Could not find gravity difference record for difference of " << | ||
(excessGravityDiffx10 / 10.0) << "so using fallback method"; | ||
return abvByOldMethod; | ||
return abvByFallbackMethod; | ||
} | ||
|
||
double abvByNewMethod = excessGravityDiff * matchingGravityDifferenceRec->factorToUse; | ||
double const abvByHmrcMethod = excessGravityDiff * matchingGravityDifferenceRec->factorToUse; | ||
|
||
qDebug() << | ||
Q_FUNC_INFO << "ABV old method:" << abvByOldMethod << "% , new method:" << abvByNewMethod << "% (used factor" << | ||
Q_FUNC_INFO << "ABV old method:" << abvByFallbackMethod << "% , new method:" << abvByHmrcMethod << "% (used factor" << | ||
matchingGravityDifferenceRec->factorToUse << "and should be in range" << | ||
matchingGravityDifferenceRec->pctAbv_Min << "% -" << matchingGravityDifferenceRec->pctAbv_Max << "%)"; | ||
|
||
// The tables from UK HMRC have some sanity-check data, so let's use it! | ||
if (abvByNewMethod < matchingGravityDifferenceRec->pctAbv_Min || | ||
abvByNewMethod > matchingGravityDifferenceRec->pctAbv_Max) { | ||
if (abvByHmrcMethod < matchingGravityDifferenceRec->pctAbv_Min || | ||
abvByHmrcMethod > matchingGravityDifferenceRec->pctAbv_Max) { | ||
qWarning() << | ||
Q_FUNC_INFO << "Calculated ABV of" << abvByNewMethod << "% is outside expected range (" << | ||
Q_FUNC_INFO << "Calculated ABV of" << abvByHmrcMethod << "% is outside expected range (" << | ||
matchingGravityDifferenceRec->pctAbv_Min << "% -" << matchingGravityDifferenceRec->pctAbv_Max << "%)"; | ||
} | ||
|
||
return abvByNewMethod; | ||
return abvByHmrcMethod; | ||
} | ||
|
||
double Algorithms::correctSgForTemperature(double measuredSg, double readingTempInC, double calibrationTempInC) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ | ||
* model/BrewNote.cpp is part of Brewtarget, and is copyright the following authors 2009-2024: | ||
* model/BrewNote.cpp is part of Brewtarget, and is copyright the following authors 2009-2025: | ||
* • Brian Rower <[email protected]> | ||
* • Greg Meess <[email protected]> | ||
* • Jonatan Pålsson <[email protected]> | ||
|
@@ -563,16 +563,17 @@ double BrewNote::calculateABV_pct() { | |
// 1 + [(og - 1) * (1.0 - %/100)] | ||
double const estFg = 1 + ((m_og-1.0)*(1.0 - atten_pct/100.0)); | ||
|
||
double const calculatedABV = (m_og-estFg)*130; | ||
this->setProjABV_pct(calculatedABV); | ||
double const calculatedAbv_pct = Algorithms::abvFromOgAndFg(this->m_og, estFg); | ||
|
||
return calculatedABV; | ||
this->setProjABV_pct(calculatedAbv_pct); | ||
|
||
return calculatedAbv_pct; | ||
} | ||
|
||
double BrewNote::calculateActualABV_pct() { | ||
double const abv = (m_og - m_fg) * 130; | ||
this->setABV(abv); | ||
return abv; | ||
double const abv_pct = Algorithms::abvFromOgAndFg(this->m_og, this->m_fg); | ||
this->setABV(abv_pct); | ||
return abv_pct; | ||
} | ||
|
||
double BrewNote::calculateAttenuation_pct() { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ | ||
* model/Recipe.cpp is part of Brewtarget, and is copyright the following authors 2009-2024: | ||
* model/Recipe.cpp is part of Brewtarget, and is copyright the following authors 2009-2025: | ||
* • Brian Rower <[email protected]> | ||
* • Greg Greenaae <[email protected]> | ||
* • Greg Meess <[email protected]> | ||
|
@@ -1225,16 +1225,11 @@ class Recipe::impl { | |
return; | ||
} | ||
|
||
|
||
/** | ||
* Emits changed(ABV_pct). Depends on: m_og, m_fg | ||
*/ | ||
void recalcABV_pct() { | ||
// The complex formula, and variations comes from Ritchie Products Ltd, (Zymurgy, Summer 1995, vol. 18, no. 2) | ||
// Michael L. Hall’s article Brew by the Numbers: Add Up What’s in Your Beer, and Designing Great Beers by Daniels. | ||
double calculatedABV_pct = | ||
(76.08 * (this->m_og_fermentable - this->m_fg_fermentable) / (1.775 - this->m_og_fermentable)) * | ||
(this->m_fg_fermentable / 0.794); | ||
double const calculatedABV_pct = Algorithms::abvFromOgAndFg(this->m_og_fermentable, this->m_fg_fermentable); | ||
|
||
if (!qFuzzyCompare(calculatedABV_pct, m_ABV_pct)) { | ||
qDebug() << | ||
|
@@ -2657,9 +2652,15 @@ double Recipe::ibuFromHopAddition(RecipeAdditionHop const & hopAddition) { | |
boilTime_mins = static_cast<int>(equipment->boilTime_min().value_or(Equipment::default_boilTime_mins)); | ||
} | ||
|
||
// Assume 30 min cool time if boil is not set | ||
double coolTime_mins = 30.0; | ||
|
||
auto boil = this->boil(); | ||
if (boil) { | ||
boilTime_mins = boil->boilTime_mins(); | ||
if (boil->coolTime_mins()) { | ||
coolTime_mins = *boil->coolTime_mins(); | ||
} | ||
} | ||
|
||
qDebug() << | ||
|
@@ -2674,7 +2675,7 @@ double Recipe::ibuFromHopAddition(RecipeAdditionHop const & hopAddition) { | |
.postBoilVolume_liters = this->pimpl->m_finalVolumeNoLosses_l, | ||
.wortGravity_sg = m_og, | ||
.timeInBoil_minutes = boilTime_mins, // Seems unlikely in reality that there would be fractions of a minute | ||
.coolTime_minutes = boil->coolTime_mins(), | ||
.coolTime_minutes = coolTime_mins, | ||
}; | ||
if (equipment) { | ||
parms.kettleInternalDiameter_cm = equipment->kettleInternalDiameter_cm(); | ||
|