diff --git a/planner.c b/planner.c index c2cfe7461..377b868af 100644 --- a/planner.c +++ b/planner.c @@ -595,6 +595,12 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool len = strlen(buffer); if (plan_verbatim) { + /* When displaying a verbatim plan, we output a waypoint for every gas change. + * Therefore, we do not need to test for difficult cases that mean we need to + * print a segment just so we don't miss a gas change. This makes the logic + * to determine whether or not to print a segment much simpler than with the + * non-verbatim plan. + */ if (dp->depth != lastprintdepth) { if (plan_display_transitions || dp->entered || !dp->next || (gaschange_after && dp->next && dp->depth != nextdp->depth)) { if (dp->setpoint) @@ -638,6 +644,22 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool } } } else { + /* When not displaying the verbatim dive plan, we typically ignore ascents between deco stops, + * unless the display transitions option has been selected. We output a segment if any of the + * following conditions are met. + * 1) Display transitions is selected + * 2) The segment was manually entered + * 3) It is the last segment of the dive + * 4) The segment is not an ascent, there was a gas change at the start of the segment and the next segment + * is a change in depth (typical deco stop) + * 5) There is a gas change at the end of the segment and the last segment was entered (first calculated + * segment if it ends in a gas change) + * 6) There is a gaschange after but no ascent. This should only occur when backgas breaks option is selected + * 7) It is an ascent ending with a gas change, but is not followed by a stop. As case 5 already matches + * the first calculated ascent if it ends with a gas change, this should only occur if a travel gas is + * 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. + */ if (plan_display_transitions || dp->entered || !dp->next || (nextdp && dp->depth != nextdp->depth) || (!isascent && gaschange_before && nextdp && dp->depth != nextdp->depth) || @@ -654,6 +676,9 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool len += snprintf(buffer + len, sizeof(buffer) - len, "%s", temp); } + /* 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 + */ if (isascent && gaschange_after && dp->next && nextdp && dp->depth != nextdp->depth) { if (dp->setpoint) { snprintf(temp, sizeof(temp), translate("gettextFromC", "(SP = %.1fbar)"), (double) nextdp->setpoint / 1000.0); @@ -666,6 +691,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool lastprintgasmix = newgasmix; gaschange_after = false; } else if (gaschange_before) { + // If a new gas has been used for this segment, now is the time to show it if (dp->setpoint) { snprintf(temp, sizeof(temp), translate("gettextFromC", "(SP = %.1fbar)"), (double) dp->setpoint / 1000.0); len += snprintf(buffer + len, sizeof(buffer) - len, "%s %s", gasname(&gasmix), @@ -673,6 +699,7 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool } else { len += snprintf(buffer + len, sizeof(buffer) - len, "%s", gasname(&gasmix)); } + // Set variables so subsequent iterations can test against the last gas printed lastprintsetpoint = dp->setpoint; lastprintgasmix = gasmix; gaschange_after = false; @@ -824,6 +851,7 @@ void track_ascent_gas(int depth, cylinder_t *cylinder, int avg_depth, int bottom } } +// Determine whether ascending to the next stop will break the ceiling. Return true if the ascent is ok, false if it isn't. bool trial_ascent(int trial_depth, int stoplevel, int avg_depth, int bottom_time, double tissue_tolerance, struct gasmix *gasmix, int po2, double surface_pressure) { @@ -854,6 +882,10 @@ bool trial_ascent(int trial_depth, int stoplevel, int avg_depth, int bottom_time return clear_to_ascend; } +/* Determine if there is enough gas for the dive. Return true if there is enough. + * Also return true if this cannot be calculated because the cylinder doesn't have + * size or a starting pressure. + */ bool enough_gas(int current_cylinder) { cylinder_t *cyl; @@ -909,6 +941,7 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool diveplan->surface_pressure = SURFACE_PRESSURE; create_dive_from_plan(diveplan, is_planner); + // Do we want deco stop array in metres or feet? if (prefs.units.length == METERS ) { decostoplevels = decostoplevels_metric; decostoplevelcount = sizeof(decostoplevels_metric) / sizeof(int); @@ -917,6 +950,9 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool decostoplevelcount = sizeof(decostoplevels_imperial) / sizeof(int); } + /* If the user has selected last stop to be at 6m/20', we need to get rid of the 3m/10' stop. + * Otherwise reinstate the last stop 3m/10' stop. + */ if (prefs.last_stop) *(decostoplevels + 1) = 0; else @@ -1124,6 +1160,9 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool if (prefs.doo2breaks && get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) o2time += prefs.min_switch_duration; } else { + /* The user has selected the option to switch gas only at required stops. + * Remember that we are waiting to switch gas + */ pendinggaschange = true; } gi--; @@ -1148,6 +1187,10 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool previous_point_time = clock; stopping = true; } + + /* Are we waiting to switch gas? + * Occurs when the user has selected the option to switch only at required stops + */ if (pendinggaschange) { current_cylinder = gaschanges[gi + 1].gasidx; gas = displayed_dive.cylinder[current_cylinder].gasmix; @@ -1179,6 +1222,9 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool break; } if (prefs.doo2breaks) { + /* The backgas breaks option limits time on oxygen to 12 minutes, followed by 6 minutes on + * backgas (first defined gas). This could be customized if there were demand. + */ if (get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) { o2time += DECOTIMESTEP; if (o2time >= 12 * 60) {