From 3e006e678a17a4229bf8e73112f8982e3b6c173a Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sat, 7 Sep 2024 14:56:34 +0200 Subject: [PATCH] planner: don't use fixed size deco stop table This was quite ominous: a 60-element fixed size table was passed as argument to plan(). But there was no check for 60 anywhere? Use a dynamic vector instead. The whole thing is weird, as the depth of the decostop table doesn't seem to be used. Signed-off-by: Berthold Stoeger --- core/planner.cpp | 14 ++++---------- core/planner.h | 2 +- qt-models/diveplannermodel.cpp | 35 ++++++++++------------------------ qt-models/diveplannermodel.h | 2 +- tests/testplan.cpp | 2 +- 5 files changed, 17 insertions(+), 38 deletions(-) diff --git a/core/planner.cpp b/core/planner.cpp index 32cda4dab..315cb8dd8 100644 --- a/core/planner.cpp +++ b/core/planner.cpp @@ -602,7 +602,7 @@ static void average_max_depth(const struct diveplan &dive, int *avg_depth, int * *avg_depth = *max_depth = 0; } -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) +bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, int dcNr, int timestep, std::vector &decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer) { int bottom_depth; @@ -635,7 +635,6 @@ bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, i int first_stop_depth = 0; int laststoptime = timestep; bool o2breaking = false; - int decostopcounter = 0; struct divecomputer *dc = dive->get_dc(dcNr); enum divemode_t divemode = dc->divemode; @@ -819,7 +818,7 @@ bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, i //CVA do { - decostopcounter = 0; + decostoptable.clear(); is_final_plan = (decoMode(true) == BUEHLMANN) || (previous_deco_time - ds->deco_time < 10); // CVA time converges if (ds->deco_time != 10000000) vpmb_next_gradient(ds, ds->deco_time, diveplan.surface_pressure / 1000.0, true); @@ -931,9 +930,7 @@ bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, i /* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */ if (trial_ascent(ds, 0, depth, stoplevels[stopidx], avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure / 1000.0, dive, divemode)) { - decostoptable[decostopcounter].depth = depth; - decostoptable[decostopcounter].time = 0; - decostopcounter++; + decostoptable.push_back( decostop { depth, 0 }); break; /* We did not hit the ceiling */ } @@ -1023,9 +1020,7 @@ bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, i add_segment(ds, dive->depth_to_bar(depth), dive->get_cylinder(stop_cylinder)->gasmix, laststoptime, po2, divemode, prefs.decosac, true); last_segment_min_switch = false; - decostoptable[decostopcounter].depth = depth; - decostoptable[decostopcounter].time = laststoptime; - ++decostopcounter; + decostoptable.push_back(decostop { depth, laststoptime } ); clock += laststoptime; if (!o2breaking) @@ -1045,7 +1040,6 @@ bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, i * Assume final ascent takes 20s, which is the time taken to ascend at 9m/min from 3m */ ds->deco_time = clock - bottom_time - (M_OR_FT(3,10) * ( prefs.last_stop ? 2 : 1)) / last_ascend_rate + 20; } while (!is_final_plan && error == PLAN_OK); - decostoptable[decostopcounter].depth = 0; plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode); if (decoMode(true) == VPMB) { diff --git a/core/planner.h b/core/planner.h index 92467d0b5..bd17753d7 100644 --- a/core/planner.h +++ b/core/planner.h @@ -66,5 +66,5 @@ struct decostop { }; extern std::string get_planner_disclaimer_formatted(); -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); +extern bool plan(struct deco_state *ds, struct diveplan &diveplan, struct dive *dive, int dcNr, int timestep, std::vector &decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer); #endif // PLANNER_H diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 7d83fce00..913d76d6f 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -1119,7 +1119,7 @@ void DivePlannerPointsModel::updateDiveProfile() return; deco_state_cache cache; - struct decostop stoptable[60]; + std::vector stoptable; struct deco_state plan_deco_state; plan(&plan_deco_state, diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), false); @@ -1182,29 +1182,14 @@ void DivePlannerPointsModel::cloneDiveplan(const struct diveplan &plan_src, stru plan_copy = plan_src; } -int DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit) +int DivePlannerPointsModel::analyzeVariations(const std::vector &min, const std::vector &mid, const std::vector &max, const char *unit) { - int minsum = 0; - int midsum = 0; - int maxsum = 0; - int leftsum = 0; - int rightsum = 0; - - while (min->depth) { - minsum += min->time; - ++min; - } - while (mid->depth) { - midsum += mid->time; - ++mid; - } - while (max->depth) { - maxsum += max->time; - ++max; - } - - leftsum = midsum - minsum; - rightsum = maxsum - midsum; + auto sum_time = [](int time, const decostop &ds) { return ds.time + time; }; + int minsum = std::accumulate(min.begin(), min.end(), 0, sum_time); + int midsum = std::accumulate(mid.begin(), mid.end(), 0, sum_time); + int maxsum = std::accumulate(max.begin(), max.end(), 0, sum_time); + int leftsum = midsum - minsum; + int rightsum = maxsum - midsum; #ifdef DEBUG_STOPVAR printf("Total + %d:%02d/%s +- %d s/%s\n\n", FRACTION_TUPLE((leftsum + rightsum) / 2, 60), unit, @@ -1237,7 +1222,7 @@ void DivePlannerPointsModel::computeVariations(std::unique_ptr auto dive = std::make_unique(); copy_dive(d, dive.get()); - struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60]; + std::vector original, deeper, shallower, shorter, longer; deco_state_cache cache, save; struct diveplan plan_copy; struct deco_state ds = *previous_ds; @@ -1331,7 +1316,7 @@ void DivePlannerPointsModel::createPlan(bool saveAsNew) removeDeco(); createTemporaryPlan(); - struct decostop stoptable[60]; + std::vector stoptable; plan(&ds_after_previous_dives, diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), true); if (shouldComputeVariations()) { diff --git a/qt-models/diveplannermodel.h b/qt-models/diveplannermodel.h index be6b07c42..38adefe5f 100644 --- a/qt-models/diveplannermodel.h +++ b/qt-models/diveplannermodel.h @@ -134,7 +134,7 @@ private: void computeVariationsDone(QString text); void computeVariations(std::unique_ptr plan, const struct deco_state *ds); void computeVariationsFreeDeco(std::unique_ptr plan, std::unique_ptr ds); - int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit); + int analyzeVariations(const std::vector &min, const std::vector &mid, const std::vector &max, const char *unit); struct dive *d; int dcNr; CylindersModel cylinders; diff --git a/tests/testplan.cpp b/tests/testplan.cpp index 1b217e513..3f74ee524 100644 --- a/tests/testplan.cpp +++ b/tests/testplan.cpp @@ -13,7 +13,7 @@ // testing the dive plan algorithm static struct dive dive; -static struct decostop stoptable[60]; +static std::vector stoptable; static struct deco_state test_deco_state; void setupPrefs() {