mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Compute variations of plans
Print out partial derivatives of stop times with respect to variation of depth and duratin of last manual segment. Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
parent
e6545a7b0f
commit
2832141d2c
4 changed files with 121 additions and 15 deletions
|
@ -913,6 +913,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
void calc_crushing_pressure(double pressure);
|
void calc_crushing_pressure(double pressure);
|
||||||
void vpmb_start_gradient();
|
void vpmb_start_gradient();
|
||||||
void clear_vpmb_state();
|
void clear_vpmb_state();
|
||||||
|
void printdecotable(struct decostop *table);
|
||||||
|
|
||||||
void delete_single_dive(int idx);
|
void delete_single_dive(int idx);
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_dept
|
||||||
|
|
||||||
/* simply overwrite the data in the displayed_dive
|
/* simply overwrite the data in the displayed_dive
|
||||||
* return false if something goes wrong */
|
* return false if something goes wrong */
|
||||||
static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, bool track_gas)
|
||||||
{
|
{
|
||||||
struct divedatapoint *dp;
|
struct divedatapoint *dp;
|
||||||
struct divecomputer *dc;
|
struct divecomputer *dc;
|
||||||
|
@ -264,7 +264,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
||||||
int lasttime = 0;
|
int lasttime = 0;
|
||||||
depth_t lastdepth = {.mm = 0};
|
depth_t lastdepth = {.mm = 0};
|
||||||
int lastcylid = 0;
|
int lastcylid = 0;
|
||||||
enum dive_comp_type type = displayed_dive.dc.divemode;
|
enum dive_comp_type type = dive->dc.divemode;
|
||||||
|
|
||||||
if (!diveplan || !diveplan->dp)
|
if (!diveplan || !diveplan->dp)
|
||||||
return;
|
return;
|
||||||
|
@ -272,12 +272,12 @@ static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
||||||
printf("in create_dive_from_plan\n");
|
printf("in create_dive_from_plan\n");
|
||||||
dump_plan(diveplan);
|
dump_plan(diveplan);
|
||||||
#endif
|
#endif
|
||||||
displayed_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
|
||||||
// displayed dive so we can restart
|
// displayed dive so we can restart
|
||||||
reset_cylinders(&displayed_dive, track_gas);
|
reset_cylinders(dive, track_gas);
|
||||||
dc = &displayed_dive.dc;
|
dc = &dive->dc;
|
||||||
dc->when = displayed_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;
|
||||||
free(dc->sample);
|
free(dc->sample);
|
||||||
|
@ -289,7 +289,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
||||||
free(ev);
|
free(ev);
|
||||||
}
|
}
|
||||||
dp = diveplan->dp;
|
dp = diveplan->dp;
|
||||||
cyl = &displayed_dive.cylinder[lastcylid];
|
cyl = &dive->cylinder[lastcylid];
|
||||||
sample = prepare_sample(dc);
|
sample = prepare_sample(dc);
|
||||||
sample->setpoint.mbar = dp->setpoint;
|
sample->setpoint.mbar = dp->setpoint;
|
||||||
sample->sac.mliter = prefs.bottomsac;
|
sample->sac.mliter = prefs.bottomsac;
|
||||||
|
@ -324,8 +324,8 @@ static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
||||||
/* 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(&displayed_dive, dc, lasttime + 1, dp->cylinderid);
|
add_gas_switch_event(dive, dc, lasttime + 1, dp->cylinderid);
|
||||||
cyl = &displayed_dive.cylinder[dp->cylinderid];
|
cyl = &dive->cylinder[dp->cylinderid];
|
||||||
sample = prepare_sample(dc);
|
sample = prepare_sample(dc);
|
||||||
sample[-1].setpoint.mbar = po2;
|
sample[-1].setpoint.mbar = po2;
|
||||||
sample->time.seconds = lasttime + 1;
|
sample->time.seconds = lasttime + 1;
|
||||||
|
@ -348,7 +348,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, bool track_gas)
|
||||||
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(&displayed_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);
|
dp->entered ? diveplan->bottomsac : diveplan->decosac, cyl, !dp->entered);
|
||||||
if (cyl->type.workingpressure.mbar)
|
if (cyl->type.workingpressure.mbar)
|
||||||
sample->pressure[0].mbar = cyl->end.mbar;
|
sample->pressure[0].mbar = cyl->end.mbar;
|
||||||
|
@ -692,7 +692,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
dive->surface_pressure.mbar = diveplan->surface_pressure;
|
dive->surface_pressure.mbar = diveplan->surface_pressure;
|
||||||
clear_deco(dive->surface_pressure.mbar / 1000.0);
|
clear_deco(dive->surface_pressure.mbar / 1000.0);
|
||||||
max_bottom_ceiling_pressure.mbar = first_ceiling_pressure.mbar = 0;
|
max_bottom_ceiling_pressure.mbar = first_ceiling_pressure.mbar = 0;
|
||||||
create_dive_from_plan(diveplan, is_planner);
|
create_dive_from_plan(diveplan, dive, is_planner);
|
||||||
|
|
||||||
// Do we want deco stop array in metres or feet?
|
// Do we want deco stop array in metres or feet?
|
||||||
if (prefs.units.length == METERS ) {
|
if (prefs.units.length == METERS ) {
|
||||||
|
@ -726,7 +726,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
if (!is_planner) {
|
if (!is_planner) {
|
||||||
transitiontime = depth / 75; /* this still needs to be made configurable */
|
transitiontime = depth / 75; /* this still needs to be made configurable */
|
||||||
plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false);
|
plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false);
|
||||||
create_dive_from_plan(diveplan, is_planner);
|
create_dive_from_plan(diveplan, dive, is_planner);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +809,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
}
|
}
|
||||||
} while (depth > 0);
|
} while (depth > 0);
|
||||||
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false);
|
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false);
|
||||||
create_dive_from_plan(diveplan, is_planner);
|
create_dive_from_plan(diveplan, dive, is_planner);
|
||||||
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
|
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
|
||||||
fixup_dc_duration(&dive->dc);
|
fixup_dc_duration(&dive->dc);
|
||||||
|
|
||||||
|
@ -947,8 +947,12 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
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(0, depth, stoplevels[stopidx], avg_depth, bottom_time,
|
if (trial_ascent(0, depth, stoplevels[stopidx], avg_depth, bottom_time,
|
||||||
&dive->cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive))
|
&dive->cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive)) {
|
||||||
|
decostoptable[decostopcounter].depth = depth;
|
||||||
|
decostoptable[decostopcounter].time = 0;
|
||||||
|
decostopcounter++;
|
||||||
break; /* We did not hit the ceiling */
|
break; /* We did not hit the ceiling */
|
||||||
|
}
|
||||||
|
|
||||||
/* Add a minute of deco time and then try again */
|
/* Add a minute of deco time and then try again */
|
||||||
if (!decodive) {
|
if (!decodive) {
|
||||||
|
@ -1053,7 +1057,7 @@ bool plan(struct diveplan *diveplan, struct dive *dive, int timestep, struct dec
|
||||||
diveplan->eff_gflow = lrint(100.0 * (regressiona() * first_stop_depth + regressionb()));
|
diveplan->eff_gflow = lrint(100.0 * (regressiona() * first_stop_depth + regressionb()));
|
||||||
}
|
}
|
||||||
|
|
||||||
create_dive_from_plan(diveplan, is_planner);
|
create_dive_from_plan(diveplan, dive, is_planner);
|
||||||
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
|
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
|
||||||
fixup_dc_duration(&dive->dc);
|
fixup_dc_duration(&dive->dc);
|
||||||
|
|
||||||
|
|
|
@ -844,6 +844,7 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
if (recalcQ() && !diveplan_empty(&diveplan)) {
|
if (recalcQ() && !diveplan_empty(&diveplan)) {
|
||||||
struct decostop stoptable[60];
|
struct decostop stoptable[60];
|
||||||
plan(&diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
|
plan(&diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
|
||||||
|
computeVariations();
|
||||||
emit calculatedPlanNotes();
|
emit calculatedPlanNotes();
|
||||||
}
|
}
|
||||||
// throw away the cache
|
// throw away the cache
|
||||||
|
@ -869,6 +870,103 @@ void DivePlannerPointsModel::saveDuplicatePlan()
|
||||||
createPlan(true);
|
createPlan(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct divedatapoint * DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_copy)
|
||||||
|
{
|
||||||
|
divedatapoint *src, *last_segment;
|
||||||
|
divedatapoint **dp;
|
||||||
|
|
||||||
|
src = diveplan.dp;
|
||||||
|
*plan_copy = diveplan;
|
||||||
|
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->next->next)
|
||||||
|
last_segment = last_segment->next;
|
||||||
|
return last_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit)
|
||||||
|
{
|
||||||
|
int leftsum = 0;
|
||||||
|
int rightsum = 0;
|
||||||
|
while (mid->depth > min->depth)
|
||||||
|
++mid;
|
||||||
|
while (max->depth > mid->depth)
|
||||||
|
++max;
|
||||||
|
|
||||||
|
while (mid->depth) {
|
||||||
|
int left = mid->time - min->time;
|
||||||
|
leftsum += left;
|
||||||
|
int right = max->time - mid->time;
|
||||||
|
rightsum += right;
|
||||||
|
if (min->time + mid->time + max->time)
|
||||||
|
printf("%dm: %dmin + %ds/%s +- %ds/%s\n", mid->depth / 1000,
|
||||||
|
(mid->time + 1)/60,
|
||||||
|
(left + right) / 2, unit,
|
||||||
|
(right - left) / 2, unit);
|
||||||
|
++min;
|
||||||
|
++mid;
|
||||||
|
++max;
|
||||||
|
}
|
||||||
|
printf("Total + %d:%02d/%s +- %d:%02d/%s\n\n", FRACTION((leftsum + rightsum) / 2, 60), unit,
|
||||||
|
FRACTION((rightsum - leftsum) / 2, 60), unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivePlannerPointsModel::computeVariations()
|
||||||
|
{
|
||||||
|
bool oldRecalc = setRecalc(false);
|
||||||
|
struct dive *dive = alloc_dive();
|
||||||
|
copy_dive(&displayed_dive, dive);
|
||||||
|
struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60];
|
||||||
|
struct deco_state *cache = NULL, *save = NULL;
|
||||||
|
struct diveplan plan_copy;
|
||||||
|
struct divedatapoint *last_segment;
|
||||||
|
|
||||||
|
cache_deco_state(&save);
|
||||||
|
cloneDiveplan(&plan_copy);
|
||||||
|
plan(&plan_copy, dive, 1, original, &cache, true, false);
|
||||||
|
free_dps(&plan_copy);
|
||||||
|
restore_deco_state(save, false);
|
||||||
|
|
||||||
|
last_segment = cloneDiveplan(&plan_copy);
|
||||||
|
last_segment->depth.mm += 1000;
|
||||||
|
last_segment->next->depth.mm += 1000;
|
||||||
|
plan(&plan_copy, dive, 1, deeper, &cache, true, false);
|
||||||
|
free_dps(&plan_copy);
|
||||||
|
restore_deco_state(save, false);
|
||||||
|
|
||||||
|
last_segment = cloneDiveplan(&plan_copy);
|
||||||
|
last_segment->depth.mm -= 1000;
|
||||||
|
last_segment->next->depth.mm -= 1000;
|
||||||
|
plan(&plan_copy, dive, 1, shallower, &cache, true, false);
|
||||||
|
free_dps(&plan_copy);
|
||||||
|
restore_deco_state(save, false);
|
||||||
|
|
||||||
|
last_segment = cloneDiveplan(&plan_copy);
|
||||||
|
last_segment->next->time += 60;
|
||||||
|
plan(&plan_copy, dive, 1, longer, &cache, true, false);
|
||||||
|
free_dps(&plan_copy);
|
||||||
|
restore_deco_state(save, false);
|
||||||
|
|
||||||
|
last_segment = cloneDiveplan(&plan_copy);
|
||||||
|
last_segment->next->time -= 60;
|
||||||
|
plan(&plan_copy, dive, 1, shorter, &cache, true, false);
|
||||||
|
free_dps(&plan_copy);
|
||||||
|
restore_deco_state(save, false);
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
analyzeVariations(shallower, original, deeper, "m");
|
||||||
|
analyzeVariations(shorter, original, longer, "min");
|
||||||
|
setRecalc(oldRecalc);
|
||||||
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::createPlan(bool replanCopy)
|
void DivePlannerPointsModel::createPlan(bool replanCopy)
|
||||||
{
|
{
|
||||||
// Ok, so, here the diveplan creates a dive
|
// Ok, so, here the diveplan creates a dive
|
||||||
|
|
|
@ -107,6 +107,9 @@ private:
|
||||||
explicit DivePlannerPointsModel(QObject *parent = 0);
|
explicit DivePlannerPointsModel(QObject *parent = 0);
|
||||||
void createPlan(bool replanCopy);
|
void createPlan(bool replanCopy);
|
||||||
struct diveplan diveplan;
|
struct diveplan diveplan;
|
||||||
|
struct divedatapoint *cloneDiveplan(struct diveplan *plan_copy);
|
||||||
|
void computeVariations();
|
||||||
|
void analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit);
|
||||||
Mode mode;
|
Mode mode;
|
||||||
bool recalc;
|
bool recalc;
|
||||||
QVector<divedatapoint> divepoints;
|
QVector<divedatapoint> divepoints;
|
||||||
|
|
Loading…
Add table
Reference in a new issue