mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-27 20:58:47 +00:00
planner: turn diveplan into a C++ structure
No more memory management woes. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
6c8f158569
commit
8704a8b6f9
6 changed files with 372 additions and 450 deletions
213
core/planner.cpp
213
core/planner.cpp
|
@ -66,18 +66,19 @@ void dump_plan(struct diveplan *diveplan)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool diveplan_empty(struct diveplan *diveplan)
|
diveplan::diveplan()
|
||||||
{
|
{
|
||||||
struct divedatapoint *dp;
|
}
|
||||||
if (!diveplan || !diveplan->dp)
|
|
||||||
return true;
|
diveplan::~diveplan()
|
||||||
dp = diveplan->dp;
|
{
|
||||||
while (dp) {
|
}
|
||||||
if (dp->time)
|
|
||||||
return false;
|
bool diveplan_empty(const struct diveplan &diveplan)
|
||||||
dp = dp->next;
|
{
|
||||||
}
|
return std::none_of(diveplan.dp.begin(), diveplan.dp.end(),
|
||||||
return true;
|
[](const divedatapoint &dp)
|
||||||
|
{ return dp.time != 0; });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the cylinder index at a certain time during the dive */
|
/* get the cylinder index at a certain time during the dive */
|
||||||
|
@ -197,9 +198,8 @@ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_dept
|
||||||
|
|
||||||
/* overwrite the data in dive
|
/* overwrite the data in dive
|
||||||
* return false if something goes wrong */
|
* return false if something goes wrong */
|
||||||
static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, struct divecomputer *dc, bool track_gas)
|
static void create_dive_from_plan(struct diveplan &diveplan, struct dive *dive, struct divecomputer *dc, bool track_gas)
|
||||||
{
|
{
|
||||||
struct divedatapoint *dp;
|
|
||||||
cylinder_t *cyl;
|
cylinder_t *cyl;
|
||||||
int oldpo2 = 0;
|
int oldpo2 = 0;
|
||||||
int lasttime = 0, last_manual_point = 0;
|
int lasttime = 0, last_manual_point = 0;
|
||||||
|
@ -207,22 +207,21 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
int lastcylid;
|
int lastcylid;
|
||||||
enum divemode_t type = dc->divemode;
|
enum divemode_t type = dc->divemode;
|
||||||
|
|
||||||
if (!diveplan || !diveplan->dp)
|
if (diveplan.dp.empty())
|
||||||
return;
|
return;
|
||||||
#if DEBUG_PLAN & 4
|
#if DEBUG_PLAN & 4
|
||||||
printf("in create_dive_from_plan\n");
|
printf("in create_dive_from_plan\n");
|
||||||
dump_plan(diveplan);
|
dump_plan(diveplan);
|
||||||
#endif
|
#endif
|
||||||
dive->salinity = diveplan->salinity;
|
dive->salinity = diveplan.salinity;
|
||||||
// reset the cylinders and clear out the samples and events of the
|
// reset the cylinders and clear out the samples and events of the
|
||||||
// dive-to-be-planned so we can restart
|
// dive-to-be-planned so we can restart
|
||||||
reset_cylinders(dive, track_gas);
|
reset_cylinders(dive, track_gas);
|
||||||
dc->when = dive->when = diveplan->when;
|
dc->when = dive->when = diveplan.when;
|
||||||
dc->surface_pressure.mbar = diveplan->surface_pressure;
|
dc->surface_pressure.mbar = diveplan.surface_pressure;
|
||||||
dc->salinity = diveplan->salinity;
|
dc->salinity = diveplan.salinity;
|
||||||
dc->samples.clear();
|
dc->samples.clear();
|
||||||
dc->events.clear();
|
dc->events.clear();
|
||||||
dp = diveplan->dp;
|
|
||||||
/* Create first sample at time = 0, not based on dp because
|
/* Create first sample at time = 0, not based on dp because
|
||||||
* there is no real dp for time = 0, set first cylinder to 0
|
* there is no real dp for time = 0, set first cylinder to 0
|
||||||
* O2 setpoint for this sample will be filled later from next dp */
|
* O2 setpoint for this sample will be filled later from next dp */
|
||||||
|
@ -233,15 +232,14 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
sample->pressure[0].mbar = cyl->end.mbar;
|
sample->pressure[0].mbar = cyl->end.mbar;
|
||||||
sample->manually_entered = true;
|
sample->manually_entered = true;
|
||||||
lastcylid = 0;
|
lastcylid = 0;
|
||||||
while (dp) {
|
for (auto &dp: diveplan.dp) {
|
||||||
int po2 = dp->setpoint;
|
int po2 = dp.setpoint;
|
||||||
int time = dp->time;
|
int time = dp.time;
|
||||||
depth_t depth = dp->depth;
|
depth_t depth = dp.depth;
|
||||||
|
|
||||||
if (time == 0) {
|
if (time == 0) {
|
||||||
/* special entries that just inform the algorithm about
|
/* special entries that just inform the algorithm about
|
||||||
* additional gases that are available */
|
* additional gases that are available */
|
||||||
dp = dp->next;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,18 +248,18 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
/* this is a bad idea - we should get a different SAMPLE_EVENT type
|
/* this is a bad idea - we should get a different SAMPLE_EVENT type
|
||||||
* reserved for this in libdivecomputer... overloading SMAPLE_EVENT_PO2
|
* reserved for this in libdivecomputer... overloading SMAPLE_EVENT_PO2
|
||||||
* with a different meaning will only cause confusion elsewhere in the code */
|
* with a different meaning will only cause confusion elsewhere in the code */
|
||||||
if (dp->divemode == type)
|
if (dp.divemode == type)
|
||||||
add_event(dc, lasttime, SAMPLE_EVENT_PO2, 0, po2, QT_TRANSLATE_NOOP("gettextFromC", "SP change"));
|
add_event(dc, lasttime, SAMPLE_EVENT_PO2, 0, po2, QT_TRANSLATE_NOOP("gettextFromC", "SP change"));
|
||||||
oldpo2 = po2;
|
oldpo2 = po2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we have the new gas, and create a gas change event */
|
/* Make sure we have the new gas, and create a gas change event */
|
||||||
if (dp->cylinderid != lastcylid) {
|
if (dp.cylinderid != lastcylid) {
|
||||||
/* need to insert a first sample for the new gas */
|
/* need to insert a first sample for the new gas */
|
||||||
add_gas_switch_event(dive, dc, lasttime + 1, dp->cylinderid);
|
add_gas_switch_event(dive, dc, lasttime + 1, dp.cylinderid);
|
||||||
cyl = dive->get_cylinder(dp->cylinderid); // FIXME: This actually may get one past the last cylinder for "surface air".
|
cyl = dive->get_cylinder(dp.cylinderid); // FIXME: This actually may get one past the last cylinder for "surface air".
|
||||||
if (!cyl) {
|
if (!cyl) {
|
||||||
report_error("Invalid cylinder in create_dive_from_plan(): %d", dp->cylinderid);
|
report_error("Invalid cylinder in create_dive_from_plan(): %d", dp.cylinderid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sample = prepare_sample(dc);
|
sample = prepare_sample(dc);
|
||||||
|
@ -270,12 +268,12 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
sample[-1].o2sensor[0].mbar = po2;
|
sample[-1].o2sensor[0].mbar = po2;
|
||||||
sample->time.seconds = lasttime + 1;
|
sample->time.seconds = lasttime + 1;
|
||||||
sample->depth = lastdepth;
|
sample->depth = lastdepth;
|
||||||
sample->manually_entered = dp->entered;
|
sample->manually_entered = dp.entered;
|
||||||
sample->sac.mliter = dp->entered ? prefs.bottomsac : prefs.decosac;
|
sample->sac.mliter = dp.entered ? prefs.bottomsac : prefs.decosac;
|
||||||
lastcylid = dp->cylinderid;
|
lastcylid = dp.cylinderid;
|
||||||
}
|
}
|
||||||
if (dp->divemode != type) {
|
if (dp.divemode != type) {
|
||||||
type = dp->divemode;
|
type = dp.divemode;
|
||||||
add_event(dc, lasttime, SAMPLE_EVENT_BOOKMARK, 0, type, "modechange");
|
add_event(dc, lasttime, SAMPLE_EVENT_BOOKMARK, 0, type, "modechange");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,17 +284,16 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
sample[-1].setpoint.mbar = po2;
|
sample[-1].setpoint.mbar = po2;
|
||||||
sample->setpoint.mbar = po2;
|
sample->setpoint.mbar = po2;
|
||||||
sample->time.seconds = lasttime = time;
|
sample->time.seconds = lasttime = time;
|
||||||
if (dp->entered) last_manual_point = dp->time;
|
if (dp.entered) last_manual_point = dp.time;
|
||||||
sample->depth = lastdepth = depth;
|
sample->depth = lastdepth = depth;
|
||||||
sample->manually_entered = dp->entered;
|
sample->manually_entered = dp.entered;
|
||||||
sample->sac.mliter = dp->entered ? prefs.bottomsac : prefs.decosac;
|
sample->sac.mliter = dp.entered ? prefs.bottomsac : prefs.decosac;
|
||||||
if (track_gas && !sample[-1].setpoint.mbar) { /* Don't track gas usage for CCR legs of dive */
|
if (track_gas && !sample[-1].setpoint.mbar) { /* Don't track gas usage for CCR legs of dive */
|
||||||
update_cylinder_pressure(dive, sample[-1].depth.mm, depth.mm, time - sample[-1].time.seconds,
|
update_cylinder_pressure(dive, sample[-1].depth.mm, depth.mm, time - sample[-1].time.seconds,
|
||||||
dp->entered ? diveplan->bottomsac : diveplan->decosac, cyl, !dp->entered, type);
|
dp.entered ? diveplan.bottomsac : diveplan.decosac, cyl, !dp.entered, type);
|
||||||
if (cyl->type.workingpressure.mbar)
|
if (cyl->type.workingpressure.mbar)
|
||||||
sample->pressure[0].mbar = cyl->end.mbar;
|
sample->pressure[0].mbar = cyl->end.mbar;
|
||||||
}
|
}
|
||||||
dp = dp->next;
|
|
||||||
}
|
}
|
||||||
dc->last_manual_time.seconds = last_manual_point;
|
dc->last_manual_time.seconds = last_manual_point;
|
||||||
|
|
||||||
|
@ -306,57 +303,35 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_dps(struct diveplan *diveplan)
|
static struct divedatapoint create_dp(int time_incr, int depth, int cylinderid, int po2)
|
||||||
{
|
{
|
||||||
if (!diveplan)
|
struct divedatapoint dp;
|
||||||
return;
|
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
|
||||||
while (dp) {
|
|
||||||
struct divedatapoint *ndp = dp->next;
|
|
||||||
free(dp);
|
|
||||||
dp = ndp;
|
|
||||||
}
|
|
||||||
diveplan->dp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct divedatapoint *create_dp(int time_incr, int depth, int cylinderid, int po2)
|
dp.time = time_incr;
|
||||||
{
|
dp.depth.mm = depth;
|
||||||
struct divedatapoint *dp;
|
dp.cylinderid = cylinderid;
|
||||||
|
dp.minimum_gas.mbar = 0;
|
||||||
dp = (divedatapoint *)malloc(sizeof(struct divedatapoint));
|
dp.setpoint = po2;
|
||||||
dp->time = time_incr;
|
dp.entered = false;
|
||||||
dp->depth.mm = depth;
|
|
||||||
dp->cylinderid = cylinderid;
|
|
||||||
dp->minimum_gas.mbar = 0;
|
|
||||||
dp->setpoint = po2;
|
|
||||||
dp->entered = false;
|
|
||||||
dp->next = NULL;
|
|
||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_to_end_of_diveplan(struct diveplan *diveplan, struct divedatapoint *dp)
|
static void add_to_end_of_diveplan(struct diveplan &diveplan, const struct divedatapoint &dp)
|
||||||
{
|
{
|
||||||
struct divedatapoint **lastdp = &diveplan->dp;
|
auto maxtime = std::max_element(diveplan.dp.begin(), diveplan.dp.end(),
|
||||||
struct divedatapoint *ldp = *lastdp;
|
[] (const divedatapoint &p1, const divedatapoint &p2)
|
||||||
int lasttime = 0;
|
{ return p1.time < p2.time; });
|
||||||
while (*lastdp) {
|
int lasttime = maxtime != diveplan.dp.end() ? maxtime->time : 0;
|
||||||
ldp = *lastdp;
|
diveplan.dp.push_back(dp);
|
||||||
if (ldp->time > lasttime)
|
diveplan.dp.back().time += lasttime;
|
||||||
lasttime = ldp->time;
|
|
||||||
lastdp = &(*lastdp)->next;
|
|
||||||
}
|
|
||||||
*lastdp = dp;
|
|
||||||
if (ldp)
|
|
||||||
dp->time += lasttime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct divedatapoint *plan_add_segment(struct diveplan *diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode)
|
void plan_add_segment(struct diveplan &diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode)
|
||||||
{
|
{
|
||||||
struct divedatapoint *dp = create_dp(duration, depth, cylinderid, divemode == CCR ? po2 : 0);
|
struct divedatapoint dp = create_dp(duration, depth, cylinderid, divemode == CCR ? po2 : 0);
|
||||||
dp->entered = entered;
|
dp.entered = entered;
|
||||||
dp->divemode = divemode;
|
dp.divemode = divemode;
|
||||||
add_to_end_of_diveplan(diveplan, dp);
|
add_to_end_of_diveplan(diveplan, dp);
|
||||||
return dp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gaschanges {
|
struct gaschanges {
|
||||||
|
@ -380,47 +355,45 @@ static int setpoint_change(struct dive *dive, int cylinderid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<gaschanges> analyze_gaslist(struct diveplan *diveplan, struct dive *dive, int dcNr, int depth, int *asc_cylinder, bool ccr, bool &inappropriate_cylinder_use)
|
static std::vector<gaschanges> analyze_gaslist(const struct diveplan &diveplan, struct dive *dive, int dcNr,
|
||||||
|
int depth, int *asc_cylinder, bool ccr, bool &inappropriate_cylinder_use)
|
||||||
{
|
{
|
||||||
size_t nr = 0;
|
size_t nr = 0;
|
||||||
std::vector<gaschanges> gaschanges;
|
std::vector<gaschanges> gaschanges;
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
const struct divedatapoint *best_ascent_dp = nullptr;
|
||||||
struct divedatapoint *best_ascent_dp = NULL;
|
|
||||||
bool total_time_zero = true;
|
bool total_time_zero = true;
|
||||||
const divecomputer *dc = dive->get_dc(dcNr);
|
const divecomputer *dc = dive->get_dc(dcNr);
|
||||||
while (dp) {
|
for (auto &dp: diveplan.dp) {
|
||||||
inappropriate_cylinder_use = inappropriate_cylinder_use || !is_cylinder_use_appropriate(*dc, *dive->get_cylinder(dp->cylinderid), false);
|
inappropriate_cylinder_use = inappropriate_cylinder_use || !is_cylinder_use_appropriate(*dc, *dive->get_cylinder(dp.cylinderid), false);
|
||||||
|
|
||||||
if (dp->time == 0 && total_time_zero && (ccr == (bool) setpoint_change(dive, dp->cylinderid))) {
|
if (dp.time == 0 && total_time_zero && (ccr == (bool) setpoint_change(dive, dp.cylinderid))) {
|
||||||
if (dp->depth.mm <= depth) {
|
if (dp.depth.mm <= depth) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
nr++;
|
nr++;
|
||||||
gaschanges.resize(nr);
|
gaschanges.resize(nr);
|
||||||
while (i < static_cast<int>(nr) - 1) {
|
while (i < static_cast<int>(nr) - 1) {
|
||||||
if (dp->depth.mm < gaschanges[i].depth) {
|
if (dp.depth.mm < gaschanges[i].depth) {
|
||||||
for (int j = static_cast<int>(nr) - 2; j >= i; j--)
|
for (int j = static_cast<int>(nr) - 2; j >= i; j--)
|
||||||
gaschanges[j + 1] = gaschanges[j];
|
gaschanges[j + 1] = gaschanges[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
gaschanges[i].depth = dp->depth.mm;
|
gaschanges[i].depth = dp.depth.mm;
|
||||||
gaschanges[i].gasidx = dp->cylinderid;
|
gaschanges[i].gasidx = dp.cylinderid;
|
||||||
assert(gaschanges[i].gasidx != -1);
|
assert(gaschanges[i].gasidx != -1);
|
||||||
} else {
|
} else {
|
||||||
/* is there a better mix to start deco? */
|
/* is there a better mix to start deco? */
|
||||||
if (!best_ascent_dp || dp->depth.mm < best_ascent_dp->depth.mm) {
|
if (!best_ascent_dp || dp.depth.mm < best_ascent_dp->depth.mm) {
|
||||||
best_ascent_dp = dp;
|
best_ascent_dp = &dp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
total_time_zero = false;
|
total_time_zero = false;
|
||||||
}
|
}
|
||||||
dp = dp->next;
|
|
||||||
}
|
}
|
||||||
if (best_ascent_dp) {
|
if (best_ascent_dp)
|
||||||
*asc_cylinder = best_ascent_dp->cylinderid;
|
*asc_cylinder = best_ascent_dp->cylinderid;
|
||||||
}
|
|
||||||
#if DEBUG_PLAN & 16
|
#if DEBUG_PLAN & 16
|
||||||
for (size_t nr = 0; nr < gaschanges.size(); nr++) {
|
for (size_t nr = 0; nr < gaschanges.size(); nr++) {
|
||||||
int idx = gaschanges[nr].gasidx;
|
int idx = gaschanges[nr].gasidx;
|
||||||
|
@ -610,25 +583,23 @@ static int wait_until(struct deco_state *ds, struct dive *dive, int clock, int m
|
||||||
return wait_until(ds, dive, clock, min, leap / 2, stepsize, depth, target_depth, avg_depth, bottom_time, gasmix, po2, surface_pressure, divemode);
|
return wait_until(ds, dive, clock, min, leap / 2, stepsize, depth, target_depth, avg_depth, bottom_time, gasmix, po2, surface_pressure, divemode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_depth)
|
static void average_max_depth(const struct diveplan &dive, int *avg_depth, int *max_depth)
|
||||||
{
|
{
|
||||||
int integral = 0;
|
int integral = 0;
|
||||||
int last_time = 0;
|
int last_time = 0;
|
||||||
int last_depth = 0;
|
int last_depth = 0;
|
||||||
struct divedatapoint *dp = dive->dp;
|
|
||||||
|
|
||||||
*max_depth = 0;
|
*max_depth = 0;
|
||||||
|
|
||||||
while (dp) {
|
for (auto &dp: dive.dp) {
|
||||||
if (dp->time) {
|
if (dp.time) {
|
||||||
/* Ignore gas indication samples */
|
/* Ignore gas indication samples */
|
||||||
integral += (dp->depth.mm + last_depth) * (dp->time - last_time) / 2;
|
integral += (dp.depth.mm + last_depth) * (dp.time - last_time) / 2;
|
||||||
last_time = dp->time;
|
last_time = dp.time;
|
||||||
last_depth = dp->depth.mm;
|
last_depth = dp.depth.mm;
|
||||||
if (dp->depth.mm > *max_depth)
|
if (dp.depth.mm > *max_depth)
|
||||||
*max_depth = dp->depth.mm;
|
*max_depth = dp.depth.mm;
|
||||||
}
|
}
|
||||||
dp = dp->next;
|
|
||||||
}
|
}
|
||||||
if (last_time)
|
if (last_time)
|
||||||
*avg_depth = integral / last_time;
|
*avg_depth = integral / last_time;
|
||||||
|
@ -636,7 +607,7 @@ static void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_de
|
||||||
*avg_depth = *max_depth = 0;
|
*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, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer)
|
||||||
{
|
{
|
||||||
|
|
||||||
int bottom_depth;
|
int bottom_depth;
|
||||||
|
@ -673,19 +644,19 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
struct divecomputer *dc = dive->get_dc(dcNr);
|
struct divecomputer *dc = dive->get_dc(dcNr);
|
||||||
enum divemode_t divemode = dc->divemode;
|
enum divemode_t divemode = dc->divemode;
|
||||||
|
|
||||||
set_gf(diveplan->gflow, diveplan->gfhigh);
|
set_gf(diveplan.gflow, diveplan.gfhigh);
|
||||||
set_vpmb_conservatism(diveplan->vpmb_conservatism);
|
set_vpmb_conservatism(diveplan.vpmb_conservatism);
|
||||||
|
|
||||||
if (!diveplan->surface_pressure) {
|
if (!diveplan.surface_pressure) {
|
||||||
// Lets use dive's surface pressure in planner, if have one...
|
// Lets use dive's surface pressure in planner, if have one...
|
||||||
if (dc->surface_pressure.mbar) { // First from DC...
|
if (dc->surface_pressure.mbar) { // First from DC...
|
||||||
diveplan->surface_pressure = dc->surface_pressure.mbar;
|
diveplan.surface_pressure = dc->surface_pressure.mbar;
|
||||||
}
|
}
|
||||||
else if (dive->surface_pressure.mbar) { // After from user...
|
else if (dive->surface_pressure.mbar) { // After from user...
|
||||||
diveplan->surface_pressure = dive->surface_pressure.mbar;
|
diveplan.surface_pressure = dive->surface_pressure.mbar;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
diveplan->surface_pressure = SURFACE_PRESSURE;
|
diveplan.surface_pressure = SURFACE_PRESSURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,7 +737,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
gi = static_cast<int>(gaschanges.size()) - 1;
|
gi = static_cast<int>(gaschanges.size()) - 1;
|
||||||
|
|
||||||
/* Set tissue tolerance and initial vpmb gradient at start of ascent phase */
|
/* Set tissue tolerance and initial vpmb gradient at start of ascent phase */
|
||||||
diveplan->surface_interval = tissue_at_end(ds, dive, dc, cache);
|
diveplan.surface_interval = tissue_at_end(ds, dive, dc, cache);
|
||||||
nuclear_regeneration(ds, clock);
|
nuclear_regeneration(ds, clock);
|
||||||
vpmb_start_gradient(ds);
|
vpmb_start_gradient(ds);
|
||||||
if (decoMode(true) == RECREATIONAL) {
|
if (decoMode(true) == RECREATIONAL) {
|
||||||
|
@ -780,7 +751,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
|
update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, dive->get_cylinder(current_cylinder), false, divemode);
|
||||||
clock += timestep;
|
clock += timestep;
|
||||||
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix,
|
} while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->get_cylinder(current_cylinder)->gasmix,
|
||||||
po2, diveplan->surface_pressure / 1000.0, dive, divemode) &&
|
po2, diveplan.surface_pressure / 1000.0, dive, divemode) &&
|
||||||
enough_gas(dive, current_cylinder) && clock < 6 * 3600);
|
enough_gas(dive, current_cylinder) && clock < 6 * 3600);
|
||||||
|
|
||||||
// We did stay one timestep too many.
|
// We did stay one timestep too many.
|
||||||
|
@ -856,7 +827,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
decostopcounter = 0;
|
decostopcounter = 0;
|
||||||
is_final_plan = (decoMode(true) == BUEHLMANN) || (previous_deco_time - ds->deco_time < 10); // CVA time converges
|
is_final_plan = (decoMode(true) == BUEHLMANN) || (previous_deco_time - ds->deco_time < 10); // CVA time converges
|
||||||
if (ds->deco_time != 10000000)
|
if (ds->deco_time != 10000000)
|
||||||
vpmb_next_gradient(ds, ds->deco_time, diveplan->surface_pressure / 1000.0, true);
|
vpmb_next_gradient(ds, ds->deco_time, diveplan.surface_pressure / 1000.0, true);
|
||||||
|
|
||||||
previous_deco_time = ds->deco_time;
|
previous_deco_time = ds->deco_time;
|
||||||
bottom_cache.restore(ds, true);
|
bottom_cache.restore(ds, true);
|
||||||
|
@ -871,7 +842,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
stopidx = bottom_stopidx;
|
stopidx = bottom_stopidx;
|
||||||
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(
|
ds->first_ceiling_pressure.mbar = dive->depth_to_mbar(
|
||||||
deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(depth), true),
|
deco_allowed_depth(tissue_tolerance_calc(ds, dive, dive->depth_to_bar(depth), true),
|
||||||
diveplan->surface_pressure / 1000.0, dive, 1));
|
diveplan.surface_pressure / 1000.0, dive, 1));
|
||||||
if (ds->max_bottom_ceiling_pressure.mbar > ds->first_ceiling_pressure.mbar)
|
if (ds->max_bottom_ceiling_pressure.mbar > ds->first_ceiling_pressure.mbar)
|
||||||
ds->first_ceiling_pressure.mbar = ds->max_bottom_ceiling_pressure.mbar;
|
ds->first_ceiling_pressure.mbar = ds->max_bottom_ceiling_pressure.mbar;
|
||||||
|
|
||||||
|
@ -928,7 +899,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
if (current_cylinder != gaschanges[gi].gasidx) {
|
if (current_cylinder != gaschanges[gi].gasidx) {
|
||||||
if (!prefs.switch_at_req_stop ||
|
if (!prefs.switch_at_req_stop ||
|
||||||
!trial_ascent(ds, 0, depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
|
!trial_ascent(ds, 0, depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
|
||||||
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode) || get_o2(dive->get_cylinder(current_cylinder)->gasmix) < 160) {
|
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure / 1000.0, dive, divemode) || get_o2(dive->get_cylinder(current_cylinder)->gasmix) < 160) {
|
||||||
if (is_final_plan)
|
if (is_final_plan)
|
||||||
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
|
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
|
||||||
stopping = true;
|
stopping = true;
|
||||||
|
@ -964,7 +935,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
|
/* 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,
|
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)) {
|
dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure / 1000.0, dive, divemode)) {
|
||||||
decostoptable[decostopcounter].depth = depth;
|
decostoptable[decostopcounter].depth = depth;
|
||||||
decostoptable[decostopcounter].time = 0;
|
decostoptable[decostopcounter].time = 0;
|
||||||
decostopcounter++;
|
decostopcounter++;
|
||||||
|
@ -1008,7 +979,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
}
|
}
|
||||||
|
|
||||||
int new_clock = wait_until(ds, dive, clock, clock, laststoptime * 2 + 1, timestep, depth, stoplevels[stopidx], avg_depth,
|
int new_clock = wait_until(ds, dive, clock, clock, laststoptime * 2 + 1, timestep, depth, stoplevels[stopidx], avg_depth,
|
||||||
bottom_time, dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan->surface_pressure / 1000.0, divemode);
|
bottom_time, dive->get_cylinder(current_cylinder)->gasmix, po2, diveplan.surface_pressure / 1000.0, divemode);
|
||||||
laststoptime = new_clock - clock;
|
laststoptime = new_clock - clock;
|
||||||
/* Finish infinite deco */
|
/* Finish infinite deco */
|
||||||
if (laststoptime >= 48 * 3600 && depth >= 6000) {
|
if (laststoptime >= 48 * 3600 && depth >= 6000) {
|
||||||
|
@ -1083,8 +1054,8 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
|
|
||||||
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
|
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
|
||||||
if (decoMode(true) == VPMB) {
|
if (decoMode(true) == VPMB) {
|
||||||
diveplan->eff_gfhigh = lrint(100.0 * regressionb(ds));
|
diveplan.eff_gfhigh = lrint(100.0 * regressionb(ds));
|
||||||
diveplan->eff_gflow = lrint(100.0 * (regressiona(ds) * first_stop_depth + regressionb(ds)));
|
diveplan.eff_gflow = lrint(100.0 * (regressiona(ds) * first_stop_depth + regressionb(ds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefs.surface_segment != 0) {
|
if (prefs.surface_segment != 0) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
#include "divemode.h"
|
#include "divemode.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/* this should be converted to use our types */
|
/* this should be converted to use our types */
|
||||||
struct divedatapoint {
|
struct divedatapoint {
|
||||||
|
@ -14,22 +15,24 @@ struct divedatapoint {
|
||||||
pressure_t minimum_gas;
|
pressure_t minimum_gas;
|
||||||
int setpoint;
|
int setpoint;
|
||||||
bool entered;
|
bool entered;
|
||||||
struct divedatapoint *next;
|
|
||||||
enum divemode_t divemode;
|
enum divemode_t divemode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct diveplan {
|
struct diveplan {
|
||||||
timestamp_t when;
|
diveplan();
|
||||||
int surface_pressure; /* mbar */
|
~diveplan();
|
||||||
int bottomsac; /* ml/min */
|
|
||||||
int decosac; /* ml/min */
|
timestamp_t when = 0;
|
||||||
int salinity;
|
int surface_pressure = 0; /* mbar */
|
||||||
short gflow;
|
int bottomsac = 0; /* ml/min */
|
||||||
short gfhigh;
|
int decosac = 0; /* ml/min */
|
||||||
short vpmb_conservatism;
|
int salinity = 0;
|
||||||
struct divedatapoint *dp;
|
short gflow = 0;
|
||||||
int eff_gflow, eff_gfhigh;
|
short gfhigh = 0;
|
||||||
int surface_interval;
|
short vpmb_conservatism = 0;
|
||||||
|
std::vector<divedatapoint> dp;
|
||||||
|
int eff_gflow = 0, eff_gfhigh = 0;
|
||||||
|
int surface_interval = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct deco_state_cache;
|
struct deco_state_cache;
|
||||||
|
@ -41,13 +44,11 @@ typedef enum {
|
||||||
} planner_error_t;
|
} planner_error_t;
|
||||||
|
|
||||||
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
||||||
extern bool diveplan_empty(struct diveplan *diveplan);
|
extern bool diveplan_empty(const struct diveplan &diveplan);
|
||||||
extern void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error);
|
extern void add_plan_to_notes(struct diveplan &diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error);
|
||||||
extern const char *get_planner_disclaimer();
|
extern const char *get_planner_disclaimer();
|
||||||
|
|
||||||
extern void free_dps(struct diveplan *diveplan);
|
void plan_add_segment(struct diveplan &diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode);
|
||||||
|
|
||||||
struct divedatapoint *plan_add_segment(struct diveplan *diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode);
|
|
||||||
#if DEBUG_PLAN
|
#if DEBUG_PLAN
|
||||||
void dump_plan(struct diveplan *diveplan);
|
void dump_plan(struct diveplan *diveplan);
|
||||||
#endif
|
#endif
|
||||||
|
@ -57,5 +58,5 @@ struct decostop {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::string get_planner_disclaimer_formatted();
|
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, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);
|
||||||
#endif // PLANNER_H
|
#endif // PLANNER_H
|
||||||
|
|
|
@ -25,17 +25,15 @@
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
static int diveplan_duration(struct diveplan *diveplan)
|
static int diveplan_duration(const struct diveplan &diveplan)
|
||||||
{
|
{
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
int lastdepth = 0;
|
int lastdepth = 0;
|
||||||
while(dp) {
|
for (auto &dp: diveplan.dp) {
|
||||||
if (dp->time > duration && (dp->depth.mm > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD)) {
|
if (dp.time > duration && (dp.depth.mm > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD)) {
|
||||||
duration = dp->time;
|
duration = dp.time;
|
||||||
lastdepth = dp->depth.mm;
|
lastdepth = dp.depth.mm;
|
||||||
}
|
}
|
||||||
dp = dp->next;
|
|
||||||
}
|
}
|
||||||
return (duration + 30) / 60;
|
return (duration + 30) / 60;
|
||||||
}
|
}
|
||||||
|
@ -96,14 +94,13 @@ extern std::string get_planner_disclaimer_formatted()
|
||||||
return format_string_std(get_planner_disclaimer(), deco);
|
return format_string_std(get_planner_disclaimer(), deco);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error)
|
void add_plan_to_notes(struct diveplan &diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error)
|
||||||
{
|
{
|
||||||
std::string buf;
|
std::string buf;
|
||||||
std::string icdbuf;
|
std::string icdbuf;
|
||||||
const char *segmentsymbol;
|
const char *segmentsymbol;
|
||||||
int lastdepth = 0, lasttime = 0, lastsetpoint = -1, newdepth = 0, lastprintdepth = 0, lastprintsetpoint = -1;
|
int lastdepth = 0, lasttime = 0, lastsetpoint = -1, newdepth = 0, lastprintdepth = 0, lastprintsetpoint = -1;
|
||||||
struct gasmix lastprintgasmix = gasmix_invalid;
|
struct gasmix lastprintgasmix = gasmix_invalid;
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
|
||||||
bool plan_verbatim = prefs.verbatim_plan;
|
bool plan_verbatim = prefs.verbatim_plan;
|
||||||
bool plan_display_runtime = prefs.display_runtime;
|
bool plan_display_runtime = prefs.display_runtime;
|
||||||
bool plan_display_duration = prefs.display_duration;
|
bool plan_display_duration = prefs.display_duration;
|
||||||
|
@ -115,11 +112,10 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
enum divemode_t lastdivemode = UNDEF_COMP_TYPE;
|
enum divemode_t lastdivemode = UNDEF_COMP_TYPE;
|
||||||
bool lastentered = true;
|
bool lastentered = true;
|
||||||
bool icdwarning = false, icdtableheader = true;
|
bool icdwarning = false, icdtableheader = true;
|
||||||
struct divedatapoint *nextdp = NULL;
|
struct divedatapoint *lastbottomdp = nullptr;
|
||||||
struct divedatapoint *lastbottomdp = NULL;
|
|
||||||
struct icd_data icdvalues;
|
struct icd_data icdvalues;
|
||||||
|
|
||||||
if (!dp)
|
if (diveplan.dp.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (error != PLAN_OK) {
|
if (error != PLAN_OK) {
|
||||||
|
@ -155,14 +151,14 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
}
|
}
|
||||||
|
|
||||||
buf += "<div>\n<b>";
|
buf += "<div>\n<b>";
|
||||||
if (diveplan->surface_interval < 0) {
|
if (diveplan.surface_interval < 0) {
|
||||||
buf += format_string_std("%s (%s) %s",
|
buf += format_string_std("%s (%s) %s",
|
||||||
translate("gettextFromC", "Subsurface"),
|
translate("gettextFromC", "Subsurface"),
|
||||||
subsurface_canonical_version(),
|
subsurface_canonical_version(),
|
||||||
translate("gettextFromC", "dive plan</b> (overlapping dives detected)"));
|
translate("gettextFromC", "dive plan</b> (overlapping dives detected)"));
|
||||||
dive->notes = std::move(buf);
|
dive->notes = std::move(buf);
|
||||||
return;
|
return;
|
||||||
} else if (diveplan->surface_interval >= 48 * 60 *60) {
|
} else if (diveplan.surface_interval >= 48 * 60 *60) {
|
||||||
buf += format_string_std("%s (%s) %s %s",
|
buf += format_string_std("%s (%s) %s %s",
|
||||||
translate("gettextFromC", "Subsurface"),
|
translate("gettextFromC", "Subsurface"),
|
||||||
subsurface_canonical_version(),
|
subsurface_canonical_version(),
|
||||||
|
@ -173,7 +169,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
translate("gettextFromC", "Subsurface"),
|
translate("gettextFromC", "Subsurface"),
|
||||||
subsurface_canonical_version(),
|
subsurface_canonical_version(),
|
||||||
translate("gettextFromC", "dive plan</b> (surface interval "),
|
translate("gettextFromC", "dive plan</b> (surface interval "),
|
||||||
FRACTION_TUPLE(diveplan->surface_interval / 60, 60),
|
FRACTION_TUPLE(diveplan.surface_interval / 60, 60),
|
||||||
translate("gettextFromC", "created on"),
|
translate("gettextFromC", "created on"),
|
||||||
get_current_date().c_str());
|
get_current_date().c_str());
|
||||||
}
|
}
|
||||||
|
@ -197,30 +193,31 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
translate("gettextFromC", "gas"));
|
translate("gettextFromC", "gas"));
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
for (auto dp = diveplan.dp.begin(); dp != diveplan.dp.end(); ++dp) {
|
||||||
|
auto nextdp = std::next(dp);
|
||||||
struct gasmix gasmix, newgasmix = {};
|
struct gasmix gasmix, newgasmix = {};
|
||||||
const char *depth_unit;
|
const char *depth_unit;
|
||||||
double depthvalue;
|
double depthvalue;
|
||||||
int decimals;
|
int decimals;
|
||||||
bool isascent = (dp->depth.mm < lastdepth);
|
bool isascent = (dp->depth.mm < lastdepth);
|
||||||
|
|
||||||
nextdp = dp->next;
|
|
||||||
if (dp->time == 0)
|
if (dp->time == 0)
|
||||||
continue;
|
continue;
|
||||||
gasmix = dive->get_cylinder(dp->cylinderid)->gasmix;
|
gasmix = dive->get_cylinder(dp->cylinderid)->gasmix;
|
||||||
depthvalue = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
|
depthvalue = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
|
||||||
/* analyze the dive points ahead */
|
/* analyze the dive points ahead */
|
||||||
while (nextdp && nextdp->time == 0)
|
while (nextdp != diveplan.dp.end() && nextdp->time == 0)
|
||||||
nextdp = nextdp->next;
|
++nextdp;
|
||||||
if (nextdp)
|
bool atend = nextdp == diveplan.dp.end();
|
||||||
|
if (!atend)
|
||||||
newgasmix = dive->get_cylinder(nextdp->cylinderid)->gasmix;
|
newgasmix = dive->get_cylinder(nextdp->cylinderid)->gasmix;
|
||||||
gaschange_after = (nextdp && (gasmix_distance(gasmix, newgasmix)));
|
gaschange_after = (!atend && (gasmix_distance(gasmix, newgasmix)));
|
||||||
gaschange_before = (gasmix_distance(lastprintgasmix, gasmix));
|
gaschange_before = (gasmix_distance(lastprintgasmix, gasmix));
|
||||||
rebreatherchange_after = (nextdp && (dp->setpoint != nextdp->setpoint || dp->divemode != nextdp->divemode));
|
rebreatherchange_after = (!atend && (dp->setpoint != nextdp->setpoint || dp->divemode != nextdp->divemode));
|
||||||
rebreatherchange_before = lastprintsetpoint != dp->setpoint || lastdivemode != dp->divemode;
|
rebreatherchange_before = lastprintsetpoint != dp->setpoint || lastdivemode != dp->divemode;
|
||||||
/* do we want to skip this leg as it is devoid of anything useful? */
|
/* do we want to skip this leg as it is devoid of anything useful? */
|
||||||
if (!dp->entered &&
|
if (!dp->entered &&
|
||||||
nextdp &&
|
!atend &&
|
||||||
dp->depth.mm != lastdepth &&
|
dp->depth.mm != lastdepth &&
|
||||||
nextdp->depth.mm != dp->depth.mm &&
|
nextdp->depth.mm != dp->depth.mm &&
|
||||||
!gaschange_before &&
|
!gaschange_before &&
|
||||||
|
@ -229,14 +226,14 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
!rebreatherchange_after)
|
!rebreatherchange_after)
|
||||||
continue;
|
continue;
|
||||||
// Ignore final surface segment for notes
|
// Ignore final surface segment for notes
|
||||||
if (lastdepth == 0 && dp->depth.mm == 0 && !dp->next)
|
if (lastdepth == 0 && dp->depth.mm == 0 && atend)
|
||||||
continue;
|
continue;
|
||||||
if ((dp->time - lasttime < 10 && lastdepth == dp->depth.mm) && !(gaschange_after && dp->next && dp->depth.mm != dp->next->depth.mm))
|
if ((dp->time - lasttime < 10 && lastdepth == dp->depth.mm) && !(gaschange_after && !atend && dp->depth.mm != nextdp->depth.mm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Store pointer to last entered datapoint for minimum gas calculation */
|
/* Store pointer to last entered datapoint for minimum gas calculation */
|
||||||
if (dp->entered && nextdp && !nextdp->entered)
|
if (dp->entered && !atend && !nextdp->entered)
|
||||||
lastbottomdp = dp;
|
lastbottomdp = &*dp;
|
||||||
|
|
||||||
if (plan_verbatim) {
|
if (plan_verbatim) {
|
||||||
/* When displaying a verbatim plan, we output a waypoint for every gas change.
|
/* When displaying a verbatim plan, we output a waypoint for every gas change.
|
||||||
|
@ -246,7 +243,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
* non-verbatim plan.
|
* non-verbatim plan.
|
||||||
*/
|
*/
|
||||||
if (dp->depth.mm != lastprintdepth) {
|
if (dp->depth.mm != lastprintdepth) {
|
||||||
if (plan_display_transitions || dp->entered || !dp->next || (gaschange_after && dp->next && dp->depth.mm != nextdp->depth.mm)) {
|
if (plan_display_transitions || dp->entered || atend || (gaschange_after && !atend && dp->depth.mm != nextdp->depth.mm)) {
|
||||||
if (dp->setpoint) {
|
if (dp->setpoint) {
|
||||||
buf += casprintf_loc(translate("gettextFromC", "%s to %.*f %s in %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"),
|
buf += casprintf_loc(translate("gettextFromC", "%s to %.*f %s in %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar)"),
|
||||||
dp->depth.mm < lastprintdepth ? translate("gettextFromC", "Ascend") : translate("gettextFromC", "Descend"),
|
dp->depth.mm < lastprintdepth ? translate("gettextFromC", "Ascend") : translate("gettextFromC", "Descend"),
|
||||||
|
@ -269,7 +266,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
newdepth = dp->depth.mm;
|
newdepth = dp->depth.mm;
|
||||||
lasttime = dp->time;
|
lasttime = dp->time;
|
||||||
} else {
|
} else {
|
||||||
if ((nextdp && dp->depth.mm != nextdp->depth.mm) || gaschange_after) {
|
if ((!atend && dp->depth.mm != nextdp->depth.mm) || gaschange_after) {
|
||||||
if (dp->setpoint) {
|
if (dp->setpoint) {
|
||||||
buf += casprintf_loc(translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar CCR)"),
|
buf += casprintf_loc(translate("gettextFromC", "Stay at %.*f %s for %d:%02d min - runtime %d:%02u on %s (SP = %.1fbar CCR)"),
|
||||||
decimals, depthvalue, depth_unit,
|
decimals, depthvalue, depth_unit,
|
||||||
|
@ -307,12 +304,12 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
* used for a calculated ascent, there is a subsequent gas change before the first deco stop, and zero
|
* used for a calculated ascent, there is a subsequent gas change before the first deco stop, and zero
|
||||||
* time has been allowed for a gas switch.
|
* time has been allowed for a gas switch.
|
||||||
*/
|
*/
|
||||||
if (plan_display_transitions || dp->entered || !dp->next ||
|
if (plan_display_transitions || dp->entered || atend ||
|
||||||
(nextdp && dp->depth.mm != nextdp->depth.mm) ||
|
(!atend && dp->depth.mm != nextdp->depth.mm) ||
|
||||||
(!isascent && (gaschange_before || rebreatherchange_before) && nextdp && dp->depth.mm != nextdp->depth.mm) ||
|
(!isascent && (gaschange_before || rebreatherchange_before) && !atend && dp->depth.mm != nextdp->depth.mm) ||
|
||||||
((gaschange_after || rebreatherchange_after) && lastentered) || ((gaschange_after || rebreatherchange_after)&& !isascent) ||
|
((gaschange_after || rebreatherchange_after) && lastentered) || ((gaschange_after || rebreatherchange_after)&& !isascent) ||
|
||||||
(isascent && (gaschange_after || rebreatherchange_after) && nextdp && dp->depth.mm != nextdp->depth.mm ) ||
|
(isascent && (gaschange_after || rebreatherchange_after) && !atend && dp->depth.mm != nextdp->depth.mm ) ||
|
||||||
(lastentered && !dp->entered && dp->next->depth.mm == dp->depth.mm)) {
|
(lastentered && !dp->entered && nextdp->depth.mm == dp->depth.mm)) {
|
||||||
// Print a symbol to indicate whether segment is an ascent, descent, constant depth (user entered) or deco stop
|
// Print a symbol to indicate whether segment is an ascent, descent, constant depth (user entered) or deco stop
|
||||||
if (isascent)
|
if (isascent)
|
||||||
segmentsymbol = "➚"; // up-right arrow for ascent
|
segmentsymbol = "➚"; // up-right arrow for ascent
|
||||||
|
@ -339,7 +336,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
/* Normally a gas change is displayed on the stopping segment, so only display a gas change at the end of
|
/* Normally a gas change is displayed on the stopping segment, so only display a gas change at the end of
|
||||||
* an ascent segment if it is not followed by a stop
|
* an ascent segment if it is not followed by a stop
|
||||||
*/
|
*/
|
||||||
if (isascent && gaschange_after && dp->next && nextdp && nextdp->entered) {
|
if (isascent && gaschange_after && !atend && nextdp->entered) {
|
||||||
if (nextdp->setpoint) {
|
if (nextdp->setpoint) {
|
||||||
temp = casprintf_loc(translate("gettextFromC", "(SP = %.1fbar CCR)"), nextdp->setpoint / 1000.0);
|
temp = casprintf_loc(translate("gettextFromC", "(SP = %.1fbar CCR)"), nextdp->setpoint / 1000.0);
|
||||||
buf += format_string_std("<td style='padding-left: 10px; color: red; float: left;'><b>%s %s</b></td>",
|
buf += format_string_std("<td style='padding-left: 10px; color: red; float: left;'><b>%s %s</b></td>",
|
||||||
|
@ -395,7 +392,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
// gas switch at this waypoint for verbatim
|
// gas switch at this waypoint for verbatim
|
||||||
if (plan_verbatim) {
|
if (plan_verbatim) {
|
||||||
if (lastsetpoint >= 0) {
|
if (lastsetpoint >= 0) {
|
||||||
if (nextdp && nextdp->setpoint) {
|
if (!atend && nextdp->setpoint) {
|
||||||
buf += casprintf_loc(translate("gettextFromC", "Switch gas to %s (SP = %.1fbar)"), newgasmix.name().c_str(), (double) nextdp->setpoint / 1000.0);
|
buf += casprintf_loc(translate("gettextFromC", "Switch gas to %s (SP = %.1fbar)"), newgasmix.name().c_str(), (double) nextdp->setpoint / 1000.0);
|
||||||
} else {
|
} else {
|
||||||
buf += format_string_std(translate("gettextFromC", "Switch gas to %s"), newgasmix.name().c_str());
|
buf += format_string_std(translate("gettextFromC", "Switch gas to %s"), newgasmix.name().c_str());
|
||||||
|
@ -419,7 +416,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
lastdepth = dp->depth.mm;
|
lastdepth = dp->depth.mm;
|
||||||
lastsetpoint = dp->setpoint;
|
lastsetpoint = dp->setpoint;
|
||||||
lastentered = dp->entered;
|
lastentered = dp->entered;
|
||||||
} while ((dp = nextdp) != NULL);
|
}
|
||||||
if (!plan_verbatim)
|
if (!plan_verbatim)
|
||||||
buf += "</tbody>\n</table>\n<br/>\n";
|
buf += "</tbody>\n</table>\n<br/>\n";
|
||||||
|
|
||||||
|
@ -433,25 +430,25 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
/* Print the settings for the diveplan next. */
|
/* Print the settings for the diveplan next. */
|
||||||
buf += "<div>\n";
|
buf += "<div>\n";
|
||||||
if (decoMode(true) == BUEHLMANN) {
|
if (decoMode(true) == BUEHLMANN) {
|
||||||
buf += casprintf_loc(translate("gettextFromC", "Deco model: Bühlmann ZHL-16C with GFLow = %d%% and GFHigh = %d%%"), diveplan->gflow, diveplan->gfhigh);
|
buf += casprintf_loc(translate("gettextFromC", "Deco model: Bühlmann ZHL-16C with GFLow = %d%% and GFHigh = %d%%"), diveplan.gflow, diveplan.gfhigh);
|
||||||
} else if (decoMode(true) == VPMB) {
|
} else if (decoMode(true) == VPMB) {
|
||||||
if (diveplan->vpmb_conservatism == 0)
|
if (diveplan.vpmb_conservatism == 0)
|
||||||
buf += translate("gettextFromC", "Deco model: VPM-B at nominal conservatism");
|
buf += translate("gettextFromC", "Deco model: VPM-B at nominal conservatism");
|
||||||
else
|
else
|
||||||
buf += casprintf_loc(translate("gettextFromC", "Deco model: VPM-B at +%d conservatism"), diveplan->vpmb_conservatism);
|
buf += casprintf_loc(translate("gettextFromC", "Deco model: VPM-B at +%d conservatism"), diveplan.vpmb_conservatism);
|
||||||
if (diveplan->eff_gflow)
|
if (diveplan.eff_gflow)
|
||||||
buf += casprintf_loc( translate("gettextFromC", ", effective GF=%d/%d"), diveplan->eff_gflow, diveplan->eff_gfhigh);
|
buf += casprintf_loc( translate("gettextFromC", ", effective GF=%d/%d"), diveplan.eff_gflow, diveplan.eff_gfhigh);
|
||||||
} else if (decoMode(true) == RECREATIONAL) {
|
} else if (decoMode(true) == RECREATIONAL) {
|
||||||
buf += casprintf_loc(translate("gettextFromC", "Deco model: Recreational mode based on Bühlmann ZHL-16B with GFLow = %d%% and GFHigh = %d%%"),
|
buf += casprintf_loc(translate("gettextFromC", "Deco model: Recreational mode based on Bühlmann ZHL-16B with GFLow = %d%% and GFHigh = %d%%"),
|
||||||
diveplan->gflow, diveplan->gfhigh);
|
diveplan.gflow, diveplan.gfhigh);
|
||||||
}
|
}
|
||||||
buf += "<br/>\n";
|
buf += "<br/>\n";
|
||||||
|
|
||||||
{
|
{
|
||||||
const char *depth_unit;
|
const char *depth_unit;
|
||||||
int altitude = (int) get_depth_units((int) (pressure_to_altitude(diveplan->surface_pressure)), NULL, &depth_unit);
|
int altitude = (int) get_depth_units((int) (pressure_to_altitude(diveplan.surface_pressure)), NULL, &depth_unit);
|
||||||
|
|
||||||
buf += casprintf_loc(translate("gettextFromC", "ATM pressure: %dmbar (%d%s)<br/>\n</div>\n"), diveplan->surface_pressure, altitude, depth_unit);
|
buf += casprintf_loc(translate("gettextFromC", "ATM pressure: %dmbar (%d%s)<br/>\n</div>\n"), diveplan.surface_pressure, altitude, depth_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get SAC values and units for printing it in gas consumption */
|
/* Get SAC values and units for printing it in gas consumption */
|
||||||
|
@ -584,44 +581,42 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
|
|
||||||
/* Print warnings for pO2 (move into separate function?) */
|
/* Print warnings for pO2 (move into separate function?) */
|
||||||
{
|
{
|
||||||
dp = diveplan->dp;
|
|
||||||
bool o2warning_exist = false;
|
bool o2warning_exist = false;
|
||||||
double amb;
|
double amb;
|
||||||
|
|
||||||
divemode_loop loop(dive->dcs[0]);
|
divemode_loop loop(dive->dcs[0]);
|
||||||
if (dive->dcs[0].divemode != CCR) {
|
if (dive->dcs[0].divemode != CCR) {
|
||||||
while (dp) {
|
for (auto &dp: diveplan.dp) {
|
||||||
if (dp->time != 0) {
|
if (dp.time != 0) {
|
||||||
std::string temp;
|
std::string temp;
|
||||||
struct gasmix gasmix = dive->get_cylinder(dp->cylinderid)->gasmix;
|
struct gasmix gasmix = dive->get_cylinder(dp.cylinderid)->gasmix;
|
||||||
|
|
||||||
divemode_t current_divemode = loop.at(dp->time);
|
divemode_t current_divemode = loop.at(dp.time);
|
||||||
amb = dive->depth_to_atm(dp->depth.mm);
|
amb = dive->depth_to_atm(dp.depth.mm);
|
||||||
gas_pressures pressures = fill_pressures(amb, gasmix, (current_divemode == OC) ? 0.0 : amb * gasmix.o2.permille / 1000.0, current_divemode);
|
gas_pressures pressures = fill_pressures(amb, gasmix, (current_divemode == OC) ? 0.0 : amb * gasmix.o2.permille / 1000.0, current_divemode);
|
||||||
|
|
||||||
if (pressures.o2 > (dp->entered ? prefs.bottompo2 : prefs.decopo2) / 1000.0) {
|
if (pressures.o2 > (dp.entered ? prefs.bottompo2 : prefs.decopo2) / 1000.0) {
|
||||||
const char *depth_unit;
|
const char *depth_unit;
|
||||||
int decimals;
|
int decimals;
|
||||||
double depth_value = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
|
double depth_value = get_depth_units(dp.depth.mm, &decimals, &depth_unit);
|
||||||
if (!o2warning_exist)
|
if (!o2warning_exist)
|
||||||
buf += "<div>\n";
|
buf += "<div>\n";
|
||||||
o2warning_exist = true;
|
o2warning_exist = true;
|
||||||
temp = casprintf_loc(translate("gettextFromC", "high pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"),
|
temp = casprintf_loc(translate("gettextFromC", "high pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"),
|
||||||
pressures.o2, FRACTION_TUPLE(dp->time, 60), gasmix.name().c_str(), decimals, depth_value, depth_unit);
|
pressures.o2, FRACTION_TUPLE(dp.time, 60), gasmix.name().c_str(), decimals, depth_value, depth_unit);
|
||||||
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>\n", translate("gettextFromC", "Warning:"), temp.c_str());
|
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>\n", translate("gettextFromC", "Warning:"), temp.c_str());
|
||||||
} else if (pressures.o2 < 0.16) {
|
} else if (pressures.o2 < 0.16) {
|
||||||
const char *depth_unit;
|
const char *depth_unit;
|
||||||
int decimals;
|
int decimals;
|
||||||
double depth_value = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
|
double depth_value = get_depth_units(dp.depth.mm, &decimals, &depth_unit);
|
||||||
if (!o2warning_exist)
|
if (!o2warning_exist)
|
||||||
buf += "<div>";
|
buf += "<div>";
|
||||||
o2warning_exist = true;
|
o2warning_exist = true;
|
||||||
temp = casprintf_loc(translate("gettextFromC", "low pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"),
|
temp = casprintf_loc(translate("gettextFromC", "low pO₂ value %.2f at %d:%02u with gas %s at depth %.*f %s"),
|
||||||
pressures.o2, FRACTION_TUPLE(dp->time, 60), gasmix.name().c_str(), decimals, depth_value, depth_unit);
|
pressures.o2, FRACTION_TUPLE(dp.time, 60), gasmix.name().c_str(), decimals, depth_value, depth_unit);
|
||||||
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>\n", translate("gettextFromC", "Warning:"), temp.c_str());
|
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>\n", translate("gettextFromC", "Warning:"), temp.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dp = dp->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o2warning_exist)
|
if (o2warning_exist)
|
||||||
|
|
|
@ -128,7 +128,7 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn)
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
removeDeco();
|
removeDeco();
|
||||||
free_dps(&diveplan);
|
diveplan.dp.clear();
|
||||||
|
|
||||||
diveplan.when = d->when;
|
diveplan.when = d->when;
|
||||||
// is this a "new" dive where we marked manually entered samples?
|
// is this a "new" dive where we marked manually entered samples?
|
||||||
|
@ -396,7 +396,7 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
|
||||||
}
|
}
|
||||||
case CCSETPOINT: {
|
case CCSETPOINT: {
|
||||||
bool ok;
|
bool ok;
|
||||||
int po2 = lrintf(value.toFloat(&ok) * 100) * 10;
|
int po2 = static_cast<int>(round(value.toFloat(&ok) * 100) * 10);
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
p.setpoint = std::max(po2, 160);
|
p.setpoint = std::max(po2, 160);
|
||||||
|
@ -499,7 +499,6 @@ DivePlannerPointsModel::DivePlannerPointsModel(QObject *parent) : QAbstractTable
|
||||||
cylinders(true),
|
cylinders(true),
|
||||||
mode(NOTHING)
|
mode(NOTHING)
|
||||||
{
|
{
|
||||||
memset(&diveplan, 0, sizeof(diveplan));
|
|
||||||
startTime.setTimeSpec(Qt::UTC);
|
startTime.setTimeSpec(Qt::UTC);
|
||||||
// use a Qt-connection to send the variations text across thread boundary (in case we
|
// use a Qt-connection to send the variations text across thread boundary (in case we
|
||||||
// are calculating the variations in a background thread).
|
// are calculating the variations in a background thread).
|
||||||
|
@ -890,7 +889,6 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int cylinderid_
|
||||||
point.minimum_gas.mbar = 0;
|
point.minimum_gas.mbar = 0;
|
||||||
point.entered = entered;
|
point.entered = entered;
|
||||||
point.divemode = divemode;
|
point.divemode = divemode;
|
||||||
point.next = NULL;
|
|
||||||
divepoints.insert(divepoints.begin() + row, point);
|
divepoints.insert(divepoints.begin() + row, point);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
return row;
|
return row;
|
||||||
|
@ -1050,7 +1048,7 @@ void DivePlannerPointsModel::cancelPlan()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setPlanMode(NOTHING);
|
setPlanMode(NOTHING);
|
||||||
free_dps(&diveplan);
|
diveplan.dp.clear();
|
||||||
|
|
||||||
emit planCanceled();
|
emit planCanceled();
|
||||||
}
|
}
|
||||||
|
@ -1086,11 +1084,11 @@ void DivePlannerPointsModel::clear()
|
||||||
void DivePlannerPointsModel::createTemporaryPlan()
|
void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
{
|
{
|
||||||
// Get the user-input and calculate the dive info
|
// Get the user-input and calculate the dive info
|
||||||
free_dps(&diveplan);
|
diveplan.dp.clear();
|
||||||
|
|
||||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
||||||
if (cyl.depth.mm && cyl.cylinder_use == OC_GAS)
|
if (cyl.depth.mm && cyl.cylinder_use == OC_GAS)
|
||||||
plan_add_segment(&diveplan, 0, cyl.depth.mm, i, 0, false, OC);
|
plan_add_segment(diveplan, 0, cyl.depth.mm, i, 0, false, OC);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastIndex = -1;
|
int lastIndex = -1;
|
||||||
|
@ -1101,15 +1099,15 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
lastIndex = i;
|
lastIndex = i;
|
||||||
if (i == 0 && mode == PLAN && prefs.drop_stone_mode) {
|
if (i == 0 && mode == PLAN && prefs.drop_stone_mode) {
|
||||||
/* Okay, we add a first segment where we go down to depth */
|
/* Okay, we add a first segment where we go down to depth */
|
||||||
plan_add_segment(&diveplan, p.depth.mm / prefs.descrate, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
plan_add_segment(diveplan, p.depth.mm / prefs.descrate, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
||||||
deltaT -= p.depth.mm / prefs.descrate;
|
deltaT -= p.depth.mm / prefs.descrate;
|
||||||
}
|
}
|
||||||
if (p.entered)
|
if (p.entered)
|
||||||
plan_add_segment(&diveplan, deltaT, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
plan_add_segment(diveplan, deltaT, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_PLAN
|
#if DEBUG_PLAN
|
||||||
dump_plan(&diveplan);
|
dump_plan(diveplan);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,27 +1121,27 @@ void DivePlannerPointsModel::updateDiveProfile()
|
||||||
if (!d)
|
if (!d)
|
||||||
return;
|
return;
|
||||||
createTemporaryPlan();
|
createTemporaryPlan();
|
||||||
if (diveplan_empty(&diveplan))
|
if (diveplan_empty(diveplan))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
deco_state_cache cache;
|
deco_state_cache cache;
|
||||||
struct decostop stoptable[60];
|
struct decostop stoptable[60];
|
||||||
struct deco_state plan_deco_state;
|
struct deco_state plan_deco_state;
|
||||||
|
|
||||||
plan(&plan_deco_state, &diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), false);
|
plan(&plan_deco_state, diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), false);
|
||||||
updateMaxDepth();
|
updateMaxDepth();
|
||||||
|
|
||||||
if (isPlanner() && shouldComputeVariations()) {
|
if (isPlanner() && shouldComputeVariations()) {
|
||||||
struct diveplan *plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
|
auto plan_copy = std::make_unique<struct diveplan>();
|
||||||
lock_planner();
|
lock_planner();
|
||||||
cloneDiveplan(&diveplan, plan_copy);
|
cloneDiveplan(diveplan, *plan_copy);
|
||||||
unlock_planner();
|
unlock_planner();
|
||||||
#ifdef VARIATIONS_IN_BACKGROUND
|
#ifdef VARIATIONS_IN_BACKGROUND
|
||||||
// Since we're calling computeVariations asynchronously and plan_deco_state is allocated
|
// Since we're calling computeVariations asynchronously and plan_deco_state is allocated
|
||||||
// on the stack, it must be copied and freed by the worker-thread.
|
// on the stack, it must be copied and freed by the worker-thread.
|
||||||
auto plan_deco_state_copy = std::make_unique<deco_state>(plan_deco_state);
|
auto deco_copy = std::make_unique<deco_state>(plan_deco_state);
|
||||||
|
|
||||||
// Ideally, we would pass the unique_ptr to the lambda for QtConcurrent::run().
|
// Ideally, we would pass the unique_ptrs to the lambda for QtConcurrent::run().
|
||||||
// This, in principle, can be done as such:
|
// This, in principle, can be done as such:
|
||||||
// [ptr = std::move(ptr)] () mutable { f(std::move(ptr)) };
|
// [ptr = std::move(ptr)] () mutable { f(std::move(ptr)) };
|
||||||
// However, this make the lambda uncopyable and QtConcurrent::run() sadly
|
// However, this make the lambda uncopyable and QtConcurrent::run() sadly
|
||||||
|
@ -1154,16 +1152,16 @@ void DivePlannerPointsModel::updateDiveProfile()
|
||||||
// exceptions anyway.
|
// exceptions anyway.
|
||||||
// Note 2: We also can't use the function / argument syntax of QtConcurrent::run(),
|
// Note 2: We also can't use the function / argument syntax of QtConcurrent::run(),
|
||||||
// because it likewise uses copy-semantics. How annoying.
|
// because it likewise uses copy-semantics. How annoying.
|
||||||
QtConcurrent::run([this, plan_copy, deco = plan_deco_state_copy.release()] ()
|
QtConcurrent::run([this, plan = plan_copy.release(), deco = deco_copy.release()] ()
|
||||||
{ this->computeVariationsFreeDeco(plan_copy, std::unique_ptr<deco_state>(deco)); });
|
{ this->computeVariationsFreeDeco(std::unique_ptr<struct diveplan>(plan),
|
||||||
|
std::unique_ptr<deco_state>(deco)); });
|
||||||
#else
|
#else
|
||||||
computeVariations(plan_copy, &plan_deco_state);
|
computeVariations(std::move(plan_copy), &plan_deco_state);
|
||||||
#endif
|
#endif
|
||||||
final_deco_state = plan_deco_state;
|
final_deco_state = plan_deco_state;
|
||||||
}
|
}
|
||||||
emit calculatedPlanNotes(QString::fromStdString(d->notes));
|
emit calculatedPlanNotes(QString::fromStdString(d->notes));
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG_PLAN
|
#if DEBUG_PLAN
|
||||||
save_dive(stderr, *d);
|
save_dive(stderr, *d);
|
||||||
dump_plan(&diveplan);
|
dump_plan(&diveplan);
|
||||||
|
@ -1172,7 +1170,7 @@ void DivePlannerPointsModel::updateDiveProfile()
|
||||||
|
|
||||||
void DivePlannerPointsModel::deleteTemporaryPlan()
|
void DivePlannerPointsModel::deleteTemporaryPlan()
|
||||||
{
|
{
|
||||||
free_dps(&diveplan);
|
diveplan.dp.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::savePlan()
|
void DivePlannerPointsModel::savePlan()
|
||||||
|
@ -1185,26 +1183,9 @@ void DivePlannerPointsModel::saveDuplicatePlan()
|
||||||
createPlan(true);
|
createPlan(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct divedatapoint *DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy)
|
void DivePlannerPointsModel::cloneDiveplan(const struct diveplan &plan_src, struct diveplan &plan_copy)
|
||||||
{
|
{
|
||||||
divedatapoint *src, *last_segment;
|
plan_copy = plan_src;
|
||||||
divedatapoint **dp;
|
|
||||||
|
|
||||||
src = plan_src->dp;
|
|
||||||
*plan_copy = *plan_src;
|
|
||||||
dp = &plan_copy->dp;
|
|
||||||
while (src && (!src->time || src->entered)) {
|
|
||||||
*dp = (struct divedatapoint *)malloc(sizeof(struct divedatapoint));
|
|
||||||
**dp = *src;
|
|
||||||
dp = &(*dp)->next;
|
|
||||||
src = src->next;
|
|
||||||
}
|
|
||||||
(*dp) = NULL;
|
|
||||||
|
|
||||||
last_segment = plan_copy->dp;
|
|
||||||
while (last_segment && last_segment->next && last_segment->next->next)
|
|
||||||
last_segment = last_segment->next;
|
|
||||||
return last_segment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit)
|
int DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit)
|
||||||
|
@ -1240,13 +1221,21 @@ int DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decos
|
||||||
return (leftsum + rightsum) / 2;
|
return (leftsum + rightsum) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::computeVariationsFreeDeco(struct diveplan *original_plan, std::unique_ptr<struct deco_state> previous_ds)
|
void DivePlannerPointsModel::computeVariationsFreeDeco(std::unique_ptr<struct diveplan> original_plan, std::unique_ptr<struct deco_state> previous_ds)
|
||||||
{
|
{
|
||||||
computeVariations(original_plan, previous_ds.get());
|
computeVariations(std::move(original_plan), previous_ds.get());
|
||||||
// Note: previous ds automatically free()d by virtue of being a unique_ptr.
|
// Note: previous ds automatically free()d by virtue of being a unique_ptr.
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, const struct deco_state *previous_ds)
|
// Return reference to second to last element.
|
||||||
|
// Caller is responsible for checking that there are at least two elements.
|
||||||
|
template <typename T>
|
||||||
|
auto &second_to_last(T &v)
|
||||||
|
{
|
||||||
|
return *std::prev(std::prev(v.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivePlannerPointsModel::computeVariations(std::unique_ptr<struct diveplan> original_plan, const struct deco_state *previous_ds)
|
||||||
{
|
{
|
||||||
// nothing to do unless there's an original plan
|
// nothing to do unless there's an original plan
|
||||||
if (!original_plan)
|
if (!original_plan)
|
||||||
|
@ -1257,7 +1246,6 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
|
||||||
struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60];
|
struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60];
|
||||||
deco_state_cache cache, save;
|
deco_state_cache cache, save;
|
||||||
struct diveplan plan_copy;
|
struct diveplan plan_copy;
|
||||||
struct divedatapoint *last_segment;
|
|
||||||
struct deco_state ds = *previous_ds;
|
struct deco_state ds = *previous_ds;
|
||||||
|
|
||||||
int my_instance = ++instanceCounter;
|
int my_instance = ++instanceCounter;
|
||||||
|
@ -1276,47 +1264,45 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
|
||||||
depth_units = tr("ft");
|
depth_units = tr("ft");
|
||||||
}
|
}
|
||||||
|
|
||||||
last_segment = cloneDiveplan(original_plan, &plan_copy);
|
cloneDiveplan(*original_plan, plan_copy);
|
||||||
if (!last_segment)
|
if (plan_copy.dp.size() < 2)
|
||||||
goto finish;
|
return;
|
||||||
if (my_instance != instanceCounter)
|
if (my_instance != instanceCounter)
|
||||||
goto finish;
|
return;
|
||||||
plan(&ds, &plan_copy, dive.get(), dcNr, 1, original, cache, true, false);
|
plan(&ds, plan_copy, dive.get(), dcNr, 1, original, cache, true, false);
|
||||||
free_dps(&plan_copy);
|
plan_copy.dp.clear();
|
||||||
save.restore(&ds, false);
|
save.restore(&ds, false);
|
||||||
|
|
||||||
last_segment = cloneDiveplan(original_plan, &plan_copy);
|
cloneDiveplan(*original_plan, plan_copy);
|
||||||
last_segment->depth.mm += delta_depth.mm;
|
second_to_last(plan_copy.dp).depth.mm += delta_depth.mm;
|
||||||
last_segment->next->depth.mm += delta_depth.mm;
|
plan_copy.dp.back().depth.mm += delta_depth.mm;
|
||||||
if (my_instance != instanceCounter)
|
if (my_instance != instanceCounter)
|
||||||
goto finish;
|
return;
|
||||||
plan(&ds, &plan_copy, dive.get(), dcNr, 1, deeper, cache, true, false);
|
plan(&ds, plan_copy, dive.get(), dcNr, 1, deeper, cache, true, false);
|
||||||
free_dps(&plan_copy);
|
plan_copy.dp.clear();
|
||||||
save.restore(&ds, false);
|
save.restore(&ds, false);
|
||||||
|
|
||||||
last_segment = cloneDiveplan(original_plan, &plan_copy);
|
second_to_last(plan_copy.dp).depth.mm -= delta_depth.mm;
|
||||||
last_segment->depth.mm -= delta_depth.mm;
|
plan_copy.dp.back().depth.mm -= delta_depth.mm;
|
||||||
last_segment->next->depth.mm -= delta_depth.mm;
|
|
||||||
if (my_instance != instanceCounter)
|
if (my_instance != instanceCounter)
|
||||||
goto finish;
|
return;
|
||||||
plan(&ds, &plan_copy, dive.get(), dcNr, 1, shallower, cache, true, false);
|
plan(&ds, plan_copy, dive.get(), dcNr, 1, shallower, cache, true, false);
|
||||||
free_dps(&plan_copy);
|
plan_copy.dp.clear();
|
||||||
save.restore(&ds, false);
|
save.restore(&ds, false);
|
||||||
|
|
||||||
last_segment = cloneDiveplan(original_plan, &plan_copy);
|
cloneDiveplan(*original_plan, plan_copy);
|
||||||
last_segment->next->time += delta_time.seconds;
|
plan_copy.dp.back().time += delta_time.seconds;
|
||||||
if (my_instance != instanceCounter)
|
if (my_instance != instanceCounter)
|
||||||
goto finish;
|
return;
|
||||||
plan(&ds, &plan_copy, dive.get(), dcNr, 1, longer, cache, true, false);
|
plan(&ds, plan_copy, dive.get(), dcNr, 1, longer, cache, true, false);
|
||||||
free_dps(&plan_copy);
|
plan_copy.dp.clear();
|
||||||
save.restore(&ds, false);
|
save.restore(&ds, false);
|
||||||
|
|
||||||
last_segment = cloneDiveplan(original_plan, &plan_copy);
|
plan_copy.dp.back().time -= delta_time.seconds;
|
||||||
last_segment->next->time -= delta_time.seconds;
|
|
||||||
if (my_instance != instanceCounter)
|
if (my_instance != instanceCounter)
|
||||||
goto finish;
|
return;
|
||||||
plan(&ds, &plan_copy, dive.get(), dcNr, 1, shorter, cache, true, false);
|
plan(&ds, plan_copy, dive.get(), dcNr, 1, shorter, cache, true, false);
|
||||||
free_dps(&plan_copy);
|
plan_copy.dp.clear();
|
||||||
save.restore(&ds, false);
|
save.restore(&ds, false);
|
||||||
|
|
||||||
char buf[200];
|
char buf[200];
|
||||||
|
@ -1329,9 +1315,6 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
|
||||||
#ifdef DEBUG_STOPVAR
|
#ifdef DEBUG_STOPVAR
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
#endif
|
#endif
|
||||||
finish:
|
|
||||||
free_dps(original_plan);
|
|
||||||
free(original_plan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::computeVariationsDone(QString variations)
|
void DivePlannerPointsModel::computeVariationsDone(QString variations)
|
||||||
|
@ -1360,15 +1343,14 @@ void DivePlannerPointsModel::createPlan(bool saveAsNew)
|
||||||
createTemporaryPlan();
|
createTemporaryPlan();
|
||||||
|
|
||||||
struct decostop stoptable[60];
|
struct decostop stoptable[60];
|
||||||
plan(&ds_after_previous_dives, &diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), true);
|
plan(&ds_after_previous_dives, diveplan, d, dcNr, decotimestep, stoptable, cache, isPlanner(), true);
|
||||||
|
|
||||||
if (shouldComputeVariations()) {
|
if (shouldComputeVariations()) {
|
||||||
struct diveplan *plan_copy;
|
auto plan_copy = std::make_unique<struct diveplan>();
|
||||||
plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
|
|
||||||
lock_planner();
|
lock_planner();
|
||||||
cloneDiveplan(&diveplan, plan_copy);
|
cloneDiveplan(diveplan, *plan_copy);
|
||||||
unlock_planner();
|
unlock_planner();
|
||||||
computeVariations(plan_copy, &ds_after_previous_dives);
|
computeVariations(std::move(plan_copy), &ds_after_previous_dives);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixup planner notes.
|
// Fixup planner notes.
|
||||||
|
@ -1426,7 +1408,7 @@ void DivePlannerPointsModel::createPlan(bool saveAsNew)
|
||||||
|
|
||||||
// Remove and clean the diveplan, so we don't delete
|
// Remove and clean the diveplan, so we don't delete
|
||||||
// the dive by mistake.
|
// the dive by mistake.
|
||||||
free_dps(&diveplan);
|
diveplan.dp.clear();
|
||||||
|
|
||||||
planCreated(); // This signal will exit the UI from planner state.
|
planCreated(); // This signal will exit the UI from planner state.
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,10 +130,10 @@ private:
|
||||||
void updateDiveProfile(); // Creates a temporary plan and updates the dive profile with it.
|
void updateDiveProfile(); // Creates a temporary plan and updates the dive profile with it.
|
||||||
void createTemporaryPlan();
|
void createTemporaryPlan();
|
||||||
struct diveplan diveplan;
|
struct diveplan diveplan;
|
||||||
struct divedatapoint *cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy);
|
void cloneDiveplan(const struct diveplan &plan_src, struct diveplan &plan_copy);
|
||||||
void computeVariationsDone(QString text);
|
void computeVariationsDone(QString text);
|
||||||
void computeVariations(struct diveplan *diveplan, const struct deco_state *ds);
|
void computeVariations(std::unique_ptr<struct diveplan> plan, const struct deco_state *ds);
|
||||||
void computeVariationsFreeDeco(struct diveplan *diveplan, std::unique_ptr<struct deco_state> ds);
|
void computeVariationsFreeDeco(std::unique_ptr<struct diveplan> plan, std::unique_ptr<struct deco_state> ds);
|
||||||
int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit);
|
int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit);
|
||||||
struct dive *d;
|
struct dive *d;
|
||||||
int dcNr;
|
int dcNr;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
static struct dive dive;
|
static struct dive dive;
|
||||||
static struct decostop stoptable[60];
|
static struct decostop stoptable[60];
|
||||||
static struct deco_state test_deco_state;
|
static struct deco_state test_deco_state;
|
||||||
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()
|
void setupPrefs()
|
||||||
{
|
{
|
||||||
prefs = default_prefs;
|
prefs = default_prefs;
|
||||||
|
@ -39,14 +38,15 @@ void setupPrefsVpmb()
|
||||||
prefs.vpmb_conservatism = 0;
|
prefs.vpmb_conservatism = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlan(struct diveplan *dp)
|
diveplan setupPlan()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->gfhigh = 100;
|
dp.surface_pressure = 1013;
|
||||||
dp->gflow = 100;
|
dp.gfhigh = 100;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.gflow = 100;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{150}, {450}};
|
struct gasmix bottomgas = {{150}, {450}};
|
||||||
struct gasmix ean36 = {{360}, {0}};
|
struct gasmix ean36 = {{360}, {0}};
|
||||||
|
@ -64,23 +64,24 @@ void setupPlan(struct diveplan *dp)
|
||||||
cyl1->gasmix = ean36;
|
cyl1->gasmix = ean36;
|
||||||
cyl2->gasmix = oxygen;
|
cyl2->gasmix = oxygen;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(79, 260) * 60 / M_OR_FT(23, 75);
|
int droptime = M_OR_FT(79, 260) * 60 / M_OR_FT(23, 75);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean36, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean36, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(79, 260), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(79, 260), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(79, 260), 0, 0, 1, OC);
|
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(79, 260), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb45m30mTx(struct diveplan *dp)
|
diveplan setupPlanVpmb45m30mTx()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->gfhigh = 100;
|
dp.surface_pressure = 1013;
|
||||||
dp->gflow = 100;
|
dp.gfhigh = 100;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.gflow = 100;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{210}, {350}};
|
struct gasmix bottomgas = {{210}, {350}};
|
||||||
struct gasmix ean50 = {{500}, {0}};
|
struct gasmix ean50 = {{500}, {0}};
|
||||||
|
@ -98,23 +99,24 @@ void setupPlanVpmb45m30mTx(struct diveplan *dp)
|
||||||
cyl1->gasmix = ean50;
|
cyl1->gasmix = ean50;
|
||||||
cyl2->gasmix = oxygen;
|
cyl2->gasmix = oxygen;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(45, 150) * 60 / M_OR_FT(23, 75);
|
int droptime = M_OR_FT(45, 150) * 60 / M_OR_FT(23, 75);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(45, 150), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(45, 150), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(45, 150), 0, 0, 1, OC);
|
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(45, 150), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb60m10mTx(struct diveplan *dp)
|
diveplan setupPlanVpmb60m10mTx()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->gfhigh = 100;
|
dp.surface_pressure = 1013;
|
||||||
dp->gflow = 100;
|
dp.gfhigh = 100;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.gflow = 100;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{180}, {450}};
|
struct gasmix bottomgas = {{180}, {450}};
|
||||||
struct gasmix tx50_15 = {{500}, {150}};
|
struct gasmix tx50_15 = {{500}, {150}};
|
||||||
|
@ -132,21 +134,22 @@ void setupPlanVpmb60m10mTx(struct diveplan *dp)
|
||||||
cyl1->gasmix = tx50_15;
|
cyl1->gasmix = tx50_15;
|
||||||
cyl2->gasmix = oxygen;
|
cyl2->gasmix = oxygen;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(23, 75);
|
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(23, 75);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(tx50_15, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(tx50_15, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb60m30minAir(struct diveplan *dp)
|
diveplan setupPlanVpmb60m30minAir()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{210}, {0}};
|
struct gasmix bottomgas = {{210}, {0}};
|
||||||
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
||||||
|
@ -155,19 +158,20 @@ void setupPlanVpmb60m30minAir(struct diveplan *dp)
|
||||||
cyl0->type.workingpressure.mbar = 232000;
|
cyl0->type.workingpressure.mbar = 232000;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb60m30minEan50(struct diveplan *dp)
|
diveplan setupPlanVpmb60m30minEan50()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{210}, {0}};
|
struct gasmix bottomgas = {{210}, {0}};
|
||||||
struct gasmix ean50 = {{500}, {0}};
|
struct gasmix ean50 = {{500}, {0}};
|
||||||
|
@ -183,20 +187,21 @@ void setupPlanVpmb60m30minEan50(struct diveplan *dp)
|
||||||
cyl1->gasmix = ean50;
|
cyl1->gasmix = ean50;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb60m30minTx(struct diveplan *dp)
|
diveplan setupPlanVpmb60m30minTx()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{180}, {450}};
|
struct gasmix bottomgas = {{180}, {450}};
|
||||||
struct gasmix ean50 = {{500}, {0}};
|
struct gasmix ean50 = {{500}, {0}};
|
||||||
|
@ -212,20 +217,21 @@ void setupPlanVpmb60m30minTx(struct diveplan *dp)
|
||||||
cyl1->gasmix = ean50;
|
cyl1->gasmix = ean50;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(60, 200) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 30 * 60 - droptime, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmbMultiLevelAir(struct diveplan *dp)
|
diveplan setupPlanVpmbMultiLevelAir()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{210}, {0}};
|
struct gasmix bottomgas = {{210}, {0}};
|
||||||
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
||||||
|
@ -234,21 +240,22 @@ void setupPlanVpmbMultiLevelAir(struct diveplan *dp)
|
||||||
cyl0->type.workingpressure.mbar = 232000;
|
cyl0->type.workingpressure.mbar = 232000;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(20, 66) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(20, 66) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(20, 66), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(20, 66), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(20, 66), 0, 0, 1, OC);
|
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(20, 66), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 1 * 60, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 1 * 60, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 29 * 60, M_OR_FT(60, 200), 0, 0, 1, OC);
|
plan_add_segment(dp, 29 * 60, M_OR_FT(60, 200), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb100m60min(struct diveplan *dp)
|
diveplan setupPlanVpmb100m60min()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{180}, {450}};
|
struct gasmix bottomgas = {{180}, {450}};
|
||||||
struct gasmix ean50 = {{500}, {0}};
|
struct gasmix ean50 = {{500}, {0}};
|
||||||
|
@ -267,21 +274,22 @@ void setupPlanVpmb100m60min(struct diveplan *dp)
|
||||||
cyl2->gasmix = oxygen;
|
cyl2->gasmix = oxygen;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 60 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
plan_add_segment(dp, 60 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb100m10min(struct diveplan *dp)
|
diveplan setupPlanVpmb100m10min()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{180}, {450}};
|
struct gasmix bottomgas = {{180}, {450}};
|
||||||
struct gasmix ean50 = {{500}, {0}};
|
struct gasmix ean50 = {{500}, {0}};
|
||||||
|
@ -300,21 +308,22 @@ void setupPlanVpmb100m10min(struct diveplan *dp)
|
||||||
cyl2->gasmix = oxygen;
|
cyl2->gasmix = oxygen;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(99, 330);
|
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(99, 330);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(ean50, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(oxygen, po2, M_OR_FT(3, 10)).mm, 2, 0, 1, OC);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
plan_add_segment(dp, 10 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb30m20min(struct diveplan *dp)
|
diveplan setupPlanVpmb30m20min()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{210}, {0}};
|
struct gasmix bottomgas = {{210}, {0}};
|
||||||
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
cylinder_t *cyl0 = dive.get_or_create_cylinder(0);
|
||||||
|
@ -323,19 +332,20 @@ void setupPlanVpmb30m20min(struct diveplan *dp)
|
||||||
cyl0->type.workingpressure.mbar = 232000;
|
cyl0->type.workingpressure.mbar = 232000;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(30, 100) * 60 / M_OR_FT(18, 60);
|
int droptime = M_OR_FT(30, 100) * 60 / M_OR_FT(18, 60);
|
||||||
plan_add_segment(dp, droptime, M_OR_FT(30, 100), 0, 0, 1, OC);
|
plan_add_segment(dp, droptime, M_OR_FT(30, 100), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 20 * 60 - droptime, M_OR_FT(30, 100), 0, 0, 1, OC);
|
plan_add_segment(dp, 20 * 60 - droptime, M_OR_FT(30, 100), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanVpmb100mTo70m30min(struct diveplan *dp)
|
diveplan setupPlanVpmb100mTo70m30min()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix bottomgas = {{120}, {650}};
|
struct gasmix bottomgas = {{120}, {650}};
|
||||||
struct gasmix tx21_35 = {{210}, {350}};
|
struct gasmix tx21_35 = {{210}, {350}};
|
||||||
|
@ -357,7 +367,6 @@ void setupPlanVpmb100mTo70m30min(struct diveplan *dp)
|
||||||
cyl3->gasmix = oxygen;
|
cyl3->gasmix = oxygen;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(18, 60);
|
int droptime = M_OR_FT(100, 330) * 60 / M_OR_FT(18, 60);
|
||||||
plan_add_segment(dp, 0, dive.gas_mod(tx21_35, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
plan_add_segment(dp, 0, dive.gas_mod(tx21_35, po2, M_OR_FT(3, 10)).mm, 1, 0, 1, OC);
|
||||||
|
@ -367,16 +376,18 @@ void setupPlanVpmb100mTo70m30min(struct diveplan *dp)
|
||||||
plan_add_segment(dp, 20 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
plan_add_segment(dp, 20 * 60 - droptime, M_OR_FT(100, 330), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, 3 * 60, M_OR_FT(70, 230), 0, 0, 1, OC);
|
plan_add_segment(dp, 3 * 60, M_OR_FT(70, 230), 0, 0, 1, OC);
|
||||||
plan_add_segment(dp, (30 - 20 - 3) * 60, M_OR_FT(70, 230), 0, 0, 1, OC);
|
plan_add_segment(dp, (30 - 20 - 3) * 60, M_OR_FT(70, 230), 0, 0, 1, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This tests handling different gases in the manually entered part of the dive */
|
/* This tests handling different gases in the manually entered part of the dive */
|
||||||
|
|
||||||
void setupPlanSeveralGases(struct diveplan *dp)
|
diveplan setupPlanSeveralGases()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.surface_pressure = 1013;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
struct gasmix ean36 = {{360}, {0}};
|
struct gasmix ean36 = {{360}, {0}};
|
||||||
struct gasmix tx11_50 = {{110}, {500}};
|
struct gasmix tx11_50 = {{110}, {500}};
|
||||||
|
@ -392,22 +403,23 @@ void setupPlanSeveralGases(struct diveplan *dp)
|
||||||
cyl1->gasmix = tx11_50;
|
cyl1->gasmix = tx11_50;
|
||||||
dive.surface_pressure.mbar = 1013;
|
dive.surface_pressure.mbar = 1013;
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
plan_add_segment(dp, 120, 40000, 0, 0, true, OC);
|
plan_add_segment(dp, 120, 40000, 0, 0, true, OC);
|
||||||
plan_add_segment(dp, 18 * 60, 40000, 0, 0, true, OC);
|
plan_add_segment(dp, 18 * 60, 40000, 0, 0, true, OC);
|
||||||
plan_add_segment(dp, 10 * 60, 10000, 1, 0, true, OC);
|
plan_add_segment(dp, 10 * 60, 10000, 1, 0, true, OC);
|
||||||
plan_add_segment(dp, 5 * 60, 10000, 0, 0, true, OC);
|
plan_add_segment(dp, 5 * 60, 10000, 0, 0, true, OC);
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPlanCcr(struct diveplan *dp)
|
diveplan setupPlanCcr()
|
||||||
{
|
{
|
||||||
dp->salinity = 10300;
|
diveplan dp;
|
||||||
dp->surface_pressure = 1013;
|
dp.salinity = 10300;
|
||||||
dp->gflow = 50;
|
dp.surface_pressure = 1013;
|
||||||
dp->gfhigh = 70;
|
dp.gflow = 50;
|
||||||
dp->bottomsac = prefs.bottomsac;
|
dp.gfhigh = 70;
|
||||||
dp->decosac = prefs.decosac;
|
dp.bottomsac = prefs.bottomsac;
|
||||||
|
dp.decosac = prefs.decosac;
|
||||||
|
|
||||||
pressure_t po2 = {1600};
|
pressure_t po2 = {1600};
|
||||||
struct gasmix diluent = {{200}, {210}};
|
struct gasmix diluent = {{200}, {210}};
|
||||||
|
@ -429,11 +441,12 @@ void setupPlanCcr(struct diveplan *dp)
|
||||||
cyl2->gasmix = tx19_33;
|
cyl2->gasmix = tx19_33;
|
||||||
cyl2->depth = dive.gas_mod(tx19_33, po2, M_OR_FT(3, 10));
|
cyl2->depth = dive.gas_mod(tx19_33, po2, M_OR_FT(3, 10));
|
||||||
reset_cylinders(&dive, true);
|
reset_cylinders(&dive, true);
|
||||||
free_dps(dp);
|
|
||||||
|
|
||||||
plan_add_segment(dp, 0, cyl1->depth.mm, 1, 0, false, OC);
|
plan_add_segment(dp, 0, cyl1->depth.mm, 1, 0, false, OC);
|
||||||
plan_add_segment(dp, 0, cyl2->depth.mm, 2, 0, false, OC);
|
plan_add_segment(dp, 0, cyl2->depth.mm, 2, 0, false, OC);
|
||||||
plan_add_segment(dp, 20 * 60, M_OR_FT(60, 197), 0, 1300, true, CCR);
|
plan_add_segment(dp, 20 * 60, M_OR_FT(60, 197), 0, 1300, true, CCR);
|
||||||
|
|
||||||
|
return dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We compare the calculated runtimes against two values:
|
/* We compare the calculated runtimes against two values:
|
||||||
|
@ -480,10 +493,9 @@ void TestPlan::testMetric()
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
prefs.planner_deco_mode = BUEHLMANN;
|
prefs.planner_deco_mode = BUEHLMANN;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlan();
|
||||||
setupPlan(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -491,9 +503,7 @@ void TestPlan::testMetric()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 148l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 148l);
|
||||||
QVERIFY(dive.dcs[0].events.size() >= 2);
|
QVERIFY(dive.dcs[0].events.size() >= 2);
|
||||||
// check first gas change to EAN36 at 33m
|
// check first gas change to EAN36 at 33m
|
||||||
|
@ -520,10 +530,9 @@ void TestPlan::testImperial()
|
||||||
prefs.units.length = units::FEET;
|
prefs.units.length = units::FEET;
|
||||||
prefs.planner_deco_mode = BUEHLMANN;
|
prefs.planner_deco_mode = BUEHLMANN;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlan();
|
||||||
setupPlan(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -531,9 +540,7 @@ void TestPlan::testImperial()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 155l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 155l);
|
||||||
QVERIFY(dive.dcs[0].events.size() >= 2);
|
QVERIFY(dive.dcs[0].events.size() >= 2);
|
||||||
// check first gas change to EAN36 at 33m
|
// check first gas change to EAN36 at 33m
|
||||||
|
@ -559,10 +566,9 @@ void TestPlan::testVpmbMetric45m30minTx()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb45m30mTx();
|
||||||
setupPlanVpmb45m30mTx(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -570,9 +576,7 @@ void TestPlan::testVpmbMetric45m30minTx()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 108l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 108l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -588,10 +592,9 @@ void TestPlan::testVpmbMetric60m10minTx()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb60m10mTx();
|
||||||
setupPlanVpmb60m10mTx(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -599,9 +602,7 @@ void TestPlan::testVpmbMetric60m10minTx()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 162l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 162l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -617,10 +618,9 @@ void TestPlan::testVpmbMetric60m30minAir()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb60m30minAir();
|
||||||
setupPlanVpmb60m30minAir(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -628,9 +628,7 @@ void TestPlan::testVpmbMetric60m30minAir()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 180l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 180l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -646,10 +644,9 @@ void TestPlan::testVpmbMetric60m30minEan50()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb60m30minEan50();
|
||||||
setupPlanVpmb60m30minEan50(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -657,9 +654,7 @@ void TestPlan::testVpmbMetric60m30minEan50()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 155l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 155l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -681,10 +676,9 @@ void TestPlan::testVpmbMetric60m30minTx()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb60m30minTx();
|
||||||
setupPlanVpmb60m30minTx(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -692,9 +686,7 @@ void TestPlan::testVpmbMetric60m30minTx()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 159l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 159l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -716,10 +708,9 @@ void TestPlan::testVpmbMetric100m60min()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb100m60min();
|
||||||
setupPlanVpmb100m60min(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -727,9 +718,7 @@ void TestPlan::testVpmbMetric100m60min()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 157l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 157l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -757,11 +746,9 @@ void TestPlan::testMultipleGases()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanSeveralGases();
|
||||||
|
|
||||||
setupPlanSeveralGases(&testPlan);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -781,10 +768,9 @@ void TestPlan::testVpmbMetricMultiLevelAir()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmbMultiLevelAir();
|
||||||
setupPlanVpmbMultiLevelAir(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -792,9 +778,7 @@ void TestPlan::testVpmbMetricMultiLevelAir()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 101l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 101l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -810,10 +794,9 @@ void TestPlan::testVpmbMetric100m10min()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb100m10min();
|
||||||
setupPlanVpmb100m10min(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -821,9 +804,7 @@ void TestPlan::testVpmbMetric100m10min()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 175l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 175l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -856,10 +837,9 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
prefs.unit_system = METRIC;
|
prefs.unit_system = METRIC;
|
||||||
prefs.units.length = units::METERS;
|
prefs.units.length = units::METERS;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanVpmb30m20min();
|
||||||
setupPlanVpmb30m20min(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -867,9 +847,7 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
struct divedatapoint *dp = testPlan.dp;
|
auto dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 61l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 61l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -878,8 +856,8 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
|
|
||||||
int firstDiveRunTimeSeconds = dive.dcs[0].duration.seconds;
|
int firstDiveRunTimeSeconds = dive.dcs[0].duration.seconds;
|
||||||
|
|
||||||
setupPlanVpmb100mTo70m30min(&testPlan);
|
testPlan = setupPlanVpmb100mTo70m30min();
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -887,9 +865,7 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
dp = testPlan.dp;
|
dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 80l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 80l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -915,8 +891,8 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
// we don't have a benchmark, known Subsurface runtime is 126 minutes
|
// we don't have a benchmark, known Subsurface runtime is 126 minutes
|
||||||
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 127u * 60u + 20u, 127u * 60u + 20u));
|
QVERIFY(compareDecoTime(dive.dcs[0].duration.seconds, 127u * 60u + 20u, 127u * 60u + 20u));
|
||||||
|
|
||||||
setupPlanVpmb30m20min(&testPlan);
|
testPlan = setupPlanVpmb30m20min();
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, 1, 0);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
@ -924,9 +900,7 @@ void TestPlan::testVpmbMetricRepeat()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check minimum gas result
|
// check minimum gas result
|
||||||
dp = testPlan.dp;
|
dp = std::find_if(testPlan.dp.begin(), testPlan.dp.end(), [](auto &dp) { return dp.minimum_gas.mbar != 0; });
|
||||||
while (!dp->minimum_gas.mbar && dp->next)
|
|
||||||
dp = dp->next;
|
|
||||||
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 61l);
|
QCOMPARE(lrint(dp->minimum_gas.mbar / 1000.0), 61l);
|
||||||
// print first ceiling
|
// print first ceiling
|
||||||
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
printf("First ceiling %.1f m\n", dive.mbar_to_depth(test_deco_state.first_ceiling_pressure.mbar) * 0.001);
|
||||||
|
@ -951,10 +925,9 @@ void TestPlan::testCcrBailoutGasSelection()
|
||||||
dive.dcs[0].divemode = CCR;
|
dive.dcs[0].divemode = CCR;
|
||||||
prefs.dobailout = true;
|
prefs.dobailout = true;
|
||||||
|
|
||||||
struct diveplan testPlan = {};
|
auto testPlan = setupPlanCcr();
|
||||||
setupPlanCcr(&testPlan);
|
|
||||||
|
|
||||||
plan(&test_deco_state, &testPlan, &dive, 0, 60, stoptable, cache, true, false);
|
plan(&test_deco_state, testPlan, &dive, 0, 60, stoptable, cache, true, false);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dive.notes.clear();
|
dive.notes.clear();
|
||||||
|
|
Loading…
Reference in a new issue