Added bottles priming calculations.

Thu, 19 May 2022 20:50:36 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 19 May 2022 20:50:36 +0200
changeset 221
54828816233f
parent 220
7792a410a277
child 222
c5a3beb15eef

Added bottles priming calculations.

src/EditProduct.cpp file | annotate | diff | comparison | revisions
src/EditProduct.h file | annotate | diff | comparison | revisions
src/EditProductTab11.cpp file | annotate | diff | comparison | revisions
ui/EditProfileWater.ui file | annotate | diff | comparison | revisions
ui/EditWater.ui file | annotate | diff | comparison | revisions
--- a/src/EditProduct.cpp	Wed May 18 22:21:16 2022 +0200
+++ b/src/EditProduct.cpp	Thu May 19 20:50:36 2022 +0200
@@ -1150,6 +1150,11 @@
     connect(ui->pack_addabvEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::pack_infusion_abv_changed);
     connect(ui->pack_notesEdit, &QLineEdit::textChanged, this, &EditProduct::pack_infusion_txt_changed);
     connect(ui->pack_abvShow, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::pack_abv_changed);
+    connect(ui->bottle_volumeEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::bottle_volume_changed);
+    connect(ui->bottle_carbEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::bottle_co2_changed);
+    connect(ui->bottle_sugarEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &EditProduct::bottle_sugar_changed);
+    connect(ui->bottle_sug_waterEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::bottle_water_changed);
+    connect(ui->bottle_tempEdit, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &EditProduct::bottle_temp_changed);
 
     /* All signals from tab Tasting */
 
@@ -1606,7 +1611,7 @@
 		obj.insert("f_name", product->fermentables.at(i).f_name);
 		obj.insert("f_origin", product->fermentables.at(i).f_origin);
 		obj.insert("f_supplier", product->fermentables.at(i).f_supplier);
-		obj.insert("f_amount", round(product->fermentables.at(i).f_amount * 10000) / 10000);
+		obj.insert("f_amount", round(product->fermentables.at(i).f_amount * 100000) / 100000);
 		obj.insert("f_cost", round(product->fermentables.at(i).f_cost * 1000) / 1000);
 		obj.insert("f_type", product->fermentables.at(i).f_type);
 		obj.insert("f_yield", round(product->fermentables.at(i).f_yield * 10) / 10);
--- a/src/EditProduct.h	Wed May 18 22:21:16 2022 +0200
+++ b/src/EditProduct.h	Thu May 19 20:50:36 2022 +0200
@@ -291,6 +291,10 @@
     void calcEfficiencyAfterBoil();
     void brew_volume_calc(double volume, double kettle_volume, double kettle_height, double est_volume, bool aboil);
     double get_fg(double gravity);
+    double ResCO2(double T);
+    double CarbCO2toS(double CO2, double T, double SFactor);
+    double GetPressure(double CO2, double T1, double T2);
+    double CarbCO2ToPressure(double CO2, double T);
     void calcPack();
 };
 
--- a/src/EditProductTab11.cpp	Wed May 18 22:21:16 2022 +0200
+++ b/src/EditProductTab11.cpp	Thu May 19 20:50:36 2022 +0200
@@ -17,10 +17,67 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+double EditProduct::ResCO2(double T)
+{
+    double F = T * 1.8 + 32;
+    return round((3.0378 - 0.050062 * F + 0.00026555 * F * F) * 1000000.0) / 1000000.0;
+}
+
+
+double EditProduct::CarbCO2toS(double CO2, double T, double SFactor)
+{
+    //var sugar = SFactor * (CO2 - ResCO2(CO2, T)) / 0.286;
+    double sugar = round((SFactor * (CO2 - ResCO2(T)) * 4.014094) * 1000000.0) / 1000000.0;
+    if (sugar < 0)
+	sugar = 0;
+    return sugar; 	//Round(sugar, 3);
+}
+
+
+double EditProduct::GetPressure(double CO2, double T1, double T2)
+{
+    double V = CO2 - ResCO2(T1);
+    V = CO2; // TODO: temp only total pressure, testing
+    if (V < 0)
+	return 0;
+
+    double P = -1.09145427669121 + 0.00800006989646477 * T2 + 0.000260276315484684 * T2 * T2 + 0.0215142075945119 * T2 * V +
+		0.674996600795854 * V + -0.00471757220150754 * V * V;
+    if (P < 0)
+	P = 0;
+    P = round((P * 1.01325) * 100.0) / 100.0;	// atm to bar
+    qDebug() << "  GetPressure(" << CO2 << "," << T1 << "," << T2 << ") V:" << V << "Bar:" << P << "ignored ResCO2:" << ResCO2(T1);
+    return P;
+}
+
+
+double EditProduct::CarbCO2ToPressure(double CO2, double T)
+{
+    return (CO2 - (-0.000005594056 * pow(T, 4) + 0.000144357886 * pow(T, 3) +
+		0.000362999168 * T * T - 0.064872987645 * T + 1.641145175049)) /
+		(0.00000498031 * pow(T, 4) - 0.00024358267 * pow(T, 3) + 0.00385867329 * T * T - 0.05671206825 * T + 1.53801423376);
+}
+
 
 void EditProduct::calcPack()
 {
-//    qDebug() << "calcPack()" << product->package_volume << product->package_abv << "inf" << product->package_infuse_amount << product->package_infuse_abv;
+    int		i, j;
+    bool	found1, found2;
+    QSqlQuery	query;
+    double	TSec, SFactor;
+
+    qDebug() << "calcPack()" << product->package_volume << product->package_abv << "inf" << product->package_infuse_amount << product->package_infuse_abv;
+
+    if (product->package_volume < 1) {
+	/*
+	 * If there is not enough to package, then don't
+	 * do any calculations and clear the rest of the form.
+	 */
+	product->package_volume = 0;
+	ui->pack_finalabvShow->setValue(0);
+
+	return;
+    }
 
     double bvol = product->package_volume - (product->package_abv * product->package_volume) / 100.0;
     double balc = product->package_volume - bvol;
@@ -31,6 +88,90 @@
 
     product->final_abv = round(talc / (tvol + talc) * 10000.0) / 100.0;
     ui->pack_finalabvShow->setValue(product->final_abv);
+
+    TSec = product->secondary_temp;
+    if (TSec < 1)
+	TSec = product->primary_end_temp;
+    if (TSec < 1)
+	TSec = 18;
+
+    /*
+     * For bottles and kegs use the following complicated procedure to
+     * find the needed priming sugars.
+     *
+     * 1. If we need a priming sugar then first see in the fermentables
+     *    table if there is one selected. If not, clear sugars and done.
+     * 2. Then, we update the data from the fermentables inventory.
+     * 3. Set the found sugar in the pulldown menu.
+     * 4. Calculate the sugar in gr/L and total amount need.
+     * 5. Calculate the ABV in the bottles/kegs.
+     * 6. Calculate the pressure build by the refermentation.
+     *
+     * Note that this is all a leftover from the web based application that
+     * did work like this. It's a bit strange but it will allways give
+     * the right data and sugar concentrations.
+     * Sometimes bugs have good things.
+     */
+    found1 = false;
+    if (product->bottle_amount) {
+	for (i = 0; i < product->fermentables.size(); i++) {
+	    if (product->fermentables.at(i).f_added == FERMENTABLE_ADDED_BOTTLE) {
+		found1 = true;
+		break;
+	    }
+	}
+       	if (found1) {
+	    SFactor = 1 / ((product->fermentables.at(i).f_yield / 100) * (1 - product->fermentables.at(i).f_moisture / 100));
+	    qDebug() << "  bottle sugar" << product->fermentables.at(i).f_name << SFactor << TSec;
+
+	    query.prepare("SELECT name,supplier FROM inventory_fermentables WHERE type = '1' OR type = '3' ORDER BY name");      // Sugars or dry extract
+	    query.exec();
+	    j = 0;
+	    found2 = false;
+	    while (query.next()) {
+		j++;
+		if (query.value(0).toString() == product->fermentables.at(i).f_name && query.value(1).toString() == product->fermentables.at(i).f_supplier) {
+		    ui->bottle_sugarEdit->setCurrentIndex(j);
+		    product->bottle_priming_sugar = j;
+		    found2 = true;
+		    break;
+		}
+	    }
+	    if (! found2) {
+		ui->bottle_sugarEdit->setCurrentIndex(0);	// Make sure not selected
+		product->fermentables.removeAt(i);		// Remove false fermentable
+		refreshFermentables();
+	    } else {
+		product->bottle_priming_amount = CarbCO2toS(product->bottle_carbonation, TSec, SFactor);
+		ui->bottle_sug_amountShow->setValue(product->bottle_priming_amount);
+		double total = round(product->bottle_priming_amount * product->bottle_amount * 100.0) / 100000.0;
+		qDebug() << "  total" << total << product->fermentables.at(i).f_amount;
+		if (total != product->fermentables.at(i).f_amount) {
+		    qDebug() << "  update priming sugar" << total;
+		    product->fermentables[i].f_amount = total;
+		    refreshFermentables();
+		    ui->bottle_sug_weightShow->setValue(total * 1000);
+		    is_changed();
+		}
+
+		double pabv = product->final_abv + product->bottle_priming_amount * 0.47 / 7.907;
+		double pvol = product->bottle_amount - (pabv * product->bottle_amount) / 100;
+		talc = product->bottle_amount - pvol;
+  		tvol = pvol + product->bottle_priming_water;
+		ui->bottle_abvShow->setValue(talc / (tvol + talc) * 100);
+		ui->bottle_barShow->setValue(GetPressure(product->bottle_carbonation, TSec, product->bottle_carbonation_temp));
+	    }
+	}
+    }
+    if (! found1) {
+	qDebug() << "  no bottle priming";
+	ui->bottle_sug_amountShow->setValue(0);
+	ui->bottle_sug_weightShow->setValue(0);
+	ui->bottle_abvShow->setValue(0);
+	ui->bottle_barShow->setValue(0);
+    }
+
+    // keg_amount keg_carbonation keg_priming_sugar keg_priming_amount keg_priming_water keg_carbonation_temp keg_forced_carb keg_pressure
 }
 
 
@@ -105,11 +246,17 @@
 
 void EditProduct::bottle_volume_changed(double val)
 {
+    product->bottle_amount = val;
+    calcPack();
+    is_changed();
 }
 
 
 void EditProduct::bottle_co2_changed(double val)
 {
+    product->bottle_carbonation = val;
+    calcPack();
+    is_changed();
 }
 
 
@@ -120,11 +267,17 @@
 
 void EditProduct::bottle_water_changed(double val)
 {
+    product->bottle_priming_water = val;
+    calcPack();
+    is_changed();
 }
 
 
 void EditProduct::bottle_temp_changed(double val)
 {
+    product->bottle_carbonation_temp = val;
+    calcPack();
+    is_changed();
 }
 
 
--- a/ui/EditProfileWater.ui	Wed May 18 22:21:16 2022 +0200
+++ b/ui/EditProfileWater.ui	Thu May 19 20:50:36 2022 +0200
@@ -430,7 +430,7 @@
        <rect>
         <x>730</x>
         <y>290</y>
-        <width>121</width>
+        <width>111</width>
         <height>24</height>
        </rect>
       </property>
@@ -440,6 +440,9 @@
       <property name="readOnly">
        <bool>true</bool>
       </property>
+      <property name="buttonSymbols">
+       <enum>QAbstractSpinBox::NoButtons</enum>
+      </property>
       <property name="accelerated">
        <bool>false</bool>
       </property>
--- a/ui/EditWater.ui	Wed May 18 22:21:16 2022 +0200
+++ b/ui/EditWater.ui	Thu May 19 20:50:36 2022 +0200
@@ -553,7 +553,7 @@
        <rect>
         <x>730</x>
         <y>290</y>
-        <width>121</width>
+        <width>111</width>
         <height>24</height>
        </rect>
       </property>
@@ -563,6 +563,9 @@
       <property name="readOnly">
        <bool>true</bool>
       </property>
+      <property name="buttonSymbols">
+       <enum>QAbstractSpinBox::NoButtons</enum>
+      </property>
       <property name="accelerated">
        <bool>false</bool>
       </property>

mercurial