core: move cylinder related functions to struct dive

Seems natural in a C++ code base.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-06-25 07:43:32 +02:00 committed by bstoeger
parent 3aab33ba4c
commit 1b593dc56c
29 changed files with 250 additions and 259 deletions

View file

@ -198,7 +198,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
put_format(&buf, "\n%% Gas use information:\n");
int qty_cyl = 0;
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
if (is_cylinder_used(dive.get(), i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){
if (dive->is_cylinder_used(i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){
put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description.c_str());
put_format(&buf, "\\def\\%scyl%cgasname{%s}\n", ssrf, 'a' + i, gasname(cyl.gasmix));
put_format(&buf, "\\def\\%scyl%cmixO2{%.1f\\%%}\n", ssrf, 'a' + i, get_o2(cyl.gasmix)/10.0);

View file

@ -1146,7 +1146,7 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt
dives.clear();
return;
}
const cylinder_t &orig = *get_cylinder(current, index);
const cylinder_t &orig = *current->get_cylinder(index);
std::vector<dive *> divesNew;
divesNew.reserve(dives.size());
@ -1156,7 +1156,7 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt
for (dive *d: dives) {
if (index >= static_cast<int>(d->cylinders.size()))
continue;
if (nonProtectedOnly && is_cylinder_prot(d, index))
if (nonProtectedOnly && d->is_cylinder_prot(index))
continue;
// We checked that the cylinder exists above.
const cylinder_t &cylinder = d->cylinders[index];
@ -1272,7 +1272,7 @@ void EditCylinder::redo()
for (size_t i = 0; i < dives.size(); ++i) {
const std::string &name = cyl[i].type.description;
set_tank_info_data(tank_info_table, name, cyl[i].type.size, cyl[i].type.workingpressure);
std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]);
std::swap(*dives[i]->get_cylinder(indexes[i]), cyl[i]);
divelog.dives.update_cylinder_related_info(*dives[i]);
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()

View file

@ -372,7 +372,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF && dt_dive->cylinders.size() > 0)
get_cylinder(dt_dive, 0)->gas_used.mliter = lrint(get_cylinder(dt_dive, 0)->type.size.mliter * (tmp_2bytes / 100.0));
dt_dive->get_cylinder(0)->gas_used.mliter = lrint(dt_dive->get_cylinder(0)->type.size.mliter * (tmp_2bytes / 100.0));
/*
* Dive Type 1 - Bit table. Subsurface don't have this record, but
@ -544,10 +544,10 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
goto bail;
}
if (is_nitrox && dt_dive->cylinders.size() > 0)
get_cylinder(dt_dive, 0)->gasmix.o2.permille =
dt_dive->get_cylinder(0)->gasmix.o2.permille =
lrint(membuf[23] & 0x0F ? 20.0 + 2 * (membuf[23] & 0x0F) : 21.0) * 10;
if (is_O2 && dt_dive->cylinders.size() > 0)
get_cylinder(dt_dive, 0)->gasmix.o2.permille = membuf[23] * 10;
dt_dive->get_cylinder(0)->gasmix.o2.permille = membuf[23] * 10;
free(compl_buffer);
}
JUMP(membuf, profile_length);
@ -560,8 +560,8 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
else
dt_dive->dcs[0].deviceid = 0xffffffff;
if (!is_SCR && dt_dive->cylinders.size() > 0) {
get_cylinder(dt_dive, 0)->end.mbar = get_cylinder(dt_dive, 0)->start.mbar -
((get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000);
dt_dive->get_cylinder(0)->end.mbar = dt_dive->get_cylinder(0)->start.mbar -
((dt_dive->get_cylinder(0)->gas_used.mliter / dt_dive->get_cylinder(0)->type.size.mliter) * 1000);
}
return (char *)membuf;
bail:
@ -638,8 +638,8 @@ static void wlog_compl_parser(std::string &wl_mem, struct dive *dt_dive, int dco
*/
tmp = (int) two_bytes_to_int(runner[pos_tank_init + 1], runner[pos_tank_init]);
if (tmp != 0x7fff) {
get_cylinder(dt_dive, 0)->start.mbar = tmp * 10;
get_cylinder(dt_dive, 0)->end.mbar = get_cylinder(dt_dive, 0)->start.mbar - lrint(get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000;
dt_dive->get_cylinder(0)->start.mbar = tmp * 10;
dt_dive->get_cylinder(0)->end.mbar = dt_dive->get_cylinder(0)->start.mbar - lrint(dt_dive->get_cylinder(0)->gas_used.mliter / dt_dive->get_cylinder(0)->type.size.mliter) * 1000;
}
/*

View file

@ -14,6 +14,7 @@
#include "divelist.h"
#include "divelog.h"
#include "divesite.h"
#include "equipment.h"
#include "errorhelper.h"
#include "event.h"
#include "extradata.h"
@ -51,6 +52,19 @@ dive::dive(dive &&) = default;
dive &dive::operator=(const dive &) = default;
dive::~dive() = default;
/* get_cylinder_idx_by_use(): Find the index of the first cylinder with a particular CCR use type.
* The index returned corresponds to that of the first cylinder with a cylinder_use that
* equals the appropriate enum value [oxygen, diluent, bailout] given by cylinder_use_type.
* A negative number returned indicates that a match could not be found.
* Call parameters: dive = the dive being processed
* cylinder_use_type = an enum, one of {oxygen, diluent, bailout} */
static int get_cylinder_idx_by_use(const struct dive &dive, enum cylinderuse cylinder_use_type)
{
auto it = std::find_if(dive.cylinders.begin(), dive.cylinders.end(), [cylinder_use_type]
(auto &cyl) { return cyl.cylinder_use == cylinder_use_type; });
return it != dive.cylinders.end() ? it - dive.cylinders.begin() : -1;
}
/*
* The legacy format for sample pressures has a single pressure
* for each sample that can have any sensor, plus a possible
@ -66,7 +80,7 @@ int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer
{
int o2sensor;
o2sensor = (dc->divemode == CCR) ? get_cylinder_idx_by_use(dive, OXYGEN) : -1;
o2sensor = (dc->divemode == CCR) ? get_cylinder_idx_by_use(*dive, OXYGEN) : -1;
for (const auto &s: dc->samples) {
int seen_pressure = 0, idx;
@ -92,11 +106,30 @@ int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer
return o2sensor < 0 ? 256 : o2sensor;
}
/* access to cylinders is controlled by two functions:
* - get_cylinder() returns the cylinder of a dive and supposes that
* the cylinder with the given index exists. If it doesn't, an error
* message is printed and the "surface air" cylinder returned.
* (NOTE: this MUST not be written into!).
* - get_or_create_cylinder() creates an empty cylinder if it doesn't exist.
* Multiple cylinders might be created if the index is bigger than the
* number of existing cylinders
*/
cylinder_t *dive::get_cylinder(int idx)
{
return &cylinders[idx];
}
const cylinder_t *dive::get_cylinder(int idx) const
{
return &cylinders[idx];
}
/* warning: does not test idx for validity */
struct event create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx)
{
/* The gas switch event format is insane for historical reasons */
struct gasmix mix = get_cylinder(dive, idx)->gasmix;
struct gasmix mix = dive->get_cylinder(idx)->gasmix;
int o2 = get_o2(mix);
int he = get_he(mix);
@ -124,13 +157,13 @@ void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int second
add_event_to_dc(dc, std::move(ev));
}
struct gasmix get_gasmix_from_event(const struct dive *dive, const struct event &ev)
struct gasmix dive::get_gasmix_from_event(const struct event &ev) const
{
if (ev.is_gaschange()) {
int index = ev.gas.index;
// FIXME: The planner uses one past cylinder-count to signify "surface air". Remove in due course.
if (index >= 0 && static_cast<size_t>(index) < dive->cylinders.size() + 1)
return get_cylinder(dive, index)->gasmix;
if (index >= 0 && static_cast<size_t>(index) < cylinders.size() + 1)
return get_cylinder(index)->gasmix;
return ev.gas.mix;
}
return gasmix_air;
@ -240,7 +273,7 @@ void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only)
d->cylinders.clear();
for (auto [i, cyl]: enumerated_range(s->cylinders)) {
if (!used_only || is_cylinder_used(s, i) || get_cylinder(s, i)->cylinder_use == NOT_USED)
if (!used_only || s->is_cylinder_used(i) || s->get_cylinder(i)->cylinder_use == NOT_USED)
d->cylinders.push_back(cyl);
}
}
@ -308,13 +341,39 @@ static int get_cylinder_used(const struct dive *dive, bool used[])
return num;
}
/*
* If the event has an explicit cylinder index,
* we return that. If it doesn't, we return the best
* match based on the gasmix.
*
* Some dive computers give cylinder indices, some
* give just the gas mix.
*/
int dive::get_cylinder_index(const struct event &ev) const
{
if (ev.gas.index >= 0)
return ev.gas.index;
/*
* This should no longer happen!
*
* We now match up gas change events with their cylinders at dive
* event fixup time.
*/
report_info("Still looking up cylinder based on gas mix in get_cylinder_index()!");
gasmix mix = get_gasmix_from_event(ev);
int best = find_best_gasmix_match(mix, cylinders);
return best < 0 ? 0 : best;
}
/* Are there any used cylinders which we do not know usage about? */
static bool has_unknown_used_cylinders(const struct dive *dive, const struct divecomputer *dc,
static bool has_unknown_used_cylinders(const struct dive &dive, const struct divecomputer *dc,
const bool used_cylinders[], int num)
{
int idx;
auto used_and_unknown = std::make_unique<bool[]>(dive->cylinders.size());
std::copy(used_cylinders, used_cylinders + dive->cylinders.size(), used_and_unknown.get());
auto used_and_unknown = std::make_unique<bool[]>(dive.cylinders.size());
std::copy(used_cylinders, used_cylinders + dive.cylinders.size(), used_and_unknown.get());
/* We know about using the O2 cylinder in a CCR dive */
if (dc->divemode == CCR) {
@ -326,7 +385,7 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div
}
/* We know about the explicit first cylinder (or first) */
idx = explicit_first_cylinder(dive, dc);
idx = dive.explicit_first_cylinder(dc);
if (idx >= 0 && used_and_unknown[idx]) {
used_and_unknown[idx] = false;
num--;
@ -336,7 +395,7 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div
event_loop loop("gaschange");
const struct event *ev;
while ((ev = loop.next(*dc)) != nullptr && num > 0) {
idx = get_cylinder_index(dive, *ev);
idx = dive.get_cylinder_index(*ev);
if (idx >= 0 && used_and_unknown[idx]) {
used_and_unknown[idx] = false;
num--;
@ -368,7 +427,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
*/
auto used_cylinders = std::make_unique<bool[]>(dive->cylinders.size());
num_used_cylinders = get_cylinder_used(dive, used_cylinders.get());
if (has_unknown_used_cylinders(dive, dc, used_cylinders.get(), num_used_cylinders)) {
if (has_unknown_used_cylinders(*dive, dc, used_cylinders.get(), num_used_cylinders)) {
/*
* If we had more than one used cylinder, but
* do not know usage of them, we simply cannot
@ -401,7 +460,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
/* Make sure to move the event past 'lasttime' */
while (ev && lasttime >= ev->time.seconds) {
idx = get_cylinder_index(dive, *ev);
idx = dive->get_cylinder_index(*ev);
ev = loop.next(*dc);
}
@ -454,19 +513,19 @@ static int same_rounded_pressure(pressure_t a, pressure_t b)
* first cylinder - in which case cylinder 0 is indeed the first cylinder.
* We likewise return 0 if the event concerns a cylinder that doesn't exist.
* If the dive has no cylinders, -1 is returned. */
int explicit_first_cylinder(const struct dive *dive, const struct divecomputer *dc)
int dive::explicit_first_cylinder(const struct divecomputer *dc) const
{
int res = 0;
if (dive->cylinders.empty())
if (cylinders.empty())
return -1;
if (dc) {
const struct event *ev = get_first_event(*dc, "gaschange");
if (ev && ((!dc->samples.empty() && ev->time.seconds == dc->samples[0].time.seconds) || ev->time.seconds <= 1))
res = get_cylinder_index(dive, *ev);
res = get_cylinder_index(*ev);
else if (dc->divemode == CCR)
res = std::max(get_cylinder_idx_by_use(dive, DILUENT), res);
res = std::max(get_cylinder_idx_by_use(*this, DILUENT), res);
}
return static_cast<size_t>(res) < dive->cylinders.size() ? res : 0;
return static_cast<size_t>(res) < cylinders.size() ? res : 0;
}
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);
@ -492,13 +551,13 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
// pO2 values we would have computed anyway.
event_loop loop("gaschange");
const struct event *ev = loop.next(*dc);
struct gasmix gasmix = get_gasmix_from_event(dive, *ev);
struct gasmix gasmix = dive->get_gasmix_from_event(*ev);
const struct event *next = loop.next(*dc);
for (auto &sample: dc->samples) {
if (next && sample.time.seconds >= next->time.seconds) {
ev = next;
gasmix = get_gasmix_from_event(dive, *ev);
gasmix = dive->get_gasmix_from_event(*ev);
next = loop.next(*dc);
}
gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
@ -1367,19 +1426,6 @@ pick_b:
add_initial_gaschange(d, res, offset, cylinders_map2[0]);
}
/* get_cylinder_idx_by_use(): Find the index of the first cylinder with a particular CCR use type.
* The index returned corresponds to that of the first cylinder with a cylinder_use that
* equals the appropriate enum value [oxygen, diluent, bailout] given by cylinder_use_type.
* A negative number returned indicates that a match could not be found.
* Call parameters: dive = the dive being processed
* cylinder_use_type = an enum, one of {oxygen, diluent, bailout} */
int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type)
{
auto it = std::find_if(dive->cylinders.begin(), dive->cylinders.end(), [cylinder_use_type]
(auto &cyl) { return cyl.cylinder_use == cylinder_use_type; });
return it != dive->cylinders.end() ? it - dive->cylinders.begin() : -1;
}
/* Force an initial gaschange event to the (old) gas #0 */
static void add_initial_gaschange(struct dive &dive, struct divecomputer &dc, int offset, int idx)
{
@ -1472,7 +1518,7 @@ int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *di
if (i == cylid)
continue;
struct gasmix gas2 = cyl.gasmix;
if (gasmix_distance(mygas, gas2) == 0 && (is_cylinder_used(dive, i) || check_unused))
if (gasmix_distance(mygas, gas2) == 0 && (dive->is_cylinder_used(i) || check_unused))
return i;
}
return -1;
@ -1598,7 +1644,7 @@ static bool cylinder_in_use(const struct dive *dive, int idx)
return false;
/* This tests for gaschange events or pressure changes */
if (is_cylinder_used(dive, idx) || prefs.include_unused_tanks)
if (dive->is_cylinder_used(idx) || prefs.include_unused_tanks)
return true;
/* This tests for typenames or gas contents */
@ -1660,7 +1706,7 @@ static void merge_cylinders(struct dive &res, const struct dive &a, const struct
if (!used_in_b[i])
continue;
j = match_cylinder(get_cylinder(&b, i), res, try_to_match.get());
j = match_cylinder(b.get_cylinder(i), res, try_to_match.get());
/* No match? Add it to the result */
if (j < 0) {
@ -1672,7 +1718,7 @@ static void merge_cylinders(struct dive &res, const struct dive &a, const struct
/* Otherwise, merge the result to the one we found */
mapping_b[i] = j;
merge_one_cylinder(get_cylinder(&res, j), get_cylinder(&b, i));
merge_one_cylinder(res.get_cylinder(j), b.get_cylinder(i));
/* Don't match the same target more than once */
try_to_match[j] = false;
@ -2589,8 +2635,8 @@ gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) :
return;
/* on first invocation, get initial gas mix and first event (if any) */
int cyl = explicit_first_cylinder(&dive, &dc);
last = get_cylinder(&dive, cyl)->gasmix;
int cyl = dive.explicit_first_cylinder(&dc);
last = dive.get_cylinder(cyl)->gasmix;
ev = loop.next(dc);
}
@ -2601,7 +2647,7 @@ gasmix gasmix_loop::next(int time)
return last;
while (ev && ev->time.seconds <= time) {
last = get_gasmix_from_event(&dive, *ev);
last = dive.get_gasmix_from_event(*ev);
ev = loop.next(dc);
}
return last;
@ -2609,9 +2655,9 @@ gasmix gasmix_loop::next(int time)
/* get the gas at a certain time during the dive */
/* If there is a gasswitch at that time, it returns the new gasmix */
struct gasmix get_gasmix_at_time(const struct dive &d, const struct divecomputer &dc, duration_t time)
struct gasmix dive::get_gasmix_at_time(const struct divecomputer &dc, duration_t time) const
{
return gasmix_loop(d, dc).next(time.seconds);
return gasmix_loop(*this, dc).next(time.seconds);
}
/* Does that cylinder have any pressure readings? */
@ -2682,7 +2728,7 @@ dive::get_maximal_gas_result dive::get_maximal_gas() const
int o2 = get_o2(cyl.gasmix);
int he = get_he(cyl.gasmix);
if (!is_cylinder_used(this, i))
if (!is_cylinder_used(i))
continue;
if (cyl.cylinder_use == OXYGEN)
continue;
@ -2703,3 +2749,48 @@ dive::get_maximal_gas_result dive::get_maximal_gas() const
maxo2 = mino2 = 0;
return { mino2, maxhe, maxo2 };
}
bool dive::has_gaschange_event(const struct divecomputer *dc, int idx) const
{
bool first_gas_explicit = false;
event_loop loop("gaschange");
while (auto event = loop.next(*dc)) {
if (!dc->samples.empty() && (event->time.seconds == 0 ||
(dc->samples[0].time.seconds == event->time.seconds)))
first_gas_explicit = true;
if (get_cylinder_index(*event) == idx)
return true;
}
return !first_gas_explicit && idx == 0;
}
bool dive::is_cylinder_used(int idx) const
{
if (idx < 0 || static_cast<size_t>(idx) >= cylinders.size())
return false;
const cylinder_t &cyl = cylinders[idx];
if ((cyl.start.mbar - cyl.end.mbar) > SOME_GAS)
return true;
if ((cyl.sample_start.mbar - cyl.sample_end.mbar) > SOME_GAS)
return true;
for (auto &dc: dcs) {
if (has_gaschange_event(&dc, idx))
return true;
else if (dc.divemode == CCR && idx == get_cylinder_idx_by_use(*this, OXYGEN))
return true;
}
return false;
}
bool dive::is_cylinder_prot(int idx) const
{
if (idx < 0 || static_cast<size_t>(idx) >= cylinders.size())
return false;
return std::any_of(dcs.begin(), dcs.end(),
[this, idx](auto &dc)
{ return has_gaschange_event(&dc, idx); });
}

View file

@ -91,6 +91,15 @@ struct dive {
bool is_planned() const;
bool is_logged() const;
bool likely_same(const struct dive &b) const;
bool is_cylinder_used(int idx) const;
bool is_cylinder_prot(int idx) const;
int explicit_first_cylinder(const struct divecomputer *dc) const;
int get_cylinder_index(const struct event &ev) const;
bool has_gaschange_event(const struct divecomputer *dc, int idx) const;
struct gasmix get_gasmix_from_event(const struct event &ev) const;
struct gasmix get_gasmix_at_time(const struct divecomputer &dc, duration_t time) const;
cylinder_t *get_cylinder(int idx);
const cylinder_t *get_cylinder(int idx) const;
int depth_to_mbar(int depth) const;
double depth_to_mbarf(int depth) const;
@ -115,7 +124,6 @@ struct dive_or_trip {
extern void invalidate_dive_cache(struct dive *dive);
extern bool dive_cache_is_valid(const struct dive *dive);
extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type);
extern void cylinder_renumber(struct dive &dive, int mapping[]);
extern int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused);
@ -139,9 +147,6 @@ struct dive_components {
unsigned int when : 1;
};
extern bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc, int idx);
extern int explicit_first_cylinder(const struct dive *dive, const struct divecomputer *dc);
extern fraction_t best_o2(depth_t depth, const struct dive *dive, bool in_planner);
extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2);
@ -193,13 +198,9 @@ extern int dive_getUniqID();
extern void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int time);
extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only);
extern bool is_cylinder_used(const struct dive *dive, int idx);
extern bool is_cylinder_prot(const struct dive *dive, int idx);
extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx);
extern struct event create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx);
extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration);
extern int get_cylinder_index(const struct dive *dive, const struct event &ev);
extern struct gasmix get_gasmix_from_event(const struct dive *, const struct event &ev);
extern bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id);
/* UI related protopypes */
@ -208,9 +209,6 @@ extern void invalidate_dive_cache(struct dive *dc);
extern int total_weight(const struct dive *);
/* Get gasmix at a given time */
extern struct gasmix get_gasmix_at_time(const struct dive &dive, const struct divecomputer &dc, duration_t time);
extern void update_setpoint_events(const struct dive *dive, struct divecomputer *dc);
/* Make pointers to dive and dive_trip "Qt metatypes" so that they can be passed through

View file

@ -117,7 +117,7 @@ int total_weight(const struct dive *dive)
static int active_o2(const struct dive &dive, const struct divecomputer *dc, duration_t time)
{
struct gasmix gas = get_gasmix_at_time(dive, *dc, time);
struct gasmix gas = dive.get_gasmix_at_time(*dc, time);
return get_o2(gas);
}
@ -137,8 +137,8 @@ static int get_sample_o2(const struct dive &dive, const struct divecomputer *dc,
double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive.depth_to_bar(psample.depth.mm );
if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, *dc, psample.time));
po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, *dc, sample.time));
po2i = pscr_o2(pamb_pressure, dive.get_gasmix_at_time(*dc, psample.time));
po2f = pscr_o2(amb_presure, dive.get_gasmix_at_time(*dc, sample.time));
} else {
int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2.
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
@ -182,8 +182,8 @@ static int calculate_otu(const struct dive &dive)
double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive.depth_to_bar(psample.depth.mm);
if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, *dc, psample.time));
po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, *dc, sample.time));
po2i = pscr_o2(pamb_pressure, dive.get_gasmix_at_time(*dc, psample.time));
po2f = pscr_o2(amb_presure, dive.get_gasmix_at_time(*dc, sample.time));
} else {
int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2.
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
@ -388,7 +388,7 @@ static double calculate_airuse(const struct dive &dive)
// better not pretend we know the total gas use.
// Eventually, logic should be fixed to compute average depth and total time
// for those segments where cylinders with known pressure drop are breathed from.
if (is_cylinder_used(&dive, i))
if (dive.is_cylinder_used(i))
return 0.0;
else
continue;

View file

@ -369,25 +369,6 @@ cylinder_t *add_empty_cylinder(struct cylinder_table *t)
return &t->back();
}
/* access to cylinders is controlled by two functions:
* - get_cylinder() returns the cylinder of a dive and supposes that
* the cylinder with the given index exists. If it doesn't, an error
* message is printed and the "surface air" cylinder returned.
* (NOTE: this MUST not be written into!).
* - get_or_create_cylinder() creates an empty cylinder if it doesn't exist.
* Multiple cylinders might be created if the index is bigger than the
* number of existing cylinders
*/
cylinder_t *get_cylinder(struct dive *d, int idx)
{
return &d->cylinders[idx];
}
const cylinder_t *get_cylinder(const struct dive *d, int idx)
{
return &d->cylinders[idx];
}
cylinder_t *get_or_create_cylinder(struct dive *d, int idx)
{
if (idx < 0) {
@ -468,7 +449,7 @@ void add_default_cylinder(struct dive *d)
static bool show_cylinder(const struct dive *d, int i)
{
if (is_cylinder_used(d, i))
if (d->is_cylinder_used(i))
return true;
const cylinder_t &cyl = d->cylinders[i];
@ -499,7 +480,7 @@ void dump_cylinders(struct dive *dive, bool verbose)
{
printf("Cylinder list:\n");
for (int i = 0; i < dive->cylinders; i++) {
cylinder_t *cyl = get_cylinder(dive, i);
cylinder_t *cyl = dive->get_cylinder(i);
printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description.c_str(), cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0);
printf(" Gasmix O2 %2.0f%% He %2.0f%%\n", cyl->gasmix.o2.permille / 10.0, cyl->gasmix.he.permille / 10.0);

View file

@ -71,8 +71,6 @@ using weightsystem_table = std::vector<weightsystem_t>;
extern enum cylinderuse cylinderuse_from_text(const char *text);
extern void copy_cylinder_types(const struct dive *s, struct dive *d);
extern cylinder_t *add_empty_cylinder(struct cylinder_table *t);
extern cylinder_t *get_cylinder(struct dive *d, int idx);
extern const cylinder_t *get_cylinder(const struct dive *d, int idx);
extern cylinder_t *get_or_create_cylinder(struct dive *d, int idx);
extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2);
extern void remove_cylinder(struct dive *dive, int idx);

View file

@ -187,7 +187,7 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
if (track_pr.empty())
return;
if (get_cylinder(dive, cyl)->cylinder_use == OC_GAS)
if (dive->get_cylinder(cyl)->cylinder_use == OC_GAS)
strategy = SAC;
else
strategy = TIME;
@ -248,7 +248,7 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
last_segment = it;
}
if(get_cylinder(dive, cyl)->cylinder_use == OC_GAS) {
if(dive->get_cylinder(cyl)->cylinder_use == OC_GAS) {
/* if this segment has pressure_time, then calculate a new interpolated pressure */
if (interpolate.pressure_time) {
@ -310,7 +310,7 @@ static void debug_print_pressures(struct plot_info &pi)
void populate_pressure_information(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi, int sensor)
{
int first, last, cyl;
const cylinder_t *cylinder = get_cylinder(dive, sensor);
const cylinder_t *cylinder = dive->get_cylinder(sensor);
std::vector<pr_track_t> track;
size_t current = std::string::npos;
int missing_pr = 0, dense = 1;
@ -350,7 +350,7 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
*/
cyl = sensor;
event_loop loop_gas("gaschange");
const struct event *ev = has_gaschange_event(dive, dc, sensor) ?
const struct event *ev = dive->has_gaschange_event(dc, sensor) ?
loop_gas.next(*dc) : nullptr;
divemode_loop loop_mode(*dc);
@ -360,7 +360,7 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
int time = entry.sec;
while (ev && ev->time.seconds <= time) { // Find 1st gaschange event after
cyl = get_cylinder_index(dive, *ev); // the current gas change.
cyl = dive->get_cylinder_index(*ev); // the current gas change.
if (cyl < 0)
cyl = sensor;
ev = loop_gas.next(*dc);

View file

@ -140,7 +140,7 @@ static int divinglog_profile(void *param, int, char **data, char **)
state->cur_sample->pressure[0].mbar = pressure * 100;
state->cur_sample->rbt.seconds = rbt;
if (oldcyl != tank && tank >= 0 && static_cast<size_t>(tank) < state->cur_dive->cylinders.size()) {
struct gasmix mix = get_cylinder(state->cur_dive.get(), tank)->gasmix;
struct gasmix mix = state->cur_dive.get()->get_cylinder(tank)->gasmix;
int o2 = get_o2(mix);
int he = get_he(mix);

View file

@ -89,7 +89,7 @@ int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_
if (event.time.seconds > time.seconds)
break;
if (event.name == "gaschange")
cylinder_idx = get_cylinder_index(dive, event);
cylinder_idx = dive->get_cylinder_index(event);
}
return cylinder_idx;
}
@ -136,7 +136,7 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct
: sample.setpoint;
duration_t t1 = sample.time;
struct gasmix gas = get_gasmix_at_time(*dive, *dc, t0);
struct gasmix gas = dive->get_gasmix_at_time(*dc, t0);
if (psample)
lastdepth = psample->depth;
@ -259,7 +259,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
if (dp->cylinderid != lastcylid) {
/* need to insert a first sample for the new gas */
add_gas_switch_event(dive, dc, lasttime + 1, dp->cylinderid);
cyl = get_cylinder(dive, dp->cylinderid); // FIXME: This actually may get one past the last cylinder for "surface air".
cyl = dive->get_cylinder(dp->cylinderid); // FIXME: This actually may get one past the last cylinder for "surface air".
if (!cyl) {
report_error("Invalid cylinder in create_dive_from_plan(): %d", dp->cylinderid);
continue;
@ -368,7 +368,7 @@ struct gaschanges {
static int setpoint_change(struct dive *dive, int cylinderid)
{
cylinder_t *cylinder = get_cylinder(dive, cylinderid);
cylinder_t *cylinder = dive->get_cylinder(cylinderid);
if (cylinder->type.description.empty())
return 0;
if (starts_with(cylinder->type.description, "SP ")) {
@ -422,7 +422,7 @@ static std::vector<gaschanges> analyze_gaslist(struct diveplan *diveplan, struct
for (size_t nr = 0; nr < gaschanges.size(); nr++) {
int idx = gaschanges[nr].gasidx;
printf("gaschange nr %d: @ %5.2lfm gasidx %d (%s)\n", nr, gaschanges[nr].depth / 1000.0,
idx, gasname(&get_cylinder(&dive, idx)->gasmix));
idx, gasname(&dive.get_cylinder(idx)->gasmix));
}
#endif
return gaschanges;
@ -507,7 +507,7 @@ int ascent_velocity(int depth, int avg_depth, int)
static void track_ascent_gas(int depth, struct dive *dive, int cylinder_id, int avg_depth, int bottom_time, bool safety_stop, enum divemode_t divemode)
{
cylinder_t *cylinder = get_cylinder(dive, cylinder_id);
cylinder_t *cylinder = dive->get_cylinder(cylinder_id);
while (depth > 0) {
int deltad = ascent_velocity(depth, avg_depth, bottom_time) * base_timestep;
if (deltad > depth)
@ -575,7 +575,7 @@ static bool enough_gas(const struct dive *dive, int current_cylinder)
{
if (current_cylinder < 0 || static_cast<size_t>(current_cylinder) >= dive->cylinders.size())
return false;
const cylinder_t *cyl = get_cylinder(dive, current_cylinder);
const cylinder_t *cyl = dive->get_cylinder(current_cylinder);
if (!cyl->start.mbar)
return true;
@ -718,7 +718,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
// Find the divemode at the end of the dive
divemode_loop loop(*dc);
divemode = loop.next(bottom_time);
gas = get_cylinder(dive, current_cylinder)->gasmix;
gas = dive->get_cylinder(current_cylinder)->gasmix;
po2 = sample.setpoint.mbar;
depth = sample.depth.mm;
@ -768,11 +768,11 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
// How long can we stay at the current depth and still directly ascent to the surface?
do {
add_segment(ds, dive->depth_to_bar(depth),
get_cylinder(dive, current_cylinder)->gasmix,
dive->get_cylinder(current_cylinder)->gasmix,
timestep, po2, divemode, prefs.bottomsac, true);
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, get_cylinder(dive, current_cylinder), false, divemode);
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
clock += timestep;
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, get_cylinder(dive, current_cylinder)->gasmix,
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix,
po2, diveplan->surface_pressure / 1000.0, dive, divemode) &&
enough_gas(dive, current_cylinder) && clock < 6 * 3600);
@ -780,7 +780,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
// In the best of all worlds, we would roll back also the last add_segment in terms of caching deco state, but
// let's ignore that since for the eventual ascent in recreational mode, nobody looks at the ceiling anymore,
// so we don't really have to compute the deco state.
update_cylinder_pressure(dive, depth, depth, -timestep, prefs.bottomsac, get_cylinder(dive, current_cylinder), false, divemode);
update_cylinder_pressure(dive, depth, depth, -timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
clock -= timestep;
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, true, divemode);
previous_point_time = clock;
@ -816,7 +816,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (best_first_ascend_cylinder != -1 && best_first_ascend_cylinder != current_cylinder) {
current_cylinder = best_first_ascend_cylinder;
gas = get_cylinder(dive, current_cylinder)->gasmix;
gas = dive->get_cylinder(current_cylinder)->gasmix;
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder,
@ -831,7 +831,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
po2 = 0;
int bailoutsegment = std::max(prefs.min_switch_duration, 60 * prefs.problemsolvingtime);
add_segment(ds, dive->depth_to_bar(depth),
get_cylinder(dive, current_cylinder)->gasmix,
dive->get_cylinder(current_cylinder)->gasmix,
bailoutsegment, po2, divemode, prefs.bottomsac, true);
plan_add_segment(diveplan, bailoutsegment, depth, current_cylinder, po2, false, divemode);
bottom_time += bailoutsegment;
@ -871,7 +871,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
/* Always prefer the best_first_ascend_cylinder if it has the right gasmix.
* Otherwise take first cylinder from list with rightgasmix */
if (best_first_ascend_cylinder != -1 && same_gasmix(gas, get_cylinder(dive, best_first_ascend_cylinder)->gasmix))
if (best_first_ascend_cylinder != -1 && same_gasmix(gas, dive->get_cylinder(best_first_ascend_cylinder)->gasmix))
current_cylinder = best_first_ascend_cylinder;
else
current_cylinder = get_gasidx(dive, gas);
@ -896,7 +896,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
deltad = depth - stoplevels[stopidx];
add_segment(ds, dive->depth_to_bar(depth),
get_cylinder(dive, current_cylinder)->gasmix,
dive->get_cylinder(current_cylinder)->gasmix,
base_timestep, po2, divemode, prefs.decosac, true);
last_segment_min_switch = false;
clock += base_timestep;
@ -921,7 +921,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (current_cylinder != gaschanges[gi].gasidx) {
if (!prefs.switch_at_req_stop ||
!trial_ascent(ds, 0, depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
get_cylinder(dive, current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode) || get_o2(get_cylinder(dive, current_cylinder)->gasmix) < 160) {
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode) || get_o2(dive->get_cylinder(current_cylinder)->gasmix) < 160) {
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
stopping = true;
@ -930,14 +930,14 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (divemode == CCR)
po2 = setpoint_change(dive, current_cylinder);
#if DEBUG_PLAN & 16
gas = get_cylinder(dive, current_cylinder)->gasmix;
gas = dive->get_cylinder(current_cylinder)->gasmix;
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0);
#endif
/* Stop for the minimum duration to switch gas unless we switch to o2 */
if (!last_segment_min_switch && get_o2(get_cylinder(dive, current_cylinder)->gasmix) != 1000) {
if (!last_segment_min_switch && get_o2(dive->get_cylinder(current_cylinder)->gasmix) != 1000) {
add_segment(ds, dive->depth_to_bar(depth),
get_cylinder(dive, current_cylinder)->gasmix,
dive->get_cylinder(current_cylinder)->gasmix,
prefs.min_switch_duration, po2, divemode, prefs.decosac, true);
clock += prefs.min_switch_duration;
last_segment_min_switch = true;
@ -957,7 +957,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
while (1) {
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
if (trial_ascent(ds, 0, depth, stoplevels[stopidx], avg_depth, bottom_time,
get_cylinder(dive, current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode)) {
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode)) {
decostoptable[decostopcounter].depth = depth;
decostoptable[decostopcounter].time = 0;
decostopcounter++;
@ -986,14 +986,14 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (divemode == CCR)
po2 = setpoint_change(dive, current_cylinder);
#if DEBUG_PLAN & 16
gas = get_cylinder(dive, current_cylinder)->gasmix;
gas = dive->get_cylinder(current_cylinder)->gasmix;
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi + 1].gasidx,
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi + 1].depth / 1000.0);
#endif
/* Stop for the minimum duration to switch gas unless we switch to o2 */
if (!last_segment_min_switch && get_o2(get_cylinder(dive, current_cylinder)->gasmix) != 1000) {
if (!last_segment_min_switch && get_o2(dive->get_cylinder(current_cylinder)->gasmix) != 1000) {
add_segment(ds, dive->depth_to_bar(depth),
get_cylinder(dive, current_cylinder)->gasmix,
dive->get_cylinder(current_cylinder)->gasmix,
prefs.min_switch_duration, po2, divemode, prefs.decosac, true);
clock += prefs.min_switch_duration;
}
@ -1001,7 +1001,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
int new_clock = wait_until(ds, dive, clock, clock, laststoptime * 2 + 1, timestep, depth, stoplevels[stopidx], avg_depth,
bottom_time, get_cylinder(dive, current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, divemode);
bottom_time, dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, divemode);
laststoptime = new_clock - clock;
/* Finish infinite deco */
if (laststoptime >= 48 * 3600 && depth >= 6000) {
@ -1016,12 +1016,12 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
* backgas. This could be customized if there were demand.
*/
if (break_cylinder == -1) {
if (best_first_ascend_cylinder != -1 && get_o2(get_cylinder(dive, best_first_ascend_cylinder)->gasmix) <= 320)
if (best_first_ascend_cylinder != -1 && get_o2(dive->get_cylinder(best_first_ascend_cylinder)->gasmix) <= 320)
break_cylinder = best_first_ascend_cylinder;
else
break_cylinder = 0;
}
if (get_o2(get_cylinder(dive, current_cylinder)->gasmix) == 1000) {
if (get_o2(dive->get_cylinder(current_cylinder)->gasmix) == 1000) {
if (laststoptime >= 12 * 60) {
laststoptime = 12 * 60;
new_clock = clock + laststoptime;
@ -1046,7 +1046,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
}
}
add_segment(ds, dive->depth_to_bar(depth), get_cylinder(dive, stop_cylinder)->gasmix,
add_segment(ds, dive->depth_to_bar(depth), dive->get_cylinder(stop_cylinder)->gasmix,
laststoptime, po2, divemode, prefs.decosac, true);
last_segment_min_switch = false;
decostoptable[decostopcounter].depth = depth;

View file

@ -191,13 +191,13 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
nextdp = dp->next;
if (dp->time == 0)
continue;
gasmix = get_cylinder(dive, dp->cylinderid)->gasmix;
gasmix = dive->get_cylinder(dp->cylinderid)->gasmix;
depthvalue = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
/* analyze the dive points ahead */
while (nextdp && nextdp->time == 0)
nextdp = nextdp->next;
if (nextdp)
newgasmix = get_cylinder(dive, nextdp->cylinderid)->gasmix;
newgasmix = dive->get_cylinder(nextdp->cylinderid)->gasmix;
gaschange_after = (nextdp && (gasmix_distance(gasmix, newgasmix)));
gaschange_before = (gasmix_distance(lastprintgasmix, gasmix));
rebreatherchange_after = (nextdp && (dp->setpoint != nextdp->setpoint || dp->divemode != nextdp->divemode));
@ -577,7 +577,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
while (dp) {
if (dp->time != 0) {
std::string temp;
struct gasmix gasmix = get_cylinder(dive, dp->cylinderid)->gasmix;
struct gasmix gasmix = dive->get_cylinder(dp->cylinderid)->gasmix;
divemode_t current_divemode = loop.next(dp->time);
amb = dive->depth_to_atm(dp->depth.mm);

View file

@ -126,7 +126,7 @@ static int get_local_sac(struct plot_info &pi, int idx1, int idx2, struct dive *
depth = (entry1.depth + entry2.depth) / 2;
atm = dive->depth_to_atm(depth);
cyl = get_cylinder(dive, index);
cyl = dive->get_cylinder(index);
airuse = gas_volume(cyl, a) - gas_volume(cyl, b);
@ -193,35 +193,6 @@ static void analyze_plot_info(struct plot_info &pi)
}
}
/*
* If the event has an explicit cylinder index,
* we return that. If it doesn't, we return the best
* match based on the gasmix.
*
* Some dive computers give cylinder indices, some
* give just the gas mix.
*/
int get_cylinder_index(const struct dive *dive, const struct event &ev)
{
int best;
struct gasmix mix;
if (ev.gas.index >= 0)
return ev.gas.index;
/*
* This should no longer happen!
*
* We now match up gas change events with their cylinders at dive
* event fixup time.
*/
report_info("Still looking up cylinder based on gas mix in get_cylinder_index()!");
mix = get_gasmix_from_event(dive, ev);
best = find_best_gasmix_match(mix, dive->cylinders);
return best < 0 ? 0 : best;
}
static size_t set_setpoint(struct plot_info &pi, size_t i, int setpoint, int end)
{
while (i < pi.entry.size()) {
@ -508,7 +479,7 @@ static int sac_between(const struct dive *dive, const struct plot_info &pi, int
a.mbar = get_plot_pressure(pi, first, i);
b.mbar = get_plot_pressure(pi, last, i);
const cylinder_t *cyl = get_cylinder(dive, i);
const cylinder_t *cyl = dive->get_cylinder(i);
int cyluse = gas_volume(cyl, a) - gas_volume(cyl, b);
if (cyluse > 0)
airuse += cyluse;
@ -704,7 +675,7 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
std::vector<int> first(num_cyl, 0);
std::vector<int> last(num_cyl, INT_MAX);
int prev = explicit_first_cylinder(dive, dc);
int prev = dive->explicit_first_cylinder(dc);
prev = prev >= 0 ? prev : 0;
seen[prev] = 1;
@ -735,7 +706,7 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
// Fill in "seen[]" array - mark cylinders we're not interested
// in as negative.
for (int i = 0; i < pi.nr_cylinders; i++) {
const cylinder_t *cyl = get_cylinder(dive, i);
const cylinder_t *cyl = dive->get_cylinder(i);
int start = cyl->start.mbar;
int end = cyl->end.mbar;
@ -756,7 +727,7 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
/* If it's only mentioned by other dc's, ignore it */
for (auto &secondary: dive->dcs) {
if (has_gaschange_event(dive, &secondary, i)) {
if (dive->has_gaschange_event(&secondary, i)) {
seen[i] = -1;
break;
}
@ -765,7 +736,7 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
for (int i = 0; i < pi.nr_cylinders; i++) {
if (seen[i] >= 0) {
const cylinder_t *cyl = get_cylinder(dive, i);
const cylinder_t *cyl = dive->get_cylinder(i);
add_plot_pressure(pi, first[i], i, cyl->start);
add_plot_pressure(pi, last[i], i, cyl->end);
@ -1306,7 +1277,7 @@ static std::vector<std::string> plot_string(const struct dive *d, const struct p
int mbar = get_plot_pressure(pi, idx, cyl);
if (!mbar)
continue;
struct gasmix mix = get_cylinder(d, cyl)->gasmix;
struct gasmix mix = d->get_cylinder(cyl)->gasmix;
pressurevalue = get_pressure_units(mbar, &pressure_unit);
res.push_back(casprintf_loc(translate("gettextFromC", "P: %d%s (%s)"), pressurevalue, pressure_unit, gasname(mix)));
}
@ -1531,7 +1502,7 @@ std::vector<std::string> compare_samples(const struct dive *d, const struct plot
if (last_pressures[cylinder_index]) {
bar_used[cylinder_index] += last_pressures[cylinder_index] - next_pressure;
const cylinder_t *cyl = get_cylinder(d, cylinder_index);
const cylinder_t *cyl = d->get_cylinder(cylinder_index);
volumes_used[cylinder_index] += gas_volume(cyl, (pressure_t){ last_pressures[cylinder_index] }) - gas_volume(cyl, (pressure_t){ next_pressure });
}
@ -1584,7 +1555,7 @@ std::vector<std::string> compare_samples(const struct dive *d, const struct plot
total_bar_used += bar_used[cylinder_index];
total_volume_used += volumes_used[cylinder_index];
const cylinder_t *cyl = get_cylinder(d, cylinder_index);
const cylinder_t *cyl = d->get_cylinder(cylinder_index);
if (cyl->type.size.mliter) {
if (cylinder_volume.mliter && cylinder_volume.mliter != cyl->type.size.mliter) {
cylindersizes_are_identical = false;

View file

@ -351,7 +351,7 @@ QVector<QPair<QString, int>> selectedDivesGasUsed()
std::vector<volume_t> diveGases = get_gas_used(d);
for (size_t j = 0; j < d->cylinders.size(); j++) {
if (diveGases[j].mliter) {
QString gasName = gasname(get_cylinder(d, j)->gasmix);
QString gasName = gasname(d->get_cylinder(j)->gasmix);
gasUsed[gasName] += diveGases[j].mliter;
}
}

View file

@ -385,7 +385,7 @@ static void save_one_event(struct membuffer *b, const struct dive &dive, const s
show_index(b, ev.value, "value=", "");
show_utf8(b, " name=", ev.name.c_str(), "");
if (ev.is_gaschange()) {
struct gasmix mix = get_gasmix_from_event(&dive, ev);
struct gasmix mix = dive.get_gasmix_from_event(ev);
if (ev.gas.index >= 0)
show_integer(b, ev.gas.index, "cylinder=", "");
put_gasmix(b, mix);

View file

@ -352,7 +352,7 @@ static void save_one_event(struct membuffer *b, const struct dive &dive, const s
show_index(b, ev.value, "value='", "'");
show_utf8(b, ev.name.c_str(), " name='", "'", 1);
if (ev.is_gaschange()) {
struct gasmix mix = get_gasmix_from_event(&dive, ev);
struct gasmix mix = dive.get_gasmix_from_event(ev);
if (ev.gas.index >= 0)
show_integer(b, ev.gas.index, "cylinder='", "'");
put_gasmix(b, mix);

View file

@ -249,51 +249,6 @@ stats_t calculate_stats_selected()
#define SOME_GAS 5000 // 5bar drop in cylinder pressure makes cylinder used
bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc, int idx)
{
bool first_gas_explicit = false;
event_loop loop("gaschange");
while (auto event = loop.next(*dc)) {
if (!dc->samples.empty() && (event->time.seconds == 0 ||
(dc->samples[0].time.seconds == event->time.seconds)))
first_gas_explicit = true;
if (get_cylinder_index(dive, *event) == idx)
return true;
}
return !first_gas_explicit && idx == 0;
}
bool is_cylinder_used(const struct dive *dive, int idx)
{
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size())
return false;
const cylinder_t &cyl = dive->cylinders[idx];
if ((cyl.start.mbar - cyl.end.mbar) > SOME_GAS)
return true;
if ((cyl.sample_start.mbar - cyl.sample_end.mbar) > SOME_GAS)
return true;
for (auto &dc: dive->dcs) {
if (has_gaschange_event(dive, &dc, idx))
return true;
else if (dc.divemode == CCR && idx == get_cylinder_idx_by_use(dive, OXYGEN))
return true;
}
return false;
}
bool is_cylinder_prot(const struct dive *dive, int idx)
{
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size())
return false;
return std::any_of(dive->dcs.begin(), dive->dcs.end(),
[dive, idx](auto &dc)
{ return has_gaschange_event(dive, &dc, idx); });
}
/* Returns a vector with dive->cylinders.size() entries */
std::vector<volume_t> get_gas_used(struct dive *dive)
{
@ -334,7 +289,7 @@ std::pair<volume_t, volume_t> selected_dives_gas_parts()
int j = 0;
for (auto &gas: get_gas_used(d.get())) {
if (gas.mliter) {
auto [o2, he] = get_gas_parts(get_cylinder(d.get(), j)->gasmix, gas, O2_IN_AIR);
auto [o2, he] = get_gas_parts(d->get_cylinder(j)->gasmix, gas, O2_IN_AIR);
o2_tot.mliter += o2.mliter;
he_tot.mliter += he.mliter;
}

View file

@ -79,7 +79,7 @@ QStringList formatGetCylinder(const dive *d)
{
QStringList getCylinder;
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
if (is_cylinder_used(d, i))
if (d->is_cylinder_used(i))
getCylinder << QString::fromStdString(cyl.type.description);
}
return getCylinder;
@ -89,7 +89,7 @@ QStringList formatStartPressure(const dive *d)
{
QStringList startPressure;
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
if (is_cylinder_used(d, i))
if (d->is_cylinder_used(i))
startPressure << getPressures(cyl, START_PRESSURE);
}
return startPressure;
@ -99,7 +99,7 @@ QStringList formatEndPressure(const dive *d)
{
QStringList endPressure;
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
if (is_cylinder_used(d, i))
if (d->is_cylinder_used(i))
endPressure << getPressures(cyl, END_PRESSURE);
}
return endPressure;
@ -109,7 +109,7 @@ QStringList formatFirstGas(const dive *d)
{
QStringList gas;
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
if (is_cylinder_used(d, i))
if (d->is_cylinder_used(i))
gas << get_gas_string(cyl.gasmix);
}
return gas;
@ -174,7 +174,7 @@ QString formatGas(const dive *d)
*/
QString gases;
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
if (!is_cylinder_used(d, i))
if (!d->is_cylinder_used(i))
continue;
QString gas = QString::fromStdString(cyl.type.description);
if (!gas.isEmpty())

View file

@ -346,7 +346,7 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button)
if (what->cylinders) {
text << tr("Cylinders:\n");
for (auto [idx, cyl]: enumerated_range(current_dive->cylinders)) {
if (is_cylinder_used(current_dive, idx))
if (current_dive->is_cylinder_used(idx))
text << QString::fromStdString(cyl.type.description) << " " << gasname(cyl.gasmix) << "\n";
}
}

View file

@ -134,12 +134,12 @@ void TabDiveInformation::updateProfile()
QString gaslist, SACs, separator;
for (size_t i = 0; i < currentDive->cylinders.size(); i++) {
if (!is_cylinder_used(currentDive, i))
if (!currentDive->is_cylinder_used(i))
continue;
gaslist.append(separator); volumes.append(separator); SACs.append(separator);
separator = "\n";
gaslist.append(gasname(get_cylinder(currentDive, i)->gasmix));
gaslist.append(gasname(currentDive->get_cylinder(i)->gasmix));
if (!gases[i].mliter)
continue;
volumes.append(get_volume_string(gases[i], true));

View file

@ -1242,7 +1242,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
if (formatStartPressure(d) != startpressure || formatEndPressure(d) != endpressure) {
diveChanged = true;
for ( int i = 0, j = 0 ; j < startpressure.length() && j < endpressure.length() ; i++ ) {
if (state != "add" && !is_cylinder_used(d, i))
if (state != "add" && !d->is_cylinder_used(i))
continue;
cylinder_t *cyl = get_or_create_cylinder(d, i);
@ -1257,7 +1257,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
// gasmix for first cylinder
if (formatFirstGas(d) != gasmix) {
for ( int i = 0, j = 0 ; j < gasmix.length() ; i++ ) {
if (state != "add" && !is_cylinder_used(d, i))
if (state != "add" && !d->is_cylinder_used(i))
continue;
int o2 = parseGasMixO2(gasmix[j]);
@ -1268,7 +1268,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
o2 + he <= 1000) {
diveChanged = true;
get_or_create_cylinder(d, i)->gasmix.o2.permille = o2;
get_cylinder(d, i)->gasmix.he.permille = he;
d->get_cylinder(i)->gasmix.he.permille = he;
}
j++;
}
@ -1278,7 +1278,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
diveChanged = true;
int size = 0, wp = 0, j = 0, k = 0;
for (j = 0; k < usedCylinder.length(); j++) {
if (state != "add" && !is_cylinder_used(d, j))
if (state != "add" && !d->is_cylinder_used(j))
continue;
for (const tank_info &ti: tank_info_table) {
@ -1294,8 +1294,8 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
}
}
get_or_create_cylinder(d, j)->type.description = usedCylinder[k].toStdString();
get_cylinder(d, j)->type.size.mliter = size;
get_cylinder(d, j)->type.workingpressure.mbar = wp;
d->get_cylinder(j)->type.size.mliter = size;
d->get_cylinder(j)->type.workingpressure.mbar = wp;
k++;
}
}

View file

@ -51,7 +51,7 @@ void DiveEventItem::setupPixmap(struct gasmix lastgasmix, const DivePixmaps &pix
setPixmap(pixmaps.bookmark);
setOffset(QPointF(0.0, -pixmap().height()));
} else if (ev.is_gaschange()) {
struct gasmix mix = get_gasmix_from_event(dive, ev);
struct gasmix mix = dive->get_gasmix_from_event(ev);
struct icd_data icd_data;
bool icd = isobaric_counterdiffusion(lastgasmix, mix, &icd_data);
if (mix.he.permille) {
@ -123,7 +123,7 @@ void DiveEventItem::setupToolTipString(struct gasmix lastgasmix)
if (ev.is_gaschange()) {
struct icd_data icd_data;
struct gasmix mix = get_gasmix_from_event(dive, ev);
struct gasmix mix = dive->get_gasmix_from_event(ev);
name += ": ";
name += gasname(mix);

View file

@ -602,9 +602,7 @@ void DiveGasPressureItem::replot(const dive *d, int fromIn, int toIn, bool in_pl
bool showDescriptions = false;
for (int cyl = 0; cyl < pInfo.nr_cylinders; cyl++) {
const cylinder_t *c = get_cylinder(d, cyl);
if (!c)
continue;
const cylinder_t *c = d->get_cylinder(cyl);
showDescriptions = showDescriptions || (c && same_gasmix_cylinder(*c, cyl, d, true) != -1);
if (act_segments[cyl].polygon.empty())
continue;
@ -634,7 +632,7 @@ void DiveGasPressureItem::replot(const dive *d, int fromIn, int toIn, bool in_pl
// For each cylinder, on right hand side of the curve, write cylinder pressure
double x_offset = plotPressureValue(segment.last.pressure, segment.last.time, Qt::AlignTop | Qt::AlignLeft, y_offset) + 2;
plotGasValue(segment.last.pressure, segment.last.time, get_cylinder(d, segment.cyl), Qt::AlignTop | Qt::AlignLeft, x_offset, y_offset, showDescriptions);
plotGasValue(segment.last.pressure, segment.last.time, d->get_cylinder(segment.cyl), Qt::AlignTop | Qt::AlignLeft, x_offset, y_offset, showDescriptions);
/* Alternate alignment as we see cylinder use.. */
startAlignVar ^= Qt::AlignTop | Qt::AlignBottom;

View file

@ -551,7 +551,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
// while all other items are up there on the constructor.
qDeleteAll(eventItems);
eventItems.clear();
struct gasmix lastgasmix = get_gasmix_at_time(*d, *currentdc, duration_t{1});
struct gasmix lastgasmix = d->get_gasmix_at_time(*currentdc, duration_t{1});
for (auto [idx, event]: enumerated_range(currentdc->events)) {
// if print mode is selected only draw headings, SP change, gas events or bookmark event
@ -571,7 +571,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
eventItems.push_back(item);
}
if (event.is_gaschange())
lastgasmix = get_gasmix_from_event(d, event);
lastgasmix = d->get_gasmix_from_event(event);
}
QString dcText = QString::fromStdString(get_dc_nickname(currentdc));

View file

@ -614,7 +614,7 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
if (gasChangeIdx < plotInfo.nr - 1) {
int newGasIdx = gasChangeIdx + 1;
const struct plot_data &newGasEntry = plotInfo.entry[newGasIdx];
if (get_plot_sensor_pressure(&plotInfo, gasChangeIdx) == 0 || get_cylinder(d, gasChangeEntry->sensor[0])->sample_start.mbar == 0) {
if (get_plot_sensor_pressure(&plotInfo, gasChangeIdx) == 0 || d->get_cylinder(gasChangeEntry->sensor[0])->sample_start.mbar == 0) {
// if we have no sensorpressure or if we have no pressure from samples we can assume that
// we only have interpolated pressure (the pressure in the entry may be stored in the sensor
// pressure field if this is the first or last entry for this tank... see details in gaspressures.c
@ -623,7 +623,7 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
QAction *adjustOldPressure = m.addAction(tr("Adjust pressure of cyl. %1 (currently interpolated as %2)")
.arg(gasChangeEntry->sensor[0] + 1).arg(get_pressure_string(pressure)));
}
if (get_plot_sensor_pressure(&plotInfo, newGasIdx) == 0 || get_cylinder(d, newGasEntry->sensor[0])->sample_start.mbar == 0) {
if (get_plot_sensor_pressure(&plotInfo, newGasIdx) == 0 || d->get_cylinder(newGasEntry->sensor[0])->sample_start.mbar == 0) {
// we only have interpolated press -- see commend above
pressure_t pressure;
pressure.mbar = get_plot_interpolated_pressure(&plotInfo, newGasIdx) ? : get_plot_sensor_pressure(&plotInfo, newGasIdx);
@ -920,7 +920,7 @@ void ProfileWidget2::repositionDiveHandlers()
QPointF pos = line.pointAt(0.5);
gases[i]->setPos(pos);
if (datapoint.cylinderid >= 0 && datapoint.cylinderid < static_cast<int>(d->cylinders.size()))
gases[i]->setText(get_gas_string(get_cylinder(d, datapoint.cylinderid)->gasmix));
gases[i]->setText(get_gas_string(d->get_cylinder(datapoint.cylinderid)->gasmix));
else
gases[i]->setText(QString());
gases[i]->setVisible(datapoint.entered &&

View file

@ -84,14 +84,14 @@ void TankItem::setData(const struct dive *d, const struct divecomputer *dc, int
struct gasmix gasmix = gasmix_invalid;
const struct event *ev;
while ((ev = loop.next(*dc)) != nullptr && ev->time.seconds <= plotStartTime)
gasmix = get_gasmix_from_event(d, *ev);
gasmix = d->get_gasmix_from_event(*ev);
// work through all the gas changes and add the rectangle for each gas while it was used
int startTime = plotStartTime;
while (ev && (int)ev->time.seconds < plotEndTime) {
createBar(startTime, ev->time.seconds, gasmix);
startTime = ev->time.seconds;
gasmix = get_gasmix_from_event(d, *ev);
gasmix = d->get_gasmix_from_event(*ev);
ev = loop.next(*dc);
}
createBar(startTime, plotEndTime, gasmix);

View file

@ -155,7 +155,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
return QVariant();
}
const cylinder_t *cyl = index.row() == tempRow ? &tempCyl : get_cylinder(d, index.row());
const cylinder_t *cyl = index.row() == tempRow ? &tempCyl : d->get_cylinder(index.row());
switch (role) {
case Qt::BackgroundRole: {
@ -259,7 +259,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
case Qt::SizeHintRole:
if (index.column() == REMOVE) {
if ((inPlanner && DivePlannerPointsModel::instance()->tankInUse(index.row())) ||
(!inPlanner && is_cylinder_prot(d, index.row()))) {
(!inPlanner && d->is_cylinder_prot(index.row()))) {
return trashForbiddenIcon();
}
return trashIcon();
@ -269,7 +269,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
switch (index.column()) {
case REMOVE:
if ((inPlanner && DivePlannerPointsModel::instance()->tankInUse(index.row())) ||
(!inPlanner && is_cylinder_prot(d, index.row()))) {
(!inPlanner && d->is_cylinder_prot(index.row()))) {
return tr("This gas is in use. Only cylinders that are not used in the dive can be removed.");
}
return tr("Clicking here will remove this cylinder.");
@ -301,7 +301,7 @@ cylinder_t *CylindersModel::cylinderAt(const QModelIndex &index)
{
if (!d)
return nullptr;
return get_cylinder(d, index.row());
return d->get_cylinder(index.row());
}
bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, int role)
@ -364,7 +364,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
// First, we make a shallow copy of the old cylinder. Then we modify the fields inside that copy.
// At the end, we either place an EditCylinder undo command (EquipmentTab) or copy the cylinder back (planner).
// Yes, this is not ideal, but the pragmatic thing to do for now.
cylinder_t cyl = *get_cylinder(d, row);
cylinder_t cyl = *d->get_cylinder(row);
if (index.column() != TYPE && !changed)
return false;
@ -470,7 +470,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
if (inPlanner) {
// In the planner - simply overwrite the cylinder in the dive with the modified cylinder.
*get_cylinder(d, row) = cyl;
*d->get_cylinder(row) = cyl;
dataChanged(index, index);
} else {
// On the EquipmentTab - place an editCylinder command.
@ -711,7 +711,7 @@ void CylindersModel::initTempCyl(int row)
if (!d || tempRow == row)
return;
clearTempCyl();
const cylinder_t *cyl = get_cylinder(d, row);
const cylinder_t *cyl = d->get_cylinder(row);
if (!cyl)
return;
@ -737,7 +737,7 @@ void CylindersModel::commitTempCyl(int row)
return;
if (row != tempRow)
return clearTempCyl(); // Huh? We are supposed to commit a different row than the one we stored?
cylinder_t *cyl = get_cylinder(d, tempRow);
cylinder_t *cyl = d->get_cylinder(tempRow);
if (!cyl)
return;
// Only submit a command if the type changed

View file

@ -507,7 +507,7 @@ static void merge_cylinder_info(cylinder_t *src, cylinder_t *dst)
static void smtk_clean_cylinders(struct dive *d)
{
int i = tanks - 1;
cylinder_t *cyl, *base = get_cylinder(d, 0);
cylinder_t *cyl, *base = d->get_cylinder(0);
cyl = base + tanks - 1;
while (cyl != base) {

View file

@ -768,8 +768,7 @@ void TestPlan::testMultipleGases()
save_dive(stdout, dive, false);
#endif
gasmix gas;
gas = get_gasmix_at_time(dive, dive.dcs[0], {20 * 60 + 1});
gasmix gas = dive.get_gasmix_at_time(dive.dcs[0], {20 * 60 + 1});
QCOMPARE(get_o2(gas), 110);
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 2480u, 2480u));
}
@ -963,17 +962,17 @@ void TestPlan::testCcrBailoutGasSelection()
#endif
// check diluent used
cylinder_t *cylinder = get_cylinder(&dive, get_cylinderid_at_time(&dive, &dive.dcs[0], { 20 * 60 - 1 }));
cylinder_t *cylinder = dive.get_cylinder(get_cylinderid_at_time(&dive, &dive.dcs[0], { 20 * 60 - 1 }));
QCOMPARE(cylinder->cylinder_use, DILUENT);
QCOMPARE(get_o2(cylinder->gasmix), 200);
// check deep bailout used
cylinder = get_cylinder(&dive, get_cylinderid_at_time(&dive, &dive.dcs[0], { 20 * 60 + 1 }));
cylinder = dive.get_cylinder(get_cylinderid_at_time(&dive, &dive.dcs[0], { 20 * 60 + 1 }));
QCOMPARE(cylinder->cylinder_use, OC_GAS);
QCOMPARE(get_o2(cylinder->gasmix), 190);
// check shallow bailout used
cylinder = get_cylinder(&dive, get_cylinderid_at_time(&dive, &dive.dcs[0], { 30 * 60 }));
cylinder = dive.get_cylinder(get_cylinderid_at_time(&dive, &dive.dcs[0], { 30 * 60 }));
QCOMPARE(cylinder->cylinder_use, OC_GAS);
QCOMPARE(get_o2(cylinder->gasmix), 530);