# HG changeset patch # User Michiel Broek # Date 1650107147 -7200 # Node ID 17030224d919cad8b93f3e24683652f44fa07fa4 # Parent e68b27ad8a406930161313ba0eafead37a37e00e Remove some water search debug messages. Added signals and slots for mash water pH and volume changes. Added manual pH adjust. diff -r e68b27ad8a40 -r 17030224d919 src/EditRecipe.cpp --- a/src/EditRecipe.cpp Fri Apr 15 20:20:22 2022 +0200 +++ b/src/EditRecipe.cpp Sat Apr 16 13:05:47 2022 +0200 @@ -517,7 +517,6 @@ query.bindValue(":water", recipe->w1_name); query.exec(); found = query.first(); - qDebug() << "found name" << recipe->w1_name << found; } if (!found) { /* @@ -527,10 +526,8 @@ query.bindValue(":record", my_default_water); query.exec(); found = query.first(); - qDebug() << "found record" << my_default_water << found; } if (found) { - qDebug() << "found record" << query.value(0).toInt(); recipe->w1_calcium = query.value(3).toDouble(); recipe->w1_magnesium = query.value(8).toDouble(); recipe->w1_total_alkalinity = query.value(11).toDouble(); @@ -567,7 +564,6 @@ query.bindValue(":water", recipe->w2_name); query.exec(); if (query.first()) { - qDebug() << "found record" << query.value(0).toInt(); recipe->w2_calcium = query.value(3).toDouble(); recipe->w2_magnesium = query.value(8).toDouble(); recipe->w2_total_alkalinity = query.value(11).toDouble(); @@ -653,6 +649,10 @@ connect(ui->bs_nahco3Edit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::on_nahco3_changed); connect(ui->bs_caco3Edit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::on_caco3_changed); connect(ui->mw_autoEdit, &QCheckBox::stateChanged, this, &EditRecipe::on_calc_acid_clicked); + connect(ui->mw_phEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::on_mw_ph_changed); + connect(ui->mw_acidvolEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::on_mw_acid_changed); + connect(ui->mw_acidPick, QOverload::of(&QComboBox::currentIndexChanged), this, &EditRecipe::on_mw_type_changed); + connect(ui->w2_volEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::on_w2_vol_changed); ui->saveButton->setEnabled(false); ui->deleteButton->setEnabled((id >= 0) ? true:false); diff -r e68b27ad8a40 -r 17030224d919 src/EditRecipe.h --- a/src/EditRecipe.h Fri Apr 15 20:20:22 2022 +0200 +++ b/src/EditRecipe.h Sat Apr 16 13:05:47 2022 +0200 @@ -304,7 +304,11 @@ void on_nahco3_changed(double val); void on_caco3_changed(double val); void on_calc_acid_clicked(); + void on_mw_ph_changed(double val); + void on_mw_acid_changed(double val); + void on_mw_type_changed(int val); + /* Modified progress bars */ void on_perc_mash_valueChanged(int value); void on_perc_sugars_valueChanged(int value); void on_perc_cara_valueChanged(int value); @@ -350,6 +354,7 @@ static bool hop_sort_test(const Hops &D1, const Hops &D2); static bool misc_sort_test(const Miscs &D1, const Miscs &D2); void WindowTitle(); + void brewing_salt_sub(QString salt, double val); void set_brewing_salt(QString salt, double val); void calcFermentables(); void calcIBUs(); diff -r e68b27ad8a40 -r 17030224d919 src/EditRecipeTab4.cpp --- a/src/EditRecipeTab4.cpp Fri Apr 15 20:20:22 2022 +0200 +++ b/src/EditRecipeTab4.cpp Sat Apr 16 13:05:47 2022 +0200 @@ -171,14 +171,84 @@ } +/* + * Manipulate the memory array and update the miscs table. + */ +void EditRecipe::brewing_salt_sub(QString salt, double val) +{ + QTableWidgetItem *item; + + if (val == 0) { + /* + * Remove this salt if it is in the table. + */ + for (int i = 0; i < recipe->miscs.size(); i++) { + if (salt.contains(recipe->miscs.at(i).m_name)) { + qDebug() << " brewing_salt_sub delete" << salt; + recipe->miscs.removeAt(i); + refreshMiscs(); + return; + } + } + qDebug() << " brewing_salt_sub delete error"; + return; + } + + /* + * First see if this salt is in the table. + * If it is, update the amount. + */ + for (int i = 0; i < recipe->miscs.size(); i++) { + if (salt.contains(recipe->miscs.at(i).m_name)) { + recipe->miscs[i].m_amount = val / 1000.0; + if (recipe->miscs.at(i).m_amount_is_weight) + item = new QTableWidgetItem(QString("%1 gr").arg(val, 3, 'f', 2, '0')); + else + item = new QTableWidgetItem(QString("%1 ml").arg(val, 3, 'f', 2, '0')); + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + ui->miscsTable->setItem(i, 4, item); + return; + } + } + + /* + * We need a new entry. Search in the database is tricky because + * we are here with possible more names for the same salt. The + * name can be like 'Lactic Melkzuur'. So we select only the + * brewing salts and manually check their names. + */ + QSqlQuery query("SELECT * FROM inventory_miscs WHERE type = 4"); + while (query.next()) { + if (salt.contains(query.value(1).toString())) { + qDebug() << " found it, append"; + Miscs m; + m.m_name = query.value(1).toString(); + m.m_amount = val / 1000.0; + m.m_type = query.value(2).toInt(); + m.m_use_use = query.value(3).toInt(); + m.m_time = query.value(4).toDouble(); + m.m_amount_is_weight = query.value(5).toInt() ? true:false; + m.m_cost = query.value(10).toDouble(); + recipe->miscs.append(m); + refreshMiscs(); + return; + } + } + + qDebug() << "brewing_salt_sub, nothing done." << salt << val; +} + + +/* + * Edit brewing salt and recalculate. + */ void EditRecipe::set_brewing_salt(QString salt, double val) { if (this->ignoreChanges) return; qDebug() << "set_brewing_salt" << salt << val; - - + brewing_salt_sub(salt, val); calcWater(); is_changed(); } diff -r e68b27ad8a40 -r 17030224d919 src/EditRecipeTab7.cpp --- a/src/EditRecipeTab7.cpp Fri Apr 15 20:20:22 2022 +0200 +++ b/src/EditRecipeTab7.cpp Sat Apr 16 13:05:47 2022 +0200 @@ -113,7 +113,7 @@ } else { error_count++; if (error_count < 5) - qDebug() << "ProtonDeficit" << pHZ << "invalid grist, return" << Result; + qDebug() << " ProtonDeficit" << pHZ << "invalid grist, return" << Result; } return Result; } @@ -136,7 +136,7 @@ pd = ProtonDeficit(pH); } pH = round(pH * 1000000) / 1000000.0; - qDebug() << "MashpH() n:" << n << "pH:" << pH; + qDebug() << " MashpH() n:" << n << "pH:" << pH; return pH; } @@ -153,12 +153,12 @@ double sulfate = 0; double ph = 0; double TpH = 0; - double frac; + double frac, RA; double protonDeficit = 0; double Acid = 0, Acidmg = 0; int AT; - qDebug() << "calcWater"; + qDebug() << "calcWater()"; /* * If there is a dilute water source, mix the waters. @@ -212,7 +212,7 @@ double wg_bicarbonate = bicarbonate; double mash_ph = MashpH(); - qDebug() << "Distilled water mash pH:" << mash_ph; + qDebug() << " Distilled water mash pH:" << mash_ph; /* Calculate Salt additions */ if (liters > 0) { @@ -246,43 +246,77 @@ */ TpH = recipe->mash_ph; protonDeficit = ProtonDeficit(TpH); - qDebug() << "calc_acid tgt:" << TpH << "protonDeficit:" << protonDeficit; + qDebug() << " calc_acid tgt:" << TpH << "protonDeficit:" << protonDeficit; if (protonDeficit > 0) { - qDebug() << "pkn:" << AT << my_acids[AT].pK1 << my_acids[AT].pK2 << my_acids[AT].pK3; frac = Utils::CalcFrac(TpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); Acid = protonDeficit / frac; - qDebug() << "1" << frac << Acid << protonDeficit; Acid *= my_acids[AT].MolWt; // mg. 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 ml:" << Acid; + qDebug() << " Mash auto Acid final ml:" << Acid; - for (int i = 0; i < recipe->miscs.size(); i++) { - qDebug() << i << recipe->miscs.at(i).m_name << my_acids[AT].name_en; - if (recipe->miscs.at(i).m_name == my_acids[AT].name_en || recipe->miscs.at(i).m_name == my_acids[AT].name_nl) { - qDebug() << "found at" << i << recipe->miscs.at(i).m_amount << Acid / 1000.0; - recipe->miscs[i].m_amount = Acid / 1000.0; - QTableWidgetItem *item = new QTableWidgetItem(QString("%1 ml").arg(Acid, 3, 'f', 2, '0')); - item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); - ui->miscsTable->setItem(i, 4, item); - this->ignoreChanges = true; - ui->mw_acidvolEdit->setValue(Acid); - this->ignoreChanges = false; - break; - } - } + QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl; + brewing_salt_sub(w, Acid); + this->ignoreChanges = true; + ui->mw_acidvolEdit->setValue(Acid); + this->ignoreChanges = false; + bicarbonate = bicarbonate - protonDeficit * frac / liters; total_alkalinity = bicarbonate * 50 / 61; } ph = TpH; ui->wb_phEdit->setValue(ph); - - //recipe->est_mash_ph = ph + recipe->mash_ph = ph; } else { // Manual /* * Manual adjust acid, calculate resulting pH. */ + double pHa = ph; // Mixed water pH. + // 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 *= ui->mw_acidvolEdit->value(); + Acid /= my_acids[AT].MolWt; // mg; + Acidmg = Acid; + + //find the pH where the protondeficit = protondeficit by the acid + frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); + protonDeficit = Acid * frac; + //qDebug() << " protonDeficit Acid:" << protonDeficit << "frac:" << frac << "pH:" << pHa; + + double deltapH = 0.001; + double deltapd = 0.1; + double pd = round(ProtonDeficit(pHa) * 1000000.0) / 1000000.0; + int n = 0; + while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) { + n++; + if (pd < (protonDeficit - deltapd)) + pHa -= deltapH; + else if (pd > (protonDeficit + deltapd)) + pHa += deltapH; + frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); + protonDeficit = Acid * frac; + pd = ProtonDeficit(pHa); + } + //qDebug() << " n:" << n << "pd:" << pd << "protonDeficit:" << protonDeficit << "frac:" << frac << "pHa:" << pHa; + + bicarbonate = wg_bicarbonate - protonDeficit * frac / liters; + total_alkalinity = bicarbonate * 50 / 61; + ph = pHa; + ui->wb_phEdit->setValue(ph); + ui->mw_phEdit->setValue(ph); + recipe->mash_ph = ph; + } + + if ((AT == 3) && (liters > 0)) { // Sulfuctic / Zwavelzuur + RA = ui->bs_caso4Edit->value() * MMSO4 / MMCaSO4 + ui->bs_mgso4Edit->value() * MMSO4 / MMMgSO4 + Acidmg / 1000 * MMSO4 / (MMSO4 + 2); + RA = 1000 * RA / liters; + sulfate = wg_sulfate + RA; // Not add to sulfate?? + } else if ((AT == 1) && (liters > 0)) { // Hydrochloric, Zoutzuur + RA = ui->bs_cacl2Edit->value() * MMCl / MMCaCl2 + ui->bs_naclEdit->value() * MMCl / MMNaCl + Acidmg / 1000 * MMCl / (MMCl + 1); + RA = 1000 * RA / liters; + chloride = wg_chloride + RA; } ui->wb_caEdit->setValue(calcium); @@ -330,51 +364,66 @@ } -void EditRecipe::on_w2_vol_changed(double val) +void EditRecipe::on_mw_ph_changed(double val) { + if (! recipe->calc_acid) + return; + + qDebug() << "on_mw_ph_changed" << val; + recipe->mash_ph = val; + is_changed(); + calcWater(); } -void EditRecipe::on_cacl2_changed(double val) -{ - set_brewing_salt("CaCl2", val); -} - - -void EditRecipe::on_caso4_changed(double val) +void EditRecipe::on_mw_acid_changed(double val) { - set_brewing_salt("CaSO4", val); -} - + if (recipe->calc_acid) + return; -void EditRecipe::on_mgso4_changed(double val) -{ - set_brewing_salt("MgSO4", val); + 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); } -void EditRecipe::on_nacl_changed(double val) +void EditRecipe::on_mw_type_changed(int val) { - set_brewing_salt("NaCl", val); -} + if (val == recipe->wa_acid_name) + return; + qDebug() << "on_mw_type_changed" << val << "old" << recipe->wa_acid_name; + /* + * 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); -void EditRecipe::on_mgcl2_changed(double val) -{ - set_brewing_salt("MgCl2", val); + 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_acidPick->setCurrentIndex(val); + ui->mw_acidpercEdit->setValue(my_acids.at(val).AcidPrc); + brewing_salt_sub(w, ui->mw_acidvolEdit->value()); // For now, set old amount. + + is_changed(); + calcWater(); } -void EditRecipe::on_nahco3_changed(double val) +void EditRecipe::on_w2_vol_changed(double val) { - set_brewing_salt("NaHCO3", val); + qDebug() << "on_w2_vol_changed" << val; } -void EditRecipe::on_caco3_changed(double val) -{ - set_brewing_salt("CaCO3", val); -} +void EditRecipe::on_cacl2_changed(double val) { set_brewing_salt("CaCl2", val); } +void EditRecipe::on_caso4_changed(double val) { set_brewing_salt("CaSO4", val); } +void EditRecipe::on_mgso4_changed(double val) { set_brewing_salt("MgSO4", val); } +void EditRecipe::on_nacl_changed(double val) { set_brewing_salt("NaCl", val); } +void EditRecipe::on_mgcl2_changed(double val) { set_brewing_salt("MgCl2", val); } +void EditRecipe::on_nahco3_changed(double val) { set_brewing_salt("NaHCO3", val); } +void EditRecipe::on_caco3_changed(double val) { set_brewing_salt("CaCO3", val); } - diff -r e68b27ad8a40 -r 17030224d919 ui/EditRecipe.ui --- a/ui/EditRecipe.ui Fri Apr 15 20:20:22 2022 +0200 +++ b/ui/EditRecipe.ui Sat Apr 16 13:05:47 2022 +0200 @@ -3712,7 +3712,7 @@ true - 1 + 2 14.000000000000000 @@ -3981,7 +3981,7 @@ true - 1 + 2 14.000000000000000