Planner: track gas consumption in cylinders and samples

This commit is a little bigger than I usually prefer, but it's all
somewhat interconnected.

- we pass around the cylinders throughout the planning process and as we
  create the plan we calculate the gas consumption in every segment and
  track this both in the end pressure of the cylinder and over time in
  the samples
- because of that we no longer try to calculate the gas consumption after
  being done planning; we just use what we calculated along the way
- we also no longer add gases during the planning process - all gases
  have to come from the list of cylinders passed in (which makes sense
  as we should only use those gases that the user added in the UI or
  inherited from a the selected dive (when starting to plan with a dive
  already selected)

With this patch I think we are close do being able to move all of the
planning logic back into the planner.c code where it belongs. The one
issue that still bothers me is that we are juggling so many dive
structures and then keep copying content around. It seems like we should
be able to reduce that.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2014-05-29 14:36:14 -07:00
parent 56395b3894
commit d054e8c457
4 changed files with 85 additions and 69 deletions

View file

@ -116,22 +116,25 @@ void DivePlannerPointsModel::copyCylinders(dive *d)
// setup the cylinder widget accordingly
void DivePlannerPointsModel::setupCylinders()
{
if (!stagingDive || stagingDive == current_dive)
if (!stagingDive)
return;
if (current_dive) {
copy_cylinders(current_dive, stagingDive);
} else {
if (!same_string(prefs.default_cylinder, "")) {
fill_default_cylinder(&stagingDive->cylinder[0]);
if (stagingDive != current_dive) {
if (current_dive) {
copy_cylinders(current_dive, stagingDive);
} else {
// roughly an AL80
stagingDive->cylinder[0].type.description = strdup(tr("unknown").toUtf8().constData());
stagingDive->cylinder[0].type.size.mliter = 11100;
stagingDive->cylinder[0].type.workingpressure.mbar = 207000;
stagingDive->cylinder[0].used = true;
if (!same_string(prefs.default_cylinder, "")) {
fill_default_cylinder(&stagingDive->cylinder[0]);
} else {
// roughly an AL80
stagingDive->cylinder[0].type.description = strdup(tr("unknown").toUtf8().constData());
stagingDive->cylinder[0].type.size.mliter = 11100;
stagingDive->cylinder[0].type.workingpressure.mbar = 207000;
stagingDive->cylinder[0].used = true;
}
}
}
reset_cylinders(stagingDive);
CylindersModel::instance()->copyFromDive(stagingDive);
}
@ -804,12 +807,14 @@ void DivePlannerPointsModel::createTemporaryPlan()
#if DEBUG_PLAN
dump_plan(&diveplan);
#endif
if (plannerModel->recalcQ())
plan(&diveplan, &cache, &tempDive, isPlanner());
if (mode == ADD || mode == PLAN) {
// copy the samples and events, but don't overwrite the cylinders
copy_samples(tempDive, current_dive);
copy_events(tempDive, current_dive);
if (plannerModel->recalcQ()) {
plan(&diveplan, &cache, &tempDive, stagingDive, isPlanner());
if (mode == ADD || mode == PLAN) {
// copy the samples and events, but don't overwrite the cylinders
copy_samples(tempDive, current_dive);
copy_events(tempDive, current_dive);
copy_cylinders(tempDive, current_dive);
}
}
// throw away the cache
free(cache);
@ -851,26 +856,7 @@ void DivePlannerPointsModel::createPlan()
plannerModel->setRecalc(oldRecalc);
//TODO: C-based function here?
plan(&diveplan, &cache, &tempDive, isPlanner());
copy_cylinders(stagingDive, tempDive);
int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS];
per_cylinder_mean_depth(tempDive, select_dc(tempDive), mean, duration);
for (int i = 0; i < MAX_CYLINDERS; i++) {
cylinder_t *cyl = tempDive->cylinder + i;
if (cylinder_none(cyl))
continue;
// FIXME: The epic assumption that all the cylinders after the first is deco
int sac = i ? diveplan.decosac : diveplan.bottomsac;
cyl->start.mbar = cyl->type.workingpressure.mbar;
if (cyl->type.size.mliter) {
int consumption = ((depth_to_mbar(mean[i], tempDive) * duration[i] / 60) * sac) / (cyl->type.size.mliter / 1000);
cyl->end.mbar = cyl->start.mbar - consumption;
} else {
// Cylinders without a proper size are easily emptied.
// Don't attempt to to calculate the infinite pressure drop.
cyl->end.mbar = 0;
}
}
plan(&diveplan, &cache, &tempDive, stagingDive, isPlanner());
record_dive(tempDive);
mark_divelist_changed(true);