Add option to calculate the best mix portion of O2 and He for the dive's max depth if the user enters * in the MOD and MND cylinder fields. Gas portions are automatically recalculated if the max depth of the dive changes.
Signed-off-by: Rick Walsh <rickmwa...@gmail.com> --- core/dive.h | 2 ++ qt-models/cylindermodel.cpp | 72 +++++++++++++++++++++++++++++++++++++----- qt-models/cylindermodel.h | 1 + qt-models/diveplannermodel.cpp | 19 ++++++++++- qt-models/diveplannermodel.h | 1 + 5 files changed, 86 insertions(+), 9 deletions(-) diff --git a/core/dive.h b/core/dive.h index 6910eb2..caafce2 100644 --- a/core/dive.h +++ b/core/dive.h @@ -78,6 +78,8 @@ typedef struct volume_t gas_used; volume_t deco_gas_used; enum cylinderuse cylinder_use; + bool bestmix_o2; + bool bestmix_he; } cylinder_t; typedef struct diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 34bf36c..a7ab3e1 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -135,12 +135,19 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const ret = get_depth_string(cyl->depth, true); break; case MOD: - pressure_t modpO2; - modpO2.mbar = prefs.bottompo2; - ret = get_depth_string(gas_mod(&cyl->gasmix, modpO2, &displayed_dive, M_OR_FT(1,1))); + if (cyl->bestmix_o2) { + ret = QString("*"); + } else { + pressure_t modpO2; + modpO2.mbar = prefs.bottompo2; + ret = get_depth_string(gas_mod(&cyl->gasmix, modpO2, &displayed_dive, M_OR_FT(1,1))); + } break; case MND: - ret = get_depth_string(gas_mnd(&cyl->gasmix, prefs.bestmixend, &displayed_dive, M_OR_FT(1,1))); + if (cyl->bestmix_he) + ret = QString("*"); + else + ret = get_depth_string(gas_mnd(&cyl->gasmix, prefs.bestmixend, &displayed_dive, M_OR_FT(1,1))); break; case USE: ret = gettextFromC::instance()->trGettext(cylinderuse_text[cyl->cylinder_use]); @@ -287,15 +294,32 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in break; case MOD: if (CHANGED()) { - // Calculate fO2 for input depth - cyl->gasmix.o2 = best_o2(string_to_depth(vString.toUtf8().data()), &displayed_dive); + if (QString::compare(vString.toUtf8().data(), "*") == 0) { + cyl->bestmix_o2 = true; + // Calculate fO2 for max depth + cyl->gasmix.o2 = best_o2(displayed_dive.maxdepth, &displayed_dive); + } else { + cyl->bestmix_o2 = false; + // Calculate fO2 for input depth + cyl->gasmix.o2 = best_o2(string_to_depth(vString.toUtf8().data()), &displayed_dive); + } + pressure_t modpO2; + modpO2.mbar = prefs.decopo2; + cyl->depth = gas_mod(&cyl->gasmix, modpO2, &displayed_dive, M_OR_FT(3, 10)); changed = true; } break; case MND: if (CHANGED()) { - // Calculate fHe for input depth - cyl->gasmix.he = best_He(string_to_depth(vString.toUtf8().data()), &displayed_dive); + if (QString::compare(vString.toUtf8().data(), "*") == 0) { + cyl->bestmix_he = true; + // Calculate fO2 for max depth + cyl->gasmix.he = best_He(displayed_dive.maxdepth, &displayed_dive); + } else { + cyl->bestmix_he = false; + // Calculate fHe for input depth + cyl->gasmix.he = best_He(string_to_depth(vString.toUtf8().data()), &displayed_dive); + } changed = true; } break; @@ -441,3 +465,35 @@ void CylindersModel::remove(const QModelIndex &index) dc = dc->next; } } + +bool CylindersModel::updateBestMixes() +{ + // Check if any of the cylinders are best mixes, update if needed + bool gasUpdated = false; + DivePlannerPointsModel::instance()->rememberTanks(); + for (int i = 0; i < MAX_CYLINDERS; i++) { + cylinder_t *cyl = &displayed_dive.cylinder[i]; + if (cyl->bestmix_o2) { + cyl->gasmix.o2 = best_o2(displayed_dive.maxdepth, &displayed_dive); + // fO2 + fHe must not be greater than 1 + if (((cyl->gasmix.o2.permille == 0) ? O2_IN_AIR : cyl->gasmix.o2.permille) + cyl->gasmix.he.permille > 1000) + cyl->gasmix.he.permille = 1000 - ((cyl->gasmix.o2.permille == 0) ? O2_IN_AIR : cyl->gasmix.o2.permille); + pressure_t modpO2; + modpO2.mbar = prefs.decopo2; + cyl->depth = gas_mod(&cyl->gasmix, modpO2, &displayed_dive, M_OR_FT(3, 10)); + gasUpdated = true; + } + if (cyl->bestmix_he) { + cyl->gasmix.he = best_He(displayed_dive.maxdepth, &displayed_dive); + // fO2 + fHe must not be greater than 1 + if (((cyl->gasmix.o2.permille == 0) ? O2_IN_AIR : cyl->gasmix.o2.permille) + cyl->gasmix.he.permille > 1000) + cyl->gasmix.o2.permille = 1000 - cyl->gasmix.he.permille; + gasUpdated = true; + } + } + if (gasUpdated) { + DivePlannerPointsModel::instance()->tanksUpdated(); + emit dataChanged(createIndex(0, 0), createIndex(MAX_CYLINDERS - 1, COLUMNS - 1)); + } + return gasUpdated; +} diff --git a/qt-models/cylindermodel.h b/qt-models/cylindermodel.h index b7c1393..d0ca714 100644 --- a/qt-models/cylindermodel.h +++ b/qt-models/cylindermodel.h @@ -37,6 +37,7 @@ public: void clear(); void updateDive(); void copyFromDive(struct dive *d); + bool updateBestMixes(); cylinder_t *cylinderAt(const QModelIndex &index); bool changed; diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 16a2e40..eb5681b 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -44,6 +44,7 @@ void DivePlannerPointsModel::createSimpleDive() addStop(M_OR_FT(5, 15), 42 * 60, &gas, 0, true); addStop(M_OR_FT(5, 15), 45 * 60, &gas, 0, true); } + updateMaxDepth(); } void DivePlannerPointsModel::setupStartTime() @@ -139,6 +140,19 @@ void DivePlannerPointsModel::setupCylinders() CylindersModel::instance()->copyFromDive(&displayed_dive); } +// Update the dive's maximum depth. Returns true if max depth changed +bool DivePlannerPointsModel::updateMaxDepth() +{ + int prevMaxDepth = displayed_dive.maxdepth.mm; + displayed_dive.maxdepth.mm = 0; + for (int i = 0; i < rowCount(); i++) { + divedatapoint p = at(i); + if (p.depth > displayed_dive.maxdepth.mm) + displayed_dive.maxdepth.mm = p.depth; + } + return (displayed_dive.maxdepth.mm != prevMaxDepth); +} + QStringList &DivePlannerPointsModel::getGasList() { static QStringList list; @@ -260,8 +274,11 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v divedatapoint &p = divepoints[index.row()]; switch (index.column()) { case DEPTH: - if (value.toInt() >= 0) + if (value.toInt() >= 0) { p.depth = units_to_depth(value.toInt()); + if (updateMaxDepth()) + CylindersModel::instance()->updateBestMixes(); + } break; case RUNTIME: p.time = value.toInt() * 60; diff --git a/qt-models/diveplannermodel.h b/qt-models/diveplannermodel.h index 0770aa0..034f4bc 100644 --- a/qt-models/diveplannermodel.h +++ b/qt-models/diveplannermodel.h @@ -44,6 +44,7 @@ public: void rememberTanks(); bool tankInUse(struct gasmix gasmix); void setupCylinders(); + bool updateMaxDepth(); /** * @return the row number. */ -- 2.7.4 _______________________________________________ subsurface mailing list subsurface@subsurface-divelog.org http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface