src/EditRecipeTab7.cpp

changeset 359
dfbb012c631c
parent 358
d89bc21e2f07
child 361
ec8de79f6ff6
--- a/src/EditRecipeTab7.cpp	Sun Jul 17 22:18:48 2022 +0200
+++ b/src/EditRecipeTab7.cpp	Mon Jul 18 17:04:02 2022 +0200
@@ -265,10 +265,17 @@
 	    Acidmg = Acid;
 	    Acid = Acid / my_acids[AT].AcidSG;
 	    Acid = round((Acid / (recipe->wa_acid_perc / 100.0)) * 100.0) / 100.0;
+	    qDebug() << "  Mash auto Acid final old ml:" << Acid;
+	    Acid = Acidmg;
+
+	    double RealSG = round(((my_acids[AT].AcidSG - 1000) * (recipe->wa_acid_perc / 100)) + 1000);
+	    Acid /= RealSG;
+	    Acid /= my_acids[AT].AcidPrc / 100;
+	    Acid = round(Acid * 100.0) / 100.0;
 	    qDebug() << "  Mash auto Acid final ml:" << Acid;
 
 	    QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl;
-	    brewing_salt_sub(w, Acid);
+	    brewing_salt_sub(w, Acid, MISC_USES_MASH);
 	    ui->mw_acidvolEdit->setValue(Acid);
 
 	    bicarbonate = bicarbonate - protonDeficit * frac / liters;
@@ -282,10 +289,12 @@
 	 * Manual adjust acid, calculate resulting pH.
 	 */
 	double pHa = ph;	// Mixed water pH.
+	double RealSG = round(((my_acids[AT].AcidSG - 1000) * (recipe->wa_acid_perc / 100)) + 1000);
 	// Then calculate the new pH with added acids and malts
 	qDebug() << "  Mash pH:" << pHa;
-	Acid = my_acids[AT].AcidSG * (recipe->wa_acid_perc / 100.0);	// ml
+	Acid = RealSG;
 	Acid *= ui->mw_acidvolEdit->value();
+	Acid *= my_acids[AT].AcidPrc / 100;
 	Acid /= my_acids[AT].MolWt;	// mg;
 	Acidmg = Acid;
 
@@ -420,80 +429,128 @@
 
     qDebug() << "calcSparge()";
 
-    const QSignalBlocker blocker1(ui->sp_sourceEdit);
+    const QSignalBlocker blocker2(ui->w1_spButton);
+    const QSignalBlocker blocker3(ui->w2_spButton);
+    const QSignalBlocker blocker4(ui->wg_spButton);
 
     // Select watersource or fallback to the first source.
     if (recipe->sparge_source == 1) { // Source 2
 	if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) {
 	    Source_pH = recipe->w2_ph;
 	    Source_alkalinity = recipe->w2_total_alkalinity;
+	    ui->sp_caEdit->setValue(recipe->w2_calcium);
+            ui->sp_mgEdit->setValue(recipe->w2_magnesium);
+            ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->w2_total_alkalinity, recipe->w2_ph));
+            ui->sp_caco3Edit->setValue(recipe->w2_total_alkalinity);
+            ui->sp_naEdit->setValue(recipe->w2_sodium);
+            ui->sp_clEdit->setValue(recipe->w2_chloride);
+            ui->sp_so4Edit->setValue(recipe->w2_sulfate);
+            ui->sp_phShow->setValue(recipe->w2_ph);
+            ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->w2_calcium, recipe->w2_magnesium));
+            ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->w2_total_alkalinity, recipe->w2_calcium, recipe->w2_magnesium));
+            ui->w2_spButton->setChecked(true);
 	} else {
-	    recipe->sparge_source = 0; // Source 1
-	    ui->sp_sourceEdit->setCurrentIndex(0);
+	    recipe->sparge_source = 0; // Fallback to source 1
+	    ui->w1_spButton->setChecked(true);
 	}
     } else if (recipe->sparge_source == 2) { // Mixed
 	if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) {
 	    Source_pH = recipe->wg_ph;
 	    Source_alkalinity = recipe->wg_total_alkalinity;
+	    ui->sp_caEdit->setValue(recipe->wg_calcium);
+	    ui->sp_mgEdit->setValue(recipe->wg_magnesium);
+	    ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->wg_total_alkalinity, recipe->wg_ph));
+	    ui->sp_caco3Edit->setValue(recipe->wg_total_alkalinity);
+	    ui->sp_naEdit->setValue(recipe->wg_sodium);
+	    ui->sp_clEdit->setValue(recipe->wg_chloride);
+	    ui->sp_so4Edit->setValue(recipe->wg_sulfate);
+	    ui->sp_phShow->setValue(recipe->wg_ph);
+	    ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->wg_calcium, recipe->wg_magnesium));
+	    ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->wg_total_alkalinity, recipe->wg_calcium, recipe->wg_magnesium));
+	    ui->wg_spButton->setChecked(true);
 	} else {
-	    recipe->sparge_source = 0; // Source 1
-            ui->sp_sourceEdit->setCurrentIndex(0);
+	    recipe->sparge_source = 0; // Fallback to source 1
+	    ui->w1_spButton->setChecked(true);
 	}
     }
+    if (recipe->sparge_source == 0) {
+       ui->sp_caEdit->setValue(recipe->w1_calcium);
+       ui->sp_mgEdit->setValue(recipe->w1_magnesium);
+       ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->w1_total_alkalinity, recipe->w1_ph));
+       ui->sp_caco3Edit->setValue(recipe->w1_total_alkalinity);
+       ui->sp_naEdit->setValue(recipe->w1_sodium);
+       ui->sp_clEdit->setValue(recipe->w1_chloride);
+       ui->sp_so4Edit->setValue(recipe->w1_sulfate);
+       ui->sp_phShow->setValue(recipe->w1_ph);
+       ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->w1_calcium, recipe->w1_magnesium));
+       ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->w1_total_alkalinity, recipe->w1_calcium, recipe->w1_magnesium));
+       ui->w1_spButton->setChecked(true);
+    }
+    // The spargewater is set.
+
+    int AT = recipe->sparge_acid_type;
+    if (AT < 0 || AT >= my_acids.size()) {
+        AT = 0;
+        recipe->sparge_acid_type = 0;
+        ui->sp_acidtypeEdit->setCurrentIndex(0);
+        recipe->sparge_acid_perc = my_acids[0].AcidPrc;
+        ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc);
+    }
 
-    // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH
-    double r1 = pow(10, Source_pH - 6.35);
-    double r2 = pow(10, Source_pH - 10.33);
-    double d = 1 + r1 + r1 * r2;
-    double f1 = 1 / d;
-    double f3 = r1 * r2 / d;
+    /*
+     * Auto calculate the required acid
+     */
+    if (recipe->calc_acid) {
+    	// Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH
+    	double r1 = pow(10, Source_pH - 6.35);
+    	double r2 = pow(10, Source_pH - 10.33);
+    	double d = 1 + r1 + r1 * r2;
+    	double f1 = 1 / d;
+    	double f3 = r1 * r2 / d;
 
-    // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
-    double r143 = pow(10, 4.3 - 6.35);
-    double r243 = pow(10, 4.3 - 10.33);
-    double d43 = 1 + r143 + r143 * r243;
-    double f143 = 1 / d43;
-    double f343 = r143 * r243 / d43;
+    	// Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
+    	double r143 = pow(10, 4.3 - 6.35);
+    	double r243 = pow(10, 4.3 - 10.33);
+    	double d43 = 1 + r143 + r143 * r243;
+    	double f143 = 1 / d43;
+    	double f343 = r143 * r243 / d43;
 
-    // Step 4. Solve
-    //double Ct = (Source_alkalinity - 1000 * (pow(10, -4.3) - pow(10, -Source_pH))) / ((f143 - f1) + (f3 - f343));
-    double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
-
-    // Step 5. Compute mole fractions at desired pH
-    double r1g = pow(10, TargetpH - 6.35);
-    double r2g = pow(10, TargetpH - 10.33);
-    double dg = 1 + r1g + r1g * r2g;
-    double f1g = 1 / dg;
-    double f3g = r1g * r2g / dg;
+    	// Step 4. Solve
+    	double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
 
-    // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
-    double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH);  //mEq/l
-    Acid += 0.01;   // Add acid that would be required for distilled water.
+    	// Step 5. Compute mole fractions at desired pH
+    	double r1g = pow(10, TargetpH - 6.35);
+    	double r2g = pow(10, TargetpH - 10.33);
+    	double dg = 1 + r1g + r1g * r2g;
+    	double f1g = 1 / dg;
+    	double f3g = r1g * r2g / dg;
+
+    	// Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
+    	double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH);  //mEq/l
+    	Acid += 0.01;   // Add acid that would be required for distilled water.
+
+    	// Step 8. Get the acid data.
+    	double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3);
 
-    //Step 8. Get the acid data.
-    int AT = recipe->sparge_acid_type;
-    if (AT < 0 || AT >= my_acids.size()) {
-	AT = 0;
-	recipe->sparge_acid_type = 0;
-	ui->sp_acidtypeEdit->setCurrentIndex(0);
-	recipe->sparge_acid_perc = my_acids[0].AcidPrc;
-	ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc);
+    	// Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid.
+    	Acid /= fract;
+
+    	// Step 10. Multiply by molecular weight of the acid
+    	Acid *= my_acids[AT].MolWt; //mg
+
+    	// Step 11. Divide by Specific Gravity and Percentage to get the final ml.
+	double RealSG = round(((my_acids[AT].AcidSG - 1000) * (recipe->sparge_acid_perc / 100)) + 1000);
+	Acid = Acid / RealSG;           //ml
+	Acid *= recipe->sparge_volume; //ml acid total at 100%
+	Acid /= my_acids[AT].AcidPrc / 100;     //ml acid at supplied strength
+	Acid = round(Acid * 100.0) / 100.0;
+	recipe->sparge_acid_amount = Acid / 1000;
+	QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl;
+	brewing_salt_sub(w, Acid, MISC_USES_SPARGE);	// Put it in the miscs table.
+    	ui->sp_acidvolEdit->setValue(Acid);
     }
-    double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3);
 
-    // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid.
-    Acid /= fract;
-
-    // Step 10. Multiply by molecular weight of the acid
-    Acid *= my_acids[AT].MolWt; //mg
-
-    // Step 11. Divide by Specific Gravity and Percentage to get the final ml.
-    Acid = Acid / my_acids[AT].AcidSG / (recipe->sparge_acid_perc / 100); //ml
-    Acid *= recipe->sparge_volume; //ml acid total
-    Acid = round(Acid * 100.0) / 100.0;
-    recipe->sparge_acid_amount = Acid / 1000;
-    ui->sp_acidvolEdit->setValue(Acid);
-
+    ui->sp_phShow->setValue(recipe->sparge_ph);
     // Finally calculate the estimate preboil pH
     recipe->preboil_ph = -log10(((pow(10, -recipe->mash_ph) * recipe->wg_amount) + (pow(10, -recipe->sparge_ph) * recipe->sparge_volume)) /
                              (recipe->wg_amount + recipe->sparge_volume));
@@ -501,19 +558,36 @@
 }
 
 
-void EditRecipe::sp_source_changed(int val)
+void EditRecipe::sp_group_changed(int val)
 {
-    recipe->sparge_source = val;
-    calcSparge();
-    is_changed();
+    if (val != recipe->sparge_source) {
+           qDebug() << "sp_group_changed" << val;
+       recipe->sparge_source = val;
+       calcSparge();
+       is_changed();
+    }
 }
 
 
 void EditRecipe::sp_type_changed(int val)
 {
+    if (val == recipe->sparge_acid_type)
+        return;
+
+    qDebug() << "sp_type_changed" << val << "old" << recipe->sparge_acid_type;
+    /*
+     * First remove current acid.
+     */
+    QString w = my_acids[recipe->sparge_acid_type].name_en + ' ' + my_acids[recipe->sparge_acid_type].name_nl;
+    brewing_salt_sub(w, 0, MISC_USES_SPARGE);
+
     recipe->sparge_acid_type = val;
+    w = my_acids[recipe->sparge_acid_type].name_en + ' ' + my_acids[recipe->sparge_acid_type].name_nl;
+
     recipe->sparge_acid_perc = my_acids[val].AcidPrc;
     ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc);
+    brewing_salt_sub(w, ui->sp_acidvolEdit->value(), MISC_USES_SPARGE);        // For now, set old amount.
+
     calcSparge();
     is_changed();
 }
@@ -527,6 +601,116 @@
 }
 
 
+void EditRecipe::sp_acid_changed(double val)
+{
+    if (recipe->calc_acid)
+        return;
+
+    qDebug() << "sp_acid_changed" << val << recipe->sparge_acid_amount * 1000.0;
+
+    double TargetpH = recipe->sparge_ph;
+    double Source_pH = recipe->w1_ph;
+    double Source_alkalinity = recipe->w1_total_alkalinity;
+
+    if (recipe->sparge_source == 1) { // Source 2
+       if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) {
+           Source_pH = recipe->w2_ph;
+            Source_alkalinity = recipe->w2_total_alkalinity;
+       }
+    } else if (recipe->sparge_source == 2) { // Mixed
+       if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) {
+           Source_pH = recipe->wg_ph;
+            Source_alkalinity = recipe->wg_total_alkalinity;
+       }
+    }
+
+    int AT = recipe->sparge_acid_type;
+    if (AT < 0 || AT >= my_acids.size()) {
+        AT = 0;
+        recipe->sparge_acid_type = 0;
+        ui->sp_acidtypeEdit->setCurrentIndex(0);
+        recipe->sparge_acid_perc = my_acids[0].AcidPrc;
+        ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc);
+    }
+
+    bool go_up = (val < (recipe->sparge_acid_amount * 1000.0));
+    bool loop = true;
+
+    while (loop) {
+
+       if (go_up)
+           TargetpH += 0.001;
+       else
+           TargetpH -= 0.001;
+       //qDebug() << "  TargetpH" << TargetpH << "up" << go_up;
+
+        // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH
+        double r1 = pow(10, Source_pH - 6.35);
+        double r2 = pow(10, Source_pH - 10.33);
+        double d = 1 + r1 + r1 * r2;
+        double f1 = 1 / d;
+        double f3 = r1 * r2 / d;
+
+        // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
+        double r143 = pow(10, 4.3 - 6.35);
+        double r243 = pow(10, 4.3 - 10.33);
+        double d43 = 1 + r143 + r143 * r243;
+        double f143 = 1 / d43;
+        double f343 = r143 * r243 / d43;
+
+        // Step 4. Solve
+        double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
+
+        // Step 5. Compute mole fractions at desired pH
+        double r1g = pow(10, TargetpH - 6.35);
+        double r2g = pow(10, TargetpH - 10.33);
+        double dg = 1 + r1g + r1g * r2g;
+        double f1g = 1 / dg;
+        double f3g = r1g * r2g / dg;
+
+        // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
+        double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH);  //mEq/l
+        Acid += 0.01;   // Add acid that would be required for distilled water.
+
+        // Step 7. There is no step 7.
+
+        // Step 8. Get the acid data.
+        double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3);
+
+        // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid.
+        Acid /= fract;
+
+        // Step 10. Multiply by molecular weight of the acid
+        Acid *= my_acids[AT].MolWt; //mg
+
+        // Step 11. Divide by Specific Gravity and Percentage to get the final ml.
+        double RealSG = round(((my_acids[AT].AcidSG - 1000) * (recipe->sparge_acid_perc / 100)) + 1000);
+        Acid = Acid / RealSG;           //ml
+        Acid *= recipe->sparge_volume; //ml acid total at 100%
+        Acid /= my_acids[AT].AcidPrc / 100;     //ml acid at supplied strength
+        Acid = round(Acid * 100.0) / 100.0;
+        recipe->sparge_acid_amount = Acid / 1000;
+       //qDebug() << "  acid" << recipe->sparge_acid_amount;
+
+       if (go_up && (val > (recipe->sparge_acid_amount * 1000.0)))
+           loop = false;
+       else if (! go_up && (val < (recipe->sparge_acid_amount * 1000.0)))
+           loop = false;
+
+       //qDebug() << "  test" << loop << go_up << val << recipe->sparge_acid_amount * 1000.0;
+    }
+
+    const QSignalBlocker blocker1(ui->sp_phEdit);
+    recipe->sparge_ph = round(TargetpH * 100) / 100;
+    ui->sp_phEdit->setValue(recipe->sparge_ph);
+    ui->sp_phShow->setValue(recipe->sparge_ph);
+
+    QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl;
+    set_brewing_salt(w, val, MISC_USES_SPARGE);
+    //qDebug() << "  new" << recipe->sparge_ph << val;
+}
+
+
 double EditRecipe::GetBUGU()
 {
     double gu = (recipe->est_og - 1) * 1000;
@@ -555,6 +739,10 @@
     ui->mw_phEdit->setButtonSymbols(recipe->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
     ui->mw_acidvolEdit->setReadOnly(recipe->calc_acid);
     ui->mw_acidvolEdit->setButtonSymbols(recipe->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
+    ui->sp_phEdit->setReadOnly(! recipe->calc_acid);
+    ui->sp_phEdit->setButtonSymbols(recipe->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
+    ui->sp_acidvolEdit->setReadOnly(recipe->calc_acid);
+    ui->sp_acidvolEdit->setButtonSymbols(recipe->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
     is_changed();
     calcWater();
 }
@@ -581,7 +769,7 @@
 
     qDebug() << "on_mw_acid_changed" << val;
     QString w = my_acids[recipe->wa_acid_name].name_en + ' ' + my_acids[recipe->wa_acid_name].name_nl;
-    set_brewing_salt(w, val);
+    set_brewing_salt(w, val, MISC_USES_MASH);
 }
 
 
@@ -595,14 +783,14 @@
      * First remove current acid.
      */
     QString w = my_acids[recipe->wa_acid_name].name_en + ' ' + my_acids[recipe->wa_acid_name].name_nl;
-    brewing_salt_sub(w, 0);
+    brewing_salt_sub(w, 0, MISC_USES_MASH);
 
     recipe->wa_acid_name = val;
     w = my_acids[recipe->wa_acid_name].name_en + ' ' + my_acids[recipe->wa_acid_name].name_nl;
 
     recipe->wa_acid_perc = my_acids.at(val).AcidPrc;
     ui->mw_acidpercEdit->setValue(my_acids.at(val).AcidPrc);
-    brewing_salt_sub(w, ui->mw_acidvolEdit->value());   // For now, set old amount.
+    brewing_salt_sub(w, ui->mw_acidvolEdit->value(), MISC_USES_MASH);   // For now, set old amount.
 
     is_changed();
     calcWater();
@@ -812,12 +1000,17 @@
 }
 
 
-void EditRecipe::wb_cacl2_changed(double val)  { set_brewing_salt("CaCl2", val);  }
-void EditRecipe::wb_caso4_changed(double val)  { set_brewing_salt("CaSO4", val);  }
-void EditRecipe::wb_mgso4_changed(double val)  { set_brewing_salt("MgSO4", val);  }
-void EditRecipe::wb_nacl_changed(double val)   { set_brewing_salt("NaCl", val);   }
-void EditRecipe::wb_mgcl2_changed(double val)  { set_brewing_salt("MgCl2", val);  }
-void EditRecipe::wb_nahco3_changed(double val) { set_brewing_salt("NaHCO3", val); }
-void EditRecipe::wb_caco3_changed(double val)  { set_brewing_salt("CaCO3", val);  }
+void EditRecipe::wb_cacl2_changed(double val)  { set_brewing_salt("CaCl2", val, MISC_USES_MASH);   }
+void EditRecipe::wb_caso4_changed(double val)  { set_brewing_salt("CaSO4", val, MISC_USES_MASH);   }
+void EditRecipe::wb_mgso4_changed(double val)  { set_brewing_salt("MgSO4", val, MISC_USES_MASH);   }
+void EditRecipe::wb_nacl_changed(double val)   { set_brewing_salt("NaCl", val, MISC_USES_MASH);    }
+void EditRecipe::wb_mgcl2_changed(double val)  { set_brewing_salt("MgCl2", val, MISC_USES_MASH);   }
+void EditRecipe::wb_nahco3_changed(double val) { set_brewing_salt("NaHCO3", val, MISC_USES_MASH);  }
+void EditRecipe::wb_caco3_changed(double val)  { set_brewing_salt("CaCO3", val, MISC_USES_MASH);   }
+void EditRecipe::sp_cacl2_changed(double val)  { set_brewing_salt("CaCl2", val, MISC_USES_SPARGE); }
+void EditRecipe::sp_caso4_changed(double val)  { set_brewing_salt("CaSO4", val, MISC_USES_SPARGE); }
+void EditRecipe::sp_mgso4_changed(double val)  { set_brewing_salt("MgSO4", val, MISC_USES_SPARGE); }
+void EditRecipe::sp_nacl_changed(double val)   { set_brewing_salt("NaCl", val, MISC_USES_SPARGE);  }
+void EditRecipe::sp_mgcl2_changed(double val)  { set_brewing_salt("MgCl2", val, MISC_USES_SPARGE); }
 
 

mercurial