Skip to content

Commit

Permalink
Fields that should always have been optional in Fermentable
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Young committed Apr 13, 2024
1 parent 8134749 commit b97982f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 44 deletions.
30 changes: 15 additions & 15 deletions src/model/Fermentable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ Fermentable::Fermentable(QString name) :
m_supplier {"" },
m_notes {"" },
m_coarseFineDiff_pct {std::nullopt },
m_moisture_pct {0.0 },
m_moisture_pct {std::nullopt },
m_diastaticPower_lintner {std::nullopt },
m_protein_pct {0.0 },
m_maxInBatch_pct {100.0 },
m_recommendMash {false },
m_ibuGalPerLb {0.0 },
m_protein_pct {std::nullopt },
m_maxInBatch_pct {std::nullopt },
m_recommendMash {std::nullopt },
m_ibuGalPerLb {std::nullopt },
/// m_isMashed {false },
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
m_grainGroup {std::nullopt },
Expand Down Expand Up @@ -322,12 +322,12 @@ QString Fermentable::origin ()
QString Fermentable::supplier () const { return this->m_supplier ; }
QString Fermentable::notes () const { return this->m_notes ; }
std::optional<double> Fermentable::coarseFineDiff_pct () const { return this->m_coarseFineDiff_pct ; }
double Fermentable::moisture_pct () const { return this->m_moisture_pct ; }
std::optional<double> Fermentable::moisture_pct () const { return this->m_moisture_pct ; }
std::optional<double> Fermentable::diastaticPower_lintner () const { return this->m_diastaticPower_lintner ; }
double Fermentable::protein_pct () const { return this->m_protein_pct ; }
double Fermentable::maxInBatch_pct () const { return this->m_maxInBatch_pct ; }
bool Fermentable::recommendMash () const { return this->m_recommendMash ; }
double Fermentable::ibuGalPerLb () const { return this->m_ibuGalPerLb ; }
std::optional<double> Fermentable::protein_pct () const { return this->m_protein_pct ; }
std::optional<double> Fermentable::maxInBatch_pct () const { return this->m_maxInBatch_pct ; }
std::optional<bool> Fermentable::recommendMash () const { return this->m_recommendMash ; }
std::optional<double> Fermentable::ibuGalPerLb () const { return this->m_ibuGalPerLb ; }
///bool Fermentable::isMashed () const { return this->m_isMashed ; }
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
std::optional<Fermentable::GrainGroup> Fermentable::grainGroup () const { return this->m_grainGroup ; }
Expand Down Expand Up @@ -365,16 +365,16 @@ void Fermentable::setType (Type const
void Fermentable::setOrigin (QString const & val) { SET_AND_NOTIFY(PropertyNames::Fermentable::origin , this->m_origin , val); return; }
void Fermentable::setSupplier (QString const & val) { SET_AND_NOTIFY(PropertyNames::Fermentable::supplier , this->m_supplier , val); return; }
void Fermentable::setNotes (QString const & val) { SET_AND_NOTIFY(PropertyNames::Fermentable::notes , this->m_notes , val); return; }
void Fermentable::setRecommendMash (bool const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::recommendMash , this->m_recommendMash , val); return; }
void Fermentable::setRecommendMash (std::optional<bool> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::recommendMash , this->m_recommendMash , val); return; }
///void Fermentable::setIsMashed (bool const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::isMashed , this->m_isMashed , val); return; }
void Fermentable::setIbuGalPerLb (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::ibuGalPerLb , this->m_ibuGalPerLb , val); return; }
void Fermentable::setIbuGalPerLb (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::ibuGalPerLb , this->m_ibuGalPerLb , val); return; }
///void Fermentable::setYield_pct (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::yield_pct , this->m_yield_pct , this->enforceMinAndMax(val, "amount", 0.0, 100.0)); return; }
void Fermentable::setColor_srm (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::color_srm , this->m_color_srm , this->enforceMin (val, "color")); return; }
void Fermentable::setCoarseFineDiff_pct (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::coarseFineDiff_pct , this->m_coarseFineDiff_pct , this->enforceMinAndMax(val, "coarseFineDiff", 0.0, 100.0)); return; }
void Fermentable::setMoisture_pct (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::moisture_pct , this->m_moisture_pct , this->enforceMinAndMax(val, "moisture", 0.0, 100.0)); return; }
void Fermentable::setMoisture_pct (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::moisture_pct , this->m_moisture_pct , this->enforceMinAndMax(val, "moisture", 0.0, 100.0)); return; }
void Fermentable::setDiastaticPower_lintner (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::diastaticPower_lintner , this->m_diastaticPower_lintner , this->enforceMin (val, "diastatic power")); return; }
void Fermentable::setProtein_pct (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::protein_pct , this->m_protein_pct , this->enforceMinAndMax(val, "protein", 0.0, 100.0)); return; }
void Fermentable::setMaxInBatch_pct (double const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::maxInBatch_pct , this->m_maxInBatch_pct , this->enforceMinAndMax(val, "max in batch", 0.0, 100.0)); return; }
void Fermentable::setProtein_pct (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::protein_pct , this->m_protein_pct , this->enforceMinAndMax(val, "protein", 0.0, 100.0)); return; }
void Fermentable::setMaxInBatch_pct (std::optional<double> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::maxInBatch_pct , this->m_maxInBatch_pct , this->enforceMinAndMax(val, "max in batch", 0.0, 100.0)); return; }
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
void Fermentable::setGrainGroup (std::optional<GrainGroup> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::grainGroup , this->m_grainGroup , val ); return; }
void Fermentable::setGrainGroupAsInt (std::optional<int> const val) { SET_AND_NOTIFY(PropertyNames::Fermentable::grainGroup , this->m_grainGroup , Optional::fromOptInt<GrainGroup>(val)); return; }
Expand Down
68 changes: 41 additions & 27 deletions src/model/Fermentable.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,22 +221,31 @@ class Fermentable : public Ingredient, public IngredientBase<Fermentable> {
* .:TODO:. We should attempt to enforce this when two or more of the values are set.
*/
Q_PROPERTY(std::optional<double> coarseFineDiff_pct READ coarseFineDiff_pct WRITE setCoarseFineDiff_pct )
//! \brief The moisture in pct.
Q_PROPERTY(double moisture_pct READ moisture_pct WRITE setMoisture_pct )
//! \brief The diastatic power in Lintner.
//! \brief The moisture in pct. Only appropriate for a "Grain" or "Other_Adjunct" type. NB Optional in both BeerXML and BeerJSON.
Q_PROPERTY(std::optional<double> moisture_pct READ moisture_pct WRITE setMoisture_pct )
//! \brief The diastatic power in Lintner. Only appropriate for a "Grain" or "Other_Adjunct" type. NB Optional in both BeerXML and BeerJSON.
Q_PROPERTY(std::optional<double> diastaticPower_lintner READ diastaticPower_lintner WRITE setDiastaticPower_lintner )
//! \brief The percent protein.
Q_PROPERTY(double protein_pct READ protein_pct WRITE setProtein_pct )
//! \brief The maximum recommended amount in a batch, as a percentage of the total grains.
Q_PROPERTY(double maxInBatch_pct READ maxInBatch_pct WRITE setMaxInBatch_pct )
//! \brief The percent protein. Only appropriate for a "Grain" or "Other_Adjunct" type. NB Optional in both BeerXML and BeerJSON.
Q_PROPERTY(std::optional<double> protein_pct READ protein_pct WRITE setProtein_pct )
//! \brief The maximum recommended amount in a batch, as a percentage of the total grains. NB Optional in both BeerXML and BeerJSON.
Q_PROPERTY(std::optional<double> maxInBatch_pct READ maxInBatch_pct WRITE setMaxInBatch_pct )
/**
* \brief Whether a mash is recommended. \c true means \c Fermentable must be mashed, \c false means if it can be
* steeped. Note that this does NOT indicate whether the \c Fermentable is mashed or not – it is only a
* recommendation used in recipe formulation.
* recommendation used in recipe formulation. NB Optional in both BeerXML and BeerJSON.
*/
Q_PROPERTY(bool recommendMash READ recommendMash WRITE setRecommendMash )
//! \brief The IBUs per gal/lb if this is a liquid extract. .:TODO:. Should this be a metric measure?
Q_PROPERTY(double ibuGalPerLb READ ibuGalPerLb WRITE setIbuGalPerLb )
Q_PROPERTY(std::optional<bool> recommendMash READ recommendMash WRITE setRecommendMash )
/**
* \brief For hopped extracts only - an estimate of the number of IBUs per pound of extract in a gallon of water.
* To convert to IBUs we multiply this number by the amount in pounds and divide by the number of gallons in
* the batch. Based on a sixty minute boil. Only suitable for use with an "Extract" type, otherwise this
* value is ignored.
*
* This is an optional field in BeerXML and unsupported in BeerJSON.
*
* .:TBD:. If we care about this, then it would be more consistent to store in internally as a metric measure.
*/
Q_PROPERTY(std::optional<double> ibuGalPerLb READ ibuGalPerLb WRITE setIbuGalPerLb )
/// //! \brief Whether the grains actually is mashed.
/// Q_PROPERTY(bool isMashed READ isMashed WRITE setIsMashed )
//! \brief Whether this fermentable is an extract.
Expand All @@ -263,6 +272,11 @@ class Fermentable : public Ingredient, public IngredientBase<Fermentable> {
* We treat this as synonymous with the BeerXML field YIELD, defined as "Percent dry yield (fine grain) for
* the grain, or the raw yield by weight if this is an extract adjunct or sugar." HOWEVER, note that the
* BeerXML field is required whereas internally, and in BeerJSON, this is an optional field.
*
* NOTE: Actually in BeerJSON, there is a required field of yield which is a record containing optional fields
* fine_grind, coarse_grind, fine_coarse_difference and potential. Technically if none of these fields
* is set, then we should still write out an empty yield record, but we would not. Hopefully this won't
* be a problem in practice.
*/
Q_PROPERTY(std::optional<double> fineGrindYield_pct READ fineGrindYield_pct WRITE setFineGrindYield_pct )
//! \brief Extract Yield Dry Basis Coarse Grind (DBCG) - aka percentage yield, compared to sucrose, of a coarse grind
Expand Down Expand Up @@ -456,13 +470,13 @@ class Fermentable : public Ingredient, public IngredientBase<Fermentable> {
QString origin () const;
QString supplier () const;
QString notes () const;
std::optional<double> coarseFineDiff_pct () const;
double moisture_pct () const;
std::optional<double> coarseFineDiff_pct () const;
std::optional<double> moisture_pct () const;
std::optional<double> diastaticPower_lintner () const;
double protein_pct () const;
double maxInBatch_pct () const;
bool recommendMash () const;
double ibuGalPerLb () const;
std::optional<double> protein_pct () const;
std::optional<double> maxInBatch_pct () const;
std::optional<bool> recommendMash () const;
std::optional<double> ibuGalPerLb () const;
/// bool isMashed () const;
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
std::optional<GrainGroup> grainGroup () const;
Expand Down Expand Up @@ -499,12 +513,12 @@ class Fermentable : public Ingredient, public IngredientBase<Fermentable> {
void setSupplier (QString const & val);
void setNotes (QString const & val);
void setCoarseFineDiff_pct (std::optional<double> const val);
void setMoisture_pct (double const val);
void setMoisture_pct (std::optional<double> const val);
void setDiastaticPower_lintner (std::optional<double> const val);
void setProtein_pct (double const val);
void setMaxInBatch_pct (double const val);
void setRecommendMash (bool const val);
void setIbuGalPerLb (double const val);
void setProtein_pct (std::optional<double> const val);
void setMaxInBatch_pct (std::optional<double> const val);
void setRecommendMash (std::optional<bool> const val);
void setIbuGalPerLb (std::optional<double> const val);
/// void setIsMashed (bool const val);
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
void setGrainGroup (std::optional<GrainGroup> const val);
Expand Down Expand Up @@ -547,12 +561,12 @@ class Fermentable : public Ingredient, public IngredientBase<Fermentable> {
QString m_supplier ;
QString m_notes ;
std::optional<double> m_coarseFineDiff_pct ;
double m_moisture_pct ;
std::optional<double> m_moisture_pct ;
std::optional<double> m_diastaticPower_lintner ;
double m_protein_pct ;
double m_maxInBatch_pct ;
bool m_recommendMash ;
double m_ibuGalPerLb ;
std::optional<double> m_protein_pct ;
std::optional<double> m_maxInBatch_pct ;
std::optional<bool> m_recommendMash ;
std::optional<double> m_ibuGalPerLb ;
/// bool m_isMashed ; // Primarily valid in "Use Of" instance
// ⮜⮜⮜ All below added for BeerJSON support ⮞⮞⮞
std::optional<GrainGroup> m_grainGroup ;
Expand Down
2 changes: 1 addition & 1 deletion src/model/Recipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1449,7 +1449,7 @@ class Recipe::impl {
for (auto const & fermentableAddition : this->m_self.fermentableAdditions()) {
if (fermentableAddition->amountIsWeight()) {
// Conversion factor for lb/gal to kg/l = 8.34538.
calculatedIbu += fermentableAddition->fermentable()->ibuGalPerLb() * (fermentableAddition->amount().quantity / this->m_self.batchSize_l()) / 8.34538;
calculatedIbu += fermentableAddition->fermentable()->ibuGalPerLb().value_or(0.0) * (fermentableAddition->amount().quantity / this->m_self.batchSize_l()) / 8.34538;
} else {
// .:TBD:. What do do about liquids
qWarning() <<
Expand Down
2 changes: 1 addition & 1 deletion src/model/RecipeAdditionFermentable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ double RecipeAdditionFermentable::equivSucrose_kg() const {
auto const & fermentable = this->fermentable();
double const ret =
amount.quantity * fermentable->fineGrindYield_pct().value_or(0.0) *
(1.0 - fermentable->moisture_pct() / 100.0) / 100.0;
(1.0 - fermentable->moisture_pct().value_or(0.0) / 100.0) / 100.0;

// If this is a steeped grain...
if (fermentable->type() == Fermentable::Type::Grain && this->stage() != RecipeAddition::Stage::Mash) {
Expand Down

0 comments on commit b97982f

Please sign in to comment.