mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Planner: Add option to treat O2 as narcotic
When computing the best mix for a target depth, for helium, one can either require that the partial pressure of N2 is the same as at the target depth or the partial pressure of N2 plus O2. Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
parent
43b16f0810
commit
9c8fbe494d
12 changed files with 121 additions and 86 deletions
|
@ -1,3 +1,4 @@
|
|||
Planner: Add checkbox on considering oxygen narcotic
|
||||
Desktop: register changes when clicking "done" on dive-site edit screen
|
||||
Mobile: re-enable GPS location service icon in global drawer
|
||||
Mobile: add support for editing the dive number of a dive
|
||||
|
|
|
@ -3545,7 +3545,8 @@ image::images/PlannerWindow1.jpg["FIGURE: Dive planner startup window",align="ce
|
|||
O~2~% according to the depth set. Set to ''*'' to calculate the best O~2~% for the dive maximum depth.
|
||||
** MND: the gas Maximum Narcotic Depth (MND). Automatically calculated based on the Best Mix END
|
||||
preference (default 30m / 98 ft). Editing this field will modify the He% according to the depth set.
|
||||
Set to ''*'' to calculate the best He% for the dive maximum depth.
|
||||
Set to ''*'' to calculate the best He% for the dive maximum depth. Depending on the checkbox, oxygen
|
||||
is considered narcotic (the END is used) or not (the EAD is used).
|
||||
|
||||
- The profile of the planned dive can be created in two ways:
|
||||
* Drag the waypoints
|
||||
|
|
|
@ -3761,13 +3761,17 @@ fraction_t best_o2(depth_t depth, const struct dive *dive)
|
|||
}
|
||||
|
||||
//Calculate He in best mix. O2 is considered narcopic
|
||||
fraction_t best_he(depth_t depth, const struct dive *dive)
|
||||
fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2)
|
||||
{
|
||||
fraction_t fhe;
|
||||
int pnarcotic, ambient;
|
||||
pnarcotic = depth_to_mbar(prefs.bestmixend.mm, dive);
|
||||
ambient = depth_to_mbar(depth.mm, dive);
|
||||
fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent
|
||||
if (o2narcotic) {
|
||||
fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent
|
||||
} else {
|
||||
fhe.permille = 1000 - fo2.permille - N2_IN_AIR * pnarcotic / ambient;
|
||||
}
|
||||
if (fhe.permille < 0)
|
||||
fhe.permille = 0;
|
||||
return fhe;
|
||||
|
|
|
@ -226,7 +226,7 @@ extern int explicit_first_cylinder(const struct dive *dive, const struct divecom
|
|||
extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time);
|
||||
|
||||
extern fraction_t best_o2(depth_t depth, const struct dive *dive);
|
||||
extern fraction_t best_he(depth_t depth, const struct dive *dive);
|
||||
extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2);
|
||||
|
||||
extern int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null);
|
||||
extern int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity);
|
||||
|
|
|
@ -160,6 +160,7 @@ struct preferences {
|
|||
bool display_variations;
|
||||
bool doo2breaks;
|
||||
bool dobailout;
|
||||
bool o2narcotic;
|
||||
bool drop_stone_mode;
|
||||
bool last_stop; // At 6m?
|
||||
int min_switch_duration; // seconds
|
||||
|
|
|
@ -35,6 +35,7 @@ void qPrefDivePlanner::loadSync(bool doSync)
|
|||
disk_display_variations(doSync);
|
||||
disk_doo2breaks(doSync);
|
||||
disk_dobailout(doSync);
|
||||
disk_o2narcotic(doSync);
|
||||
disk_drop_stone_mode(doSync);
|
||||
disk_last_stop(doSync);
|
||||
disk_min_switch_duration(doSync);
|
||||
|
@ -76,6 +77,7 @@ HANDLE_PREFERENCE_BOOL(DivePlanner, "display_variations", display_variations);
|
|||
|
||||
HANDLE_PREFERENCE_BOOL(DivePlanner, "doo2breaks", doo2breaks);
|
||||
HANDLE_PREFERENCE_BOOL(DivePlanner, "dobailbout", dobailout);
|
||||
HANDLE_PREFERENCE_BOOL(DivePlanner, "o2narcotic", o2narcotic);
|
||||
|
||||
HANDLE_PREFERENCE_BOOL(DivePlanner, "drop_stone_mode", drop_stone_mode);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ class qPrefDivePlanner : public QObject {
|
|||
Q_PROPERTY(bool display_variations READ display_variations WRITE set_display_variations NOTIFY display_variationsChanged);
|
||||
Q_PROPERTY(bool doo2breaks READ doo2breaks WRITE set_doo2breaks NOTIFY doo2breaksChanged);
|
||||
Q_PROPERTY(bool dobailout READ dobailout WRITE set_dobailout NOTIFY dobailoutChanged);
|
||||
Q_PROPERTY(bool o2narcotic READ o2narcotic WRITE set_o2narcotic NOTIFY o2narcoticChanged)
|
||||
Q_PROPERTY(bool drop_stone_mode READ drop_stone_mode WRITE set_drop_stone_mode NOTIFY drop_stone_modeChanged);
|
||||
Q_PROPERTY(bool last_stop READ last_stop WRITE set_last_stop NOTIFY last_stopChanged);
|
||||
Q_PROPERTY(int min_switch_duration READ min_switch_duration WRITE set_min_switch_duration NOTIFY min_switch_durationChanged);
|
||||
|
@ -60,6 +61,7 @@ public:
|
|||
static bool display_variations() { return prefs.display_variations; }
|
||||
static bool doo2breaks() { return prefs.doo2breaks; }
|
||||
static bool dobailout() { return prefs.dobailout; }
|
||||
static bool o2narcotic() { return prefs.o2narcotic; }
|
||||
static bool drop_stone_mode() { return prefs.drop_stone_mode; }
|
||||
static bool last_stop() { return prefs.last_stop; }
|
||||
static int min_switch_duration() { return prefs.min_switch_duration; }
|
||||
|
@ -89,6 +91,7 @@ public slots:
|
|||
static void set_display_variations(bool value);
|
||||
static void set_doo2breaks(bool value);
|
||||
static void set_dobailout(bool value);
|
||||
static void set_o2narcotic(bool value);
|
||||
static void set_drop_stone_mode(bool value);
|
||||
static void set_last_stop(bool value);
|
||||
static void set_min_switch_duration(int value);
|
||||
|
@ -118,6 +121,7 @@ signals:
|
|||
void display_variationsChanged(bool value);
|
||||
void doo2breaksChanged(bool value);
|
||||
void dobailoutChanged(bool value);
|
||||
void o2narcoticChanged(bool value);
|
||||
void drop_stone_modeChanged(bool value);
|
||||
void last_stopChanged(bool value);
|
||||
void min_switch_durationChanged(int value);
|
||||
|
@ -148,6 +152,7 @@ private:
|
|||
static void disk_display_variations(bool doSync);
|
||||
static void disk_doo2breaks(bool doSync);
|
||||
static void disk_dobailout(bool doSync);
|
||||
static void disk_o2narcotic(bool doSync);
|
||||
static void disk_drop_stone_mode(bool doSync);
|
||||
static void disk_last_stop(bool doSync);
|
||||
static void disk_min_switch_duration(bool doSync);
|
||||
|
|
|
@ -73,6 +73,7 @@ struct preferences default_prefs = {
|
|||
.display_duration = true,
|
||||
.display_transitions = true,
|
||||
.display_variations = false,
|
||||
.o2narcotic = true,
|
||||
.safetystop = true,
|
||||
.bottomsac = 20000,
|
||||
.decosac = 17000,
|
||||
|
|
|
@ -451,6 +451,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
ui.backgasBreaks->setChecked(prefs.doo2breaks);
|
||||
setBailout(false);
|
||||
setBailoutVisibility(false);
|
||||
ui.o2narcotic->setChecked(prefs.o2narcotic);
|
||||
ui.drop_stone_mode->setChecked(prefs.drop_stone_mode);
|
||||
ui.switch_at_req_stop->setChecked(prefs.switch_at_req_stop);
|
||||
ui.min_switch_duration->setValue(prefs.min_switch_duration / 60);
|
||||
|
@ -496,6 +497,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
connect(ui.vpmb_conservatism, SIGNAL(valueChanged(int)), plannerModel, SLOT(setVpmbConservatism(int)));
|
||||
connect(ui.backgasBreaks, SIGNAL(toggled(bool)), this, SLOT(setBackgasBreaks(bool)));
|
||||
connect(ui.bailout, SIGNAL(toggled(bool)), this, SLOT(setBailout(bool)));
|
||||
connect(ui.o2narcotic, SIGNAL(toggled(bool)), this, SLOT(setO2narcotic(bool)));
|
||||
connect(ui.switch_at_req_stop, SIGNAL(toggled(bool)), plannerModel, SLOT(setSwitchAtReqStop(bool)));
|
||||
connect(ui.min_switch_duration, SIGNAL(valueChanged(int)), plannerModel, SLOT(setMinSwitchDuration(int)));
|
||||
connect(ui.surface_segment, SIGNAL(valueChanged(int)), plannerModel, SLOT(setSurfaceSegment(int)));
|
||||
|
@ -504,6 +506,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
|
||||
connect(ui.bottompo2, SIGNAL(valueChanged(double)), CylindersModel::instance(), SLOT(updateBestMixes()));
|
||||
connect(ui.bestmixEND, SIGNAL(valueChanged(int)), CylindersModel::instance(), SLOT(updateBestMixes()));
|
||||
connect(ui.o2narcotic, SIGNAL(toggled(bool)), CylindersModel::instance(), SLOT(updateBestMixes()));
|
||||
|
||||
connect(modeMapper, SIGNAL(mapped(int)), this, SLOT(disableDecoElements(int)));
|
||||
connect(ui.ascRate75, SIGNAL(valueChanged(int)), this, SLOT(setAscrate75(int)));
|
||||
|
@ -679,6 +682,12 @@ void PlannerSettingsWidget::setBailout(bool dobailout)
|
|||
plannerModel->emitDataChanged();
|
||||
}
|
||||
|
||||
void PlannerSettingsWidget::setO2narcotic(bool o2narcotic)
|
||||
{
|
||||
qPrefDivePlanner::instance()->set_o2narcotic(o2narcotic);
|
||||
plannerModel->emitDataChanged();
|
||||
}
|
||||
|
||||
void PlannerSettingsWidget::setBailoutVisibility(int mode)
|
||||
{
|
||||
ui.bailout->setDisabled(!(mode == CCR || mode == PSCR));
|
||||
|
|
|
@ -86,6 +86,7 @@ slots:
|
|||
void setBestmixEND(int depth);
|
||||
void setBackgasBreaks(bool dobreaks);
|
||||
void setBailout(bool dobailout);
|
||||
void setO2narcotic(bool o2narcotic);
|
||||
void disableDecoElements(int mode);
|
||||
void disableBackgasBreaks(bool enabled);
|
||||
void setDiveMode(int mode);
|
||||
|
|
|
@ -561,6 +561,83 @@
|
|||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="Notes">
|
||||
<property name="title">
|
||||
<string>Notes</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="verbatim_plan">
|
||||
<property name="text">
|
||||
<string>Verbatim dive plan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="display_transitions">
|
||||
<property name="toolTip">
|
||||
<string>In diveplan, list transitions or treat them as implicit</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display transitions in deco</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="display_runtime">
|
||||
<property name="toolTip">
|
||||
<string>In dive plan, show runtime (absolute time) of stops</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display runtime</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="display_duration">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>In dive plan, show duration (relative time) of stops</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display segment duration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="display_variations">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Compute variations of plan (performance cost)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display plan variations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="decoStopSAC">
|
||||
<property name="suffix">
|
||||
|
@ -581,7 +658,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -594,7 +671,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -692,83 +769,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="Notes">
|
||||
<property name="title">
|
||||
<string>Notes</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="verbatim_plan">
|
||||
<property name="text">
|
||||
<string>Verbatim dive plan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="display_transitions">
|
||||
<property name="toolTip">
|
||||
<string>In diveplan, list transitions or treat them as implicit</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display transitions in deco</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="display_runtime">
|
||||
<property name="toolTip">
|
||||
<string>In dive plan, show runtime (absolute time) of stops</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display runtime</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="display_duration">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>In dive plan, show duration (relative time) of stops</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display segment duration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="display_variations">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Compute variations of plan (performance cost)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display plan variations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="decopO2">
|
||||
<property name="text">
|
||||
|
@ -831,6 +831,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="o2narcotic">
|
||||
<property name="toolTip">
|
||||
<string>Treat oxygen as narcotic when computing best mix</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>O₂ narcotic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -391,11 +391,11 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||
if (QString::compare(qPrintable(vString), "*") == 0) {
|
||||
cyl->bestmix_he = true;
|
||||
// Calculate fO2 for max. depth
|
||||
cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive);
|
||||
cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
|
||||
} else {
|
||||
cyl->bestmix_he = false;
|
||||
// Calculate fHe for input depth
|
||||
cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive);
|
||||
cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
@ -605,7 +605,7 @@ bool CylindersModel::updateBestMixes()
|
|||
gasUpdated = true;
|
||||
}
|
||||
if (cyl->bestmix_he) {
|
||||
cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive);
|
||||
cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2);
|
||||
// fO2 + fHe must not be greater than 1
|
||||
if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000)
|
||||
cyl->gasmix.o2.permille = 1000 - get_he(cyl->gasmix);
|
||||
|
|
Loading…
Reference in a new issue