Planner: Fix Editing of Plans in Multi-Divecomputer Dives.

Currently editing of planned dives that have been merged with actual
(logged) dives only works if the 'Planned dive' divecomputer is the
first divecomputer, and this divecomputer is selected when clicking
'Edit planned dive'. In other cases the profile of the first
divecomputer is overlaid with the profile of the planned dive, and the
first divecomputer's profile is overwritten when saving the dive plan.
Fix this problem.

Triggered by @SeppoTakalo's comment (https://github.com/subsurface/subsurface/issues/1913#issuecomment-2075562119): Users don't like that planned dives show up as their own entries in the dive list, so being able to merge them with the actual dive after it has been executed is a good feature - but this wasn't working well until now.

Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
Michael Keller 2024-04-26 08:16:08 +12:00
parent a83349015a
commit 528532572f
11 changed files with 114 additions and 106 deletions

View file

@ -339,28 +339,27 @@ extern "C" void selective_copy_dive(const struct dive *s, struct dive *d, struct
}
#undef CONDITIONAL_COPY_STRING
/* copies all events from all dive computers before a given time
/* copies all events from the given dive computer before a given time
this is used when editing a dive in the planner to preserve the events
of the old dive */
extern "C" void copy_events_until(const struct dive *sd, struct dive *dd, int time)
extern "C" void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int time)
{
if (!sd || !dd)
return;
const struct divecomputer *s = &sd->dc;
struct divecomputer *d = &dd->dc;
struct divecomputer *d = get_dive_dc(dd, dcNr);
while (s && d) {
const struct event *ev;
ev = s->events;
while (ev != NULL) {
// Don't add events the planner knows about
if (ev->time.seconds < time && !event_is_gaschange(ev) && !event_is_divemodechange(ev))
add_event(d, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name);
ev = ev->next;
}
s = s->next;
d = d->next;
if (!s || !d)
return;
const struct event *ev;
ev = s->events;
while (ev != NULL) {
// Don't add events the planner knows about
if (ev->time.seconds < time && !event_is_gaschange(ev) && !event_is_divemodechange(ev))
add_event(d, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name);
ev = ev->next;
}
}

View file

@ -186,7 +186,7 @@ extern int split_dive(const struct dive *dive, struct dive **new1, struct dive *
extern int split_dive_at_time(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2);
extern struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site);
extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded);
extern void copy_events_until(const struct dive *sd, struct dive *dd, int time);
extern void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int time);
extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only);
extern bool is_cylinder_used(const struct dive *dive, int idx);
extern bool is_cylinder_prot(const struct dive *dive, int idx);

View file

@ -111,9 +111,8 @@ static void interpolate_transition(struct deco_state *ds, struct dive *dive, dur
}
/* returns the tissue tolerance at the end of this (partial) dive */
static int tissue_at_end(struct deco_state *ds, struct dive *dive, deco_state_cache &cache)
static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct divecomputer *dc, deco_state_cache &cache)
{
struct divecomputer *dc;
struct sample *sample, *psample;
int i;
depth_t lastdepth = {};
@ -129,7 +128,6 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, deco_state_ca
surface_interval = init_decompression(ds, dive, true);
cache.cache(ds);
}
dc = &dive->dc;
if (!dc->samples)
return 0;
psample = sample = dc->sample;
@ -208,10 +206,9 @@ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_dept
/* overwrite the data in dive
* return false if something goes wrong */
static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, bool track_gas)
static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, struct divecomputer *dc, bool track_gas)
{
struct divedatapoint *dp;
struct divecomputer *dc;
struct sample *sample;
struct event *ev;
cylinder_t *cyl;
@ -219,7 +216,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
int lasttime = 0, last_manual_point = 0;
depth_t lastdepth = {.mm = 0};
int lastcylid;
enum divemode_t type = dive->dc.divemode;
enum divemode_t type = dc->divemode;
if (!diveplan || !diveplan->dp)
return;
@ -231,7 +228,6 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
// reset the cylinders and clear out the samples and events of the
// dive-to-be-planned so we can restart
reset_cylinders(dive, track_gas);
dc = &dive->dc;
dc->when = dive->when = diveplan->when;
dc->surface_pressure.mbar = diveplan->surface_pressure;
dc->salinity = diveplan->salinity;
@ -319,7 +315,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
finish_sample(dc);
dp = dp->next;
}
dive->dc.last_manual_time.seconds = last_manual_point;
dc->last_manual_time.seconds = last_manual_point;
#if DEBUG_PLAN & 32
save_dive(stdout, dive);
@ -655,7 +651,7 @@ static void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_de
*avg_depth = *max_depth = 0;
}
bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer)
bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int dcNr, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer)
{
int bottom_depth;
@ -690,15 +686,16 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
int laststoptime = timestep;
bool o2breaking = false;
int decostopcounter = 0;
enum divemode_t divemode = dive->dc.divemode;
struct divecomputer *dc = get_dive_dc(dive, dcNr);
enum divemode_t divemode = dc->divemode;
set_gf(diveplan->gflow, diveplan->gfhigh);
set_vpmb_conservatism(diveplan->vpmb_conservatism);
if (!diveplan->surface_pressure) {
// Lets use dive's surface pressure in planner, if have one...
if (dive->dc.surface_pressure.mbar) { // First from DC...
diveplan->surface_pressure = dive->dc.surface_pressure.mbar;
if (dc->surface_pressure.mbar) { // First from DC...
diveplan->surface_pressure = dc->surface_pressure.mbar;
}
else if (dive->surface_pressure.mbar) { // After from user...
diveplan->surface_pressure = dive->surface_pressure.mbar;
@ -707,10 +704,10 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
diveplan->surface_pressure = SURFACE_PRESSURE;
}
}
clear_deco(ds, dive->surface_pressure.mbar / 1000.0, true);
ds->max_bottom_ceiling_pressure.mbar = ds->first_ceiling_pressure.mbar = 0;
create_dive_from_plan(diveplan, dive, is_planner);
create_dive_from_plan(diveplan, dive, dc, is_planner);
// Do we want deco stop array in metres or feet?
if (prefs.units.length == units::METERS ) {
@ -731,20 +728,20 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
*(decostoplevels + 1) = M_OR_FT(3,10);
/* Let's start at the last 'sample', i.e. the last manually entered waypoint. */
sample = &dive->dc.sample[dive->dc.samples - 1];
sample = &dc->sample[dc->samples - 1];
/* Keep time during the ascend */
bottom_time = clock = previous_point_time = dive->dc.sample[dive->dc.samples - 1].time.seconds;
bottom_time = clock = previous_point_time = dc->sample[dc->samples - 1].time.seconds;
current_cylinder = get_cylinderid_at_time(dive, &dive->dc, sample->time);
current_cylinder = get_cylinderid_at_time(dive, dc, sample->time);
// Find the divemode at the end of the dive
const struct event *ev = NULL;
divemode = UNDEF_COMP_TYPE;
divemode = get_current_divemode(&dive->dc, bottom_time, &ev, &divemode);
divemode = get_current_divemode(dc, bottom_time, &ev, &divemode);
gas = get_cylinder(dive, current_cylinder)->gasmix;
po2 = sample->setpoint.mbar;
depth = dive->dc.sample[dive->dc.samples - 1].depth.mm;
depth = dc->sample[dc->samples - 1].depth.mm;
average_max_depth(diveplan, &avg_depth, &max_depth);
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
@ -755,7 +752,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
*/
transitiontime = lrint(depth / (double)prefs.ascratelast6m);
plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false, divemode);
create_dive_from_plan(diveplan, dive, is_planner);
create_dive_from_plan(diveplan, dive, dc, is_planner);
return false;
}
@ -782,7 +779,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
gi = static_cast<int>(gaschanges.size()) - 1;
/* Set tissue tolerance and initial vpmb gradient at start of ascent phase */
diveplan->surface_interval = tissue_at_end(ds, dive, cache);
diveplan->surface_interval = tissue_at_end(ds, dive, dc, cache);
nuclear_regeneration(ds, clock);
vpmb_start_gradient(ds);
if (decoMode(true) == RECREATIONAL) {
@ -830,9 +827,9 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
} while (depth > 0);
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
create_dive_from_plan(diveplan, dive, is_planner);
create_dive_from_plan(diveplan, dive, dc, is_planner);
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
fixup_dc_duration(&dive->dc);
fixup_dc_duration(dc);
return false;
}
@ -848,7 +845,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
// VPM-B or Buehlmann Deco
tissue_at_end(ds, dive, cache);
tissue_at_end(ds, dive, dc, cache);
if ((divemode == CCR || divemode == PSCR) && prefs.dobailout) {
divemode = OC;
po2 = 0;
@ -1112,9 +1109,9 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
current_cylinder = dive->cylinders.nr;
plan_add_segment(diveplan, prefs.surface_segment, 0, current_cylinder, 0, false, OC);
}
create_dive_from_plan(diveplan, dive, is_planner);
create_dive_from_plan(diveplan, dive, dc, is_planner);
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
fixup_dc_duration(&dive->dc);
fixup_dc_duration(dc);
return decodive;
}

View file

@ -60,6 +60,6 @@ struct decostop {
#include <string>
extern std::string get_planner_disclaimer_formatted();
extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);
extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int dcNr, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);
#endif
#endif // PLANNER_H

View file

@ -23,7 +23,7 @@
#include <QBuffer>
#endif
DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
DivePlannerWidget::DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent)
{
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
CylindersModel *cylinders = DivePlannerPointsModel::instance()->cylindersModel();
@ -52,7 +52,7 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent)
view->setColumnHidden(CylindersModel::SENSORS, true);
view->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this));
auto tankUseDelegate = new TankUseDelegate(this);
tankUseDelegate->setCurrentDC(get_dive_dc(&planned_dive, 0));
tankUseDelegate->setCurrentDC(get_dive_dc(&planned_dive, dcNr));
view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate);
connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked);
connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop);
@ -539,7 +539,8 @@ void PlannerDetails::setPlanNotes(QString plan)
PlannerWidgets::PlannerWidgets() :
planned_dive(alloc_dive()),
plannerWidget(*planned_dive, this),
dcNr(0),
plannerWidget(*planned_dive, dcNr, this),
plannerSettingsWidget(this)
{
connect(plannerDetails.printPlan(), &QPushButton::pressed, this, &PlannerWidgets::printDecoPlan);
@ -556,21 +557,27 @@ struct dive *PlannerWidgets::getDive() const
return planned_dive.get();
}
divemode_t PlannerWidgets::getRebreatherMode() const
int PlannerWidgets::getDcNr()
{
return planned_dive->dc.divemode;
return dcNr;
}
void PlannerWidgets::preparePlanDive(const dive *currentDive)
divemode_t PlannerWidgets::getRebreatherMode() const
{
return get_dive_dc_const(planned_dive.get(), dcNr)->divemode;
}
void PlannerWidgets::preparePlanDive(const dive *currentDive, int currentDcNr)
{
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
// create a simple starting dive, using the first gas from the just copied cylinders
DivePlannerPointsModel::instance()->createSimpleDive(planned_dive.get());
dcNr = 0;
// plan the dive in the same mode as the currently selected one
if (currentDive) {
plannerSettingsWidget.setDiveMode(currentDive->dc.divemode);
plannerSettingsWidget.setBailoutVisibility(currentDive->dc.divemode);
plannerSettingsWidget.setDiveMode(get_dive_dc_const(currentDive, currentDcNr)->divemode);
plannerSettingsWidget.setBailoutVisibility(get_dive_dc_const(currentDive, currentDcNr)->divemode);
if (currentDive->salinity)
plannerWidget.setSalinity(currentDive->salinity);
else // No salinity means salt water
@ -586,15 +593,16 @@ void PlannerWidgets::planDive()
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile!
}
void PlannerWidgets::prepareReplanDive(const dive *d)
void PlannerWidgets::prepareReplanDive(const dive *currentDive, int currentDcNr)
{
copy_dive(d, planned_dive.get());
copy_dive(currentDive, planned_dive.get());
dcNr = currentDcNr;
}
void PlannerWidgets::replanDive(int currentDC)
void PlannerWidgets::replanDive()
{
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
DivePlannerPointsModel::instance()->loadFromDive(planned_dive.get(), currentDC);
DivePlannerPointsModel::instance()->loadFromDive(planned_dive.get(), dcNr);
plannerWidget.setReplanButton(true);
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when));
@ -603,7 +611,7 @@ void PlannerWidgets::replanDive(int currentDC)
if (planned_dive->salinity)
plannerWidget.setSalinity(planned_dive->salinity);
reset_cylinders(planned_dive.get(), true);
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), currentDC);
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), dcNr);
}
void PlannerWidgets::printDecoPlan()

View file

@ -18,7 +18,7 @@ struct dive;
class DivePlannerWidget : public QWidget {
Q_OBJECT
public:
explicit DivePlannerWidget(dive &planned_dive, PlannerWidgets *parent);
explicit DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent);
~DivePlannerWidget();
void setReplanButton(bool replan);
public
@ -80,17 +80,20 @@ class PlannerWidgets : public QObject {
public:
PlannerWidgets();
~PlannerWidgets();
void preparePlanDive(const dive *currentDive); // Create a new planned dive
void preparePlanDive(const dive *currentDive, int currentDc); // Create a new planned dive
void planDive();
void prepareReplanDive(const dive *d); // Make a copy of the dive to be replanned
void replanDive(int currentDC);
void prepareReplanDive(const dive *currentDive, int currentDc); // Make a copy of the dive to be replanned
void replanDive();
struct dive *getDive() const;
int getDcNr();
divemode_t getRebreatherMode() const;
public
slots:
void printDecoPlan();
public:
private:
OwningDivePtr planned_dive;
int dcNr;
public:
DivePlannerWidget plannerWidget;
PlannerSettingsWidget plannerSettingsWidget;
PlannerDetails plannerDetails;

View file

@ -665,8 +665,8 @@ void MainWindow::on_actionReplanDive_triggered()
{
if (!plannerStateClean() || !current_dive || !userMayChangeAppState())
return;
else if (!is_dc_planner(&current_dive->dc)) {
if (QMessageBox::warning(this, tr("Warning"), tr("Trying to replan a dive that's not a planned dive."),
else if (!is_dc_planner(get_dive_dc(current_dive, profile->dc))) {
if (QMessageBox::warning(this, tr("Warning"), tr("Trying to replan a dive dive profile that is not a dive plan."),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
@ -675,9 +675,9 @@ void MainWindow::on_actionReplanDive_triggered()
setApplicationState(ApplicationState::PlanDive);
disableShortcuts(true);
plannerWidgets->prepareReplanDive(current_dive);
profile->setPlanState(plannerWidgets->getDive(), profile->dc);
plannerWidgets->replanDive(profile->dc);
plannerWidgets->prepareReplanDive(current_dive, profile->dc);
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
plannerWidgets->replanDive();
}
void MainWindow::on_actionDivePlanner_triggered()
@ -689,8 +689,8 @@ void MainWindow::on_actionDivePlanner_triggered()
setApplicationState(ApplicationState::PlanDive);
disableShortcuts(true);
plannerWidgets->preparePlanDive(current_dive);
profile->setPlanState(plannerWidgets->getDive(), 0);
plannerWidgets->preparePlanDive(current_dive, profile->dc);
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
plannerWidgets->planDive();
}

View file

@ -157,11 +157,11 @@ void ProfileWidget::setEnabledToolbar(bool enabled)
b->setEnabled(enabled);
}
void ProfileWidget::setDive(const struct dive *d)
void ProfileWidget::setDive(const struct dive *d, int dcNr)
{
stack->setCurrentIndex(1); // show profile
bool freeDiveMode = d->dc.divemode == FREEDIVE;
bool freeDiveMode = get_dive_dc_const(d, dcNr)->divemode == FREEDIVE;
ui.profCalcCeiling->setDisabled(freeDiveMode);
ui.profCalcCeiling->setDisabled(freeDiveMode);
ui.profCalcAllTissues ->setDisabled(freeDiveMode);
@ -217,12 +217,12 @@ void ProfileWidget::plotDive(dive *dIn, int dcIn)
setEnabledToolbar(d != nullptr);
if (editedDive) {
view->plotDive(editedDive.get(), editedDc);
setDive(editedDive.get());
setDive(editedDive.get(), dc);
} else if (d) {
view->setProfileState(d, dc);
view->resetZoom(); // when switching dive, reset the zoomLevel
view->plotDive(d, dc);
setDive(d);
setDive(d, dc);
} else {
view->clear();
stack->setCurrentIndex(0);
@ -274,11 +274,12 @@ void ProfileWidget::divesChanged(const QVector<dive *> &dives, DiveField field)
plotCurrentDive();
}
void ProfileWidget::setPlanState(const struct dive *d, int dc)
void ProfileWidget::setPlanState(const struct dive *d, int dcNr)
{
exitEditMode();
view->setPlanState(d, dc);
setDive(d);
dc = dcNr;
view->setPlanState(d, dcNr);
setDive(d, dcNr);
}
void ProfileWidget::unsetProfHR()

View file

@ -44,7 +44,7 @@ private:
std::vector<QAction *> toolbarActions;
Ui::ProfileWidget ui;
QStackedWidget *stack;
void setDive(const struct dive *d);
void setDive(const struct dive *d, int dcNr);
void editDive();
void exitEditMode();
void rotateDC(int dir);

View file

@ -65,6 +65,7 @@ void DivePlannerPointsModel::createSimpleDive(struct dive *dIn)
{
// clean out the dive and give it an id and the correct dc model
d = dIn;
dcNr = 0;
clear_dive(d);
d->id = dive_getUniqID();
d->when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600;
@ -117,7 +118,7 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn)
int depthsum = 0;
int samplecount = 0;
o2pressure_t last_sp;
struct divecomputer *dc = &(d->dc);
struct divecomputer *dc = get_dive_dc(d, dcNr);
const struct event *evd = NULL;
enum divemode_t current_divemode = UNDEF_COMP_TYPE;
cylinders.updateDive(d, dcNr);
@ -180,9 +181,9 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn)
}
}
// make sure we get the last point right so the duration is correct
current_divemode = get_current_divemode(dc, d->dc.duration.seconds, &evd, &current_divemode);
current_divemode = get_current_divemode(dc, dc->duration.seconds, &evd, &current_divemode);
if (!hasMarkedSamples && !dc->last_manual_time.seconds)
addStop(0, d->dc.duration.seconds,cylinderid, last_sp.mbar, true, current_divemode);
addStop(0, dc->duration.seconds,cylinderid, last_sp.mbar, true, current_divemode);
preserved_until = d->duration;
updateDiveProfile();
@ -549,9 +550,8 @@ int DivePlannerPointsModel::gfLow() const
void DivePlannerPointsModel::setRebreatherMode(int mode)
{
int i;
d->dc.divemode = (divemode_t) mode;
for (i = 0; i < rowCount(); i++) {
get_dive_dc(d, dcNr)->divemode = (divemode_t) mode;
for (int i = 0; i < rowCount(); i++) {
divepoints[i].setpoint = mode == CCR ? prefs.defaultsetpoint : 0;
divepoints[i].divemode = (enum divemode_t) mode;
}
@ -830,7 +830,7 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int cylinderid_
}
}
if (divemode == UNDEF_COMP_TYPE)
divemode = d->dc.divemode;
divemode = get_dive_dc_const(d, dcNr)->divemode;
// add the new stop
beginInsertRows(QModelIndex(), row, row);
@ -1084,7 +1084,7 @@ void DivePlannerPointsModel::updateDiveProfile()
struct deco_state plan_deco_state;
memset(&plan_deco_state, 0, sizeof(struct deco_state));
plan(&plan_deco_state, &diveplan, d, decotimestep, stoptable, cache, isPlanner(), false);
plan(&plan_deco_state, &diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), false);
updateMaxDepth();
if (isPlanner() && shouldComputeVariations()) {
@ -1226,7 +1226,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
goto finish;
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, original, cache, true, false);
plan(&ds, &plan_copy, dive, dcNr, 1, original, cache, true, false);
free_dps(&plan_copy);
save.restore(&ds, false);
@ -1235,7 +1235,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->depth.mm += delta_depth.mm;
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, deeper, cache, true, false);
plan(&ds, &plan_copy, dive, dcNr, 1, deeper, cache, true, false);
free_dps(&plan_copy);
save.restore(&ds, false);
@ -1244,7 +1244,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->depth.mm -= delta_depth.mm;
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, shallower, cache, true, false);
plan(&ds, &plan_copy, dive, dcNr, 1, shallower, cache, true, false);
free_dps(&plan_copy);
save.restore(&ds, false);
@ -1252,7 +1252,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->time += delta_time.seconds;
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, longer, cache, true, false);
plan(&ds, &plan_copy, dive, dcNr, 1, longer, cache, true, false);
free_dps(&plan_copy);
save.restore(&ds, false);
@ -1260,7 +1260,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->time -= delta_time.seconds;
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, shorter, cache, true, false);
plan(&ds, &plan_copy, dive, dcNr, 1, shorter, cache, true, false);
free_dps(&plan_copy);
save.restore(&ds, false);
@ -1296,7 +1296,7 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
createTemporaryPlan();
struct decostop stoptable[60];
plan(&ds_after_previous_dives, &diveplan, d, decotimestep, stoptable, cache, isPlanner(), true);
plan(&ds_after_previous_dives, &diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), true);
if (shouldComputeVariations()) {
struct diveplan *plan_copy;
@ -1349,7 +1349,7 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
Command::addDive(d, divelog.autogroup, true);
#endif // !SUBSURFACE_TESTING
} else {
copy_events_until(current_dive, d, preserved_until.seconds);
copy_events_until(current_dive, d, dcNr, preserved_until.seconds);
if (replanCopy) {
// we were planning an old dive and save as a new dive
d->id = dive_getUniqID(); // Things will break horribly if we create dives with the same id.

View file

@ -15,7 +15,7 @@
static struct dive dive = { 0 };
static struct decostop stoptable[60];
static struct deco_state test_deco_state;
extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);
extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int dcNr, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);
void setupPrefs()
{
copy_prefs(&default_prefs, &prefs);
@ -453,7 +453,7 @@ void TestPlan::testMetric()
struct diveplan testPlan = {};
setupPlan(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -494,7 +494,7 @@ void TestPlan::testImperial()
struct diveplan testPlan = {};
setupPlan(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -534,7 +534,7 @@ void TestPlan::testVpmbMetric45m30minTx()
struct diveplan testPlan = {};
setupPlanVpmb45m30mTx(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -564,7 +564,7 @@ void TestPlan::testVpmbMetric60m10minTx()
struct diveplan testPlan = {};
setupPlanVpmb60m10mTx(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -594,7 +594,7 @@ void TestPlan::testVpmbMetric60m30minAir()
struct diveplan testPlan = {};
setupPlanVpmb60m30minAir(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -624,7 +624,7 @@ void TestPlan::testVpmbMetric60m30minEan50()
struct diveplan testPlan = {};
setupPlanVpmb60m30minEan50(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -660,7 +660,7 @@ void TestPlan::testVpmbMetric60m30minTx()
struct diveplan testPlan = {};
setupPlanVpmb60m30minTx(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -696,7 +696,7 @@ void TestPlan::testVpmbMetric100m60min()
struct diveplan testPlan = {};
setupPlanVpmb100m60min(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -739,7 +739,7 @@ void TestPlan::testMultipleGases()
setupPlanSeveralGases(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -764,7 +764,7 @@ void TestPlan::testVpmbMetricMultiLevelAir()
struct diveplan testPlan = {};
setupPlanVpmbMultiLevelAir(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -794,7 +794,7 @@ void TestPlan::testVpmbMetric100m10min()
struct diveplan testPlan = {};
setupPlanVpmb100m10min(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -840,7 +840,7 @@ void TestPlan::testVpmbMetricRepeat()
struct diveplan testPlan = {};
setupPlanVpmb30m20min(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -861,7 +861,7 @@ void TestPlan::testVpmbMetricRepeat()
int firstDiveRunTimeSeconds = dive.dc.duration.seconds;
setupPlanVpmb100mTo70m30min(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -898,7 +898,7 @@ void TestPlan::testVpmbMetricRepeat()
QVERIFY(compareDecoTime(dive.dc.duration.seconds, 127u * 60u + 20u, 127u * 60u + 20u));
setupPlanVpmb30m20min(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, 1, 0);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
#if DEBUG
free(dive.notes);
@ -937,7 +937,7 @@ void TestPlan::testCcrBailoutGasSelection()
struct diveplan testPlan = {};
setupPlanCcr(&testPlan);
plan(&test_deco_state, &testPlan, &dive, 60, stoptable, cache, true, false);
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, true, false);
#if DEBUG
free(dive.notes);