mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-27 20:58:47 +00:00
core: convert cylinder_t and cylinder_table to C++
This had to be done simultaneously, because the table macros do not work properly with C++ objects. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
284582d2e8
commit
28520da655
48 changed files with 593 additions and 710 deletions
|
@ -205,10 +205,10 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
// Print cylinder data
|
||||
put_format(&buf, "\n%% Gas use information:\n");
|
||||
qty_cyl = 0;
|
||||
for (i = 0; i < dive->cylinders.nr; i++){
|
||||
const cylinder_t &cyl = *get_cylinder(dive, i);
|
||||
if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && cyl.type.description)){
|
||||
put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description);
|
||||
for (int i = 0; i < static_cast<int>(dive->cylinders.size()); i++){
|
||||
const cylinder_t &cyl = dive->cylinders[i];
|
||||
if (is_cylinder_used(dive, 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);
|
||||
put_format(&buf, "\\def\\%scyl%cmixHe{%.1f\\%%}\n", ssrf, 'a' + i, get_he(cyl.gasmix)/10.0);
|
||||
|
|
|
@ -962,7 +962,7 @@ MergeDives::MergeDives(const QVector <dive *> &dives)
|
|||
{
|
||||
setText(Command::Base::tr("merge dive"));
|
||||
|
||||
// Just a safety check - if there's not two or more dives - do nothing
|
||||
// Just a safety check - if there's not two or more dives - do nothing.
|
||||
// The caller should have made sure that this doesn't happen.
|
||||
if (dives.count() < 2) {
|
||||
qWarning("Merging less than two dives");
|
||||
|
|
|
@ -629,7 +629,6 @@ static void swapCandQString(QString &q, char *&c)
|
|||
PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dIn),
|
||||
tags(nullptr)
|
||||
{
|
||||
memset(&cylinders, 0, sizeof(cylinders));
|
||||
memset(&weightsystems, 0, sizeof(weightsystems));
|
||||
if (what.notes)
|
||||
notes = data->notes;
|
||||
|
@ -656,14 +655,14 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
|
|||
if (what.tags)
|
||||
tags = taglist_copy(data->tag_list);
|
||||
if (what.cylinders) {
|
||||
copy_cylinders(&data->cylinders, &cylinders);
|
||||
cylinders = data->cylinders;
|
||||
// Paste cylinders is "special":
|
||||
// 1) For cylinders that exist in the destination dive we keep the gas-mix and pressures.
|
||||
// 2) For cylinders that do not yet exist in the destination dive, we set the pressures to 0, i.e. unset.
|
||||
// Moreover, for these we set the manually_added flag, because they weren't downloaded from a DC.
|
||||
for (int i = 0; i < d->cylinders.nr && i < cylinders.nr; ++i) {
|
||||
const cylinder_t &src = *get_cylinder(d, i);
|
||||
cylinder_t &dst = cylinders.cylinders[i];
|
||||
for (size_t i = 0; i < d->cylinders.size() && i < cylinders.size(); ++i) {
|
||||
const cylinder_t &src = d->cylinders[i];
|
||||
cylinder_t &dst = cylinders[i];
|
||||
dst.gasmix = src.gasmix;
|
||||
dst.start = src.start;
|
||||
dst.end = src.end;
|
||||
|
@ -677,8 +676,8 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
|
|||
dst.bestmix_o2 = src.bestmix_o2;
|
||||
dst.bestmix_he = src.bestmix_he;
|
||||
}
|
||||
for (int i = d->cylinders.nr; i < cylinders.nr; ++i) {
|
||||
cylinder_t &cyl = cylinders.cylinders[i];
|
||||
for (size_t i = d->cylinders.size(); i < cylinders.size(); ++i) {
|
||||
cylinder_t &cyl = cylinders[i];
|
||||
cyl.start.mbar = 0;
|
||||
cyl.end.mbar = 0;
|
||||
cyl.sample_start.mbar = 0;
|
||||
|
@ -697,7 +696,6 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
|
|||
PasteState::~PasteState()
|
||||
{
|
||||
taglist_free(tags);
|
||||
clear_cylinder_table(&cylinders);
|
||||
clear_weightsystem_table(&weightsystems);
|
||||
free(weightsystems.weightsystems);
|
||||
}
|
||||
|
@ -803,7 +801,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive),
|
|||
duration({0}),
|
||||
salinity(0)
|
||||
{
|
||||
memset(&cylinders, 0, sizeof(cylinders));
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
|
@ -828,7 +825,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive),
|
|||
|
||||
ReplanDive::~ReplanDive()
|
||||
{
|
||||
clear_cylinder_table(&cylinders);
|
||||
free(notes);
|
||||
}
|
||||
|
||||
|
@ -1124,7 +1120,6 @@ AddCylinder::AddCylinder(bool currentDiveOnly) :
|
|||
|
||||
AddCylinder::~AddCylinder()
|
||||
{
|
||||
free_cylinder(cyl);
|
||||
}
|
||||
|
||||
bool AddCylinder::workToBeDone()
|
||||
|
@ -1148,7 +1143,7 @@ void AddCylinder::redo()
|
|||
for (dive *d: dives) {
|
||||
int index = first_hidden_cylinder(d);
|
||||
indexes.push_back(index);
|
||||
add_cylinder(&d->cylinders, index, clone_cylinder(cyl));
|
||||
add_cylinder(&d->cylinders, index, cyl);
|
||||
update_cylinder_related_info(d);
|
||||
emit diveListNotifier.cylinderAdded(d, index);
|
||||
invalidate_dive_cache(d); // Ensure that dive is written in git_save()
|
||||
|
@ -1157,14 +1152,14 @@ void AddCylinder::redo()
|
|||
|
||||
static bool same_cylinder_type(const cylinder_t &cyl1, const cylinder_t &cyl2)
|
||||
{
|
||||
return same_string(cyl1.type.description, cyl2.type.description) &&
|
||||
cyl1.cylinder_use == cyl2.cylinder_use;
|
||||
return std::tie(cyl1.cylinder_use, cyl1.type.description) ==
|
||||
std::tie(cyl2.cylinder_use, cyl2.type.description);
|
||||
}
|
||||
|
||||
static bool same_cylinder_size(const cylinder_t &cyl1, const cylinder_t &cyl2)
|
||||
{
|
||||
return cyl1.type.size.mliter == cyl2.type.size.mliter &&
|
||||
cyl1.type.workingpressure.mbar == cyl2.type.workingpressure.mbar;
|
||||
return std::tie(cyl1.type.size.mliter, cyl1.type.workingpressure.mbar) ==
|
||||
std::tie(cyl2.type.size.mliter, cyl2.type.workingpressure.mbar);
|
||||
}
|
||||
|
||||
// Flags for comparing cylinders
|
||||
|
@ -1177,7 +1172,7 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt
|
|||
EditDivesBase(currentDiveOnly)
|
||||
{
|
||||
// Get the old cylinder, bail if index is invalid
|
||||
if (!current || index < 0 || index >= current->cylinders.nr) {
|
||||
if (!current || index < 0 || index >= static_cast<int>(current->cylinders.size())) {
|
||||
dives.clear();
|
||||
return;
|
||||
}
|
||||
|
@ -1189,12 +1184,12 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt
|
|||
cyl.reserve(dives.size());
|
||||
|
||||
for (dive *d: dives) {
|
||||
if (index >= d->cylinders.nr)
|
||||
if (index >= static_cast<int>(d->cylinders.size()))
|
||||
continue;
|
||||
if (nonProtectedOnly && is_cylinder_prot(d, index))
|
||||
continue;
|
||||
// We checked that the cylinder exists above.
|
||||
const cylinder_t &cylinder = *get_cylinder(d, index);
|
||||
const cylinder_t &cylinder = d->cylinders[index];
|
||||
if (d != current &&
|
||||
(!same_cylinder_size(orig, cylinder) || !same_cylinder_type(orig, cylinder))) {
|
||||
// when editing cylinders, we assume that the user wanted to edit the 'n-th' cylinder
|
||||
|
@ -1206,15 +1201,13 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt
|
|||
// that's silly as it's always the same value - but we need this vector of indices in the case where we add
|
||||
// a cylinder to several dives as the spot will potentially be different in different dives
|
||||
indexes.push_back(index);
|
||||
cyl.push_back(clone_cylinder(cylinder));
|
||||
cyl.push_back(cylinder);
|
||||
}
|
||||
dives = std::move(divesNew);
|
||||
}
|
||||
|
||||
EditCylinderBase::~EditCylinderBase()
|
||||
{
|
||||
for (cylinder_t c: cyl)
|
||||
free_cylinder(c);
|
||||
}
|
||||
|
||||
bool EditCylinderBase::workToBeDone()
|
||||
|
@ -1235,8 +1228,8 @@ RemoveCylinder::RemoveCylinder(int index, bool currentDiveOnly) :
|
|||
void RemoveCylinder::undo()
|
||||
{
|
||||
for (size_t i = 0; i < dives.size(); ++i) {
|
||||
std::vector<int> mapping = get_cylinder_map_for_add(dives[i]->cylinders.nr, indexes[i]);
|
||||
add_cylinder(&dives[i]->cylinders, indexes[i], clone_cylinder(cyl[i]));
|
||||
std::vector<int> mapping = get_cylinder_map_for_add(dives[i]->cylinders.size(), indexes[i]);
|
||||
add_cylinder(&dives[i]->cylinders, indexes[i], cyl[i]);
|
||||
cylinder_renumber(dives[i], &mapping[0]);
|
||||
update_cylinder_related_info(dives[i]);
|
||||
emit diveListNotifier.cylinderAdded(dives[i], indexes[i]);
|
||||
|
@ -1247,7 +1240,7 @@ void RemoveCylinder::undo()
|
|||
void RemoveCylinder::redo()
|
||||
{
|
||||
for (size_t i = 0; i < dives.size(); ++i) {
|
||||
std::vector<int> mapping = get_cylinder_map_for_remove(dives[i]->cylinders.nr, indexes[i]);
|
||||
std::vector<int> mapping = get_cylinder_map_for_remove(dives[i]->cylinders.size(), indexes[i]);
|
||||
remove_cylinder(dives[i], indexes[i]);
|
||||
cylinder_renumber(dives[i], &mapping[0]);
|
||||
update_cylinder_related_info(dives[i]);
|
||||
|
@ -1282,15 +1275,12 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
|
|||
else
|
||||
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
|
||||
|
||||
QString description = cylIn.type.description;
|
||||
|
||||
// The base class copied the cylinders for us, let's edit them
|
||||
for (int i = 0; i < (int)indexes.size(); ++i) {
|
||||
switch (type) {
|
||||
case EditCylinderType::TYPE:
|
||||
free((void *)cyl[i].type.description);
|
||||
cyl[i].type = cylIn.type;
|
||||
cyl[i].type.description = copy_qstring(description);
|
||||
cyl[i].type.description = cylIn.type.description;
|
||||
cyl[i].cylinder_use = cylIn.cylinder_use;
|
||||
break;
|
||||
case EditCylinderType::PRESSURE:
|
||||
|
@ -1301,7 +1291,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
|
|||
cyl[i].gasmix = cylIn.gasmix;
|
||||
cyl[i].bestmix_o2 = cylIn.bestmix_o2;
|
||||
cyl[i].bestmix_he = cylIn.bestmix_he;
|
||||
sanitize_gasmix(&cyl[i].gasmix);
|
||||
sanitize_gasmix(cyl[i].gasmix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1310,7 +1300,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
|
|||
void EditCylinder::redo()
|
||||
{
|
||||
for (size_t i = 0; i < dives.size(); ++i) {
|
||||
std::string name = cyl[i].type.description;
|
||||
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]);
|
||||
update_cylinder_related_info(dives[i]);
|
||||
|
|
|
@ -672,24 +672,22 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
|
|||
case TYPE_GEMINI:
|
||||
case TYPE_COMMANDER:
|
||||
if (config.type == TYPE_GEMINI) {
|
||||
cylinder_t cyl;
|
||||
dc->model = "Gemini";
|
||||
dc->deviceid = buf[0x18c] * 256 + buf[0x18d]; // serial no
|
||||
fill_default_cylinder(dive.get(), &cyl);
|
||||
cylinder_t cyl = default_cylinder(dive.get());
|
||||
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256
|
||||
+ log[CMD_O2_PERCENT + 1]) * 10;
|
||||
cyl.gasmix.he.permille = 0;
|
||||
add_cylinder(&dive->cylinders, 0, cyl);
|
||||
add_cylinder(&dive->cylinders, 0, std::move(cyl));
|
||||
} else {
|
||||
dc->model = "Commander";
|
||||
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
|
||||
for (g = 0; g < 2; g++) {
|
||||
cylinder_t cyl;
|
||||
fill_default_cylinder(dive.get(), &cyl);
|
||||
cylinder_t cyl = default_cylinder(dive.get());
|
||||
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256
|
||||
+ log[CMD_O2_PERCENT + g * 2 + 1]) * 10;
|
||||
cyl.gasmix.he.permille = 0;
|
||||
add_cylinder(&dive->cylinders, g, cyl);
|
||||
add_cylinder(&dive->cylinders, g, std::move(cyl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -727,15 +725,14 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
|
|||
dc->model = "EMC";
|
||||
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
|
||||
for (g = 0; g < 4; g++) {
|
||||
cylinder_t cyl;
|
||||
fill_default_cylinder(dive.get(), &cyl);
|
||||
cylinder_t cyl = default_cylinder(dive.get());
|
||||
cyl.gasmix.o2.permille =
|
||||
(log[EMC_O2_PERCENT + g * 2] / 256
|
||||
+ log[EMC_O2_PERCENT + g * 2 + 1]) * 10;
|
||||
cyl.gasmix.he.permille =
|
||||
(log[EMC_HE_PERCENT + g * 2] / 256
|
||||
+ log[EMC_HE_PERCENT + g * 2 + 1]) * 10;
|
||||
add_cylinder(&dive->cylinders, g, cyl);
|
||||
add_cylinder(&dive->cylinders, g, std::move(cyl));
|
||||
}
|
||||
|
||||
tm.tm_year = log[EMC_YEAR];
|
||||
|
|
|
@ -334,14 +334,13 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
read_bytes(2);
|
||||
if (tmp_2bytes != 0x7FFF) {
|
||||
cylinder_t cyl;
|
||||
std::string desc = cyl_type_by_size(tmp_2bytes * 10);
|
||||
cyl.type.size.mliter = tmp_2bytes * 10;
|
||||
cyl.type.description = desc.c_str();
|
||||
cyl.type.description = cyl_type_by_size(tmp_2bytes * 10);
|
||||
cyl.start.mbar = 200000;
|
||||
cyl.gasmix.he.permille = 0;
|
||||
cyl.gasmix.o2.permille = 210;
|
||||
cyl.manually_added = true;
|
||||
add_cloned_cylinder(&dt_dive->cylinders, cyl);
|
||||
dt_dive->cylinders.push_back(std::move(cyl));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -372,7 +371,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
* Air used in bar*100.
|
||||
*/
|
||||
read_bytes(2);
|
||||
if (tmp_2bytes != 0x7FFF && dt_dive->cylinders.nr > 0)
|
||||
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));
|
||||
|
||||
/*
|
||||
|
@ -548,10 +547,10 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
free(compl_buffer);
|
||||
goto bail;
|
||||
}
|
||||
if (is_nitrox && dt_dive->cylinders.nr > 0)
|
||||
if (is_nitrox && dt_dive->cylinders.size() > 0)
|
||||
get_cylinder(dt_dive, 0)->gasmix.o2.permille =
|
||||
lrint(membuf[23] & 0x0F ? 20.0 + 2 * (membuf[23] & 0x0F) : 21.0) * 10;
|
||||
if (is_O2 && dt_dive->cylinders.nr > 0)
|
||||
if (is_O2 && dt_dive->cylinders.size() > 0)
|
||||
get_cylinder(dt_dive, 0)->gasmix.o2.permille = membuf[23] * 10;
|
||||
free(compl_buffer);
|
||||
}
|
||||
|
@ -564,7 +563,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
dt_dive->dcs[0].deviceid = 0;
|
||||
else
|
||||
dt_dive->dcs[0].deviceid = 0xffffffff;
|
||||
if (!is_SCR && dt_dive->cylinders.nr > 0) {
|
||||
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);
|
||||
}
|
||||
|
|
255
core/dive.cpp
255
core/dive.cpp
|
@ -17,6 +17,7 @@
|
|||
#include "errorhelper.h"
|
||||
#include "event.h"
|
||||
#include "extradata.h"
|
||||
#include "format.h"
|
||||
#include "interpolate.h"
|
||||
#include "qthelper.h"
|
||||
#include "membuffer.h"
|
||||
|
@ -121,8 +122,8 @@ void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int second
|
|||
/* sanity check so we don't crash */
|
||||
/* FIXME: The planner uses a dummy cylinder one past the official number of cylinders
|
||||
* in the table to mark no-cylinder surface interavals. This is horrendous. Fix ASAP. */
|
||||
//if (idx < 0 || idx >= dive->cylinders.nr) {
|
||||
if (idx < 0 || idx >= dive->cylinders.nr + 1 || idx >= dive->cylinders.allocated) {
|
||||
//if (idx < 0 || idx >= dive->cylinders.size()) {
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size() + 1) {
|
||||
report_error("Unknown cylinder index: %d", idx);
|
||||
return;
|
||||
}
|
||||
|
@ -135,9 +136,7 @@ struct gasmix get_gasmix_from_event(const struct dive *dive, const struct event
|
|||
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 == dive->cylinders.nr)
|
||||
return gasmix_air;
|
||||
if (index >= 0 && index < dive->cylinders.nr)
|
||||
if (index >= 0 && static_cast<size_t>(index) < dive->cylinders.size() + 1)
|
||||
return get_cylinder(dive, index)->gasmix;
|
||||
return ev.gas.mix;
|
||||
}
|
||||
|
@ -176,8 +175,7 @@ static void free_dive_structures(struct dive *d)
|
|||
free(d->suit);
|
||||
/* free tags, additional dive computers, and pictures */
|
||||
taglist_free(d->tag_list);
|
||||
clear_cylinder_table(&d->cylinders);
|
||||
free(d->cylinders.cylinders);
|
||||
d->cylinders.clear();
|
||||
clear_weightsystem_table(&d->weightsystems);
|
||||
free(d->weightsystems.weightsystems);
|
||||
clear_picture_table(&d->pictures);
|
||||
|
@ -185,7 +183,7 @@ static void free_dive_structures(struct dive *d)
|
|||
}
|
||||
|
||||
/* copy_dive makes duplicates of many components of a dive;
|
||||
* in order not to leak memory, we need to free those .
|
||||
* in order not to leak memory, we need to free those.
|
||||
* copy_dive doesn't play with the divetrip and forward/backward pointers
|
||||
* so we can ignore those */
|
||||
void clear_dive(struct dive *d)
|
||||
|
@ -206,7 +204,6 @@ void copy_dive(const struct dive *s, struct dive *d)
|
|||
* relevant components that are referenced through pointers,
|
||||
* so all the strings and the structured lists */
|
||||
*d = *s;
|
||||
memset(&d->cylinders, 0, sizeof(d->cylinders));
|
||||
memset(&d->weightsystems, 0, sizeof(d->weightsystems));
|
||||
memset(&d->pictures, 0, sizeof(d->pictures));
|
||||
d->full_text = NULL;
|
||||
|
@ -215,7 +212,6 @@ void copy_dive(const struct dive *s, struct dive *d)
|
|||
d->diveguide = copy_string(s->diveguide);
|
||||
d->notes = copy_string(s->notes);
|
||||
d->suit = copy_string(s->suit);
|
||||
copy_cylinders(&s->cylinders, &d->cylinders);
|
||||
copy_weights(&s->weightsystems, &d->weightsystems);
|
||||
copy_pictures(&s->pictures, &d->pictures);
|
||||
d->tag_list = taglist_copy(s->tag_list);
|
||||
|
@ -293,11 +289,6 @@ void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int tim
|
|||
}
|
||||
}
|
||||
|
||||
int nr_cylinders(const struct dive *dive)
|
||||
{
|
||||
return dive->cylinders.nr;
|
||||
}
|
||||
|
||||
int nr_weightsystems(const struct dive *dive)
|
||||
{
|
||||
return dive->weightsystems.nr;
|
||||
|
@ -305,14 +296,13 @@ int nr_weightsystems(const struct dive *dive)
|
|||
|
||||
void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only)
|
||||
{
|
||||
int i;
|
||||
if (!s || !d)
|
||||
return;
|
||||
|
||||
clear_cylinder_table(&d->cylinders);
|
||||
for (i = 0; i < s->cylinders.nr; i++) {
|
||||
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)
|
||||
add_cloned_cylinder(&d->cylinders, *get_cylinder(s, i));
|
||||
d->cylinders.push_back(cyl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,12 +344,12 @@ static void update_temperature(temperature_t *temperature, int new_temp)
|
|||
|
||||
/* Which cylinders had gas used? */
|
||||
#define SOME_GAS 5000
|
||||
static bool cylinder_used(const cylinder_t *cyl)
|
||||
static bool cylinder_used(const cylinder_t &cyl)
|
||||
{
|
||||
int start_mbar, end_mbar;
|
||||
|
||||
start_mbar = cyl->start.mbar ?: cyl->sample_start.mbar;
|
||||
end_mbar = cyl->end.mbar ?: cyl->sample_end.mbar;
|
||||
start_mbar = cyl.start.mbar ?: cyl.sample_start.mbar;
|
||||
end_mbar = cyl.end.mbar ?: cyl.sample_end.mbar;
|
||||
|
||||
// More than 5 bar used? This matches statistics.cpp
|
||||
// heuristics
|
||||
|
@ -369,10 +359,10 @@ static bool cylinder_used(const cylinder_t *cyl)
|
|||
/* Get list of used cylinders. Returns the number of used cylinders. */
|
||||
static int get_cylinder_used(const struct dive *dive, bool used[])
|
||||
{
|
||||
int i, num = 0;
|
||||
int num = 0;
|
||||
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
used[i] = cylinder_used(get_cylinder(dive, i));
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
|
||||
used[i] = cylinder_used(cyl);
|
||||
if (used[i])
|
||||
num++;
|
||||
}
|
||||
|
@ -384,8 +374,8 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div
|
|||
const bool used_cylinders[], int num)
|
||||
{
|
||||
int idx;
|
||||
auto used_and_unknown = std::make_unique<bool[]>(dive->cylinders.nr);
|
||||
std::copy(used_cylinders, used_cylinders + dive->cylinders.nr, 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) {
|
||||
|
@ -419,16 +409,15 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div
|
|||
|
||||
void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration)
|
||||
{
|
||||
int i;
|
||||
int32_t lasttime = 0;
|
||||
int lastdepth = 0;
|
||||
int idx = 0;
|
||||
int num_used_cylinders;
|
||||
|
||||
if (dive->cylinders.nr <= 0)
|
||||
if (dive->cylinders.empty())
|
||||
return;
|
||||
|
||||
for (i = 0; i < dive->cylinders.nr; i++)
|
||||
for (size_t i = 0; i < dive->cylinders.size(); i++)
|
||||
mean[i] = duration[i] = 0;
|
||||
if (!dc)
|
||||
return;
|
||||
|
@ -438,7 +427,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
|
|||
* if we don't actually know about the usage of all the
|
||||
* used cylinders.
|
||||
*/
|
||||
auto used_cylinders = std::make_unique<bool[]>(dive->cylinders.nr);
|
||||
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)) {
|
||||
/*
|
||||
|
@ -453,7 +442,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
|
|||
* For a single cylinder, use the overall mean
|
||||
* and duration
|
||||
*/
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
for (size_t i = 0; i < dive->cylinders.size(); i++) {
|
||||
if (used_cylinders[i]) {
|
||||
mean[i] = dc->meandepth.mm;
|
||||
duration[i] = dc->duration.seconds;
|
||||
|
@ -466,7 +455,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
|
|||
fake_dc(dc);
|
||||
event_loop loop("gaschange");
|
||||
const struct event *ev = loop.next(*dc);
|
||||
std::vector<int> depthtime(dive->cylinders.nr, 0);
|
||||
std::vector<int> depthtime(dive->cylinders.size(), 0);
|
||||
for (auto it = dc->samples.begin(); it != dc->samples.end(); ++it) {
|
||||
int32_t time = it->time.seconds;
|
||||
int depth = it->depth.mm;
|
||||
|
@ -494,7 +483,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
|
|||
lastdepth = depth;
|
||||
lasttime = time;
|
||||
}
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
for (size_t i = 0; i < dive->cylinders.size(); i++) {
|
||||
if (duration[i])
|
||||
mean[i] = (depthtime[i] + duration[i] / 2) / duration[i];
|
||||
}
|
||||
|
@ -529,7 +518,7 @@ static int same_rounded_pressure(pressure_t a, pressure_t b)
|
|||
int explicit_first_cylinder(const struct dive *dive, const struct divecomputer *dc)
|
||||
{
|
||||
int res = 0;
|
||||
if (!dive->cylinders.nr)
|
||||
if (dive->cylinders.empty())
|
||||
return -1;
|
||||
if (dc) {
|
||||
const struct event *ev = get_first_event(*dc, "gaschange");
|
||||
|
@ -538,7 +527,7 @@ int explicit_first_cylinder(const struct dive *dive, const struct divecomputer *
|
|||
else if (dc->divemode == CCR)
|
||||
res = std::max(get_cylinder_idx_by_use(dive, DILUENT), res);
|
||||
}
|
||||
return res < dive->cylinders.nr ? res : 0;
|
||||
return static_cast<size_t>(res) < dive->cylinders.size() ? res : 0;
|
||||
}
|
||||
|
||||
/* this gets called when the dive mode has changed (so OC vs. CC)
|
||||
|
@ -598,22 +587,18 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
|
|||
* cylinder name is independent from the gasmix, and different
|
||||
* gasmixes have different compressibility.
|
||||
*/
|
||||
static void match_standard_cylinder(cylinder_type_t *type)
|
||||
static void match_standard_cylinder(cylinder_type_t &type)
|
||||
{
|
||||
double cuft, bar;
|
||||
int psi, len;
|
||||
const char *fmt;
|
||||
char buffer[40], *p;
|
||||
|
||||
/* Do we already have a cylinder description? */
|
||||
if (type->description)
|
||||
if (!type.description.empty())
|
||||
return;
|
||||
|
||||
bar = type->workingpressure.mbar / 1000.0;
|
||||
cuft = ml_to_cuft(type->size.mliter);
|
||||
double bar = type.workingpressure.mbar / 1000.0;
|
||||
double cuft = ml_to_cuft(type.size.mliter);
|
||||
cuft *= bar_to_atm(bar);
|
||||
psi = lrint(to_PSI(type->workingpressure));
|
||||
int psi = lrint(to_PSI(type.workingpressure));
|
||||
|
||||
const char *fmt;
|
||||
switch (psi) {
|
||||
case 2300 ... 2500: /* 2400 psi: LP tank */
|
||||
fmt = "LP%d";
|
||||
|
@ -633,12 +618,7 @@ static void match_standard_cylinder(cylinder_type_t *type)
|
|||
default:
|
||||
return;
|
||||
}
|
||||
len = snprintf(buffer, sizeof(buffer), fmt, (int)lrint(cuft));
|
||||
p = (char *)malloc(len + 1);
|
||||
if (!p)
|
||||
return;
|
||||
memcpy(p, buffer, len + 1);
|
||||
type->description = p;
|
||||
type.description = format_string_std(fmt, (int)lrint(cuft));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -651,14 +631,14 @@ static void match_standard_cylinder(cylinder_type_t *type)
|
|||
* We internally use physical size only. But we save the workingpressure
|
||||
* so that we can do the conversion if required.
|
||||
*/
|
||||
static void sanitize_cylinder_type(cylinder_type_t *type)
|
||||
static void sanitize_cylinder_type(cylinder_type_t &type)
|
||||
{
|
||||
/* If we have no working pressure, it had *better* be just a physical size! */
|
||||
if (!type->workingpressure.mbar)
|
||||
if (!type.workingpressure.mbar)
|
||||
return;
|
||||
|
||||
/* No size either? Nothing to go on */
|
||||
if (!type->size.mliter)
|
||||
if (!type.size.mliter)
|
||||
return;
|
||||
|
||||
/* Ok, we have both size and pressure: try to match a description */
|
||||
|
@ -667,11 +647,9 @@ static void sanitize_cylinder_type(cylinder_type_t *type)
|
|||
|
||||
static void sanitize_cylinder_info(struct dive *dive)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
sanitize_gasmix(&get_cylinder(dive, i)->gasmix);
|
||||
sanitize_cylinder_type(&get_cylinder(dive, i)->type);
|
||||
for (auto &cyl :dive->cylinders) {
|
||||
sanitize_gasmix(cyl.gasmix);
|
||||
sanitize_cylinder_type(cyl.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -935,19 +913,19 @@ static void simplify_dc_pressures(struct divecomputer &dc)
|
|||
/* Do we need a sensor -> cylinder mapping? */
|
||||
static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
|
||||
{
|
||||
if (idx >= 0 && idx < dive->cylinders.nr) {
|
||||
cylinder_t *cyl = get_cylinder(dive, idx);
|
||||
if (p.mbar && !cyl->sample_start.mbar)
|
||||
cyl->sample_start = p;
|
||||
if (idx >= 0 && static_cast<size_t>(idx) < dive->cylinders.size()) {
|
||||
cylinder_t &cyl = dive->cylinders[idx];
|
||||
if (p.mbar && !cyl.sample_start.mbar)
|
||||
cyl.sample_start = p;
|
||||
}
|
||||
}
|
||||
|
||||
static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
|
||||
{
|
||||
if (idx >= 0 && idx < dive->cylinders.nr) {
|
||||
cylinder_t *cyl = get_cylinder(dive, idx);
|
||||
if (p.mbar && !cyl->sample_end.mbar)
|
||||
cyl->sample_end = p;
|
||||
if (idx >= 0 && static_cast<size_t>(idx) < dive->cylinders.size()) {
|
||||
cylinder_t &cyl = dive->cylinders[idx];
|
||||
if (p.mbar && !cyl.sample_end.mbar)
|
||||
cyl.sample_end = p;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1003,13 +981,13 @@ static bool validate_gaschange(struct dive *dive, struct event &event)
|
|||
if (event.gas.index >= 0)
|
||||
return true;
|
||||
|
||||
index = find_best_gasmix_match(event.gas.mix, &dive->cylinders);
|
||||
if (index < 0 || index >= dive->cylinders.nr)
|
||||
index = find_best_gasmix_match(event.gas.mix, dive->cylinders);
|
||||
if (index < 0 || static_cast<size_t>(index) >= dive->cylinders.size())
|
||||
return false;
|
||||
|
||||
/* Fix up the event to have the right information */
|
||||
event.gas.index = index;
|
||||
event.gas.mix = get_cylinder(dive, index)->gasmix;
|
||||
event.gas.mix = dive->cylinders[index].gasmix;
|
||||
|
||||
/* Convert to odd libdivecomputer format */
|
||||
o2 = get_o2(event.gas.mix);
|
||||
|
@ -1094,7 +1072,7 @@ static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer &dc)
|
|||
}
|
||||
|
||||
// Ignore the sensors we have cylinders for
|
||||
sensor_mask >>= dive->cylinders.nr;
|
||||
sensor_mask >>= dive->cylinders.size();
|
||||
|
||||
// Do we need to add empty cylinders?
|
||||
while (sensor_mask) {
|
||||
|
@ -1160,13 +1138,12 @@ struct dive *fixup_dive(struct dive *dive)
|
|||
fixup_duration(dive);
|
||||
fixup_watertemp(dive);
|
||||
fixup_airtemp(dive);
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(dive, i);
|
||||
add_cylinder_description(cyl->type);
|
||||
if (same_rounded_pressure(cyl->sample_start, cyl->start))
|
||||
cyl->start.mbar = 0;
|
||||
if (same_rounded_pressure(cyl->sample_end, cyl->end))
|
||||
cyl->end.mbar = 0;
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
add_cylinder_description(cyl.type);
|
||||
if (same_rounded_pressure(cyl.sample_start, cyl.start))
|
||||
cyl.start.mbar = 0;
|
||||
if (same_rounded_pressure(cyl.sample_end, cyl.end))
|
||||
cyl.end.mbar = 0;
|
||||
}
|
||||
update_cylinder_related_info(dive);
|
||||
for (i = 0; i < dive->weightsystems.nr; i++) {
|
||||
|
@ -1487,12 +1464,9 @@ pick_b:
|
|||
* 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)
|
||||
{
|
||||
int cylinder_index;
|
||||
for (cylinder_index = 0; cylinder_index < dive->cylinders.nr; cylinder_index++) {
|
||||
if (get_cylinder(dive, cylinder_index)->cylinder_use == cylinder_use_type)
|
||||
return cylinder_index; // return the index of the cylinder with that cylinder use type
|
||||
}
|
||||
return -1; // negative number means cylinder_use_type not found in list of cylinders
|
||||
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 */
|
||||
|
@ -1580,13 +1554,13 @@ void cylinder_renumber(struct dive *dive, int mapping[])
|
|||
dc_cylinder_renumber(dive, dc, mapping);
|
||||
}
|
||||
|
||||
int same_gasmix_cylinder(const cylinder_t *cyl, int cylid, const struct dive *dive, bool check_unused)
|
||||
int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused)
|
||||
{
|
||||
struct gasmix mygas = cyl->gasmix;
|
||||
for (int i = 0; i < dive->cylinders.nr; i++) {
|
||||
struct gasmix mygas = cyl.gasmix;
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
|
||||
if (i == cylid)
|
||||
continue;
|
||||
struct gasmix gas2 = get_cylinder(dive, i)->gasmix;
|
||||
struct gasmix gas2 = cyl.gasmix;
|
||||
if (gasmix_distance(mygas, gas2) == 0 && (is_cylinder_used(dive, i) || check_unused))
|
||||
return i;
|
||||
}
|
||||
|
@ -1614,20 +1588,15 @@ static int different_manual_pressures(const cylinder_t *a, const cylinder_t *b)
|
|||
*/
|
||||
static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, const bool try_match[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
const cylinder_t *target;
|
||||
|
||||
for (auto [i, target]: enumerated_range(dive->cylinders)) {
|
||||
if (!try_match[i])
|
||||
continue;
|
||||
|
||||
target = get_cylinder(dive, i);
|
||||
if (!same_gasmix(cyl->gasmix, target->gasmix))
|
||||
if (!same_gasmix(cyl->gasmix, target.gasmix))
|
||||
continue;
|
||||
if (cyl->cylinder_use != target->cylinder_use)
|
||||
if (cyl->cylinder_use != target.cylinder_use)
|
||||
continue;
|
||||
if (different_manual_pressures(cyl, target))
|
||||
if (different_manual_pressures(cyl, &target))
|
||||
continue;
|
||||
|
||||
/* open question: Should we check sizes too? */
|
||||
|
@ -1679,8 +1648,8 @@ static void merge_one_cylinder(cylinder_t *a, const cylinder_t *b)
|
|||
a->type.size.mliter = b->type.size.mliter;
|
||||
if (!a->type.workingpressure.mbar)
|
||||
a->type.workingpressure.mbar = b->type.workingpressure.mbar;
|
||||
if (empty_string(a->type.description))
|
||||
a->type.description = copy_string(b->type.description);
|
||||
if (a->type.description.empty())
|
||||
a->type.description = b->type.description;
|
||||
|
||||
/* If either cylinder has manually entered pressures, try to merge them.
|
||||
* Use pressures from divecomputer samples if only one cylinder has such a value.
|
||||
|
@ -1697,24 +1666,24 @@ static void merge_one_cylinder(cylinder_t *a, const cylinder_t *b)
|
|||
a->bestmix_he = a->bestmix_he && b->bestmix_he;
|
||||
}
|
||||
|
||||
static bool cylinder_has_data(const cylinder_t *cyl)
|
||||
static bool cylinder_has_data(const cylinder_t &cyl)
|
||||
{
|
||||
return !cyl->type.size.mliter &&
|
||||
!cyl->type.workingpressure.mbar &&
|
||||
!cyl->type.description &&
|
||||
!cyl->gasmix.o2.permille &&
|
||||
!cyl->gasmix.he.permille &&
|
||||
!cyl->start.mbar &&
|
||||
!cyl->end.mbar &&
|
||||
!cyl->sample_start.mbar &&
|
||||
!cyl->sample_end.mbar &&
|
||||
!cyl->gas_used.mliter &&
|
||||
!cyl->deco_gas_used.mliter;
|
||||
return !cyl.type.size.mliter &&
|
||||
!cyl.type.workingpressure.mbar &&
|
||||
cyl.type.description.empty() &&
|
||||
!cyl.gasmix.o2.permille &&
|
||||
!cyl.gasmix.he.permille &&
|
||||
!cyl.start.mbar &&
|
||||
!cyl.end.mbar &&
|
||||
!cyl.sample_start.mbar &&
|
||||
!cyl.sample_end.mbar &&
|
||||
!cyl.gas_used.mliter &&
|
||||
!cyl.deco_gas_used.mliter;
|
||||
}
|
||||
|
||||
static bool cylinder_in_use(const struct dive *dive, int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= dive->cylinders.nr)
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size())
|
||||
return false;
|
||||
|
||||
/* This tests for gaschange events or pressure changes */
|
||||
|
@ -1722,7 +1691,7 @@ static bool cylinder_in_use(const struct dive *dive, int idx)
|
|||
return true;
|
||||
|
||||
/* This tests for typenames or gas contents */
|
||||
return cylinder_has_data(get_cylinder(dive, idx));
|
||||
return cylinder_has_data(dive->cylinders[idx]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1738,22 +1707,21 @@ static bool cylinder_in_use(const struct dive *dive, int idx)
|
|||
static void merge_cylinders(struct dive *res, const struct dive *a, const struct dive *b,
|
||||
int mapping_a[], int mapping_b[])
|
||||
{
|
||||
int i;
|
||||
int max_cylinders = a->cylinders.nr + b->cylinders.nr;
|
||||
size_t max_cylinders = a->cylinders.size() + b->cylinders.size();
|
||||
auto used_in_a = std::make_unique<bool[]>(max_cylinders);
|
||||
auto used_in_b = std::make_unique<bool[]>(max_cylinders);
|
||||
auto try_to_match = std::make_unique<bool[]>(max_cylinders);
|
||||
std::fill(try_to_match.get(), try_to_match.get() + max_cylinders, false);
|
||||
|
||||
/* First, clear all cylinders in destination */
|
||||
clear_cylinder_table(&res->cylinders);
|
||||
res->cylinders.clear();
|
||||
|
||||
/* Clear all cylinder mappings */
|
||||
std::fill(mapping_a, mapping_a + a->cylinders.nr, -1);
|
||||
std::fill(mapping_b, mapping_b + b->cylinders.nr, -1);
|
||||
std::fill(mapping_a, mapping_a + a->cylinders.size(), -1);
|
||||
std::fill(mapping_b, mapping_b + b->cylinders.size(), -1);
|
||||
|
||||
/* Calculate usage map of cylinders, clear matching map */
|
||||
for (i = 0; i < max_cylinders; i++) {
|
||||
for (size_t i = 0; i < max_cylinders; i++) {
|
||||
used_in_a[i] = cylinder_in_use(a, i);
|
||||
used_in_b[i] = cylinder_in_use(b, i);
|
||||
}
|
||||
|
@ -1762,20 +1730,20 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct
|
|||
* For each cylinder in 'a' that is used, copy it to 'res'.
|
||||
* These are also potential matches for 'b' to use.
|
||||
*/
|
||||
for (i = 0; i < max_cylinders; i++) {
|
||||
int res_nr = res->cylinders.nr;
|
||||
for (size_t i = 0; i < max_cylinders; i++) {
|
||||
size_t res_nr = res->cylinders.size();
|
||||
if (!used_in_a[i])
|
||||
continue;
|
||||
mapping_a[i] = res_nr;
|
||||
mapping_a[i] = static_cast<int>(res_nr);
|
||||
try_to_match[res_nr] = true;
|
||||
add_cloned_cylinder(&res->cylinders, *get_cylinder(a, i));
|
||||
res->cylinders.push_back(a->cylinders[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* For each cylinder in 'b' that is used, try to match it
|
||||
* with an existing cylinder in 'res' from 'a'
|
||||
*/
|
||||
for (i = 0; i < b->cylinders.nr; i++) {
|
||||
for (size_t i = 0; i < b->cylinders.size(); i++) {
|
||||
int j;
|
||||
|
||||
if (!used_in_b[i])
|
||||
|
@ -1785,9 +1753,9 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct
|
|||
|
||||
/* No match? Add it to the result */
|
||||
if (j < 0) {
|
||||
int res_nr = res->cylinders.nr;
|
||||
mapping_b[i] = res_nr;
|
||||
add_cloned_cylinder(&res->cylinders, *get_cylinder(b, i));
|
||||
size_t res_nr = res->cylinders.size();
|
||||
mapping_b[i] = static_cast<int>(res_nr);
|
||||
res->cylinders.push_back(b->cylinders[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2402,8 +2370,8 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset,
|
|||
taglist_merge(&res->tag_list, a->tag_list, b->tag_list);
|
||||
/* if we get dives without any gas / cylinder information in an import, make sure
|
||||
* that there is at leatst one entry in the cylinder map for that dive */
|
||||
auto cylinders_map_a = std::make_unique<int[]>(std::max(1, a->cylinders.nr));
|
||||
auto cylinders_map_b = std::make_unique<int[]>(std::max(1, b->cylinders.nr));
|
||||
auto cylinders_map_a = std::make_unique<int[]>(std::max(size_t(1), a->cylinders.size()));
|
||||
auto cylinders_map_b = std::make_unique<int[]>(std::max(size_t(1), b->cylinders.size()));
|
||||
merge_cylinders(res, a, b, cylinders_map_a.get(), cylinders_map_b.get());
|
||||
merge_equipment(res, a, b);
|
||||
merge_temperatures(res, a, b);
|
||||
|
@ -2456,7 +2424,7 @@ static void force_fixup_dive(struct dive *d)
|
|||
int old_mintemp = d->mintemp.mkelvin;
|
||||
int old_maxtemp = d->maxtemp.mkelvin;
|
||||
duration_t old_duration = d->duration;
|
||||
std::vector<start_end_pressure> old_pressures(d->cylinders.nr);
|
||||
std::vector<start_end_pressure> old_pressures(d->cylinders.size());
|
||||
|
||||
d->maxdepth.mm = 0;
|
||||
dc->maxdepth.mm = 0;
|
||||
|
@ -2465,12 +2433,11 @@ static void force_fixup_dive(struct dive *d)
|
|||
d->duration.seconds = 0;
|
||||
d->maxtemp.mkelvin = 0;
|
||||
d->mintemp.mkelvin = 0;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(d, i);
|
||||
old_pressures[i].start = cyl->start;
|
||||
old_pressures[i].end = cyl->end;
|
||||
cyl->start.mbar = 0;
|
||||
cyl->end.mbar = 0;
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
old_pressures[i].start = cyl.start;
|
||||
old_pressures[i].end = cyl.end;
|
||||
cyl.start.mbar = 0;
|
||||
cyl.end.mbar = 0;
|
||||
}
|
||||
|
||||
fixup_dive(d);
|
||||
|
@ -2489,11 +2456,11 @@ static void force_fixup_dive(struct dive *d)
|
|||
|
||||
if (!d->duration.seconds)
|
||||
d->duration = old_duration;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
if (!get_cylinder(d, i)->start.mbar)
|
||||
get_cylinder(d, i)->start = old_pressures[i].start;
|
||||
if (!get_cylinder(d, i)->end.mbar)
|
||||
get_cylinder(d, i)->end = old_pressures[i].end;
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (!cyl.start.mbar)
|
||||
cyl.start = old_pressures[i].start;
|
||||
if (!cyl.end.mbar)
|
||||
cyl.end = old_pressures[i].end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3171,7 +3138,7 @@ gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) :
|
|||
dive(d), dc(dc), last(gasmix_air), loop("gaschange")
|
||||
{
|
||||
/* if there is no cylinder, return air */
|
||||
if (dive.cylinders.nr <= 0)
|
||||
if (dive.cylinders.empty())
|
||||
return;
|
||||
|
||||
/* on first invocation, get initial gas mix and first event (if any) */
|
||||
|
@ -3183,7 +3150,7 @@ gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) :
|
|||
gasmix gasmix_loop::next(int time)
|
||||
{
|
||||
/* if there is no cylinder, return air */
|
||||
if (dive.cylinders.nr <= 0)
|
||||
if (dive.cylinders.empty())
|
||||
return last;
|
||||
|
||||
while (ev && ev->time.seconds <= time) {
|
||||
|
|
|
@ -30,7 +30,7 @@ struct dive {
|
|||
struct dive_site *dive_site = nullptr;
|
||||
char *notes = nullptr;
|
||||
char *diveguide = nullptr, *buddy = nullptr;
|
||||
struct cylinder_table cylinders = { };
|
||||
struct cylinder_table cylinders;
|
||||
struct weightsystem_table weightsystems = { };
|
||||
char *suit = nullptr;
|
||||
int number = 0;
|
||||
|
@ -74,7 +74,7 @@ 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);
|
||||
extern int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused);
|
||||
|
||||
/* when selectively copying dive information, which parts should be copied? */
|
||||
struct dive_components {
|
||||
|
@ -190,7 +190,6 @@ extern struct event create_gas_switch_event(struct dive *dive, struct divecomput
|
|||
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 int nr_cylinders(const struct dive *dive);
|
||||
extern int nr_weightsystems(const struct dive *dive);
|
||||
extern bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id);
|
||||
|
||||
|
|
|
@ -32,19 +32,17 @@
|
|||
*/
|
||||
void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2max_p)
|
||||
{
|
||||
int i;
|
||||
int maxo2 = -1, maxhe = -1, mino2 = 1000;
|
||||
|
||||
for (i = 0; i < dive->cylinders.nr; i++) {
|
||||
const cylinder_t *cyl = get_cylinder(dive, i);
|
||||
int o2 = get_o2(cyl->gasmix);
|
||||
int he = get_he(cyl->gasmix);
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
|
||||
int o2 = get_o2(cyl.gasmix);
|
||||
int he = get_he(cyl.gasmix);
|
||||
|
||||
if (!is_cylinder_used(dive, i))
|
||||
continue;
|
||||
if (cyl->cylinder_use == OXYGEN)
|
||||
if (cyl.cylinder_use == OXYGEN)
|
||||
continue;
|
||||
if (cyl->cylinder_use == NOT_USED)
|
||||
if (cyl.cylinder_use == NOT_USED)
|
||||
continue;
|
||||
if (o2 > maxo2)
|
||||
maxo2 = o2;
|
||||
|
@ -337,12 +335,11 @@ static double calculate_airuse(const struct dive *dive)
|
|||
if (dive->dcs[0].divemode == CCR)
|
||||
return 0.0;
|
||||
|
||||
for (int i = 0; i < dive->cylinders.nr; i++) {
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders)) {
|
||||
pressure_t start, end;
|
||||
const cylinder_t *cyl = get_cylinder(dive, i);
|
||||
|
||||
start = cyl->start.mbar ? cyl->start : cyl->sample_start;
|
||||
end = cyl->end.mbar ? cyl->end : cyl->sample_end;
|
||||
start = cyl.start.mbar ? cyl.start : cyl.sample_start;
|
||||
end = cyl.end.mbar ? cyl.end : cyl.sample_end;
|
||||
if (!end.mbar || start.mbar <= end.mbar) {
|
||||
// If a cylinder is used but we do not have info on amout of gas used
|
||||
// better not pretend we know the total gas use.
|
||||
|
@ -354,7 +351,7 @@ static double calculate_airuse(const struct dive *dive)
|
|||
continue;
|
||||
}
|
||||
|
||||
airuse += gas_volume(cyl, start) - gas_volume(cyl, end);
|
||||
airuse += gas_volume(&cyl, start) - gas_volume(&cyl, end);
|
||||
}
|
||||
return airuse / 1000.0;
|
||||
}
|
||||
|
|
|
@ -18,9 +18,43 @@
|
|||
#include "divelog.h"
|
||||
#include "errorhelper.h"
|
||||
#include "pref.h"
|
||||
#include "range.h"
|
||||
#include "subsurface-string.h"
|
||||
#include "table.h"
|
||||
|
||||
cylinder_t::cylinder_t() = default;
|
||||
cylinder_t::~cylinder_t() = default;
|
||||
|
||||
static cylinder_t make_surface_air_cylinder()
|
||||
{
|
||||
cylinder_t res;
|
||||
res.cylinder_use = NOT_USED;
|
||||
return res;
|
||||
}
|
||||
static const cylinder_t surface_air_cylinder = make_surface_air_cylinder();
|
||||
|
||||
static void warn_index(size_t i, size_t max)
|
||||
{
|
||||
if (i >= max + 1) {
|
||||
report_info("Warning: accessing invalid cylinder %lu (%lu existing)",
|
||||
static_cast<unsigned long>(i), static_cast<unsigned long>(max));
|
||||
}
|
||||
}
|
||||
|
||||
cylinder_t &cylinder_table::operator[](size_t i)
|
||||
{
|
||||
warn_index(i, size());
|
||||
return i < size() ? std::vector<cylinder_t>::operator[](i)
|
||||
: const_cast<cylinder_t &>(surface_air_cylinder);
|
||||
}
|
||||
|
||||
const cylinder_t &cylinder_table::operator[](size_t i) const
|
||||
{
|
||||
warn_index(i, size());
|
||||
return i < size() ? std::vector<cylinder_t>::operator[](i)
|
||||
: surface_air_cylinder;
|
||||
}
|
||||
|
||||
/* Warning: this has strange semantics for C-code! Not the weightsystem object
|
||||
* is freed, but the data it references. The object itself is passed in by value.
|
||||
* This is due to the fact how the table macros work.
|
||||
|
@ -31,12 +65,6 @@ void free_weightsystem(weightsystem_t ws)
|
|||
ws.description = NULL;
|
||||
}
|
||||
|
||||
void free_cylinder(cylinder_t c)
|
||||
{
|
||||
free((void *)c.type.description);
|
||||
c.type.description = NULL;
|
||||
}
|
||||
|
||||
void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d)
|
||||
{
|
||||
clear_weightsystem_table(d);
|
||||
|
@ -44,14 +72,6 @@ void copy_weights(const struct weightsystem_table *s, struct weightsystem_table
|
|||
add_cloned_weightsystem(d, s->weightsystems[i]);
|
||||
}
|
||||
|
||||
void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d)
|
||||
{
|
||||
int i;
|
||||
clear_cylinder_table(d);
|
||||
for (i = 0; i < s->nr; i++)
|
||||
add_cloned_cylinder(d, s->cylinders[i]);
|
||||
}
|
||||
|
||||
/* weightsystem table functions */
|
||||
//static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems)
|
||||
static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems)
|
||||
|
@ -62,16 +82,6 @@ static MAKE_REMOVE_FROM(weightsystem_table, weightsystems)
|
|||
//MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem)
|
||||
MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem)
|
||||
|
||||
/* cylinder table functions */
|
||||
//static MAKE_GET_IDX(cylinder_table, cylinder_t, cylinders)
|
||||
static MAKE_GROW_TABLE(cylinder_table, cylinder_t, cylinders)
|
||||
//static MAKE_GET_INSERTION_INDEX(cylinder_table, cylinder_t, cylinders, cylinder_less_than)
|
||||
static MAKE_ADD_TO(cylinder_table, cylinder_t, cylinders)
|
||||
static MAKE_REMOVE_FROM(cylinder_table, cylinders)
|
||||
//MAKE_SORT(cylinder_table, cylinder_t, cylinders, comp_cylinders)
|
||||
//MAKE_REMOVE(cylinder_table, cylinder_t, cylinder)
|
||||
MAKE_CLEAR_TABLE(cylinder_table, cylinders, cylinder)
|
||||
|
||||
const char *cylinderuse_text[NUM_GAS_USE] = {
|
||||
QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used")
|
||||
};
|
||||
|
@ -144,11 +154,11 @@ std::pair<volume_t, pressure_t> get_tank_info_data(const std::vector<tank_info>
|
|||
|
||||
void add_cylinder_description(const cylinder_type_t &type)
|
||||
{
|
||||
std::string desc = type.description ? type.description : std::string();
|
||||
const std::string &desc = type.description;
|
||||
if (desc.empty())
|
||||
return;
|
||||
if (std::any_of(tank_info_table.begin(), tank_info_table.end(),
|
||||
[&type](const tank_info &info) { return info.name == type.description; }))
|
||||
[&desc](const tank_info &info) { return info.name == desc; }))
|
||||
return;
|
||||
add_tank_info_metric(tank_info_table, desc, type.size.mliter,
|
||||
type.workingpressure.mbar / 1000);
|
||||
|
@ -191,30 +201,16 @@ void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws)
|
|||
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
|
||||
}
|
||||
|
||||
cylinder_t clone_cylinder(cylinder_t cyl)
|
||||
/* Add a clone of a weightsystem to the end of a weightsystem table.
|
||||
* Cloned means that the description-string is copied. */
|
||||
void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws)
|
||||
{
|
||||
cylinder_t res = cyl;
|
||||
res.type.description = copy_string(res.type.description);
|
||||
return res;
|
||||
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
|
||||
}
|
||||
|
||||
void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl)
|
||||
{
|
||||
add_to_cylinder_table(t, idx, cyl);
|
||||
/* FIXME: This is a horrible hack: we make sure that at the end of
|
||||
* every single cylinder table there is an empty cylinder that can
|
||||
* be used by the planner as "surface air" cylinder. Fix this.
|
||||
*/
|
||||
add_to_cylinder_table(t, t->nr, cylinder_t());
|
||||
t->nr--;
|
||||
t->cylinders[t->nr].cylinder_use = NOT_USED;
|
||||
}
|
||||
|
||||
/* Add a clone of a cylinder to the end of a cylinder table.
|
||||
* Cloned means that the description-string is copied. */
|
||||
void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl)
|
||||
{
|
||||
add_cylinder(t, t->nr, clone_cylinder(cyl));
|
||||
t->insert(t->begin() + idx, std::move(cyl));
|
||||
}
|
||||
|
||||
bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
|
||||
|
@ -250,17 +246,12 @@ int gas_volume(const cylinder_t *cyl, pressure_t p)
|
|||
return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
|
||||
}
|
||||
|
||||
int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders)
|
||||
int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table &cylinders)
|
||||
{
|
||||
int i;
|
||||
int best = -1, score = INT_MAX;
|
||||
|
||||
for (i = 0; i < cylinders->nr; i++) {
|
||||
const cylinder_t *match;
|
||||
int distance;
|
||||
|
||||
match = cylinders->cylinders + i;
|
||||
distance = gasmix_distance(mix, match->gasmix);
|
||||
for (auto [i, match]: enumerated_range(cylinders)) {
|
||||
int distance = gasmix_distance(mix, match.gasmix);
|
||||
if (distance >= score)
|
||||
continue;
|
||||
best = i;
|
||||
|
@ -336,10 +327,8 @@ void reset_tank_info_table(std::vector<tank_info> &table)
|
|||
/* Add cylinders from dive list */
|
||||
for (int i = 0; i < divelog.dives->nr; ++i) {
|
||||
const struct dive *dive = divelog.dives->dives[i];
|
||||
for (int j = 0; j < dive->cylinders.nr; j++) {
|
||||
const cylinder_t *cyl = get_cylinder(dive, j);
|
||||
add_cylinder_description(cyl->type);
|
||||
}
|
||||
for (auto &cyl: dive->cylinders)
|
||||
add_cylinder_description(cyl.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,7 +346,7 @@ struct std::vector<ws_info> ws_info_table = {
|
|||
|
||||
void remove_cylinder(struct dive *dive, int idx)
|
||||
{
|
||||
remove_from_cylinder_table(&dive->cylinders, idx);
|
||||
dive->cylinders.erase(dive->cylinders.begin() + idx);
|
||||
}
|
||||
|
||||
void remove_weightsystem(struct dive *dive, int idx)
|
||||
|
@ -380,68 +369,61 @@ void reset_cylinders(struct dive *dive, bool track_gas)
|
|||
{
|
||||
pressure_t decopo2 = {.mbar = prefs.decopo2};
|
||||
|
||||
for (int i = 0; i < dive->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(dive, i);
|
||||
if (cyl->depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */
|
||||
cyl->depth = gas_mod(cyl->gasmix, decopo2, dive, M_OR_FT(3,10));
|
||||
for (cylinder_t &cyl: dive->cylinders) {
|
||||
if (cyl.depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */
|
||||
cyl.depth = gas_mod(cyl.gasmix, decopo2, dive, M_OR_FT(3,10));
|
||||
if (track_gas)
|
||||
cyl->start.mbar = cyl->end.mbar = cyl->type.workingpressure.mbar;
|
||||
cyl->gas_used.mliter = 0;
|
||||
cyl->deco_gas_used.mliter = 0;
|
||||
cyl.start.mbar = cyl.end.mbar = cyl.type.workingpressure.mbar;
|
||||
cyl.gas_used.mliter = 0;
|
||||
cyl.deco_gas_used.mliter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_cylinder_type(const cylinder_t *s, cylinder_t *d)
|
||||
static void copy_cylinder_type(const cylinder_t &s, cylinder_t &d)
|
||||
{
|
||||
free_cylinder(*d);
|
||||
d->type = s->type;
|
||||
d->type.description = s->type.description ? strdup(s->type.description) : NULL;
|
||||
d->gasmix = s->gasmix;
|
||||
d->depth = s->depth;
|
||||
d->cylinder_use = s->cylinder_use;
|
||||
d->manually_added = true;
|
||||
d.type = s.type;
|
||||
d.gasmix = s.gasmix;
|
||||
d.depth = s.depth;
|
||||
d.cylinder_use = s.cylinder_use;
|
||||
d.manually_added = true;
|
||||
}
|
||||
|
||||
/* copy the equipment data part of the cylinders but keep pressures */
|
||||
void copy_cylinder_types(const struct dive *s, struct dive *d)
|
||||
{
|
||||
int i;
|
||||
if (!s || !d)
|
||||
return;
|
||||
|
||||
for (i = 0; i < s->cylinders.nr && i < d->cylinders.nr; i++)
|
||||
copy_cylinder_type(get_cylinder(s, i), get_cylinder(d, i));
|
||||
for (size_t i = 0; i < s->cylinders.size() && i < d->cylinders.size(); i++)
|
||||
copy_cylinder_type(s->cylinders[i], d->cylinders[i]);
|
||||
|
||||
for ( ; i < s->cylinders.nr; i++)
|
||||
add_cloned_cylinder(&d->cylinders, *get_cylinder(s, i));
|
||||
for (size_t i = d->cylinders.size(); i < s->cylinders.size(); i++)
|
||||
d->cylinders.push_back(s->cylinders[i]);
|
||||
}
|
||||
|
||||
cylinder_t *add_empty_cylinder(struct cylinder_table *t)
|
||||
{
|
||||
cylinder_t cyl;
|
||||
cyl.type.description = strdup("");
|
||||
add_cylinder(t, t->nr, cyl);
|
||||
return &t->cylinders[t->nr - 1];
|
||||
t->emplace_back();
|
||||
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 NULL returned.
|
||||
* 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(const struct dive *d, int idx)
|
||||
cylinder_t *get_cylinder(struct dive *d, int idx)
|
||||
{
|
||||
/* FIXME: The planner uses a dummy cylinder one past the official number of cylinders
|
||||
* in the table to mark no-cylinder surface interavals. This is horrendous. Fix ASAP. */
|
||||
// if (idx < 0 || idx >= d->cylinders.nr) {
|
||||
if (idx < 0 || idx >= d->cylinders.nr + 1 || idx >= d->cylinders.allocated) {
|
||||
report_info("Warning: accessing invalid cylinder %d (%d existing)", idx, d->cylinders.nr);
|
||||
return NULL;
|
||||
}
|
||||
return &d->cylinders.cylinders[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)
|
||||
|
@ -450,9 +432,9 @@ cylinder_t *get_or_create_cylinder(struct dive *d, int idx)
|
|||
report_info("Warning: accessing invalid cylinder %d", idx);
|
||||
return NULL;
|
||||
}
|
||||
while (idx >= d->cylinders.nr)
|
||||
while (static_cast<size_t>(idx) >= d->cylinders.size())
|
||||
add_empty_cylinder(&d->cylinders);
|
||||
return &d->cylinders.cylinders[idx];
|
||||
return &d->cylinders[idx];
|
||||
}
|
||||
|
||||
/* if a default cylinder is set, use that */
|
||||
|
@ -465,7 +447,7 @@ void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl)
|
|||
return;
|
||||
for (auto &ti: tank_info_table) {
|
||||
if (ti.name == cyl_name) {
|
||||
cyl->type.description = strdup(ti.name.c_str());
|
||||
cyl->type.description = ti.name;
|
||||
if (ti.ml) {
|
||||
cyl->type.size.mliter = ti.ml;
|
||||
cyl->type.workingpressure.mbar = ti.bar * 1000;
|
||||
|
@ -481,10 +463,16 @@ void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl)
|
|||
}
|
||||
}
|
||||
|
||||
cylinder_t default_cylinder(const struct dive *d)
|
||||
{
|
||||
cylinder_t res;
|
||||
fill_default_cylinder(d, &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
cylinder_t create_new_cylinder(const struct dive *d)
|
||||
{
|
||||
cylinder_t cyl;
|
||||
fill_default_cylinder(d, &cyl);
|
||||
cylinder_t cyl = default_cylinder(d);
|
||||
cyl.start = cyl.type.workingpressure;
|
||||
cyl.cylinder_use = OC_GAS;
|
||||
return cyl;
|
||||
|
@ -500,7 +488,7 @@ cylinder_t create_new_manual_cylinder(const struct dive *d)
|
|||
void add_default_cylinder(struct dive *d)
|
||||
{
|
||||
// Only add if there are no cylinders yet
|
||||
if (d->cylinders.nr > 0)
|
||||
if (!d->cylinders.empty())
|
||||
return;
|
||||
|
||||
cylinder_t cyl;
|
||||
|
@ -508,7 +496,7 @@ void add_default_cylinder(struct dive *d)
|
|||
cyl = create_new_cylinder(d);
|
||||
} else {
|
||||
// roughly an AL80
|
||||
cyl.type.description = strdup(translate("gettextFromC", "unknown"));
|
||||
cyl.type.description = translate("gettextFromC", "unknown");
|
||||
cyl.type.size.mliter = 11100;
|
||||
cyl.type.workingpressure.mbar = 207000;
|
||||
}
|
||||
|
@ -521,11 +509,11 @@ static bool show_cylinder(const struct dive *d, int i)
|
|||
if (is_cylinder_used(d, i))
|
||||
return true;
|
||||
|
||||
const cylinder_t *cyl = &d->cylinders.cylinders[i];
|
||||
if (cyl->start.mbar || cyl->sample_start.mbar ||
|
||||
cyl->end.mbar || cyl->sample_end.mbar)
|
||||
const cylinder_t &cyl = d->cylinders[i];
|
||||
if (cyl.start.mbar || cyl.sample_start.mbar ||
|
||||
cyl.end.mbar || cyl.sample_end.mbar)
|
||||
return true;
|
||||
if (cyl->manually_added)
|
||||
if (cyl.manually_added)
|
||||
return true;
|
||||
|
||||
/*
|
||||
|
@ -538,10 +526,10 @@ static bool show_cylinder(const struct dive *d, int i)
|
|||
/* The unused cylinders at the end of the cylinder list are hidden. */
|
||||
int first_hidden_cylinder(const struct dive *d)
|
||||
{
|
||||
int res = d->cylinders.nr;
|
||||
size_t res = d->cylinders.size();
|
||||
while (res > 0 && !show_cylinder(d, res - 1))
|
||||
--res;
|
||||
return res;
|
||||
return static_cast<int>(res);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CYL
|
||||
|
@ -551,7 +539,7 @@ void dump_cylinders(struct dive *dive, bool verbose)
|
|||
for (int i = 0; i < dive->cylinders; i++) {
|
||||
cylinder_t *cyl = get_cylinder(dive, i);
|
||||
|
||||
printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description, cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0);
|
||||
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);
|
||||
printf(" Pressure Start %3.0fbar End %3.0fbar Sample start %3.0fbar Sample end %3.0fbar\n", cyl->start.mbar / 1000.0, cyl->end.mbar / 1000.0, cyl->sample_start.mbar / 1000.0, cyl->sample_end.mbar / 1000.0);
|
||||
if (verbose) {
|
||||
|
|
|
@ -17,7 +17,7 @@ struct cylinder_type_t
|
|||
{
|
||||
volume_t size;
|
||||
pressure_t workingpressure;
|
||||
const char *description = nullptr; /* "LP85", "AL72", "AL80", "HP100+" or whatever */
|
||||
std::string description; /* "LP85", "AL72", "AL80", "HP100+" or whatever */
|
||||
};
|
||||
|
||||
struct cylinder_t
|
||||
|
@ -32,17 +32,23 @@ struct cylinder_t
|
|||
enum cylinderuse cylinder_use = OC_GAS;
|
||||
bool bestmix_o2 = false;
|
||||
bool bestmix_he = false;
|
||||
|
||||
cylinder_t();
|
||||
~cylinder_t();
|
||||
};
|
||||
|
||||
/* Table of cylinders. Attention: this stores cylinders,
|
||||
* *not* pointers to cylinders. This has two crucial consequences:
|
||||
* 1) Pointers to cylinders are not stable. They may be
|
||||
* invalidated if the table is reallocated.
|
||||
* 2) add_cylinder(), etc. take ownership of the
|
||||
* cylinder. Notably of the description string. */
|
||||
struct cylinder_table {
|
||||
int nr, allocated;
|
||||
cylinder_t *cylinders;
|
||||
/* Table of cylinders.
|
||||
* This is a crazy class: it is basically a std::vector<>, but overrides
|
||||
* the [] accessor functions and allows out-of-bound accesses.
|
||||
* This is used in the planner, which uses "max_index + 1" for the
|
||||
* surface air cylinder.
|
||||
* Note: an out-of-bound access returns a reference to an object with
|
||||
* static linkage that MUST NOT be written into.
|
||||
* Yes, this is all very mad, but it grew historically.
|
||||
*/
|
||||
struct cylinder_table : public std::vector<cylinder_t> {
|
||||
cylinder_t &operator[](size_t i);
|
||||
const cylinder_t &operator[](size_t i) const;
|
||||
};
|
||||
|
||||
struct weightsystem_t
|
||||
|
@ -68,16 +74,13 @@ struct weightsystem_table {
|
|||
|
||||
extern enum cylinderuse cylinderuse_from_text(const char *text);
|
||||
extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d);
|
||||
extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d);
|
||||
extern weightsystem_t clone_weightsystem(weightsystem_t ws);
|
||||
extern void free_weightsystem(weightsystem_t ws);
|
||||
extern void copy_cylinder_types(const struct dive *s, struct dive *d);
|
||||
extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws);
|
||||
extern cylinder_t clone_cylinder(cylinder_t cyl);
|
||||
extern void free_cylinder(cylinder_t cyl);
|
||||
extern cylinder_t *add_empty_cylinder(struct cylinder_table *t);
|
||||
extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl);
|
||||
extern cylinder_t *get_cylinder(const struct dive *d, int idx);
|
||||
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);
|
||||
|
@ -85,8 +88,9 @@ extern void remove_weightsystem(struct dive *dive, int idx);
|
|||
extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws);
|
||||
extern void reset_cylinders(struct dive *dive, bool track_gas);
|
||||
extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */
|
||||
extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders);
|
||||
extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table &cylinders);
|
||||
extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); /* dive is needed to fill out MOD, which depends on salinity. */
|
||||
extern cylinder_t default_cylinder(const struct dive *d);
|
||||
extern cylinder_t create_new_manual_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */
|
||||
extern void add_default_cylinder(struct dive *dive);
|
||||
extern int first_hidden_cylinder(const struct dive *d);
|
||||
|
@ -99,7 +103,6 @@ extern void clear_weightsystem_table(struct weightsystem_table *);
|
|||
extern void add_to_weightsystem_table(struct weightsystem_table *, int idx, weightsystem_t ws);
|
||||
|
||||
/* Cylinder table functions */
|
||||
extern void clear_cylinder_table(struct cylinder_table *);
|
||||
extern void add_cylinder(struct cylinder_table *, int idx, cylinder_t cyl);
|
||||
|
||||
void get_gas_string(struct gasmix gasmix, char *text, int len);
|
||||
|
|
|
@ -857,8 +857,8 @@ static bool has_weight_type(const filter_constraint &c, const struct dive *d)
|
|||
static bool has_cylinder_type(const filter_constraint &c, const struct dive *d)
|
||||
{
|
||||
QStringList cylinderTypes;
|
||||
for (int i = 0; i < d->cylinders.nr; ++i)
|
||||
cylinderTypes.push_back(d->cylinders.cylinders[i].type.description);
|
||||
for (const cylinder_t &cyl: d->cylinders)
|
||||
cylinderTypes.push_back(QString::fromStdString(cyl.type.description));
|
||||
|
||||
return check(c, cylinderTypes);
|
||||
}
|
||||
|
@ -904,22 +904,15 @@ static bool check_numerical_range_non_zero(const filter_constraint &c, int v)
|
|||
|
||||
static bool check_cylinder_size(const filter_constraint &c, const struct dive *d)
|
||||
{
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
const cylinder_t &cyl = d->cylinders.cylinders[i];
|
||||
if (cyl.type.size.mliter && check_numerical_range(c, cyl.type.size.mliter))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return std::any_of(d->cylinders.begin(), d->cylinders.end(), [&c](auto &cyl)
|
||||
{ return cyl.type.size.mliter &&
|
||||
check_numerical_range(c, cyl.type.size.mliter); });
|
||||
}
|
||||
|
||||
static bool check_gas_range(const filter_constraint &c, const struct dive *d, gas_component component)
|
||||
{
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
const cylinder_t &cyl = d->cylinders.cylinders[i];
|
||||
if (check_numerical_range(c, get_gas_component_fraction(cyl.gasmix, component).permille))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return std::any_of(d->cylinders.begin(), d->cylinders.end(), [&c, &component](auto &cyl)
|
||||
{ return check_numerical_range(c, get_gas_component_fraction(cyl.gasmix, component).permille); });
|
||||
}
|
||||
|
||||
static long days_since_epoch(timestamp_t timestamp)
|
||||
|
|
|
@ -125,10 +125,8 @@ static std::vector<QString> getWords(const dive *d)
|
|||
tokenize(QString(d->suit), res);
|
||||
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
||||
tokenize(QString::fromStdString(tag->tag->name), res);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
const cylinder_t &cyl = *get_cylinder(d, i);
|
||||
tokenize(QString(cyl.type.description), res);
|
||||
}
|
||||
for (auto &cyl: d->cylinders)
|
||||
tokenize(QString::fromStdString(cyl.type.description), res);
|
||||
for (int i = 0; i < d->weightsystems.nr; ++i) {
|
||||
const weightsystem_t &ws = d->weightsystems.weightsystems[i];
|
||||
tokenize(QString(ws.description), res);
|
||||
|
|
12
core/gas.cpp
12
core/gas.cpp
|
@ -40,20 +40,20 @@ int same_gasmix(struct gasmix a, struct gasmix b)
|
|||
return get_o2(a) == get_o2(b) && get_he(a) == get_he(b);
|
||||
}
|
||||
|
||||
void sanitize_gasmix(struct gasmix *mix)
|
||||
void sanitize_gasmix(struct gasmix &mix)
|
||||
{
|
||||
unsigned int o2, he;
|
||||
|
||||
o2 = get_o2(*mix);
|
||||
he = get_he(*mix);
|
||||
o2 = get_o2(mix);
|
||||
he = get_he(mix);
|
||||
|
||||
/* Regular air: leave empty */
|
||||
if (!he) {
|
||||
if (!o2)
|
||||
return;
|
||||
/* 20.8% to 21% O2 is just air */
|
||||
if (gasmix_is_air(*mix)) {
|
||||
mix->o2.permille = 0;
|
||||
if (gasmix_is_air(mix)) {
|
||||
mix.o2.permille = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ void sanitize_gasmix(struct gasmix *mix)
|
|||
if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000)
|
||||
return;
|
||||
report_info("Odd gasmix: %u O2 %u He", o2, he);
|
||||
*mix = gasmix_air;
|
||||
mix = gasmix_air;
|
||||
}
|
||||
|
||||
int gasmix_distance(struct gasmix a, struct gasmix b)
|
||||
|
|
|
@ -58,7 +58,7 @@ struct gas_pressures {
|
|||
double o2 = 0.0, n2 = 0.0, he = 0.0;
|
||||
};
|
||||
|
||||
extern void sanitize_gasmix(struct gasmix *mix);
|
||||
extern void sanitize_gasmix(struct gasmix &mix);
|
||||
extern int gasmix_distance(struct gasmix a, struct gasmix b);
|
||||
extern fraction_t get_gas_component_fraction(struct gasmix mix, enum gas_component component);
|
||||
extern gas_pressures fill_pressures(double amb_pressure, struct gasmix mix, double po2, enum divemode_t dctype);
|
||||
|
|
|
@ -310,13 +310,13 @@ 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;
|
||||
cylinder_t *cylinder = get_cylinder(dive, sensor);
|
||||
const cylinder_t *cylinder = get_cylinder(dive, sensor);
|
||||
std::vector<pr_track_t> track;
|
||||
size_t current = std::string::npos;
|
||||
int missing_pr = 0, dense = 1;
|
||||
const double gasfactor[5] = {1.0, 0.0, prefs.pscr_ratio/1000.0, 1.0, 1.0 };
|
||||
|
||||
if (sensor < 0 || sensor >= dive->cylinders.nr)
|
||||
if (sensor < 0 || static_cast<size_t>(sensor) >= dive->cylinders.size())
|
||||
return;
|
||||
|
||||
/* if we have no pressure data whatsoever, this is pointless, so let's just return */
|
||||
|
|
|
@ -494,7 +494,6 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
|
|||
bool has_depth = false, has_setpoint = false, has_ndl = false;
|
||||
char *lineptr;
|
||||
int prev_time = 0;
|
||||
cylinder_t cyl;
|
||||
|
||||
struct divecomputer *dc;
|
||||
struct tm cur_tm;
|
||||
|
@ -517,26 +516,32 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
|
|||
dive->dcs[0].divemode = CCR;
|
||||
dive->dcs[0].no_o2sensors = 2;
|
||||
|
||||
cyl.cylinder_use = OXYGEN;
|
||||
cyl.type.size.mliter = 3000;
|
||||
cyl.type.workingpressure.mbar = 200000;
|
||||
cyl.type.description = "3l Mk6";
|
||||
cyl.gasmix.o2.permille = 1000;
|
||||
cyl.manually_added = true;
|
||||
cyl.bestmix_o2 = 0;
|
||||
cyl.bestmix_he = 0;
|
||||
add_cloned_cylinder(&dive->cylinders, cyl);
|
||||
{
|
||||
cylinder_t cyl;
|
||||
cyl.cylinder_use = OXYGEN;
|
||||
cyl.type.size.mliter = 3000;
|
||||
cyl.type.workingpressure.mbar = 200000;
|
||||
cyl.type.description = "3l Mk6";
|
||||
cyl.gasmix.o2.permille = 1000;
|
||||
cyl.manually_added = true;
|
||||
cyl.bestmix_o2 = 0;
|
||||
cyl.bestmix_he = 0;
|
||||
dive->cylinders.push_back(std::move(cyl));
|
||||
}
|
||||
|
||||
cyl.cylinder_use = DILUENT;
|
||||
cyl.type.size.mliter = 3000;
|
||||
cyl.type.workingpressure.mbar = 200000;
|
||||
cyl.type.description = "3l Mk6";
|
||||
value = parse_mkvi_value(memtxt.data(), "Helium percentage");
|
||||
he = atoi(value.c_str());
|
||||
value = parse_mkvi_value(memtxt.data(), "Nitrogen percentage");
|
||||
cyl.gasmix.o2.permille = (100 - atoi(value.c_str()) - he) * 10;
|
||||
cyl.gasmix.he.permille = he * 10;
|
||||
add_cloned_cylinder(&dive->cylinders, cyl);
|
||||
{
|
||||
cylinder_t cyl;
|
||||
cyl.cylinder_use = DILUENT;
|
||||
cyl.type.size.mliter = 3000;
|
||||
cyl.type.workingpressure.mbar = 200000;
|
||||
cyl.type.description = "3l Mk6";
|
||||
value = parse_mkvi_value(memtxt.data(), "Helium percentage");
|
||||
he = atoi(value.c_str());
|
||||
value = parse_mkvi_value(memtxt.data(), "Nitrogen percentage");
|
||||
cyl.gasmix.o2.permille = (100 - atoi(value.c_str()) - he) * 10;
|
||||
cyl.gasmix.he.permille = he * 10;
|
||||
dive->cylinders.push_back(std::move(cyl));
|
||||
}
|
||||
|
||||
lineptr = strstr(memtxt.data(), "Dive started at");
|
||||
while (!empty_string(lineptr) && (lineptr = strchr(lineptr, '\n'))) {
|
||||
|
|
|
@ -130,7 +130,7 @@ static int divinglog_profile(void *param, int, char **data, char **)
|
|||
state->cur_sample->temperature.mkelvin = C_to_mkelvin(temp / 10.0f);
|
||||
state->cur_sample->pressure[0].mbar = pressure * 100;
|
||||
state->cur_sample->rbt.seconds = rbt;
|
||||
if (oldcyl != tank && tank >= 0 && tank < state->cur_dive->cylinders.nr) {
|
||||
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;
|
||||
int o2 = get_o2(mix);
|
||||
int he = get_he(mix);
|
||||
|
|
|
@ -58,24 +58,20 @@ static int shearwater_changes(void *param, int columns, char **data, char **)
|
|||
o2 = 1000;
|
||||
|
||||
// Find the cylinder index
|
||||
int index;
|
||||
bool found = false;
|
||||
for (index = 0; index < state->cur_dive->cylinders.nr; ++index) {
|
||||
const cylinder_t *cyl = get_cylinder(state->cur_dive.get(), index);
|
||||
if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
auto it = std::find_if(state->cur_dive->cylinders.begin(), state->cur_dive->cylinders.end(),
|
||||
[o2, he](auto &cyl)
|
||||
{ return cyl.gasmix.o2.permille == o2 && cyl.gasmix.he.permille == he; });
|
||||
if (it == state->cur_dive->cylinders.end()) {
|
||||
// Cylinder not found, creating a new one
|
||||
cyl = cylinder_start(state);
|
||||
cyl->gasmix.o2.permille = o2;
|
||||
cyl->gasmix.he.permille = he;
|
||||
cylinder_end(state);
|
||||
it = std::prev(state->cur_dive->cylinders.end());
|
||||
}
|
||||
|
||||
add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), index);
|
||||
add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]),
|
||||
it - state->cur_dive->cylinders.begin());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -103,9 +99,8 @@ static int shearwater_profile_sample(void *param, int, char **data, char **)
|
|||
state->cur_sample->depth.mm = state->metric ? lrint(permissive_strtod(data[1], NULL) * 1000) : feet_to_mm(permissive_strtod(data[1], NULL));
|
||||
if (data[2])
|
||||
state->cur_sample->temperature.mkelvin = state->metric ? C_to_mkelvin(permissive_strtod(data[2], NULL)) : F_to_mkelvin(permissive_strtod(data[2], NULL));
|
||||
if (data[3]) {
|
||||
if (data[3])
|
||||
state->cur_sample->setpoint.mbar = lrint(permissive_strtod(data[3], NULL) * 1000);
|
||||
}
|
||||
if (data[4])
|
||||
state->cur_sample->ndl.seconds = atoi(data[4]) * 60;
|
||||
if (data[5])
|
||||
|
|
|
@ -165,7 +165,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
|
|||
bottom_gas = gasmix_air;
|
||||
}
|
||||
|
||||
clear_cylinder_table(&dive->cylinders);
|
||||
dive->cylinders.clear();
|
||||
for (i = 0; i < std::max(ngases, ntanks); i++) {
|
||||
cylinder_t cyl;
|
||||
cyl.cylinder_use = NOT_USED;
|
||||
|
@ -266,7 +266,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
|
|||
snprintf(name_buffer, sizeof(name_buffer), "%d cuft", rounded_size);
|
||||
break;
|
||||
}
|
||||
cyl.type.description = copy_string(name_buffer);
|
||||
cyl.type.description = name_buffer;
|
||||
cyl.type.size.mliter = lrint(cuft_to_l(rounded_size) * 1000 /
|
||||
mbar_to_atm(cyl.type.workingpressure.mbar));
|
||||
}
|
||||
|
@ -301,10 +301,10 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
|
|||
fill_default_cylinder(dive, &cyl);
|
||||
}
|
||||
/* whatever happens, make sure there is a name for the cylinder */
|
||||
if (empty_string(cyl.type.description))
|
||||
cyl.type.description = strdup(translate("gettextFromC", "unknown"));
|
||||
if (cyl.type.description.empty())
|
||||
cyl.type.description = translate("gettextFromC", "unknown");
|
||||
|
||||
add_cylinder(&dive->cylinders, dive->cylinders.nr, cyl);
|
||||
dive->cylinders.push_back(std::move(cyl));
|
||||
}
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -147,8 +147,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
|
|||
|
||||
/* Just the main cylinder until we can handle the buddy cylinder porperly */
|
||||
for (i = 0; i < 1; i++) {
|
||||
cylinder_t cyl;
|
||||
fill_default_cylinder(dive.get(), &cyl);
|
||||
cylinder_t cyl = default_cylinder(dive.get());
|
||||
add_cylinder(&dive->cylinders, i, cyl);
|
||||
}
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ static void parse_cylinder_keyvalue(void *_cylinder, const char *key, const std:
|
|||
return;
|
||||
}
|
||||
if (!strcmp(key, "description")) {
|
||||
cylinder->type.description = strdup(value.c_str());
|
||||
cylinder->type.description = value;
|
||||
return;
|
||||
}
|
||||
if (!strcmp(key, "o2")) {
|
||||
|
@ -444,9 +444,9 @@ static void parse_dive_cylinder(char *line, struct git_parser_state *state)
|
|||
line = parse_keyvalue_entry(parse_cylinder_keyvalue, &cylinder, line, state);
|
||||
}
|
||||
if (cylinder.cylinder_use == OXYGEN)
|
||||
state->o2pressure_sensor = state->active_dive->cylinders.nr;
|
||||
state->o2pressure_sensor = static_cast<int>(state->active_dive->cylinders.size());
|
||||
|
||||
add_cylinder(&state->active_dive->cylinders, state->active_dive->cylinders.nr, cylinder);
|
||||
state->active_dive->cylinders.push_back(std::move(cylinder));
|
||||
}
|
||||
|
||||
static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::string &value)
|
||||
|
@ -655,7 +655,7 @@ static char *parse_sample_unit(struct sample *sample, double val, char *unit)
|
|||
*/
|
||||
static int sanitize_sensor_id(const struct dive *d, int nr)
|
||||
{
|
||||
return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR;
|
||||
return d && nr >= 0 && static_cast<size_t>(nr) < d->cylinders.size() ? nr : NO_SENSOR;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "membuffer.h"
|
||||
#include "picture.h"
|
||||
#include "qthelper.h"
|
||||
#include "range.h"
|
||||
#include "sample.h"
|
||||
#include "tag.h"
|
||||
#include "xmlparams.h"
|
||||
|
@ -233,7 +234,7 @@ static void cylinder_use(const char *buffer, enum cylinderuse *cyl_use, struct p
|
|||
enum cylinderuse use = cylinderuse_from_text(trimmed.c_str());
|
||||
*cyl_use = use;
|
||||
if (use == OXYGEN)
|
||||
state->o2pressure_sensor = state->cur_dive->cylinders.nr - 1;
|
||||
state->o2pressure_sensor = static_cast<int>(state->cur_dive->cylinders.size()) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -990,10 +991,8 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf,
|
|||
{
|
||||
/* For cylinder related fields, we might have to create a cylinder first. */
|
||||
cylinder_t cyl;
|
||||
if (MATCH("tanktype", utf8_string, (char **)&cyl.type.description)) {
|
||||
cylinder_t *cyl0 = get_or_create_cylinder(dive, 0);
|
||||
free((void *)cyl0->type.description);
|
||||
cyl0->type.description = cyl.type.description;
|
||||
if (MATCH("tanktype", utf8_string_std, &cyl.type.description)) {
|
||||
get_or_create_cylinder(dive, 0)->type.description = std::move(cyl.type.description);
|
||||
return 1;
|
||||
}
|
||||
if (MATCH("tanksize", cylindersize, &cyl.type.size)) {
|
||||
|
@ -1230,7 +1229,7 @@ static void gps_picture_location(const char *buffer, struct picture *pic)
|
|||
/* We're in the top-level dive xml. Try to convert whatever value to a dive value */
|
||||
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, struct parser_state *state)
|
||||
{
|
||||
cylinder_t *cyl = dive->cylinders.nr > 0 ? get_cylinder(dive, dive->cylinders.nr - 1) : NULL;
|
||||
cylinder_t *cyl = !dive->cylinders.empty() ? &dive->cylinders.back() : NULL;
|
||||
weightsystem_t *ws = dive->weightsystems.nr > 0 ?
|
||||
&dive->weightsystems.weightsystems[dive->weightsystems.nr - 1] : NULL;
|
||||
pressure_t p;
|
||||
|
@ -1356,7 +1355,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
|
|||
return;
|
||||
if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure))
|
||||
return;
|
||||
if (MATCH("description.cylinder", utf8_string, (char **)&cyl->type.description))
|
||||
if (MATCH("description.cylinder", utf8_string_std, &cyl->type.description))
|
||||
return;
|
||||
if (MATCH_STATE("start.cylinder", pressure, &cyl->start))
|
||||
return;
|
||||
|
@ -1798,7 +1797,6 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
|
|||
unsigned char event;
|
||||
bool found;
|
||||
unsigned int time = 0;
|
||||
int i;
|
||||
char serial[6];
|
||||
struct battery_status {
|
||||
uint16_t volt1;
|
||||
|
@ -1971,11 +1969,10 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
|
|||
state.cur_event.type = SAMPLE_EVENT_GASCHANGE2;
|
||||
state.cur_event.value = ptr[7] << 8 ^ ptr[6];
|
||||
|
||||
found = false;
|
||||
for (i = 0; i < state.cur_dive->cylinders.nr; ++i) {
|
||||
const cylinder_t *cyl = get_cylinder(state.cur_dive.get(), i);
|
||||
if (cyl->gasmix.o2.permille == ptr[6] * 10 && cyl->gasmix.he.permille == ptr[7] * 10) {
|
||||
for (const auto [i, cyl]: enumerated_range(state.cur_dive->cylinders)) {
|
||||
if (cyl.gasmix.o2.permille == ptr[6] * 10 && cyl.gasmix.he.permille == ptr[7] * 10) {
|
||||
found = true;
|
||||
state.cur_event.gas.index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1984,9 +1981,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
|
|||
cyl->gasmix.o2.permille = ptr[6] * 10;
|
||||
cyl->gasmix.he.permille = ptr[7] * 10;
|
||||
cylinder_end(&state);
|
||||
state.cur_event.gas.index = state.cur_dive->cylinders.nr - 1;
|
||||
} else {
|
||||
state.cur_event.gas.index = i;
|
||||
state.cur_event.gas.index = static_cast<int>(state.cur_dive->cylinders.size()) - 1;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
|
|
|
@ -335,7 +335,7 @@ void ws_end(struct parser_state *state)
|
|||
*/
|
||||
static int sanitize_sensor_id(const struct dive *d, int nr)
|
||||
{
|
||||
return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR;
|
||||
return d && nr >= 0 && static_cast<size_t>(nr) < d->cylinders.size() ? nr : NO_SENSOR;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "event.h"
|
||||
#include "interpolate.h"
|
||||
#include "planner.h"
|
||||
#include "range.h"
|
||||
#include "subsurface-time.h"
|
||||
#include "gettext.h"
|
||||
#include "libdivecomputer/parser.h"
|
||||
|
@ -94,7 +95,7 @@ int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_
|
|||
|
||||
static int get_gasidx(struct dive *dive, struct gasmix mix)
|
||||
{
|
||||
return find_best_gasmix_match(mix, &dive->cylinders);
|
||||
return find_best_gasmix_match(mix, dive->cylinders);
|
||||
}
|
||||
|
||||
static void interpolate_transition(struct deco_state *ds, struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, struct gasmix gasmix, o2pressure_t po2, enum divemode_t divemode)
|
||||
|
@ -368,12 +369,12 @@ struct gaschanges {
|
|||
static int setpoint_change(struct dive *dive, int cylinderid)
|
||||
{
|
||||
cylinder_t *cylinder = get_cylinder(dive, cylinderid);
|
||||
if (!cylinder->type.description)
|
||||
if (cylinder->type.description.empty())
|
||||
return 0;
|
||||
if (!strncmp(cylinder->type.description, "SP ", 3)) {
|
||||
if (starts_with(cylinder->type.description, "SP ")) {
|
||||
float sp;
|
||||
sscanf(cylinder->type.description + 3, "%f", &sp);
|
||||
return (int) (sp * 1000);
|
||||
sscanf(cylinder->type.description.c_str() + 3, "%f", &sp);
|
||||
return (int) (sp * 1000.0);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -572,10 +573,9 @@ static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth,
|
|||
*/
|
||||
static bool enough_gas(const struct dive *dive, int current_cylinder)
|
||||
{
|
||||
cylinder_t *cyl;
|
||||
if (current_cylinder < 0 || current_cylinder >= dive->cylinders.nr)
|
||||
if (current_cylinder < 0 || static_cast<size_t>(current_cylinder) >= dive->cylinders.size())
|
||||
return false;
|
||||
cyl = get_cylinder(dive, current_cylinder);
|
||||
const cylinder_t *cyl = get_cylinder(dive, current_cylinder);
|
||||
|
||||
if (!cyl->start.mbar)
|
||||
return true;
|
||||
|
@ -1086,7 +1086,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
// we had a fixed cylinder table: It uses an extra fake cylinder
|
||||
// past the regular cylinder table, which is not visible to the UI.
|
||||
// Fix this as soon as possible!
|
||||
current_cylinder = dive->cylinders.nr;
|
||||
current_cylinder = static_cast<int>(dive->cylinders.size());
|
||||
plan_add_segment(diveplan, prefs.surface_segment, 0, current_cylinder, 0, false, OC);
|
||||
}
|
||||
create_dive_from_plan(diveplan, dive, dc, is_planner);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "units.h"
|
||||
#include "divelist.h"
|
||||
#include "planner.h"
|
||||
#include "range.h"
|
||||
#include "gettext.h"
|
||||
#include "libdivecomputer/parser.h"
|
||||
#include "qthelper.h"
|
||||
|
@ -461,34 +462,33 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
|||
}
|
||||
|
||||
/* Print gas consumption: This loop covers all cylinders */
|
||||
for (int gasidx = 0; gasidx < dive->cylinders.nr; gasidx++) {
|
||||
for (auto [gasidx, cyl]: enumerated_range(dive->cylinders)) {
|
||||
double volume, pressure, deco_volume, deco_pressure, mingas_volume, mingas_pressure, mingas_d_pressure, mingas_depth;
|
||||
const char *unit, *pressure_unit, *depth_unit;
|
||||
std::string temp;
|
||||
std::string warning;
|
||||
std::string mingas;
|
||||
cylinder_t *cyl = get_cylinder(dive, gasidx);
|
||||
if (cyl->cylinder_use == NOT_USED)
|
||||
if (cyl.cylinder_use == NOT_USED)
|
||||
continue;
|
||||
|
||||
volume = get_volume_units(cyl->gas_used.mliter, NULL, &unit);
|
||||
deco_volume = get_volume_units(cyl->deco_gas_used.mliter, NULL, &unit);
|
||||
if (cyl->type.size.mliter) {
|
||||
int remaining_gas = lrint((double)cyl->end.mbar * cyl->type.size.mliter / 1000.0 / gas_compressibility_factor(cyl->gasmix, cyl->end.mbar / 1000.0));
|
||||
double deco_pressure_mbar = isothermal_pressure(cyl->gasmix, 1.0, remaining_gas + cyl->deco_gas_used.mliter,
|
||||
cyl->type.size.mliter) * 1000 - cyl->end.mbar;
|
||||
volume = get_volume_units(cyl.gas_used.mliter, NULL, &unit);
|
||||
deco_volume = get_volume_units(cyl.deco_gas_used.mliter, NULL, &unit);
|
||||
if (cyl.type.size.mliter) {
|
||||
int remaining_gas = lrint((double)cyl.end.mbar * cyl.type.size.mliter / 1000.0 / gas_compressibility_factor(cyl.gasmix, cyl.end.mbar / 1000.0));
|
||||
double deco_pressure_mbar = isothermal_pressure(cyl.gasmix, 1.0, remaining_gas + cyl.deco_gas_used.mliter,
|
||||
cyl.type.size.mliter) * 1000 - cyl.end.mbar;
|
||||
deco_pressure = get_pressure_units(lrint(deco_pressure_mbar), &pressure_unit);
|
||||
pressure = get_pressure_units(cyl->start.mbar - cyl->end.mbar, &pressure_unit);
|
||||
pressure = get_pressure_units(cyl.start.mbar - cyl.end.mbar, &pressure_unit);
|
||||
/* Warn if the plan uses more gas than is available in a cylinder
|
||||
* This only works if we have working pressure for the cylinder
|
||||
* 10bar is a made up number - but it seemed silly to pretend you could breathe cylinder down to 0 */
|
||||
if (cyl->end.mbar < 10000)
|
||||
if (cyl.end.mbar < 10000)
|
||||
warning = format_string_std("<br/>\n — <span style='color: red;'>%s </span> %s",
|
||||
translate("gettextFromC", "Warning:"),
|
||||
translate("gettextFromC", "this is more gas than available in the specified cylinder!"));
|
||||
else
|
||||
if (cyl->end.mbar / 1000.0 * cyl->type.size.mliter / gas_compressibility_factor(cyl->gasmix, cyl->end.mbar / 1000.0)
|
||||
< cyl->deco_gas_used.mliter)
|
||||
if (cyl.end.mbar / 1000.0 * cyl.type.size.mliter / gas_compressibility_factor(cyl.gasmix, cyl.end.mbar / 1000.0)
|
||||
< cyl.deco_gas_used.mliter)
|
||||
warning = format_string_std("<br/>\n — <span style='color: red;'>%s </span> %s",
|
||||
translate("gettextFromC", "Warning:"),
|
||||
translate("gettextFromC", "not enough reserve for gas sharing on ascent!"));
|
||||
|
@ -502,17 +502,17 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
|||
volume_t mingasv;
|
||||
mingasv.mliter = lrint(prefs.sacfactor / 100.0 * prefs.problemsolvingtime * prefs.bottomsac
|
||||
* depth_to_bar(lastbottomdp->depth.mm, dive)
|
||||
+ prefs.sacfactor / 100.0 * cyl->deco_gas_used.mliter);
|
||||
+ prefs.sacfactor / 100.0 * cyl.deco_gas_used.mliter);
|
||||
/* Calculate minimum gas pressure for cyclinder. */
|
||||
lastbottomdp->minimum_gas.mbar = lrint(isothermal_pressure(cyl->gasmix, 1.0,
|
||||
mingasv.mliter, cyl->type.size.mliter) * 1000);
|
||||
lastbottomdp->minimum_gas.mbar = lrint(isothermal_pressure(cyl.gasmix, 1.0,
|
||||
mingasv.mliter, cyl.type.size.mliter) * 1000);
|
||||
/* Translate all results into correct units */
|
||||
mingas_volume = get_volume_units(mingasv.mliter, NULL, &unit);
|
||||
mingas_pressure = get_pressure_units(lastbottomdp->minimum_gas.mbar, &pressure_unit);
|
||||
mingas_d_pressure = get_pressure_units(lrint((double)cyl->end.mbar + deco_pressure_mbar - lastbottomdp->minimum_gas.mbar), &pressure_unit);
|
||||
mingas_d_pressure = get_pressure_units(lrint((double)cyl.end.mbar + deco_pressure_mbar - lastbottomdp->minimum_gas.mbar), &pressure_unit);
|
||||
mingas_depth = get_depth_units(lastbottomdp->depth.mm, NULL, &depth_unit);
|
||||
/* Print it to results */
|
||||
if (cyl->start.mbar > lastbottomdp->minimum_gas.mbar) {
|
||||
if (cyl.start.mbar > lastbottomdp->minimum_gas.mbar) {
|
||||
mingas = casprintf_loc("<br/>\n — <span style='color: %s;'>%s</span> (%s %.1fx%s/+%d%s@%.0f%s): "
|
||||
"%.0f%s/%.0f%s<span style='color: %s;'>/Δ:%+.0f%s</span>",
|
||||
mingas_d_pressure > 0 ? "green" :"red",
|
||||
|
@ -536,18 +536,18 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
|||
/* Print the gas consumption for every cylinder here to temp buffer. */
|
||||
if (lrint(volume) > 0) {
|
||||
temp = casprintf_loc(translate("gettextFromC", "%.0f%s/%.0f%s of <span style='color: red;'><b>%s</b></span> (%.0f%s/%.0f%s in planned ascent)"),
|
||||
volume, unit, pressure, pressure_unit, gasname(cyl->gasmix), deco_volume, unit, deco_pressure, pressure_unit);
|
||||
volume, unit, pressure, pressure_unit, gasname(cyl.gasmix), deco_volume, unit, deco_pressure, pressure_unit);
|
||||
} else {
|
||||
temp = casprintf_loc(translate("gettextFromC", "%.0f%s/%.0f%s of <span style='color: red;'><b>%s</b></span>"),
|
||||
volume, unit, pressure, pressure_unit, gasname(cyl->gasmix));
|
||||
volume, unit, pressure, pressure_unit, gasname(cyl.gasmix));
|
||||
}
|
||||
} else {
|
||||
if (lrint(volume) > 0) {
|
||||
temp = casprintf_loc(translate("gettextFromC", "%.0f%s of <span style='color: red;'><b>%s</b></span> (%.0f%s during planned ascent)"),
|
||||
volume, unit, gasname(cyl->gasmix), deco_volume, unit);
|
||||
volume, unit, gasname(cyl.gasmix), deco_volume, unit);
|
||||
} else {
|
||||
temp = casprintf_loc(translate("gettextFromC", "%.0f%s of <span style='color: red;'><b>%s</b></span>"),
|
||||
volume, unit, gasname(cyl->gasmix));
|
||||
volume, unit, gasname(cyl.gasmix));
|
||||
}
|
||||
}
|
||||
/* Gas consumption: Now finally print all strings to output */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libdivecomputer/version.h"
|
||||
#include "membuffer.h"
|
||||
#include "qthelper.h"
|
||||
#include "range.h"
|
||||
#include "format.h"
|
||||
|
||||
//#define DEBUG_GAS 1
|
||||
|
@ -216,7 +217,7 @@ int get_cylinder_index(const struct dive *dive, const struct event &ev)
|
|||
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);
|
||||
best = find_best_gasmix_match(mix, dive->cylinders);
|
||||
return best < 0 ? 0 : best;
|
||||
}
|
||||
|
||||
|
@ -259,12 +260,11 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec
|
|||
int maxhr = 0, minhr = INT_MAX;
|
||||
int mintemp = dive->mintemp.mkelvin;
|
||||
int maxtemp = dive->maxtemp.mkelvin;
|
||||
int cyl;
|
||||
|
||||
/* Get the per-cylinder maximum pressure if they are manual */
|
||||
for (cyl = 0; cyl < dive->cylinders.nr; cyl++) {
|
||||
int mbar_start = get_cylinder(dive, cyl)->start.mbar;
|
||||
int mbar_end = get_cylinder(dive, cyl)->end.mbar;
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
int mbar_start = cyl.start.mbar;
|
||||
int mbar_end = cyl.end.mbar;
|
||||
if (mbar_start > maxpressure)
|
||||
maxpressure = mbar_start;
|
||||
if (mbar_end && mbar_end < minpressure)
|
||||
|
@ -364,7 +364,7 @@ static void insert_entry(struct plot_info &pi, int time, int depth, int sac)
|
|||
|
||||
static void populate_plot_entries(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi)
|
||||
{
|
||||
pi.nr_cylinders = dive->cylinders.nr;
|
||||
pi.nr_cylinders = static_cast<int>(dive->cylinders.size());
|
||||
|
||||
/*
|
||||
* To avoid continuous reallocation, allocate the expected number of entries.
|
||||
|
@ -494,26 +494,21 @@ static void populate_plot_entries(const struct dive *dive, const struct divecomp
|
|||
*/
|
||||
static int sac_between(const struct dive *dive, const struct plot_info &pi, int first, int last, const char gases[])
|
||||
{
|
||||
int i, airuse;
|
||||
double pressuretime;
|
||||
|
||||
if (first == last)
|
||||
return 0;
|
||||
|
||||
/* Get airuse for the set of cylinders over the range */
|
||||
airuse = 0;
|
||||
for (i = 0; i < pi.nr_cylinders; i++) {
|
||||
int airuse = 0;
|
||||
for (int i = 0; i < pi.nr_cylinders; i++) {
|
||||
pressure_t a, b;
|
||||
cylinder_t *cyl;
|
||||
int cyluse;
|
||||
|
||||
if (!gases[i])
|
||||
continue;
|
||||
|
||||
a.mbar = get_plot_pressure(pi, first, i);
|
||||
b.mbar = get_plot_pressure(pi, last, i);
|
||||
cyl = get_cylinder(dive, i);
|
||||
cyluse = gas_volume(cyl, a) - gas_volume(cyl, b);
|
||||
const cylinder_t *cyl = get_cylinder(dive, i);
|
||||
int cyluse = gas_volume(cyl, a) - gas_volume(cyl, b);
|
||||
if (cyluse > 0)
|
||||
airuse += cyluse;
|
||||
}
|
||||
|
@ -521,7 +516,7 @@ static int sac_between(const struct dive *dive, const struct plot_info &pi, int
|
|||
return 0;
|
||||
|
||||
/* Calculate depthpressure integrated over time */
|
||||
pressuretime = 0.0;
|
||||
double pressuretime = 0.0;
|
||||
do {
|
||||
const struct plot_data &entry = pi.entry[first];
|
||||
const struct plot_data &next = pi.entry[first + 1];
|
||||
|
@ -632,8 +627,8 @@ static void fill_sac(const struct dive *dive, struct plot_info &pi, int idx, con
|
|||
*/
|
||||
static void matching_gases(const struct dive *dive, struct gasmix gasmix, char gases[])
|
||||
{
|
||||
for (int i = 0; i < dive->cylinders.nr; i++)
|
||||
gases[i] = same_gasmix(gasmix, get_cylinder(dive, i)->gasmix);
|
||||
for (auto [i, cyl]: enumerated_range(dive->cylinders))
|
||||
gases[i] = same_gasmix(gasmix, cyl.gasmix);
|
||||
}
|
||||
|
||||
static void calculate_sac(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi)
|
||||
|
@ -1536,7 +1531,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;
|
||||
|
||||
cylinder_t *cyl = get_cylinder(d, cylinder_index);
|
||||
const cylinder_t *cyl = get_cylinder(d, cylinder_index);
|
||||
|
||||
volumes_used[cylinder_index] += gas_volume(cyl, (pressure_t){ last_pressures[cylinder_index] }) - gas_volume(cyl, (pressure_t){ next_pressure });
|
||||
}
|
||||
|
@ -1589,7 +1584,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];
|
||||
|
||||
cylinder_t *cyl = get_cylinder(d, cylinder_index);
|
||||
const cylinder_t *cyl = get_cylinder(d, cylinder_index);
|
||||
if (cyl->type.size.mliter) {
|
||||
if (cylinder_volume.mliter && cylinder_volume.mliter != cyl->type.size.mliter) {
|
||||
cylindersizes_are_identical = false;
|
||||
|
|
|
@ -95,7 +95,7 @@ struct plot_info {
|
|||
double maxpp = 0.0;
|
||||
bool waypoint_above_ceiling = false;
|
||||
std::vector<plot_data> entry;
|
||||
std::vector<plot_pressure_data> pressures; /* cylinders.nr blocks of nr entries. */
|
||||
std::vector<plot_pressure_data> pressures; /* cylinders.size() blocks of nr entries. */
|
||||
|
||||
plot_info();
|
||||
~plot_info();
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "version.h"
|
||||
#include "errorhelper.h"
|
||||
#include "planner.h"
|
||||
#include "range.h"
|
||||
#include "subsurface-time.h"
|
||||
#include "gettextfromc.h"
|
||||
#include "metadata.h"
|
||||
|
@ -357,11 +358,10 @@ static bool lessThan(const QPair<QString, int> &a, const QPair<QString, int> &b)
|
|||
|
||||
QVector<QPair<QString, int>> selectedDivesGasUsed()
|
||||
{
|
||||
int j;
|
||||
QMap<QString, int> gasUsed;
|
||||
for (dive *d: getDiveSelection()) {
|
||||
std::vector<volume_t> diveGases = get_gas_used(d);
|
||||
for (j = 0; j < d->cylinders.nr; j++) {
|
||||
for (size_t j = 0; j < d->cylinders.size(); j++) {
|
||||
if (diveGases[j].mliter) {
|
||||
QString gasName = gasname(get_cylinder(d, j)->gasmix);
|
||||
gasUsed[gasName] += diveGases[j].mliter;
|
||||
|
@ -1189,16 +1189,15 @@ QString get_gas_string(struct gasmix gas)
|
|||
QStringList get_dive_gas_list(const struct dive *d)
|
||||
{
|
||||
QStringList list;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
const cylinder_t *cyl = get_cylinder(d, i);
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
/* Check if we have the same gasmix two or more times
|
||||
* If yes return more verbose string */
|
||||
int same_gas = same_gasmix_cylinder(cyl, i, d, true);
|
||||
if (same_gas == -1)
|
||||
list.push_back(get_gas_string(cyl->gasmix));
|
||||
list.push_back(get_gas_string(cyl.gasmix));
|
||||
else
|
||||
list.push_back(get_gas_string(cyl->gasmix) + QString(" (%1 %2 ").arg(gettextFromC::tr("cyl.")).arg(i + 1) +
|
||||
cyl->type.description + ")");
|
||||
list.push_back(get_gas_string(cyl.gasmix) + QStringLiteral(" (%1 %2 ").arg(gettextFromC::tr("cyl.")).arg(i + 1) +
|
||||
QString::fromStdString(cyl.type.description) + ")");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -141,28 +141,23 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix)
|
|||
|
||||
static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
||||
{
|
||||
int i, nr;
|
||||
|
||||
nr = nr_cylinders(dive);
|
||||
for (i = 0; i < nr; i++) {
|
||||
cylinder_t *cylinder = get_cylinder(dive, i);
|
||||
int volume = cylinder->type.size.mliter;
|
||||
const char *description = cylinder->type.description;
|
||||
int use = cylinder->cylinder_use;
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
int volume = cyl.type.size.mliter;
|
||||
int use = cyl.cylinder_use;
|
||||
|
||||
put_string(b, "cylinder");
|
||||
if (volume)
|
||||
put_milli(b, " vol=", volume, "l");
|
||||
put_pressure(b, cylinder->type.workingpressure, " workpressure=", "bar");
|
||||
show_utf8(b, " description=", description, "");
|
||||
put_pressure(b, cyl.type.workingpressure, " workpressure=", "bar");
|
||||
show_utf8(b, " description=", cyl.type.description.c_str(), "");
|
||||
strip_mb(b);
|
||||
put_gasmix(b, cylinder->gasmix);
|
||||
put_pressure(b, cylinder->start, " start=", "bar");
|
||||
put_pressure(b, cylinder->end, " end=", "bar");
|
||||
put_gasmix(b, cyl.gasmix);
|
||||
put_pressure(b, cyl.start, " start=", "bar");
|
||||
put_pressure(b, cyl.end, " end=", "bar");
|
||||
if (use > OC_GAS && use < NUM_GAS_USE)
|
||||
show_utf8(b, " use=", cylinderuse_text[use], "");
|
||||
if (cylinder->depth.mm != 0)
|
||||
put_milli(b, " depth=", cylinder->depth.mm, "m");
|
||||
if (cyl.depth.mm != 0)
|
||||
put_milli(b, " depth=", cyl.depth.mm, "m");
|
||||
put_string(b, "\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,43 +121,40 @@ static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive)
|
|||
|
||||
static void put_cylinder_HTML(struct membuffer *b, const struct dive *dive)
|
||||
{
|
||||
int i, nr;
|
||||
const char *separator = "\"Cylinders\":[";
|
||||
nr = nr_cylinders(dive);
|
||||
|
||||
if (!nr)
|
||||
if (dive->cylinders.empty())
|
||||
put_string(b, separator);
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
cylinder_t *cylinder = get_cylinder(dive, i);
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
put_format(b, "%s{", separator);
|
||||
separator = ", ";
|
||||
write_attribute(b, "Type", cylinder->type.description, ", ");
|
||||
if (cylinder->type.size.mliter) {
|
||||
int volume = cylinder->type.size.mliter;
|
||||
if (prefs.units.volume == units::CUFT && cylinder->type.workingpressure.mbar)
|
||||
volume = lrint(volume * bar_to_atm(cylinder->type.workingpressure.mbar / 1000.0));
|
||||
write_attribute(b, "Type", cyl.type.description.c_str(), ", ");
|
||||
if (cyl.type.size.mliter) {
|
||||
int volume = cyl.type.size.mliter;
|
||||
if (prefs.units.volume == units::CUFT && cyl.type.workingpressure.mbar)
|
||||
volume = lrint(volume * bar_to_atm(cyl.type.workingpressure.mbar / 1000.0));
|
||||
put_HTML_volume_units(b, volume, "\"Size\":\"", " \", ");
|
||||
} else {
|
||||
write_attribute(b, "Size", "--", ", ");
|
||||
}
|
||||
put_HTML_pressure_units(b, cylinder->type.workingpressure, "\"WPressure\":\"", " \", ");
|
||||
put_HTML_pressure_units(b, cyl.type.workingpressure, "\"WPressure\":\"", " \", ");
|
||||
|
||||
if (cylinder->start.mbar) {
|
||||
put_HTML_pressure_units(b, cylinder->start, "\"SPressure\":\"", " \", ");
|
||||
if (cyl.start.mbar) {
|
||||
put_HTML_pressure_units(b, cyl.start, "\"SPressure\":\"", " \", ");
|
||||
} else {
|
||||
write_attribute(b, "SPressure", "--", ", ");
|
||||
}
|
||||
|
||||
if (cylinder->end.mbar) {
|
||||
put_HTML_pressure_units(b, cylinder->end, "\"EPressure\":\"", " \", ");
|
||||
if (cyl.end.mbar) {
|
||||
put_HTML_pressure_units(b, cyl.end, "\"EPressure\":\"", " \", ");
|
||||
} else {
|
||||
write_attribute(b, "EPressure", "--", ", ");
|
||||
}
|
||||
|
||||
if (cylinder->gasmix.o2.permille) {
|
||||
put_format(b, "\"O2\":\"%u.%u%%\",", FRACTION_TUPLE(cylinder->gasmix.o2.permille, 10));
|
||||
put_format(b, "\"He\":\"%u.%u%%\"", FRACTION_TUPLE(cylinder->gasmix.he.permille, 10));
|
||||
if (cyl.gasmix.o2.permille) {
|
||||
put_format(b, "\"O2\":\"%u.%u%%\",", FRACTION_TUPLE(cyl.gasmix.o2.permille, 10));
|
||||
put_format(b, "\"He\":\"%u.%u%%\"", FRACTION_TUPLE(cyl.gasmix.he.permille, 10));
|
||||
} else {
|
||||
write_attribute(b, "O2", "Air", "");
|
||||
}
|
||||
|
|
|
@ -177,28 +177,22 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix)
|
|||
|
||||
static void save_cylinder_info(struct membuffer *b, struct dive *dive)
|
||||
{
|
||||
int i, nr;
|
||||
|
||||
nr = nr_cylinders(dive);
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
cylinder_t *cylinder = get_cylinder(dive, i);
|
||||
int volume = cylinder->type.size.mliter;
|
||||
const char *description = cylinder->type.description;
|
||||
int use = cylinder->cylinder_use;
|
||||
for (auto &cyl: dive->cylinders) {
|
||||
int volume = cyl.type.size.mliter;
|
||||
int use = cyl.cylinder_use;
|
||||
|
||||
put_format(b, " <cylinder");
|
||||
if (volume)
|
||||
put_milli(b, " size='", volume, " l'");
|
||||
put_pressure(b, cylinder->type.workingpressure, " workpressure='", " bar'");
|
||||
show_utf8(b, description, " description='", "'", 1);
|
||||
put_gasmix(b, cylinder->gasmix);
|
||||
put_pressure(b, cylinder->start, " start='", " bar'");
|
||||
put_pressure(b, cylinder->end, " end='", " bar'");
|
||||
put_pressure(b, cyl.type.workingpressure, " workpressure='", " bar'");
|
||||
show_utf8(b, cyl.type.description.c_str(), " description='", "'", 1);
|
||||
put_gasmix(b, cyl.gasmix);
|
||||
put_pressure(b, cyl.start, " start='", " bar'");
|
||||
put_pressure(b, cyl.end, " end='", " bar'");
|
||||
if (use > OC_GAS && use < NUM_GAS_USE)
|
||||
show_utf8(b, cylinderuse_text[use], " use='", "'", 1);
|
||||
if (cylinder->depth.mm != 0)
|
||||
put_milli(b, " depth='", cylinder->depth.mm, " m'");
|
||||
if (cyl.depth.mm != 0)
|
||||
put_milli(b, " depth='", cyl.depth.mm, " m'");
|
||||
put_format(b, " />\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "divelog.h"
|
||||
#include "event.h"
|
||||
#include "gettext.h"
|
||||
#include "range.h"
|
||||
#include "sample.h"
|
||||
#include "subsurface-time.h"
|
||||
#include "trip.h"
|
||||
|
@ -273,15 +274,14 @@ bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc,
|
|||
|
||||
bool is_cylinder_used(const struct dive *dive, int idx)
|
||||
{
|
||||
cylinder_t *cyl;
|
||||
if (idx < 0 || idx >= dive->cylinders.nr)
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size())
|
||||
return false;
|
||||
|
||||
cyl = get_cylinder(dive, idx);
|
||||
if ((cyl->start.mbar - cyl->end.mbar) > SOME_GAS)
|
||||
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)
|
||||
if ((cyl.sample_start.mbar - cyl.sample_end.mbar) > SOME_GAS)
|
||||
return true;
|
||||
|
||||
for (auto &dc: dive->dcs) {
|
||||
|
@ -295,7 +295,7 @@ bool is_cylinder_used(const struct dive *dive, int idx)
|
|||
|
||||
bool is_cylinder_prot(const struct dive *dive, int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= dive->cylinders.nr)
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= dive->cylinders.size())
|
||||
return false;
|
||||
|
||||
return std::any_of(dive->dcs.begin(), dive->dcs.end(),
|
||||
|
@ -303,18 +303,17 @@ bool is_cylinder_prot(const struct dive *dive, int idx)
|
|||
{ return has_gaschange_event(dive, &dc, idx); });
|
||||
}
|
||||
|
||||
/* Returns a vector with dive->cylinders.nr entries */
|
||||
/* Returns a vector with dive->cylinders.size() entries */
|
||||
std::vector<volume_t> get_gas_used(struct dive *dive)
|
||||
{
|
||||
std::vector<volume_t> gases(dive->cylinders.nr);
|
||||
for (int idx = 0; idx < dive->cylinders.nr; idx++) {
|
||||
cylinder_t *cyl = get_cylinder(dive, idx);
|
||||
std::vector<volume_t> gases(dive->cylinders.size());
|
||||
for (auto [idx, cyl]: enumerated_range(dive->cylinders)) {
|
||||
pressure_t start, end;
|
||||
|
||||
start = cyl->start.mbar ? cyl->start : cyl->sample_start;
|
||||
end = cyl->end.mbar ? cyl->end : cyl->sample_end;
|
||||
start = cyl.start.mbar ? cyl.start : cyl.sample_start;
|
||||
end = cyl.end.mbar ? cyl.end : cyl.sample_end;
|
||||
if (end.mbar && start.mbar > end.mbar)
|
||||
gases[idx].mliter = gas_volume(cyl, start) - gas_volume(cyl, end);
|
||||
gases[idx].mliter = gas_volume(&cyl, start) - gas_volume(&cyl, end);
|
||||
else
|
||||
gases[idx].mliter = 0;
|
||||
}
|
||||
|
@ -327,7 +326,7 @@ std::vector<volume_t> get_gas_used(struct dive *dive)
|
|||
static std::pair<volume_t, volume_t> get_gas_parts(struct gasmix mix, volume_t vol, int o2_in_topup)
|
||||
{
|
||||
if (gasmix_is_air(mix))
|
||||
return { {0}, {0} };
|
||||
return { volume_t() , volume_t() };
|
||||
|
||||
volume_t air = { (int)lrint(((double)vol.mliter * get_n2(mix)) / (1000 - o2_in_topup)) };
|
||||
volume_t he = { (int)lrint(((double)vol.mliter * get_he(mix)) / 1000.0) };
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "event.h"
|
||||
#include "format.h"
|
||||
#include "qthelper.h"
|
||||
#include "range.h"
|
||||
#include "subsurface-string.h"
|
||||
#include "trip.h"
|
||||
#include <QDateTime>
|
||||
|
@ -13,23 +14,21 @@
|
|||
enum returnPressureSelector { START_PRESSURE, END_PRESSURE };
|
||||
static QLocale loc;
|
||||
|
||||
static QString getPressures(const struct dive *dive, int i, enum returnPressureSelector ret)
|
||||
static QString getPressures(const cylinder_t &cyl, enum returnPressureSelector ret)
|
||||
{
|
||||
const cylinder_t *cyl = get_cylinder(dive, i);
|
||||
QString fmt;
|
||||
if (ret == START_PRESSURE) {
|
||||
if (cyl->start.mbar)
|
||||
fmt = get_pressure_string(cyl->start, true);
|
||||
else if (cyl->sample_start.mbar)
|
||||
fmt = get_pressure_string(cyl->sample_start, true);
|
||||
if (cyl.start.mbar)
|
||||
return get_pressure_string(cyl.start, true);
|
||||
else if (cyl.sample_start.mbar)
|
||||
return get_pressure_string(cyl.sample_start, true);
|
||||
}
|
||||
if (ret == END_PRESSURE) {
|
||||
if (cyl->end.mbar)
|
||||
fmt = get_pressure_string(cyl->end, true);
|
||||
else if(cyl->sample_end.mbar)
|
||||
fmt = get_pressure_string(cyl->sample_end, true);
|
||||
if (cyl.end.mbar)
|
||||
return get_pressure_string(cyl.end, true);
|
||||
else if (cyl.sample_end.mbar)
|
||||
return get_pressure_string(cyl.sample_end, true);
|
||||
}
|
||||
return fmt;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString formatSac(const dive *d)
|
||||
|
@ -77,9 +76,9 @@ QString format_gps_decimal(const dive *d)
|
|||
QStringList formatGetCylinder(const dive *d)
|
||||
{
|
||||
QStringList getCylinder;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (is_cylinder_used(d, i))
|
||||
getCylinder << get_cylinder(d, i)->type.description;
|
||||
getCylinder << QString::fromStdString(cyl.type.description);
|
||||
}
|
||||
return getCylinder;
|
||||
}
|
||||
|
@ -87,9 +86,9 @@ QStringList formatGetCylinder(const dive *d)
|
|||
QStringList formatStartPressure(const dive *d)
|
||||
{
|
||||
QStringList startPressure;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (is_cylinder_used(d, i))
|
||||
startPressure << getPressures(d, i, START_PRESSURE);
|
||||
startPressure << getPressures(cyl, START_PRESSURE);
|
||||
}
|
||||
return startPressure;
|
||||
}
|
||||
|
@ -97,9 +96,9 @@ QStringList formatStartPressure(const dive *d)
|
|||
QStringList formatEndPressure(const dive *d)
|
||||
{
|
||||
QStringList endPressure;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (is_cylinder_used(d, i))
|
||||
endPressure << getPressures(d, i, END_PRESSURE);
|
||||
endPressure << getPressures(cyl, END_PRESSURE);
|
||||
}
|
||||
return endPressure;
|
||||
}
|
||||
|
@ -107,9 +106,9 @@ QStringList formatEndPressure(const dive *d)
|
|||
QStringList formatFirstGas(const dive *d)
|
||||
{
|
||||
QStringList gas;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (is_cylinder_used(d, i))
|
||||
gas << get_gas_string(get_cylinder(d, i)->gasmix);
|
||||
gas << get_gas_string(cyl.gasmix);
|
||||
}
|
||||
return gas;
|
||||
}
|
||||
|
@ -133,20 +132,14 @@ static void addStringToSortedList(QStringList &l, const std::string &s)
|
|||
l.insert(it, qs);
|
||||
}
|
||||
|
||||
// Safely treat null-strings. Remove once everyhting is converted to std::string
|
||||
static std::string c_to_std(const char *s)
|
||||
{
|
||||
return s ? std::string(s) : std::string();
|
||||
}
|
||||
|
||||
QStringList formatFullCylinderList()
|
||||
{
|
||||
QStringList cylinders;
|
||||
struct dive *d;
|
||||
int i = 0;
|
||||
for_each_dive (i, d) {
|
||||
for (int j = 0; j < d->cylinders.nr; j++)
|
||||
addStringToSortedList(cylinders, c_to_std(get_cylinder(d, j)->type.description));
|
||||
for (const cylinder_t &cyl: d->cylinders)
|
||||
addStringToSortedList(cylinders, cyl.type.description);
|
||||
}
|
||||
|
||||
for (const auto &ti: tank_info_table)
|
||||
|
@ -155,25 +148,22 @@ QStringList formatFullCylinderList()
|
|||
return cylinders;
|
||||
}
|
||||
|
||||
static QString formattedCylinder(const struct dive *dive, int idx)
|
||||
static QString formattedCylinder(const cylinder_t &cyl)
|
||||
{
|
||||
const cylinder_t *cyl = get_cylinder(dive, idx);
|
||||
const char *desc = cyl->type.description;
|
||||
QString fmt = desc ? QString(desc) : gettextFromC::tr("unknown");
|
||||
fmt += ", " + get_volume_string(cyl->type.size, true);
|
||||
fmt += ", " + get_pressure_string(cyl->type.workingpressure, true);
|
||||
fmt += ", " + get_pressure_string(cyl->start, false) + " - " + get_pressure_string(cyl->end, true);
|
||||
fmt += ", " + get_gas_string(cyl->gasmix);
|
||||
const std::string &desc = cyl.type.description;
|
||||
QString fmt = !desc.empty() ? QString::fromStdString(desc) : gettextFromC::tr("unknown");
|
||||
fmt += ", " + get_volume_string(cyl.type.size, true);
|
||||
fmt += ", " + get_pressure_string(cyl.type.workingpressure, true);
|
||||
fmt += ", " + get_pressure_string(cyl.start, false) + " - " + get_pressure_string(cyl.end, true);
|
||||
fmt += ", " + get_gas_string(cyl.gasmix);
|
||||
return fmt;
|
||||
}
|
||||
|
||||
QStringList formatCylinders(const dive *d)
|
||||
{
|
||||
QStringList cylinders;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
QString cyl = formattedCylinder(d, i);
|
||||
cylinders << cyl;
|
||||
}
|
||||
for (const cylinder_t &cyl: d->cylinders)
|
||||
cylinders << formattedCylinder(cyl);
|
||||
return cylinders;
|
||||
}
|
||||
|
||||
|
@ -182,14 +172,14 @@ QString formatGas(const dive *d)
|
|||
/*WARNING: here should be the gastlist, returned
|
||||
* from the get_gas_string function or this is correct?
|
||||
*/
|
||||
QString gas, gases;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
QString gases;
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (!is_cylinder_used(d, i))
|
||||
continue;
|
||||
gas = get_cylinder(d, i)->type.description;
|
||||
QString gas = QString::fromStdString(cyl.type.description);
|
||||
if (!gas.isEmpty())
|
||||
gas += QChar(' ');
|
||||
gas += gasname(get_cylinder(d, i)->gasmix);
|
||||
gas += gasname(cyl.gasmix);
|
||||
// if has a description and if such gas is not already present
|
||||
if (!gas.isEmpty() && gases.indexOf(gas) == -1) {
|
||||
if (!gases.isEmpty())
|
||||
|
|
|
@ -335,7 +335,7 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
|
|||
u_sample = (uemis_sample *)(data.data() + i);
|
||||
while ((i <= data.size()) && (data[i] != 0 || data[i + 1] != 0)) {
|
||||
if (u_sample->active_tank != active) {
|
||||
if (u_sample->active_tank >= dive->cylinders.nr) {
|
||||
if (u_sample->active_tank >= static_cast<int>(dive->cylinders.size())) {
|
||||
report_info("got invalid sensor #%d was #%d", u_sample->active_tank, active);
|
||||
} else {
|
||||
active = u_sample->active_tank;
|
||||
|
|
|
@ -298,7 +298,7 @@ void ProfileWidget::cylindersChanged(struct dive *changed, int pos)
|
|||
// If we're editing the current dive we have to update the
|
||||
// cylinders of the edited dive.
|
||||
if (editedDive) {
|
||||
copy_cylinders(&d->cylinders, &editedDive.get()->cylinders);
|
||||
editedDive.get()->cylinders = d->cylinders;
|
||||
// TODO: Holy moly that function sends too many signals. Fix it!
|
||||
DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "profile-widget/profilewidget2.h"
|
||||
#include "commands/command.h"
|
||||
#include "core/metadata.h"
|
||||
#include "core/range.h"
|
||||
#include "core/tag.h"
|
||||
|
||||
void RenumberDialog::buttonClicked(QAbstractButton *button)
|
||||
|
@ -348,11 +349,10 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button)
|
|||
text << "\n";
|
||||
}
|
||||
if (what->cylinders) {
|
||||
int cyl;
|
||||
text << tr("Cylinders:\n");
|
||||
for (cyl = 0; cyl < current_dive->cylinders.nr; cyl++) {
|
||||
if (is_cylinder_used(current_dive, cyl))
|
||||
text << get_cylinder(current_dive, cyl)->type.description << " " << gasname(get_cylinder(current_dive, cyl)->gasmix) << "\n";
|
||||
for (auto [idx, cyl]: enumerated_range(current_dive->cylinders)) {
|
||||
if (is_cylinder_used(current_dive, idx))
|
||||
text << QString::fromStdString(cyl.type.description) << " " << gasname(cyl.gasmix) << "\n";
|
||||
}
|
||||
}
|
||||
if (what->weights) {
|
||||
|
|
|
@ -126,14 +126,14 @@ void TabDiveInformation::updateProfile()
|
|||
|
||||
std::vector<volume_t> gases = get_gas_used(currentDive);
|
||||
QString volumes;
|
||||
std::vector<int> mean(currentDive->cylinders.nr), duration(currentDive->cylinders.nr);
|
||||
std::vector<int> mean(currentDive->cylinders.size()), duration(currentDive->cylinders.size());
|
||||
struct divecomputer *currentdc = parent.getCurrentDC();
|
||||
if (currentdc && currentDive->cylinders.nr >= 0)
|
||||
if (currentdc && !currentDive->cylinders.empty())
|
||||
per_cylinder_mean_depth(currentDive, currentdc, mean.data(), duration.data());
|
||||
volume_t sac;
|
||||
QString gaslist, SACs, separator;
|
||||
|
||||
for (int i = 0; i < currentDive->cylinders.nr; i++) {
|
||||
for (size_t i = 0; i < currentDive->cylinders.size(); i++) {
|
||||
if (!is_cylinder_used(currentDive, i))
|
||||
continue;
|
||||
gaslist.append(separator); volumes.append(separator); SACs.append(separator);
|
||||
|
@ -154,7 +154,7 @@ void TabDiveInformation::updateProfile()
|
|||
ui->diveTimeText->setText(get_dive_duration_string(currentDive->duration.seconds, tr("h"), tr("min"), tr("sec"),
|
||||
" ", currentDive->dcs[0].divemode == FREEDIVE));
|
||||
|
||||
ui->sacText->setText(currentDive->cylinders.nr > 0 && mean[0] && currentDive->dcs[0].divemode != CCR ? std::move(SACs) : QString());
|
||||
ui->sacText->setText(!currentDive->cylinders.empty() && mean[0] && currentDive->dcs[0].divemode != CCR ? std::move(SACs) : QString());
|
||||
|
||||
if (currentDive->surface_pressure.mbar == 0) {
|
||||
ui->atmPressVal->clear(); // If no atm pressure for dive then clear text box
|
||||
|
|
|
@ -303,9 +303,9 @@ static int findEnd(const QList<token> &tokenList, int from, int to, token_t star
|
|||
static std::vector<const cylinder_t *> cylinderList(const dive *d)
|
||||
{
|
||||
std::vector<const cylinder_t *> res;
|
||||
res.reserve(d->cylinders.nr);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i)
|
||||
res.push_back(&d->cylinders.cylinders[i]);
|
||||
res.reserve(d->cylinders.size());
|
||||
for (auto &cyl: d->cylinders)
|
||||
res.push_back(&cyl);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -481,7 +481,7 @@ QVariant TemplateLayout::getValue(QString list, QString property, const State &s
|
|||
return QVariant();
|
||||
const cylinder_t *cylinder = *state.currentCylinderObject;
|
||||
if (property == "description") {
|
||||
return cylinder->type.description;
|
||||
return QString::fromStdString(cylinder->type.description);
|
||||
} else if (property == "size") {
|
||||
return get_volume_string(cylinder->type.size, true);
|
||||
} else if (property == "workingPressure") {
|
||||
|
|
|
@ -1295,7 +1295,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
|
|||
break;
|
||||
}
|
||||
}
|
||||
get_or_create_cylinder(d, j)->type.description = copy_qstring(usedCylinder[k]);
|
||||
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;
|
||||
k++;
|
||||
|
|
|
@ -602,7 +602,10 @@ 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++) {
|
||||
showDescriptions = showDescriptions || same_gasmix_cylinder(get_cylinder(d, cyl), cyl, d, true) != -1;
|
||||
const cylinder_t *c = get_cylinder(d, cyl);
|
||||
if (!c)
|
||||
continue;
|
||||
showDescriptions = showDescriptions || (c && same_gasmix_cylinder(*c, cyl, d, true) != -1);
|
||||
if (act_segments[cyl].polygon.empty())
|
||||
continue;
|
||||
act_segments[cyl].cyl = cyl;
|
||||
|
@ -655,7 +658,7 @@ void DiveGasPressureItem::plotGasValue(double mbar, double sec, const cylinder_t
|
|||
QString gas = get_gas_string(cylinder->gasmix);
|
||||
QString label;
|
||||
if (showDescription)
|
||||
label = QStringLiteral("(%1) %2").arg(cylinder->type.description, gas);
|
||||
label = QStringLiteral("(%1) %2").arg(QString::fromStdString(cylinder->type.description), gas);
|
||||
else
|
||||
label = gas;
|
||||
auto text = std::make_unique<DiveTextItem>(dpr, 1.0, align, this);
|
||||
|
|
|
@ -502,13 +502,11 @@ struct int ProfileWidget2::getEntryFromPos(QPointF pos)
|
|||
#ifndef SUBSURFACE_MOBILE
|
||||
/// Prints cylinder information for display.
|
||||
/// eg : "Cyl 1 (AL80 EAN32)"
|
||||
static QString printCylinderDescription(int i, const cylinder_t *cylinder)
|
||||
static QString printCylinderDescription(int i, const cylinder_t &cylinder)
|
||||
{
|
||||
QString label = gettextFromC::tr("Cyl") + QString(" %1").arg(i+1);
|
||||
if( cylinder != NULL ) {
|
||||
QString mix = get_gas_string(cylinder->gasmix);
|
||||
label += QString(" (%2 %3)").arg(cylinder->type.description).arg(mix);
|
||||
}
|
||||
QString mix = get_gas_string(cylinder.gasmix);
|
||||
label += QString(" (%2 %3)").arg(QString::fromStdString(cylinder.type.description)).arg(mix);
|
||||
return label;
|
||||
}
|
||||
|
||||
|
@ -562,18 +560,16 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
|||
if (d && item && item->ev.is_gaschange()) {
|
||||
int eventTime = item->ev.time.seconds;
|
||||
QMenu *gasChange = m.addMenu(tr("Edit Gas Change"));
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
const cylinder_t *cylinder = get_cylinder(d, i);
|
||||
QString label = printCylinderDescription(i, cylinder);
|
||||
gasChange->addAction(label, [this, i, eventTime] { addGasSwitch(i, eventTime); });
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
QString label = printCylinderDescription(i, cyl);
|
||||
gasChange->addAction(label, [this, idx = i, eventTime] { addGasSwitch(idx, eventTime); });
|
||||
}
|
||||
} else if (d && d->cylinders.nr > 1) {
|
||||
} else if (d && d->cylinders.size() > 1) {
|
||||
// if we have more than one gas, offer to switch to another one
|
||||
QMenu *gasChange = m.addMenu(tr("Add gas change"));
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
const cylinder_t *cylinder = get_cylinder(d, i);
|
||||
QString label = printCylinderDescription(i, cylinder);
|
||||
gasChange->addAction(label, [this, i, seconds] { addGasSwitch(i, seconds); });
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
QString label = printCylinderDescription(i, cyl);
|
||||
gasChange->addAction(label, [this, idx = i, seconds] { addGasSwitch(idx, seconds); });
|
||||
}
|
||||
}
|
||||
m.addAction(tr("Add setpoint change"), [this, seconds]() { ProfileWidget2::addSetpointChange(seconds); });
|
||||
|
@ -763,7 +759,7 @@ void ProfileWidget2::splitDive(int seconds)
|
|||
|
||||
void ProfileWidget2::addGasSwitch(int tank, int seconds)
|
||||
{
|
||||
if (!d || tank < 0 || tank >= d->cylinders.nr)
|
||||
if (!d || tank < 0 || static_cast<size_t>(tank) >= d->cylinders.size())
|
||||
return;
|
||||
|
||||
Command::addGasSwitch(mutable_dive(), dc, seconds, tank);
|
||||
|
@ -923,7 +919,7 @@ void ProfileWidget2::repositionDiveHandlers()
|
|||
QLineF line(p1, p2);
|
||||
QPointF pos = line.pointAt(0.5);
|
||||
gases[i]->setPos(pos);
|
||||
if (datapoint.cylinderid >= 0 && datapoint.cylinderid < d->cylinders.nr)
|
||||
if (datapoint.cylinderid >= 0 && datapoint.cylinderid < static_cast<int>(d->cylinders.size()))
|
||||
gases[i]->setText(get_gas_string(get_cylinder(d, datapoint.cylinderid)->gasmix));
|
||||
else
|
||||
gases[i]->setText(QString());
|
||||
|
|
|
@ -76,7 +76,7 @@ void TankItem::setData(const struct dive *d, const struct divecomputer *dc, int
|
|||
return;
|
||||
|
||||
// Bail if there are no cylinders
|
||||
if (d->cylinders.nr <= 0)
|
||||
if (d->cylinders.empty())
|
||||
return;
|
||||
|
||||
// start with the first gasmix and at the start of the plotted range
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/color.h"
|
||||
#include "qt-models/diveplannermodel.h"
|
||||
#include "core/gettextfromc.h"
|
||||
#include "core/range.h"
|
||||
#include "core/sample.h"
|
||||
#include "core/selection.h"
|
||||
#include "core/subsurface-qt/divelistnotifier.h"
|
||||
|
@ -140,7 +141,7 @@ int CylindersModel::calcNumRows() const
|
|||
if (!d)
|
||||
return 0;
|
||||
if (inPlanner || prefs.include_unused_tanks)
|
||||
return d->cylinders.nr;
|
||||
return static_cast<int>(d->cylinders.size());
|
||||
return first_hidden_cylinder(d);
|
||||
}
|
||||
|
||||
|
@ -192,7 +193,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
|
|||
case Qt::EditRole:
|
||||
switch (index.column()) {
|
||||
case TYPE:
|
||||
return QString(cyl->type.description);
|
||||
return QString::fromStdString(cyl->type.description);
|
||||
case SIZE:
|
||||
if (cyl->type.size.mliter)
|
||||
return get_cylinder_string(cyl);
|
||||
|
@ -326,10 +327,9 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||
|
||||
switch (index.column()) {
|
||||
case TYPE: {
|
||||
QString type = value.toString();
|
||||
if (!same_string(qPrintable(type), tempCyl.type.description)) {
|
||||
free((void *)tempCyl.type.description);
|
||||
tempCyl.type.description = strdup(qPrintable(type));
|
||||
std::string type = value.toString().toStdString();
|
||||
if (type != tempCyl.type.description) {
|
||||
tempCyl.type.description = type;
|
||||
dataChanged(index, index);
|
||||
}
|
||||
return true;
|
||||
|
@ -361,8 +361,6 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||
QString vString = value.toString();
|
||||
bool changed = vString != data(index, role).toString();
|
||||
|
||||
std::string newType; // If we allocate a new type string, this makes sure that it is freed at the end of the function
|
||||
|
||||
// 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.
|
||||
|
@ -374,8 +372,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||
Command::EditCylinderType type = Command::EditCylinderType::TYPE;
|
||||
switch (index.column()) {
|
||||
case TYPE:
|
||||
newType = qPrintable(vString);
|
||||
cyl.type.description = newType.c_str();
|
||||
cyl.type.description = vString.toStdString();
|
||||
type = Command::EditCylinderType::TYPE;
|
||||
break;
|
||||
case SIZE:
|
||||
|
@ -473,10 +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.
|
||||
// We have only made a shallow copy, therefore copy the new cylinder first.
|
||||
cylinder_t copy = clone_cylinder(cyl);
|
||||
std::swap(copy, *get_cylinder(d, row));
|
||||
free_cylinder(copy);
|
||||
*get_cylinder(d, row) = cyl;
|
||||
dataChanged(index, index);
|
||||
} else {
|
||||
// On the EquipmentTab - place an editCylinder command.
|
||||
|
@ -496,10 +490,10 @@ void CylindersModel::add()
|
|||
{
|
||||
if (!d)
|
||||
return;
|
||||
int row = d->cylinders.nr;
|
||||
int row = static_cast<int>(d->cylinders.size());
|
||||
cylinder_t cyl = create_new_manual_cylinder(d);
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
add_cylinder(&d->cylinders, row, cyl);
|
||||
add_cylinder(&d->cylinders, row, std::move(cyl));
|
||||
++numRows;
|
||||
endInsertRows();
|
||||
emit dataChanged(createIndex(row, 0), createIndex(row, COLUMNS - 1));
|
||||
|
@ -552,7 +546,7 @@ void CylindersModel::remove(QModelIndex index)
|
|||
--numRows;
|
||||
endRemoveRows();
|
||||
|
||||
std::vector<int> mapping = get_cylinder_map_for_remove(d->cylinders.nr + 1, index.row());
|
||||
std::vector<int> mapping = get_cylinder_map_for_remove(static_cast<int>(d->cylinders.size() + 1), index.row());
|
||||
cylinder_renumber(d, mapping.data());
|
||||
DivePlannerPointsModel::instance()->cylinderRenumber(mapping.data());
|
||||
}
|
||||
|
@ -612,21 +606,18 @@ void CylindersModel::updateNumRows()
|
|||
// Only invoked from planner.
|
||||
void CylindersModel::moveAtFirst(int cylid)
|
||||
{
|
||||
if (!d || cylid <= 0 || cylid >= d->cylinders.nr)
|
||||
if (!d || cylid <= 0 || cylid >= static_cast<int>(d->cylinders.size()))
|
||||
return;
|
||||
cylinder_t temp_cyl;
|
||||
|
||||
beginMoveRows(QModelIndex(), cylid, cylid, QModelIndex(), 0);
|
||||
memmove(&temp_cyl, get_cylinder(d, cylid), sizeof(temp_cyl));
|
||||
for (int i = cylid - 1; i >= 0; i--)
|
||||
memmove(get_cylinder(d, i + 1), get_cylinder(d, i), sizeof(temp_cyl));
|
||||
memmove(get_cylinder(d, 0), &temp_cyl, sizeof(temp_cyl));
|
||||
move_in_range(d->cylinders, cylid, cylid + 1, 0);
|
||||
|
||||
// Create a mapping of cylinder indices:
|
||||
// 1) Fill mapping[0]..mapping[cyl] with 0..index
|
||||
// 2) Set mapping[cyl] to 0
|
||||
// 3) Fill mapping[cyl+1]..mapping[end] with cyl..
|
||||
std::vector<int> mapping(d->cylinders.nr);
|
||||
std::vector<int> mapping(d->cylinders.size());
|
||||
std::iota(mapping.begin(), mapping.begin() + cylid, 1);
|
||||
mapping[cylid] = 0;
|
||||
std::iota(mapping.begin() + (cylid + 1), mapping.end(), cylid);
|
||||
|
@ -644,12 +635,11 @@ void CylindersModel::updateDecoDepths(pressure_t olddecopo2)
|
|||
|
||||
pressure_t decopo2;
|
||||
decopo2.mbar = prefs.decopo2;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(d, i);
|
||||
for (auto &cyl: d->cylinders) {
|
||||
/* If the gas's deco MOD matches the old pO2, it will have been automatically calculated and should be updated.
|
||||
* If they don't match, we should leave the user entered depth as it is */
|
||||
if (cyl->depth.mm == gas_mod(cyl->gasmix, olddecopo2, d, M_OR_FT(3, 10)).mm) {
|
||||
cyl->depth = gas_mod(cyl->gasmix, decopo2, d, M_OR_FT(3, 10));
|
||||
if (cyl.depth.mm == gas_mod(cyl.gasmix, olddecopo2, d, M_OR_FT(3, 10)).mm) {
|
||||
cyl.depth = gas_mod(cyl.gasmix, decopo2, d, M_OR_FT(3, 10));
|
||||
}
|
||||
}
|
||||
emit dataChanged(createIndex(0, 0), createIndex(numRows - 1, COLUMNS - 1));
|
||||
|
@ -671,23 +661,22 @@ bool CylindersModel::updateBestMixes()
|
|||
|
||||
// Check if any of the cylinders are best mixes, update if needed
|
||||
bool gasUpdated = false;
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(d, i);
|
||||
if (cyl->bestmix_o2) {
|
||||
cyl->gasmix.o2 = best_o2(d->maxdepth, d, inPlanner);
|
||||
for (auto &cyl: d->cylinders) {
|
||||
if (cyl.bestmix_o2) {
|
||||
cyl.gasmix.o2 = best_o2(d->maxdepth, d, inPlanner);
|
||||
// fO2 + fHe must not be greater than 1
|
||||
if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000)
|
||||
cyl->gasmix.he.permille = 1000 - get_o2(cyl->gasmix);
|
||||
if (get_o2(cyl.gasmix) + get_he(cyl.gasmix) > 1000)
|
||||
cyl.gasmix.he.permille = 1000 - get_o2(cyl.gasmix);
|
||||
pressure_t modpO2;
|
||||
modpO2.mbar = prefs.decopo2;
|
||||
cyl->depth = gas_mod(cyl->gasmix, modpO2, d, M_OR_FT(3, 10));
|
||||
cyl.depth = gas_mod(cyl.gasmix, modpO2, d, M_OR_FT(3, 10));
|
||||
gasUpdated = true;
|
||||
}
|
||||
if (cyl->bestmix_he) {
|
||||
cyl->gasmix.he = best_he(d->maxdepth, d, prefs.o2narcotic, cyl->gasmix.o2);
|
||||
if (cyl.bestmix_he) {
|
||||
cyl.gasmix.he = best_he(d->maxdepth, d, 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);
|
||||
if (get_o2(cyl.gasmix) + get_he(cyl.gasmix) > 1000)
|
||||
cyl.gasmix.o2.permille = 1000 - get_he(cyl.gasmix);
|
||||
gasUpdated = true;
|
||||
}
|
||||
}
|
||||
|
@ -727,7 +716,7 @@ void CylindersModel::initTempCyl(int row)
|
|||
return;
|
||||
|
||||
tempRow = row;
|
||||
tempCyl = clone_cylinder(*cyl);
|
||||
tempCyl = *cyl;
|
||||
|
||||
dataChanged(index(row, TYPE), index(row, USE));
|
||||
}
|
||||
|
@ -738,7 +727,7 @@ void CylindersModel::clearTempCyl()
|
|||
return;
|
||||
int oldRow = tempRow;
|
||||
tempRow = -1;
|
||||
free_cylinder(tempCyl);
|
||||
tempCyl = cylinder_t();
|
||||
dataChanged(index(oldRow, TYPE), index(oldRow, USE));
|
||||
}
|
||||
|
||||
|
@ -752,7 +741,7 @@ void CylindersModel::commitTempCyl(int row)
|
|||
if (!cyl)
|
||||
return;
|
||||
// Only submit a command if the type changed
|
||||
if (!same_string(cyl->type.description, tempCyl.type.description) || gettextFromC::tr(cyl->type.description) != QString(tempCyl.type.description)) {
|
||||
if (cyl->type.description != tempCyl.type.description || gettextFromC::tr(cyl->type.description.c_str()) != QString::fromStdString(tempCyl.type.description)) {
|
||||
if (inPlanner) {
|
||||
std::swap(*cyl, tempCyl);
|
||||
} else {
|
||||
|
@ -760,6 +749,6 @@ void CylindersModel::commitTempCyl(int row)
|
|||
emit divesEdited(count);
|
||||
}
|
||||
}
|
||||
free_cylinder(tempCyl);
|
||||
tempCyl = cylinder_t();
|
||||
tempRow = -1;
|
||||
}
|
||||
|
|
|
@ -195,13 +195,13 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn)
|
|||
// setup the cylinder widget accordingly
|
||||
void DivePlannerPointsModel::setupCylinders()
|
||||
{
|
||||
clear_cylinder_table(&d->cylinders);
|
||||
d->cylinders.clear();
|
||||
if (mode == PLAN && current_dive) {
|
||||
// take the displayed cylinders from the selected dive as starting point
|
||||
copy_used_cylinders(current_dive, d, !prefs.include_unused_tanks);
|
||||
reset_cylinders(d, true);
|
||||
|
||||
if (d->cylinders.nr > 0) {
|
||||
if (!d->cylinders.empty()) {
|
||||
cylinders.updateDive(d, dcNr);
|
||||
return; // We have at least one cylinder
|
||||
}
|
||||
|
@ -281,13 +281,14 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
|
|||
case GAS:
|
||||
/* Check if we have the same gasmix two or more times
|
||||
* If yes return more verbose string */
|
||||
int same_gas = same_gasmix_cylinder(get_cylinder(d, p.cylinderid), p.cylinderid, d, true);
|
||||
const cylinder_t &cyl = d->cylinders[p.cylinderid];
|
||||
int same_gas = same_gasmix_cylinder(cyl, p.cylinderid, d, true);
|
||||
if (same_gas == -1)
|
||||
return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix);
|
||||
return get_gas_string(cyl.gasmix);
|
||||
else
|
||||
return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix) +
|
||||
return get_gas_string(cyl.gasmix) +
|
||||
QString(" (%1 %2 ").arg(tr("cyl.")).arg(p.cylinderid + 1) +
|
||||
get_cylinder(d, p.cylinderid)->type.description + ")";
|
||||
QString::fromStdString(cyl.type.description) + ")";
|
||||
}
|
||||
} else if (role == Qt::DecorationRole) {
|
||||
switch (index.column()) {
|
||||
|
@ -602,6 +603,7 @@ void DivePlannerPointsModel::setAscratestopsDisplay(int rate)
|
|||
qPrefDivePlanner::set_ascratestops(lrint(rate * unit_factor()));
|
||||
emitDataChanged();
|
||||
}
|
||||
|
||||
int DivePlannerPointsModel::ascratestopsDisplay() const
|
||||
{
|
||||
return lrint((float)prefs.ascratestops / unit_factor());
|
||||
|
@ -1028,11 +1030,9 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
|||
// Get the user-input and calculate the dive info
|
||||
free_dps(&diveplan);
|
||||
|
||||
for (int i = 0; i < d->cylinders.nr; i++) {
|
||||
cylinder_t *cyl = get_cylinder(d, i);
|
||||
if (cyl->depth.mm && cyl->cylinder_use == OC_GAS) {
|
||||
plan_add_segment(&diveplan, 0, cyl->depth.mm, i, 0, false, OC);
|
||||
}
|
||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||
if (cyl.depth.mm && cyl.cylinder_use == OC_GAS)
|
||||
plan_add_segment(&diveplan, 0, cyl.depth.mm, i, 0, false, OC);
|
||||
}
|
||||
|
||||
int lastIndex = -1;
|
||||
|
|
|
@ -151,12 +151,9 @@ static void calculateDive(struct dive *dive, Stats &stats)
|
|||
}
|
||||
|
||||
// EAN dive ?
|
||||
for (int j = 0; j < dive->cylinders.nr; ++j) {
|
||||
if (get_cylinder(dive, j)->gasmix.o2.permille > 210) {
|
||||
stats.divesEAN++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (std::any_of(dive->cylinders.begin(), dive->cylinders.end(), [] (auto &cyl)
|
||||
{ return cyl.gasmix.o2.permille > 210; }))
|
||||
stats.divesEAN++;
|
||||
}
|
||||
|
||||
// Returns a (first_dive, last_dive) pair
|
||||
|
|
|
@ -336,7 +336,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
|
|||
case SUIT:
|
||||
return QString(d->suit);
|
||||
case CYLINDER:
|
||||
return d->cylinders.nr > 0 ? QString(get_cylinder(d, 0)->type.description) : QString();
|
||||
return !d->cylinders.empty() ? QString::fromStdString(d->cylinders[0].type.description) : QString();
|
||||
case SAC:
|
||||
return displaySac(d, prefs.units.show_units_table);
|
||||
case OTU:
|
||||
|
@ -1721,6 +1721,11 @@ static int strCmp(const char *s1, const char *s2)
|
|||
return QString::localeAwareCompare(QString(s1), QString(s2)); // TODO: avoid copy
|
||||
}
|
||||
|
||||
static int strCmp(const std::string &s1, const std::string &s2)
|
||||
{
|
||||
return QString::localeAwareCompare(QString::fromStdString(s1), QString::fromStdString(s2)); // TODO: avoid copy
|
||||
}
|
||||
|
||||
bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) const
|
||||
{
|
||||
// We assume that i1.column() == i2.column().
|
||||
|
@ -1750,9 +1755,9 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c
|
|||
case SUIT:
|
||||
return lessThanHelper(strCmp(d1->suit, d2->suit), row_diff);
|
||||
case CYLINDER:
|
||||
if (d1->cylinders.nr > 0 && d2->cylinders.nr > 0)
|
||||
return lessThanHelper(strCmp(get_cylinder(d1, 0)->type.description, get_cylinder(d2, 0)->type.description), row_diff);
|
||||
return d1->cylinders.nr - d2->cylinders.nr < 0;
|
||||
if (!d1->cylinders.empty() && !d2->cylinders.empty())
|
||||
return lessThanHelper(strCmp(d1->cylinders[0].type.description, d2->cylinders[0].type.description), row_diff);
|
||||
return d1->cylinders.size() < d2->cylinders.size();
|
||||
case GAS:
|
||||
return lessThanHelper(nitrox_sort_value(d1) - nitrox_sort_value(d2), row_diff);
|
||||
case SAC:
|
||||
|
@ -1764,19 +1769,19 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c
|
|||
case TAGS: {
|
||||
std::string s1 = taglist_get_tagstring(d1->tag_list);
|
||||
std::string s2 = taglist_get_tagstring(d2->tag_list);
|
||||
int diff = strCmp(s1.c_str(), s2.c_str());
|
||||
int diff = strCmp(s1, s2);
|
||||
return lessThanHelper(diff, row_diff);
|
||||
}
|
||||
case PHOTOS:
|
||||
return lessThanHelper(countPhotos(d1) - countPhotos(d2), row_diff);
|
||||
case COUNTRY:
|
||||
return lessThanHelper(strCmp(get_dive_country(d1).c_str(), get_dive_country(d2).c_str()), row_diff);
|
||||
return lessThanHelper(strCmp(get_dive_country(d1), get_dive_country(d2)), row_diff);
|
||||
case BUDDIES:
|
||||
return lessThanHelper(strCmp(d1->buddy, d2->buddy), row_diff);
|
||||
case DIVEGUIDE:
|
||||
return lessThanHelper(strCmp(d1->diveguide, d2->diveguide), row_diff);
|
||||
case LOCATION:
|
||||
return lessThanHelper(strCmp(get_dive_location(d1).c_str(), get_dive_location(d2).c_str()), row_diff);
|
||||
return lessThanHelper(strCmp(get_dive_location(d1), get_dive_location(d2)), row_diff);
|
||||
case NOTES:
|
||||
return lessThanHelper(strCmp(d1->notes, d2->notes), row_diff);
|
||||
case DIVEMODE:
|
||||
|
|
|
@ -449,7 +449,7 @@ static void smtk_build_tank_info(MdbHandle *mdb, cylinder_t *tank, char *idx)
|
|||
|
||||
for (i = 1; i <= atoi(idx); i++)
|
||||
table.fetch_row();
|
||||
tank->type.description = copy_string(table.get_data(1));
|
||||
tank->type.description = table.get_data(1);
|
||||
tank->type.size.mliter = lrint(strtod(table.get_data(2), NULL) * 1000);
|
||||
tank->type.workingpressure.mbar = lrint(strtod(table.get_data(4), NULL) * 1000);
|
||||
}
|
||||
|
@ -472,9 +472,9 @@ static bool is_same_cylinder(cylinder_t *cyl_a, cylinder_t *cyl_b)
|
|||
if (!(abs(cyl_a->end.mbar - cyl_b->end.mbar) <= 100))
|
||||
return false;
|
||||
// different names (none of them null)
|
||||
if (!same_string(cyl_a->type.description, "---") &&
|
||||
!same_string(cyl_b->type.description, "---") &&
|
||||
!same_string(cyl_a->type.description, cyl_b->type.description))
|
||||
if (cyl_a->type.description != "---" &&
|
||||
cyl_b->type.description != "---" &&
|
||||
cyl_a->type.description != cyl_b->type.description)
|
||||
return false;
|
||||
// Cylinders are most probably the same
|
||||
return true;
|
||||
|
@ -495,9 +495,8 @@ static void merge_cylinder_type(cylinder_type_t *src, cylinder_type_t *dst)
|
|||
dst->size.mliter = src->size.mliter;
|
||||
if (!dst->workingpressure.mbar)
|
||||
dst->workingpressure.mbar = src->workingpressure.mbar;
|
||||
if (!dst->description || same_string(dst->description, "---")) {
|
||||
dst->description = src->description;
|
||||
src->description = NULL;
|
||||
if (dst->description.empty() || dst->description == "---") {
|
||||
dst->description = std::move(src->description);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -532,7 +531,7 @@ static void smtk_clean_cylinders(struct dive *d)
|
|||
|
||||
cyl = base + tanks - 1;
|
||||
while (cyl != base) {
|
||||
if (same_string(cyl->type.description, "---") && cyl->start.mbar == 0 && cyl->end.mbar == 0)
|
||||
if (cyl->type.description == "---" && cyl->start.mbar == 0 && cyl->end.mbar == 0)
|
||||
remove_cylinder(d, i);
|
||||
else
|
||||
if (is_same_cylinder(cyl, cyl - 1)) {
|
||||
|
|
|
@ -1553,9 +1553,9 @@ struct GasTypeBinner : public MultiBinner<GasTypeBinner, GasTypeBin> {
|
|||
}
|
||||
std::vector<gas_bin_t> to_bin_values(const dive *d) const {
|
||||
std::vector<gas_bin_t> res;
|
||||
res.reserve(d->cylinders.nr);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
struct gasmix mix = d->cylinders.cylinders[i].gasmix;
|
||||
res.reserve(d->cylinders.size());
|
||||
for (auto &cyl: d->cylinders) {
|
||||
struct gasmix mix = cyl.gasmix;
|
||||
if (gasmix_is_invalid(mix))
|
||||
continue;
|
||||
// Add dive to each bin only once.
|
||||
|
@ -1591,9 +1591,9 @@ struct GasTypeGeneralBinner : public MultiBinner<GasTypeGeneralBinner, IntBin> {
|
|||
}
|
||||
std::vector<int> to_bin_values(const dive *d) const {
|
||||
std::vector<int> res;
|
||||
res.reserve(d->cylinders.nr);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
struct gasmix mix = d->cylinders.cylinders[i].gasmix;
|
||||
res.reserve(d->cylinders.size());
|
||||
for (auto &cyl: d->cylinders) {
|
||||
struct gasmix mix = cyl.gasmix;
|
||||
if (gasmix_is_invalid(mix))
|
||||
continue;
|
||||
res.push_back(gasmix_to_type(mix));
|
||||
|
@ -1619,9 +1619,9 @@ struct GasTypeVariable : public StatsVariableTemplate<StatsVariable::Type::Discr
|
|||
QString diveCategories(const dive *d) const override {
|
||||
QString res;
|
||||
std::vector<gasmix> mixes; // List multiple cylinders only once
|
||||
mixes.reserve(d->cylinders.nr);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i) {
|
||||
struct gasmix mix = d->cylinders.cylinders[i].gasmix;
|
||||
mixes.reserve(d->cylinders.size());
|
||||
for (auto &cyl: d->cylinders) {
|
||||
struct gasmix mix = cyl.gasmix;
|
||||
if (gasmix_is_invalid(mix))
|
||||
continue;
|
||||
if (std::find_if(mixes.begin(), mixes.end(),
|
||||
|
@ -1648,7 +1648,7 @@ struct GasTypeVariable : public StatsVariableTemplate<StatsVariable::Type::Discr
|
|||
// - max_he: get cylinder with maximum he content, otherwise with maximum o2 content
|
||||
static int get_gas_content(const struct dive *d, bool he, bool max_he)
|
||||
{
|
||||
if (d->cylinders.nr <= 0)
|
||||
if (d->cylinders.empty())
|
||||
return invalid_value<int>();
|
||||
// If sorting be He, the second sort criterion is O2 descending, because
|
||||
// we are interested in the "bottom gas": highest He and lowest O2.
|
||||
|
@ -1657,7 +1657,7 @@ static int get_gas_content(const struct dive *d, bool he, bool max_he)
|
|||
std::make_tuple(get_he(c2.gasmix), -get_o2(c2.gasmix)); }
|
||||
: [] (const cylinder_t &c1, const cylinder_t &c2)
|
||||
{ return get_o2(c1.gasmix) < get_o2(c2.gasmix); };
|
||||
auto it = std::max_element(d->cylinders.cylinders, d->cylinders.cylinders + d->cylinders.nr, comp);
|
||||
auto it = std::max_element(d->cylinders.begin(), d->cylinders.end(), comp);
|
||||
return he ? get_he(it->gasmix) : get_o2(it->gasmix);
|
||||
}
|
||||
|
||||
|
@ -1798,9 +1798,9 @@ struct WeightsystemVariable : public StatsVariableTemplate<StatsVariable::Type::
|
|||
static std::vector<QString> cylinder_types(const dive *d)
|
||||
{
|
||||
std::vector<QString> res;
|
||||
res.reserve(d->cylinders.nr);
|
||||
for (int i = 0; i < d->cylinders.nr; ++i)
|
||||
add_to_vector_unique(res, QString(d->cylinders.cylinders[i].type.description).trimmed());
|
||||
res.reserve(d->cylinders.size());
|
||||
for (auto &cyl: d->cylinders)
|
||||
add_to_vector_unique(res, QString::fromStdString(cyl.type.description).trimmed());
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue