From 528532572fcf7b4cf4cbfd4783450ec9dbc3b5f4 Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Fri, 26 Apr 2024 08:16:08 +1200 Subject: [PATCH] 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 --- core/dive.cpp | 27 ++++++++--------- core/dive.h | 2 +- core/planner.cpp | 49 +++++++++++++++---------------- core/planner.h | 2 +- desktop-widgets/diveplanner.cpp | 34 +++++++++++++-------- desktop-widgets/diveplanner.h | 13 ++++---- desktop-widgets/mainwindow.cpp | 14 ++++----- desktop-widgets/profilewidget.cpp | 15 +++++----- desktop-widgets/profilewidget.h | 2 +- qt-models/diveplannermodel.cpp | 30 +++++++++---------- tests/testplan.cpp | 32 ++++++++++---------- 11 files changed, 114 insertions(+), 106 deletions(-) diff --git a/core/dive.cpp b/core/dive.cpp index a6fdfe6cd..63be1dea4 100644 --- a/core/dive.cpp +++ b/core/dive.cpp @@ -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; } } diff --git a/core/dive.h b/core/dive.h index adc0fdb11..e85f19bed 100644 --- a/core/dive.h +++ b/core/dive.h @@ -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); diff --git a/core/planner.cpp b/core/planner.cpp index b33c97624..3cd0a5d6b 100644 --- a/core/planner.cpp +++ b/core/planner.cpp @@ -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(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; } diff --git a/core/planner.h b/core/planner.h index 9f26cac37..dc145604d 100644 --- a/core/planner.h +++ b/core/planner.h @@ -60,6 +60,6 @@ struct decostop { #include 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 diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp index 98508d3d9..4ffef5104 100644 --- a/desktop-widgets/diveplanner.cpp +++ b/desktop-widgets/diveplanner.cpp @@ -23,7 +23,7 @@ #include #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() diff --git a/desktop-widgets/diveplanner.h b/desktop-widgets/diveplanner.h index e4c68f80c..0c1cfd1c5 100644 --- a/desktop-widgets/diveplanner.h +++ b/desktop-widgets/diveplanner.h @@ -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; diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index b2883d60d..57dd6615e 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -665,8 +665,8 @@ void MainWindow::on_actionReplanDive_triggered() { if (!plannerStateClean() || !current_dive || !userMayChangeAppState()) return; - else if (!is_dc_planner(¤t_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(); } diff --git a/desktop-widgets/profilewidget.cpp b/desktop-widgets/profilewidget.cpp index e9c4eee56..648dda898 100644 --- a/desktop-widgets/profilewidget.cpp +++ b/desktop-widgets/profilewidget.cpp @@ -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 &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() diff --git a/desktop-widgets/profilewidget.h b/desktop-widgets/profilewidget.h index abdf01795..84d03a5a5 100644 --- a/desktop-widgets/profilewidget.h +++ b/desktop-widgets/profilewidget.h @@ -44,7 +44,7 @@ private: std::vector 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); diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 6c16eae9c..b065138f6 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -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, ¤t_divemode); + current_divemode = get_current_divemode(dc, dc->duration.seconds, &evd, ¤t_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. diff --git a/tests/testplan.cpp b/tests/testplan.cpp index b916d8f27..856206111 100644 --- a/tests/testplan.cpp +++ b/tests/testplan.cpp @@ -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);