core: move fixup_dive() to struct dive_table

This accesses the global dive_table, so make this explicit.

Since force_fixup_dive() and default_dive() use fixup_dive(),
also move them to struct dive_table.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-06-23 14:20:59 +02:00 committed by bstoeger
parent d81ca005ab
commit a2903b31a7
12 changed files with 233 additions and 228 deletions

View file

@ -391,7 +391,7 @@ AddDive::AddDive(std::unique_ptr<dive> d, bool autogroup, bool newNumber)
setText(Command::Base::tr("add dive")); setText(Command::Base::tr("add dive"));
d->maxdepth.mm = 0; d->maxdepth.mm = 0;
d->dcs[0].maxdepth.mm = 0; d->dcs[0].maxdepth.mm = 0;
fixup_dive(d.get()); divelog.dives.fixup_dive(*d);
// this only matters if undoit were called before redoit // this only matters if undoit were called before redoit
currentDive = nullptr; currentDive = nullptr;

View file

@ -256,7 +256,7 @@ void EditWaterTemp::set(struct dive *d, int value) const
d->watertemp.mkelvin = value > 0 ? (uint32_t)value : 0u; d->watertemp.mkelvin = value > 0 ? (uint32_t)value : 0u;
// re-populate the temperatures - easiest way to do this is by calling fixup_dive // re-populate the temperatures - easiest way to do this is by calling fixup_dive
fixup_dive(d); divelog.dives.fixup_dive(*d);
} }
int EditWaterTemp::data(struct dive *d) const int EditWaterTemp::data(struct dive *d) const
@ -787,7 +787,7 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive),
// Fix source. Things might be inconsistent after modifying the profile. // Fix source. Things might be inconsistent after modifying the profile.
source->maxdepth.mm = source->dcs[0].maxdepth.mm = 0; source->maxdepth.mm = source->dcs[0].maxdepth.mm = 0;
fixup_dive(source); divelog.dives.fixup_dive(*source);
when = source->when; when = source->when;
maxdepth = source->maxdepth; maxdepth = source->maxdepth;
@ -824,7 +824,7 @@ void ReplanDive::undo()
std::swap(d->surface_pressure, surface_pressure); std::swap(d->surface_pressure, surface_pressure);
std::swap(d->duration, duration); std::swap(d->duration, duration);
std::swap(d->salinity, salinity); std::swap(d->salinity, salinity);
fixup_dive(d); divelog.dives.fixup_dive(*d);
invalidate_dive_cache(d); // Ensure that dive is written in git_save() invalidate_dive_cache(d); // Ensure that dive is written in git_save()
QVector<dive *> divesToNotify = { d }; QVector<dive *> divesToNotify = { d };
@ -899,7 +899,7 @@ void EditProfile::undo()
std::swap(d->maxdepth, maxdepth); std::swap(d->maxdepth, maxdepth);
std::swap(d->meandepth, meandepth); std::swap(d->meandepth, meandepth);
std::swap(d->duration, duration); std::swap(d->duration, duration);
fixup_dive(d); divelog.dives.fixup_dive(*d);
invalidate_dive_cache(d); // Ensure that dive is written in git_save() invalidate_dive_cache(d); // Ensure that dive is written in git_save()
QVector<dive *> divesToNotify = { d }; QVector<dive *> divesToNotify = { d };
@ -1101,7 +1101,7 @@ void AddCylinder::undo()
{ {
for (size_t i = 0; i < dives.size(); ++i) { for (size_t i = 0; i < dives.size(); ++i) {
remove_cylinder(dives[i], indexes[i]); remove_cylinder(dives[i], indexes[i]);
divelog.dives.update_cylinder_related_info(dives[i]); divelog.dives.update_cylinder_related_info(*dives[i]);
emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]); emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save() invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
} }
@ -1114,7 +1114,7 @@ void AddCylinder::redo()
int index = first_hidden_cylinder(d); int index = first_hidden_cylinder(d);
indexes.push_back(index); indexes.push_back(index);
add_cylinder(&d->cylinders, index, cyl); add_cylinder(&d->cylinders, index, cyl);
divelog.dives.update_cylinder_related_info(d); divelog.dives.update_cylinder_related_info(*d);
emit diveListNotifier.cylinderAdded(d, index); emit diveListNotifier.cylinderAdded(d, index);
invalidate_dive_cache(d); // Ensure that dive is written in git_save() invalidate_dive_cache(d); // Ensure that dive is written in git_save()
} }
@ -1201,7 +1201,7 @@ void RemoveCylinder::undo()
std::vector<int> mapping = get_cylinder_map_for_add(dives[i]->cylinders.size(), indexes[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]); add_cylinder(&dives[i]->cylinders, indexes[i], cyl[i]);
cylinder_renumber(*dives[i], &mapping[0]); cylinder_renumber(*dives[i], &mapping[0]);
divelog.dives.update_cylinder_related_info(dives[i]); divelog.dives.update_cylinder_related_info(*dives[i]);
emit diveListNotifier.cylinderAdded(dives[i], indexes[i]); emit diveListNotifier.cylinderAdded(dives[i], indexes[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save() invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
} }
@ -1213,7 +1213,7 @@ void RemoveCylinder::redo()
std::vector<int> mapping = get_cylinder_map_for_remove(dives[i]->cylinders.size(), indexes[i]); std::vector<int> mapping = get_cylinder_map_for_remove(dives[i]->cylinders.size(), indexes[i]);
remove_cylinder(dives[i], indexes[i]); remove_cylinder(dives[i], indexes[i]);
cylinder_renumber(*dives[i], &mapping[0]); cylinder_renumber(*dives[i], &mapping[0]);
divelog.dives.update_cylinder_related_info(dives[i]); divelog.dives.update_cylinder_related_info(*dives[i]);
emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]); emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save() invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
} }
@ -1273,7 +1273,7 @@ void EditCylinder::redo()
const 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); set_tank_info_data(tank_info_table, name, cyl[i].type.size, cyl[i].type.workingpressure);
std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]); std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]);
divelog.dives.update_cylinder_related_info(dives[i]); divelog.dives.update_cylinder_related_info(*dives[i]);
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]); emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save() invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
} }

View file

@ -2,6 +2,8 @@
#include "command_event.h" #include "command_event.h"
#include "core/dive.h" #include "core/dive.h"
#include "core/divelist.h"
#include "core/divelog.h"
#include "core/selection.h" #include "core/selection.h"
#include "core/subsurface-qt/divelistnotifier.h" #include "core/subsurface-qt/divelistnotifier.h"
#include "core/libdivecomputer.h" #include "core/libdivecomputer.h"
@ -145,7 +147,7 @@ void RemoveEvent::post() const
if (cylinder < 0) if (cylinder < 0)
return; return;
fixup_dive(d); divelog.dives.fixup_dive(*d);
emit diveListNotifier.cylinderEdited(d, cylinder); emit diveListNotifier.cylinderEdited(d, cylinder);
// TODO: This is silly we send a DURATION change event so that the statistics are recalculated. // TODO: This is silly we send a DURATION change event so that the statistics are recalculated.
@ -199,7 +201,7 @@ void AddGasSwitch::redoit()
eventsToRemove = std::move(newEventsToRemove); eventsToRemove = std::move(newEventsToRemove);
// this means we potentially have a new tank that is being used and needs to be shown // this means we potentially have a new tank that is being used and needs to be shown
fixup_dive(d); divelog.dives.fixup_dive(*d);
for (int idx: cylinders) for (int idx: cylinders)
emit diveListNotifier.cylinderEdited(d, idx); emit diveListNotifier.cylinderEdited(d, idx);

View file

@ -28,8 +28,6 @@
#include "trip.h" #include "trip.h"
#include "fulltext.h" #include "fulltext.h"
#include <time.h>
// For user visible text but still not translated // For user visible text but still not translated
const char *divemode_text_ui[] = { const char *divemode_text_ui[] = {
QT_TRANSLATE_NOOP("gettextFromC", "Open circuit"), QT_TRANSLATE_NOOP("gettextFromC", "Open circuit"),
@ -53,22 +51,6 @@ dive::dive(dive &&) = default;
dive &dive::operator=(const dive &) = default; dive &dive::operator=(const dive &) = default;
dive::~dive() = default; dive::~dive() = default;
// create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes)
// as a starting point for the user to edit
std::unique_ptr<dive> dive::default_dive()
{
auto d = std::make_unique<dive>();
d->when = time(nullptr) + gettimezoneoffset() + 3600;
d->dcs[0].duration.seconds = 40 * 60;
d->dcs[0].maxdepth.mm = M_OR_FT(15, 45);
d->dcs[0].meandepth.mm = M_OR_FT(13, 39); // this creates a resonable looking safety stop
make_manually_added_dive_dc(&d->dcs[0]);
fake_dc(&d->dcs[0]);
add_default_cylinder(d.get());
fixup_dive(d.get());
return d;
}
/* /*
* The legacy format for sample pressures has a single pressure * The legacy format for sample pressures has a single pressure
* for each sample that can have any sensor, plus a possible * for each sample that can have any sensor, plus a possible
@ -446,13 +428,13 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
} }
} }
static void update_min_max_temperatures(struct dive *dive, temperature_t temperature) static void update_min_max_temperatures(struct dive &dive, temperature_t temperature)
{ {
if (temperature.mkelvin) { if (temperature.mkelvin) {
if (!dive->maxtemp.mkelvin || temperature.mkelvin > dive->maxtemp.mkelvin) if (!dive.maxtemp.mkelvin || temperature.mkelvin > dive.maxtemp.mkelvin)
dive->maxtemp = temperature; dive.maxtemp = temperature;
if (!dive->mintemp.mkelvin || temperature.mkelvin < dive->mintemp.mkelvin) if (!dive.mintemp.mkelvin || temperature.mkelvin < dive.mintemp.mkelvin)
dive->mintemp = temperature; dive.mintemp = temperature;
} }
} }
@ -604,9 +586,9 @@ static void sanitize_cylinder_type(cylinder_type_t &type)
match_standard_cylinder(type); match_standard_cylinder(type);
} }
static void sanitize_cylinder_info(struct dive *dive) static void sanitize_cylinder_info(struct dive &dive)
{ {
for (auto &cyl :dive->cylinders) { for (auto &cyl: dive.cylinders) {
sanitize_gasmix(cyl.gasmix); sanitize_gasmix(cyl.gasmix);
sanitize_cylinder_type(cyl.type); sanitize_cylinder_type(cyl.type);
} }
@ -640,9 +622,9 @@ pressure_t dive::calculate_surface_pressure() const
return res; return res;
} }
static void fixup_surface_pressure(struct dive *dive) static void fixup_surface_pressure(struct dive &dive)
{ {
dive->surface_pressure = dive->calculate_surface_pressure(); dive.surface_pressure = dive.calculate_surface_pressure();
} }
/* if the surface pressure in the dive data is redundant to the calculated /* if the surface pressure in the dive data is redundant to the calculated
@ -654,12 +636,12 @@ pressure_t dive::un_fixup_surface_pressure() const
pressure_t() : surface_pressure; pressure_t() : surface_pressure;
} }
static void fixup_water_salinity(struct dive *dive) static void fixup_water_salinity(struct dive &dive)
{ {
int sum = 0, nr = 0; int sum = 0, nr = 0;
bool logged = dive->is_logged(); bool logged = dive.is_logged();
for (auto &dc: dive->dcs) { for (auto &dc: dive.dcs) {
if ((logged || !is_dc_planner(&dc)) && dc.salinity) { if ((logged || !is_dc_planner(&dc)) && dc.salinity) {
if (dc.salinity < 500) if (dc.salinity < 500)
dc.salinity += FRESHWATER_SALINITY; dc.salinity += FRESHWATER_SALINITY;
@ -668,7 +650,7 @@ static void fixup_water_salinity(struct dive *dive)
} }
} }
if (nr) if (nr)
dive->salinity = (sum + nr / 2) / nr; dive.salinity = (sum + nr / 2) / nr;
} }
int get_dive_salinity(const struct dive *dive) int get_dive_salinity(const struct dive *dive)
@ -676,12 +658,12 @@ int get_dive_salinity(const struct dive *dive)
return dive->user_salinity ? dive->user_salinity : dive->salinity; return dive->user_salinity ? dive->user_salinity : dive->salinity;
} }
static void fixup_meandepth(struct dive *dive) static void fixup_meandepth(struct dive &dive)
{ {
int sum = 0, nr = 0; int sum = 0, nr = 0;
bool logged = dive->is_logged(); bool logged = dive.is_logged();
for (auto &dc: dive->dcs) { for (auto &dc: dive.dcs) {
if ((logged || !is_dc_planner(&dc)) && dc.meandepth.mm) { if ((logged || !is_dc_planner(&dc)) && dc.meandepth.mm) {
sum += dc.meandepth.mm; sum += dc.meandepth.mm;
nr++; nr++;
@ -689,31 +671,31 @@ static void fixup_meandepth(struct dive *dive)
} }
if (nr) if (nr)
dive->meandepth.mm = (sum + nr / 2) / nr; dive.meandepth.mm = (sum + nr / 2) / nr;
} }
static void fixup_duration(struct dive *dive) static void fixup_duration(struct dive &dive)
{ {
duration_t duration = { }; duration_t duration;
bool logged = dive->is_logged(); bool logged = dive.is_logged();
for (auto &dc: dive->dcs) { for (auto &dc: dive.dcs) {
if (logged || !is_dc_planner(&dc)) if (logged || !is_dc_planner(&dc))
duration.seconds = std::max(duration.seconds, dc.duration.seconds); duration.seconds = std::max(duration.seconds, dc.duration.seconds);
} }
dive->duration.seconds = duration.seconds; dive.duration.seconds = duration.seconds;
} }
static void fixup_watertemp(struct dive *dive) static void fixup_watertemp(struct dive &dive)
{ {
if (!dive->watertemp.mkelvin) if (!dive.watertemp.mkelvin)
dive->watertemp = dive->dc_watertemp(); dive.watertemp = dive.dc_watertemp();
} }
static void fixup_airtemp(struct dive *dive) static void fixup_airtemp(struct dive &dive)
{ {
if (!dive->airtemp.mkelvin) if (!dive.airtemp.mkelvin)
dive->airtemp = dive->dc_airtemp(); dive.airtemp = dive.dc_airtemp();
} }
/* if the air temperature in the dive data is redundant to the one in its /* if the air temperature in the dive data is redundant to the one in its
@ -772,7 +754,7 @@ static int interpolate_depth(struct divecomputer &dc, int idx, int lastdepth, in
return interpolate(lastdepth, nextdepth, now-lasttime, nexttime-lasttime); return interpolate(lastdepth, nextdepth, now-lasttime, nexttime-lasttime);
} }
static void fixup_dc_depths(struct dive *dive, struct divecomputer &dc) static void fixup_dc_depths(struct dive &dive, struct divecomputer &dc)
{ {
int maxdepth = dc.maxdepth.mm; int maxdepth = dc.maxdepth.mm;
int lasttime = 0, lastdepth = 0; int lasttime = 0, lastdepth = 0;
@ -793,14 +775,14 @@ static void fixup_dc_depths(struct dive *dive, struct divecomputer &dc)
lastdepth = depth; lastdepth = depth;
lasttime = time; lasttime = time;
if (sample.cns > dive->maxcns) if (sample.cns > dive.maxcns)
dive->maxcns = sample.cns; dive.maxcns = sample.cns;
} }
update_depth(&dc.maxdepth, maxdepth); update_depth(&dc.maxdepth, maxdepth);
if (!dive->is_logged() || !is_dc_planner(&dc)) if (!dive.is_logged() || !is_dc_planner(&dc))
if (maxdepth > dive->maxdepth.mm) if (maxdepth > dive.maxdepth.mm)
dive->maxdepth.mm = maxdepth; dive.maxdepth.mm = maxdepth;
} }
static void fixup_dc_ndl(struct divecomputer &dc) static void fixup_dc_ndl(struct divecomputer &dc)
@ -813,7 +795,7 @@ static void fixup_dc_ndl(struct divecomputer &dc)
} }
} }
static void fixup_dc_temp(struct dive *dive, struct divecomputer &dc) static void fixup_dc_temp(struct dive &dive, struct divecomputer &dc)
{ {
int mintemp = 0, lasttemp = 0; int mintemp = 0, lasttemp = 0;
@ -866,19 +848,19 @@ static void simplify_dc_pressures(struct divecomputer &dc)
} }
/* Do we need a sensor -> cylinder mapping? */ /* Do we need a sensor -> cylinder mapping? */
static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p) static void fixup_start_pressure(struct dive &dive, int idx, pressure_t p)
{ {
if (idx >= 0 && static_cast<size_t>(idx) < dive->cylinders.size()) { if (idx >= 0 && static_cast<size_t>(idx) < dive.cylinders.size()) {
cylinder_t &cyl = dive->cylinders[idx]; cylinder_t &cyl = dive.cylinders[idx];
if (p.mbar && !cyl.sample_start.mbar) if (p.mbar && !cyl.sample_start.mbar)
cyl.sample_start = p; cyl.sample_start = p;
} }
} }
static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p) static void fixup_end_pressure(struct dive &dive, int idx, pressure_t p)
{ {
if (idx >= 0 && static_cast<size_t>(idx) < dive->cylinders.size()) { if (idx >= 0 && static_cast<size_t>(idx) < dive.cylinders.size()) {
cylinder_t &cyl = dive->cylinders[idx]; cylinder_t &cyl = dive.cylinders[idx];
if (p.mbar && !cyl.sample_end.mbar) if (p.mbar && !cyl.sample_end.mbar)
cyl.sample_end = p; cyl.sample_end = p;
} }
@ -897,7 +879,7 @@ static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
* for computers like the Uemis Zurich that end up saving * for computers like the Uemis Zurich that end up saving
* quite a bit of samples after the dive has ended). * quite a bit of samples after the dive has ended).
*/ */
static void fixup_dive_pressures(struct dive *dive, struct divecomputer &dc) static void fixup_dive_pressures(struct dive &dive, struct divecomputer &dc)
{ {
/* Walk the samples from the beginning to find starting pressures.. */ /* Walk the samples from the beginning to find starting pressures.. */
for (auto &sample: dc.samples) { for (auto &sample: dc.samples) {
@ -923,7 +905,7 @@ static void fixup_dive_pressures(struct dive *dive, struct divecomputer &dc)
/* /*
* Match a gas change event against the cylinders we have * Match a gas change event against the cylinders we have
*/ */
static bool validate_gaschange(struct dive *dive, struct event &event) static bool validate_gaschange(struct dive &dive, struct event &event)
{ {
int index; int index;
int o2, he, value; int o2, he, value;
@ -936,13 +918,13 @@ static bool validate_gaschange(struct dive *dive, struct event &event)
if (event.gas.index >= 0) if (event.gas.index >= 0)
return true; return true;
index = find_best_gasmix_match(event.gas.mix, dive->cylinders); index = find_best_gasmix_match(event.gas.mix, dive.cylinders);
if (index < 0 || static_cast<size_t>(index) >= dive->cylinders.size()) if (index < 0 || static_cast<size_t>(index) >= dive.cylinders.size())
return false; return false;
/* Fix up the event to have the right information */ /* Fix up the event to have the right information */
event.gas.index = index; event.gas.index = index;
event.gas.mix = dive->cylinders[index].gasmix; event.gas.mix = dive.cylinders[index].gasmix;
/* Convert to odd libdivecomputer format */ /* Convert to odd libdivecomputer format */
o2 = get_o2(event.gas.mix); o2 = get_o2(event.gas.mix);
@ -960,19 +942,19 @@ static bool validate_gaschange(struct dive *dive, struct event &event)
} }
/* Clean up event, return true if event is ok, false if it should be dropped as bogus */ /* Clean up event, return true if event is ok, false if it should be dropped as bogus */
static bool validate_event(struct dive *dive, struct event &event) static bool validate_event(struct dive &dive, struct event &event)
{ {
if (event.is_gaschange()) if (event.is_gaschange())
return validate_gaschange(dive, event); return validate_gaschange(dive, event);
return true; return true;
} }
static void fixup_dc_gasswitch(struct dive *dive, struct divecomputer &dc) static void fixup_dc_gasswitch(struct dive &dive, struct divecomputer &dc)
{ {
// erase-remove idiom // erase-remove idiom
auto &events = dc.events; auto &events = dc.events;
events.erase(std::remove_if(events.begin(), events.end(), events.erase(std::remove_if(events.begin(), events.end(),
[dive](auto &ev) { return !validate_event(dive, ev); }), [&dive](auto &ev) { return !validate_event(dive, ev); }),
events.end()); events.end());
} }
@ -1000,7 +982,7 @@ static void fixup_no_o2sensors(struct divecomputer &dc)
} }
} }
static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer &dc) static void fixup_dc_sample_sensors(struct dive &dive, struct divecomputer &dc)
{ {
unsigned long sensor_mask = 0; unsigned long sensor_mask = 0;
@ -1027,16 +1009,16 @@ static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer &dc)
} }
// Ignore the sensors we have cylinders for // Ignore the sensors we have cylinders for
sensor_mask >>= dive->cylinders.size(); sensor_mask >>= dive.cylinders.size();
// Do we need to add empty cylinders? // Do we need to add empty cylinders?
while (sensor_mask) { while (sensor_mask) {
add_empty_cylinder(&dive->cylinders); add_empty_cylinder(&dive.cylinders);
sensor_mask >>= 1; sensor_mask >>= 1;
} }
} }
static void fixup_dive_dc(struct dive *dive, struct divecomputer &dc) static void fixup_dive_dc(struct dive &dive, struct divecomputer &dc)
{ {
/* Fixup duration and mean depth */ /* Fixup duration and mean depth */
fixup_dc_duration(dc); fixup_dc_duration(dc);
@ -1069,44 +1051,38 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer &dc)
fake_dc(&dc); fake_dc(&dc);
} }
struct dive *fixup_dive(struct dive *dive) void dive::fixup_no_cylinder()
{ {
sanitize_cylinder_info(dive); sanitize_cylinder_info(*this);
dive->maxcns = dive->cns; maxcns = cns;
/* /*
* Use the dive's temperatures for minimum and maximum in case * Use the dive's temperatures for minimum and maximum in case
* we do not have temperatures recorded by DC. * we do not have temperatures recorded by DC.
*/ */
update_min_max_temperatures(dive, dive->watertemp); update_min_max_temperatures(*this, watertemp);
for (auto &dc: dive->dcs) for (auto &dc: dcs)
fixup_dive_dc(dive, dc); fixup_dive_dc(*this, dc);
fixup_water_salinity(dive); fixup_water_salinity(*this);
if (!dive->surface_pressure.mbar) if (!surface_pressure.mbar)
fixup_surface_pressure(dive); fixup_surface_pressure(*this);
fixup_meandepth(dive); fixup_meandepth(*this);
fixup_duration(dive); fixup_duration(*this);
fixup_watertemp(dive); fixup_watertemp(*this);
fixup_airtemp(dive); fixup_airtemp(*this);
for (auto &cyl: dive->cylinders) { for (auto &cyl: cylinders) {
add_cylinder_description(cyl.type); add_cylinder_description(cyl.type);
if (same_rounded_pressure(cyl.sample_start, cyl.start)) if (same_rounded_pressure(cyl.sample_start, cyl.start))
cyl.start.mbar = 0; cyl.start.mbar = 0;
if (same_rounded_pressure(cyl.sample_end, cyl.end)) if (same_rounded_pressure(cyl.sample_end, cyl.end))
cyl.end.mbar = 0; cyl.end.mbar = 0;
} }
divelog.dives.update_cylinder_related_info(dive);
for (auto &ws: dive->weightsystems)
add_weightsystem_description(ws);
/* we should always have a uniq ID as that gets assigned during dive creation,
* but we want to make sure... */
if (!dive->id)
dive->id = dive_getUniqID();
return dive; for (auto &ws: weightsystems)
add_weightsystem_description(ws);
} }
/* Don't pick a zero for MERGE_MIN() */ /* Don't pick a zero for MERGE_MIN() */
@ -2316,62 +2292,10 @@ merge_result merge_dives(const struct dive &a_in, const struct dive &b_in, int o
* Keep the dive site, but add the GPS data */ * Keep the dive site, but add the GPS data */
res.site->location = b->dive_site->location; res.site->location = b->dive_site->location;
} }
fixup_dive(res.dive.get()); divelog.dives.fixup_dive(*res.dive);
return res; return res;
} }
struct start_end_pressure {
pressure_t start;
pressure_t end;
};
static void force_fixup_dive(struct dive *d)
{
struct divecomputer *dc = &d->dcs[0];
int old_temp = dc->watertemp.mkelvin;
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.size());
d->maxdepth.mm = 0;
dc->maxdepth.mm = 0;
d->watertemp.mkelvin = 0;
dc->watertemp.mkelvin = 0;
d->duration.seconds = 0;
d->maxtemp.mkelvin = 0;
d->mintemp.mkelvin = 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);
if (!d->watertemp.mkelvin)
d->watertemp.mkelvin = old_temp;
if (!dc->watertemp.mkelvin)
dc->watertemp.mkelvin = old_temp;
if (!d->maxtemp.mkelvin)
d->maxtemp.mkelvin = old_maxtemp;
if (!d->mintemp.mkelvin)
d->mintemp.mkelvin = old_mintemp;
if (!d->duration.seconds)
d->duration = old_duration;
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;
}
}
/* /*
* Split a dive that has a surface interval from samples 'a' to 'b' * Split a dive that has a surface interval from samples 'a' to 'b'
* into two dives, but don't add them to the log yet. * into two dives, but don't add them to the log yet.
@ -2457,8 +2381,8 @@ static std::array<std::unique_ptr<dive>, 2> split_dive_at(const struct dive &div
++it2; ++it2;
} }
force_fixup_dive(d1.get()); divelog.dives.force_fixup_dive(*d1);
force_fixup_dive(d2.get()); divelog.dives.force_fixup_dive(*d2);
/* /*
* Was the dive numbered? If it was the last dive, then we'll * Was the dive numbered? If it was the last dive, then we'll
@ -2677,7 +2601,7 @@ std::unique_ptr<dive> clone_delete_divecomputer(const struct dive &d, int dc_num
res->dcs.erase(res->dcs.begin() + dc_number); res->dcs.erase(res->dcs.begin() + dc_number);
force_fixup_dive(res.get()); divelog.dives.force_fixup_dive(*res);
return res; return res;
} }
@ -2715,8 +2639,8 @@ std::array<std::unique_ptr<dive>, 2> split_divecomputer(const struct dive &src,
} }
// Recalculate gas data, etc. // Recalculate gas data, etc.
fixup_dive(out1.get()); divelog.dives.fixup_dive(*out1);
fixup_dive(out2.get()); divelog.dives.fixup_dive(*out2);
return { std::move(out1), std::move(out2) }; return { std::move(out1), std::move(out2) };
} }

View file

@ -78,8 +78,8 @@ struct dive {
dive(const dive &); dive(const dive &);
dive(dive &&); dive(dive &&);
dive &operator=(const dive &); dive &operator=(const dive &);
static std::unique_ptr<dive> default_dive();
void fixup_no_cylinder(); /* to fix cylinders, we need the divelist (to calculate cns) */
timestamp_t endtime() const; /* maximum over divecomputers (with samples) */ timestamp_t endtime() const; /* maximum over divecomputers (with samples) */
duration_t totaltime() const; /* maximum over divecomputers (with samples) */ duration_t totaltime() const; /* maximum over divecomputers (with samples) */
temperature_t dc_airtemp() const; /* average over divecomputers */ temperature_t dc_airtemp() const; /* average over divecomputers */
@ -182,7 +182,6 @@ extern int legacy_format_o2pressures(const struct dive *dive, const struct divec
extern bool dive_less_than(const struct dive &a, const struct dive &b); extern bool dive_less_than(const struct dive &a, const struct dive &b);
extern bool dive_less_than_ptr(const struct dive *a, const struct dive *b); extern bool dive_less_than_ptr(const struct dive *a, const struct dive *b);
extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b); extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b);
extern struct dive *fixup_dive(struct dive *dive);
extern int get_dive_salinity(const struct dive *dive); extern int get_dive_salinity(const struct dive *dive);
extern int dive_getUniqID(); extern int dive_getUniqID();
extern std::array<std::unique_ptr<dive>, 2> split_dive(const struct dive &dive); extern std::array<std::unique_ptr<dive>, 2> split_dive(const struct dive &dive);

View file

@ -22,12 +22,88 @@
#include "sample.h" #include "sample.h"
#include "trip.h" #include "trip.h"
#include <time.h>
void dive_table::record_dive(std::unique_ptr<dive> d) void dive_table::record_dive(std::unique_ptr<dive> d)
{ {
fixup_dive(d.get()); fixup_dive(*d);
put(std::move(d)); put(std::move(d));
} }
void dive_table::fixup_dive(struct dive &dive) const
{
dive.fixup_no_cylinder();
update_cylinder_related_info(dive);
}
struct start_end_pressure {
pressure_t start;
pressure_t end;
};
void dive_table::force_fixup_dive(struct dive &d) const
{
struct divecomputer *dc = &d.dcs[0];
int old_temp = dc->watertemp.mkelvin;
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.size());
d.maxdepth.mm = 0;
dc->maxdepth.mm = 0;
d.watertemp.mkelvin = 0;
dc->watertemp.mkelvin = 0;
d.duration.seconds = 0;
d.maxtemp.mkelvin = 0;
d.mintemp.mkelvin = 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);
if (!d.watertemp.mkelvin)
d.watertemp.mkelvin = old_temp;
if (!dc->watertemp.mkelvin)
dc->watertemp.mkelvin = old_temp;
if (!d.maxtemp.mkelvin)
d.maxtemp.mkelvin = old_maxtemp;
if (!d.mintemp.mkelvin)
d.mintemp.mkelvin = old_mintemp;
if (!d.duration.seconds)
d.duration = old_duration;
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;
}
}
// create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes)
// as a starting point for the user to edit
std::unique_ptr<dive> dive_table::default_dive()
{
auto d = std::make_unique<dive>();
d->when = time(nullptr) + gettimezoneoffset() + 3600;
d->dcs[0].duration.seconds = 40 * 60;
d->dcs[0].maxdepth.mm = M_OR_FT(15, 45);
d->dcs[0].meandepth.mm = M_OR_FT(13, 39); // this creates a resonable looking safety stop
make_manually_added_dive_dc(&d->dcs[0]);
fake_dc(&d->dcs[0]);
add_default_cylinder(d.get());
fixup_dive(*d);
return d;
}
/* /*
* Get "maximal" dive gas for a dive. * Get "maximal" dive gas for a dive.
* Rules: * Rules:
@ -78,14 +154,14 @@ int total_weight(const struct dive *dive)
return total_grams; return total_grams;
} }
static int active_o2(const struct dive *dive, const struct divecomputer *dc, duration_t time) static int active_o2(const struct dive &dive, const struct divecomputer *dc, duration_t time)
{ {
struct gasmix gas = get_gasmix_at_time(*dive, *dc, time); struct gasmix gas = get_gasmix_at_time(dive, *dc, time);
return get_o2(gas); return get_o2(gas);
} }
// Do not call on first sample as it acccesses the previous sample // Do not call on first sample as it acccesses the previous sample
static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc, const struct sample &sample, const struct sample &psample) static int get_sample_o2(const struct dive &dive, const struct divecomputer *dc, const struct sample &sample, const struct sample &psample)
{ {
int po2i, po2f, po2; int po2i, po2f, po2;
// Use sensor[0] if available // Use sensor[0] if available
@ -95,13 +171,13 @@ static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc,
po2 = (po2f + po2i) / 2; po2 = (po2f + po2i) / 2;
} else if (sample.setpoint.mbar > 0) { } else if (sample.setpoint.mbar > 0) {
po2 = std::min((int) sample.setpoint.mbar, po2 = std::min((int) sample.setpoint.mbar,
dive->depth_to_mbar(sample.depth.mm)); dive.depth_to_mbar(sample.depth.mm));
} else { } else {
double amb_presure = dive->depth_to_bar(sample.depth.mm); double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive->depth_to_bar(psample.depth.mm ); double pamb_pressure = dive.depth_to_bar(psample.depth.mm );
if (dc->divemode == PSCR) { if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(*dive, *dc, psample.time)); po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, *dc, psample.time));
po2f = pscr_o2(amb_presure, get_gasmix_at_time(*dive, *dc, sample.time)); po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, *dc, sample.time));
} else { } else {
int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2. int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2.
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
@ -119,10 +195,10 @@ static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc,
Comroe Jr. JH et al. (1945) Oxygen toxicity. J. Am. Med. Assoc. 128,710-717 Comroe Jr. JH et al. (1945) Oxygen toxicity. J. Am. Med. Assoc. 128,710-717
Clark JM & CJ Lambertsen (1970) Pulmonary oxygen tolerance in man and derivation of pulmonary Clark JM & CJ Lambertsen (1970) Pulmonary oxygen tolerance in man and derivation of pulmonary
oxygen tolerance curves. Inst. env. Med. Report 1-70, University of Pennsylvania, Philadelphia, USA. */ oxygen tolerance curves. Inst. env. Med. Report 1-70, University of Pennsylvania, Philadelphia, USA. */
static int calculate_otu(const struct dive *dive) static int calculate_otu(const struct dive &dive)
{ {
double otu = 0.0; double otu = 0.0;
const struct divecomputer *dc = &dive->dcs[0]; const struct divecomputer *dc = &dive.dcs[0];
for (auto [psample, sample]: pairwise_range(dc->samples)) { for (auto [psample, sample]: pairwise_range(dc->samples)) {
int t; int t;
int po2i, po2f; int po2i, po2f;
@ -135,18 +211,18 @@ static int calculate_otu(const struct dive *dive)
} else { } else {
if (sample.setpoint.mbar > 0) { if (sample.setpoint.mbar > 0) {
po2f = std::min((int) sample.setpoint.mbar, po2f = std::min((int) sample.setpoint.mbar,
dive->depth_to_mbar(sample.depth.mm)); dive.depth_to_mbar(sample.depth.mm));
if (psample.setpoint.mbar > 0) if (psample.setpoint.mbar > 0)
po2i = std::min((int) psample.setpoint.mbar, po2i = std::min((int) psample.setpoint.mbar,
dive->depth_to_mbar(psample.depth.mm)); dive.depth_to_mbar(psample.depth.mm));
else else
po2i = po2f; po2i = po2f;
} else { // For OC and rebreather without o2 sensor/setpoint } else { // For OC and rebreather without o2 sensor/setpoint
double amb_presure = dive->depth_to_bar(sample.depth.mm); double amb_presure = dive.depth_to_bar(sample.depth.mm);
double pamb_pressure = dive->depth_to_bar(psample.depth.mm); double pamb_pressure = dive.depth_to_bar(psample.depth.mm);
if (dc->divemode == PSCR) { if (dc->divemode == PSCR) {
po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(*dive, *dc, psample.time)); po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, *dc, psample.time));
po2f = pscr_o2(amb_presure, get_gasmix_at_time(*dive, *dc, sample.time)); po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, *dc, sample.time));
} else { } else {
int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2. int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2.
po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment
@ -189,7 +265,7 @@ static double calculate_cns_dive(const struct dive &dive)
/* Calculate the CNS for each sample in this dive and sum them */ /* Calculate the CNS for each sample in this dive and sum them */
for (auto [psample, sample]: pairwise_range(dc->samples)) { for (auto [psample, sample]: pairwise_range(dc->samples)) {
int t = sample.time.seconds - psample.time.seconds; int t = sample.time.seconds - psample.time.seconds;
int po2 = get_sample_o2(&dive, dc, sample, psample); int po2 = get_sample_o2(dive, dc, sample, psample);
/* Don't increase CNS when po2 below 500 matm */ /* Don't increase CNS when po2 below 500 matm */
if (po2 <= 500) if (po2 <= 500)
continue; continue;
@ -201,19 +277,19 @@ static double calculate_cns_dive(const struct dive &dive)
return cns; return cns;
} }
/* this only gets called if dive->maxcns == 0 which means we know that /* this only gets called if dive.maxcns == 0 which means we know that
* none of the divecomputers has tracked any CNS for us * none of the divecomputers has tracked any CNS for us
* so we calculated it "by hand" */ * so we calculated it "by hand" */
int dive_table::calculate_cns(struct dive *dive) const int dive_table::calculate_cns(struct dive &dive) const
{ {
double cns = 0.0; double cns = 0.0;
timestamp_t last_starttime, last_endtime = 0; timestamp_t last_starttime, last_endtime = 0;
/* shortcut */ /* shortcut */
if (dive->cns) if (dive.cns)
return dive->cns; return dive.cns;
size_t divenr = get_idx(dive); size_t divenr = get_idx(&dive);
int nr_dives = static_cast<int>(size()); int nr_dives = static_cast<int>(size());
int i = divenr != std::string::npos ? static_cast<int>(divenr) int i = divenr != std::string::npos ? static_cast<int>(divenr)
: nr_dives; : nr_dives;
@ -225,20 +301,20 @@ int dive_table::calculate_cns(struct dive *dive) const
#endif #endif
/* Look at next dive in dive list table and correct i when needed */ /* Look at next dive in dive list table and correct i when needed */
while (i < nr_dives - 1) { while (i < nr_dives - 1) {
if ((*this)[i]->when > dive->when) if ((*this)[i]->when > dive.when)
break; break;
i++; i++;
} }
/* Look at previous dive in dive list table and correct i when needed */ /* Look at previous dive in dive list table and correct i when needed */
while (i > 0) { while (i > 0) {
if ((*this)[i - 1]->when < dive->when) if ((*this)[i - 1]->when < dive.when)
break; break;
i--; i--;
} }
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("Dive number corrected to #%d\n", i); printf("Dive number corrected to #%d\n", i);
#endif #endif
last_starttime = dive->when; last_starttime = dive.when;
/* Walk backwards to check previous dives - how far do we need to go back? */ /* Walk backwards to check previous dives - how far do we need to go back? */
while (i--) { while (i--) {
if (static_cast<size_t>(i) == divenr && i > 0) if (static_cast<size_t>(i) == divenr && i > 0)
@ -249,13 +325,13 @@ int dive_table::calculate_cns(struct dive *dive) const
const struct dive &pdive = *(*this)[i]; const struct dive &pdive = *(*this)[i];
/* we don't want to mix dives from different trips as we keep looking /* we don't want to mix dives from different trips as we keep looking
* for how far back we need to go */ * for how far back we need to go */
if (dive->divetrip && pdive.divetrip != dive->divetrip) { if (dive.divetrip && pdive.divetrip != dive.divetrip) {
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("No - other dive trip\n"); printf("No - other dive trip\n");
#endif #endif
continue; continue;
} }
if (pdive.when >= dive->when || pdive.endtime() + 12 * 60 * 60 < last_starttime) { if (pdive.when >= dive.when || pdive.endtime() + 12 * 60 * 60 < last_starttime) {
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("No\n"); printf("No\n");
#endif #endif
@ -273,14 +349,14 @@ int dive_table::calculate_cns(struct dive *dive) const
#endif #endif
const struct dive &pdive = *(*this)[i]; const struct dive &pdive = *(*this)[i];
/* again skip dives from different trips */ /* again skip dives from different trips */
if (dive->divetrip && dive->divetrip != pdive.divetrip) { if (dive.divetrip && dive.divetrip != pdive.divetrip) {
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("No - other dive trip\n"); printf("No - other dive trip\n");
#endif #endif
continue; continue;
} }
/* Don't add future dives */ /* Don't add future dives */
if (pdive.when >= dive->when) { if (pdive.when >= dive.when) {
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("No - future or same dive\n"); printf("No - future or same dive\n");
#endif #endif
@ -315,32 +391,32 @@ int dive_table::calculate_cns(struct dive *dive) const
/* CNS reduced with 90min halftime during surface interval */ /* CNS reduced with 90min halftime during surface interval */
if (last_endtime) if (last_endtime)
cns /= pow(2, (dive->when - last_endtime) / (90.0 * 60.0)); cns /= pow(2, (dive.when - last_endtime) / (90.0 * 60.0));
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("CNS after last surface interval: %f\n", cns); printf("CNS after last surface interval: %f\n", cns);
#endif #endif
cns += calculate_cns_dive(*dive); cns += calculate_cns_dive(dive);
#if DECO_CALC_DEBUG & 2 #if DECO_CALC_DEBUG & 2
printf("CNS after dive: %f\n", cns); printf("CNS after dive: %f\n", cns);
#endif #endif
/* save calculated cns in dive struct */ /* save calculated cns in dive struct */
dive->cns = lrint(cns); dive.cns = lrint(cns);
return dive->cns; return dive.cns;
} }
/* /*
* Return air usage (in liters). * Return air usage (in liters).
*/ */
static double calculate_airuse(const struct dive *dive) static double calculate_airuse(const struct dive &dive)
{ {
int airuse = 0; int airuse = 0;
// SAC for a CCR dive does not make sense. // SAC for a CCR dive does not make sense.
if (dive->dcs[0].divemode == CCR) if (dive.dcs[0].divemode == CCR)
return 0.0; return 0.0;
for (auto [i, cyl]: enumerated_range(dive->cylinders)) { for (auto [i, cyl]: enumerated_range(dive.cylinders)) {
pressure_t start, end; pressure_t start, end;
start = cyl.start.mbar ? cyl.start : cyl.sample_start; start = cyl.start.mbar ? cyl.start : cyl.sample_start;
@ -350,7 +426,7 @@ static double calculate_airuse(const struct dive *dive)
// better not pretend we know the total gas use. // better not pretend we know the total gas use.
// Eventually, logic should be fixed to compute average depth and total time // Eventually, logic should be fixed to compute average depth and total time
// for those segments where cylinders with known pressure drop are breathed from. // for those segments where cylinders with known pressure drop are breathed from.
if (is_cylinder_used(dive, i)) if (is_cylinder_used(&dive, i))
return 0.0; return 0.0;
else else
continue; continue;
@ -362,9 +438,9 @@ static double calculate_airuse(const struct dive *dive)
} }
/* this only uses the first divecomputer to calculate the SAC rate */ /* this only uses the first divecomputer to calculate the SAC rate */
static int calculate_sac(const struct dive *dive) static int calculate_sac(const struct dive &dive)
{ {
const struct divecomputer *dc = &dive->dcs[0]; const struct divecomputer *dc = &dive.dcs[0];
double airuse, pressure, sac; double airuse, pressure, sac;
int duration, meandepth; int duration, meandepth;
@ -381,7 +457,7 @@ static int calculate_sac(const struct dive *dive)
return 0; return 0;
/* Mean pressure in ATM (SAC calculations are in atm*l/min) */ /* Mean pressure in ATM (SAC calculations are in atm*l/min) */
pressure = dive->depth_to_atm(meandepth); pressure = dive.depth_to_atm(meandepth);
sac = airuse / pressure * 60 / duration; sac = airuse / pressure * 60 / duration;
/* milliliters per minute.. */ /* milliliters per minute.. */
@ -389,12 +465,12 @@ static int calculate_sac(const struct dive *dive)
} }
/* for now we do this based on the first divecomputer */ /* for now we do this based on the first divecomputer */
static void add_dive_to_deco(struct deco_state *ds, const struct dive *dive, bool in_planner) static void add_dive_to_deco(struct deco_state *ds, const struct dive &dive, bool in_planner)
{ {
const struct divecomputer *dc = &dive->dcs[0]; const struct divecomputer *dc = &dive.dcs[0];
gasmix_loop loop(*dive, dive->dcs[0]); gasmix_loop loop(dive, dive.dcs[0]);
divemode_loop loop_d(dive->dcs[0]); divemode_loop loop_d(dive.dcs[0]);
for (auto [psample, sample]: pairwise_range(dc->samples)) { for (auto [psample, sample]: pairwise_range(dc->samples)) {
int t0 = psample.time.seconds; int t0 = psample.time.seconds;
int t1 = sample.time.seconds; int t1 = sample.time.seconds;
@ -403,8 +479,8 @@ static void add_dive_to_deco(struct deco_state *ds, const struct dive *dive, boo
for (j = t0; j < t1; j++) { for (j = t0; j < t1; j++) {
int depth = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0); int depth = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0);
auto gasmix = loop.next(j); auto gasmix = loop.next(j);
add_segment(ds, dive->depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar, add_segment(ds, dive.depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar,
loop_d.next(j), dive->sac, loop_d.next(j), dive.sac,
in_planner); in_planner);
} }
} }
@ -536,7 +612,7 @@ int dive_table::init_decompression(struct deco_state *ds, const struct dive *div
#endif #endif
} }
add_dive_to_deco(ds, &pdive, in_planner); add_dive_to_deco(ds, pdive, in_planner);
last_starttime = pdive.when; last_starttime = pdive.when;
last_endtime = pdive.endtime(); last_endtime = pdive.endtime();
@ -578,14 +654,12 @@ int dive_table::init_decompression(struct deco_state *ds, const struct dive *div
return surface_time; return surface_time;
} }
void dive_table::update_cylinder_related_info(struct dive *dive) const void dive_table::update_cylinder_related_info(struct dive &dive) const
{ {
if (dive != NULL) { dive.sac = calculate_sac(dive);
dive->sac = calculate_sac(dive); dive.otu = calculate_otu(dive);
dive->otu = calculate_otu(dive); if (dive.maxcns == 0)
if (dive->maxcns == 0) dive.maxcns = calculate_cns(dive);
dive->maxcns = calculate_cns(dive);
}
} }
/* Compare list of dive computers by model name */ /* Compare list of dive computers by model name */

View file

@ -21,14 +21,20 @@ struct dive_table : public sorted_owning_table<dive, &comp_dives> {
void record_dive(std::unique_ptr<dive> d); // call fixup_dive() before adding dive to table. void record_dive(std::unique_ptr<dive> d); // call fixup_dive() before adding dive to table.
struct dive *register_dive(std::unique_ptr<dive> d); struct dive *register_dive(std::unique_ptr<dive> d);
std::unique_ptr<dive> unregister_dive(int idx); std::unique_ptr<dive> unregister_dive(int idx);
std::unique_ptr<dive> default_dive(); // generate a sensible looking defaultdive 1h from now.
// Some of these functions act on dives, but need data from adjacent dives,
// notably to calculate CNS, surface interval, etc. Therefore, they are called
// on the dive_table and not on the dive.
void fixup_dive(struct dive &dive) const;
void force_fixup_dive(struct dive &d) const;
int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_planner) const; int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_planner) const;
void update_cylinder_related_info(struct dive *) const; void update_cylinder_related_info(struct dive &dive) const;
int get_dive_nr_at_idx(int idx) const; int get_dive_nr_at_idx(int idx) const;
timestamp_t get_surface_interval(timestamp_t when) const; timestamp_t get_surface_interval(timestamp_t when) const;
struct dive *find_next_visible_dive(timestamp_t when); struct dive *find_next_visible_dive(timestamp_t when);
private: private:
int calculate_cns(struct dive *dive) const; // Note: writes into dive->cns int calculate_cns(struct dive &dive) const; // Note: writes into dive->cns
}; };
/* this is used for both git and xml format */ /* this is used for both git and xml format */

View file

@ -410,7 +410,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
/* Print the CNS and OTU next.*/ /* Print the CNS and OTU next.*/
dive->cns = 0; dive->cns = 0;
dive->maxcns = 0; dive->maxcns = 0;
divelog.dives.update_cylinder_related_info(dive); divelog.dives.update_cylinder_related_info(*dive);
buf += casprintf_loc("<div>\n%s: %i%%", translate("gettextFromC", "CNS"), dive->cns); buf += casprintf_loc("<div>\n%s: %i%%", translate("gettextFromC", "CNS"), dive->cns);
buf += casprintf_loc("<br/>\n%s: %i<br/>\n</div>\n", translate("gettextFromC", "OTU"), dive->otu); buf += casprintf_loc("<br/>\n%s: %i<br/>\n</div>\n", translate("gettextFromC", "OTU"), dive->otu);

View file

@ -698,7 +698,7 @@ void MainWindow::on_actionAddDive_triggered()
if (!plannerStateClean()) if (!plannerStateClean())
return; return;
auto d = dive::default_dive(); auto d = divelog.dives.default_dive();
Command::addDive(std::move(d), divelog.autogroup, true); Command::addDive(std::move(d), divelog.autogroup, true);
} }

View file

@ -347,7 +347,7 @@ void ProfileWidget::exitEditMode()
static void calcDepth(dive &d, int dcNr) static void calcDepth(dive &d, int dcNr)
{ {
d.maxdepth.mm = get_dive_dc(&d, dcNr)->maxdepth.mm = 0; d.maxdepth.mm = get_dive_dc(&d, dcNr)->maxdepth.mm = 0;
fixup_dive(&d); divelog.dives.fixup_dive(d);
} }
// Silly RAII-variable setter class: reset variable when going out of scope. // Silly RAII-variable setter class: reset variable when going out of scope.

View file

@ -1358,7 +1358,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
d->meandepth.mm = d->dcs[0].meandepth.mm = 0; d->meandepth.mm = d->dcs[0].meandepth.mm = 0;
fake_dc(&d->dcs[0]); fake_dc(&d->dcs[0]);
} }
fixup_dive(d); divelog.dives.fixup_dive(*d);
Command::editDive(orig, d_ptr.release(), dsChange.createdDs.release(), dsChange.editDs, dsChange.location); // With release() we're giving up ownership Command::editDive(orig, d_ptr.release(), dsChange.createdDs.release(), dsChange.editDs, dsChange.location); // With release() we're giving up ownership
changesNeedSaving(); changesNeedSaving();
} }
@ -1717,7 +1717,7 @@ int QMLManager::addDive()
{ {
// we do NOT save the modified data at this stage because of the UI flow here... this will // we do NOT save the modified data at this stage because of the UI flow here... this will
// be saved once the user finishes editing the newly added dive // be saved once the user finishes editing the newly added dive
auto d = dive::default_dive(); auto d = divelog.dives.default_dive();
int diveId = d->id; int diveId = d->id;
Command::addDive(std::move(d), divelog.autogroup, true); Command::addDive(std::move(d), divelog.autogroup, true);

View file

@ -708,7 +708,7 @@ void DiveTripModelTree::populate()
uiNotification(QObject::tr("populate data model")); uiNotification(QObject::tr("populate data model"));
uiNotification(QObject::tr("start processing")); uiNotification(QObject::tr("start processing"));
for (auto &d: divelog.dives) { for (auto &d: divelog.dives) {
divelog.dives.update_cylinder_related_info(d.get()); divelog.dives.update_cylinder_related_info(*d);
if (d->hidden_by_filter) if (d->hidden_by_filter)
continue; continue;
dive_trip *trip = d->divetrip; dive_trip *trip = d->divetrip;