aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/schedule.c
diff options
context:
space:
mode:
authorGravatar Tim Segers <tsegers@pm.me>2022-10-19 16:48:08 +0200
committerGravatar Tim Segers <tsegers@pm.me>2022-10-19 16:48:08 +0200
commit16d1b52543f73d972d33feaa94316dbb67ab907d (patch)
tree03c1934a0f3d13e9d45e5ab86223919214500fb3 /src/schedule.c
parentbc19593e867562f43f4c7ee0a367af3762eb22bd (diff)
downloadopendeco-16d1b52543f73d972d33feaa94316dbb67ab907d.tar.gz
Ascend along fixed stops instead of along rounded ceiling
Diffstat (limited to 'src/schedule.c')
-rw-r--r--src/schedule.c139
1 files changed, 44 insertions, 95 deletions
diff --git a/src/schedule.c b/src/schedule.c
index bf5a8ec..00a2b13 100644
--- a/src/schedule.c
+++ b/src/schedule.c
@@ -18,7 +18,7 @@ const gas_t *best_gas(const double depth, const gas_t *gasses, const int nof_gas
for (int i = 0; i < nof_gasses; i++) {
double mod = gas_mod(&gasses[i]);
- if (depth <= mod && (mod_best == -1 || mod < mod_best)) {
+ if (depth - mod < 1E-2 && (mod_best == -1 || mod < mod_best)) {
best = &gasses[i];
mod_best = mod;
}
@@ -27,23 +27,6 @@ const gas_t *best_gas(const double depth, const gas_t *gasses, const int nof_gas
return best;
}
-const gas_t *next_gas(const double depth, const gas_t *gasses, const int nof_gasses)
-{
- const gas_t *next = NULL;
- double mod_best = 0;
-
- for (int i = 0; i < nof_gasses; i++) {
- double mod = gas_mod(&gasses[i]);
-
- if (depth > mod && mod > mod_best) {
- next = &gasses[i];
- mod_best = mod;
- }
- }
-
- return next;
-}
-
int direct_ascent(const decostate_t *ds, const double depth, const double time, const gas_t *gas)
{
decostate_t ds_ = *ds;
@@ -109,7 +92,8 @@ double calc_ndl(decostate_t *ds, const double depth, const double ascrate, const
return ndl;
}
-double deco_stop(decostate_t *ds, const double depth, const double current_gf, const gas_t *gas)
+double deco_stop(decostate_t *ds, const double depth, const double next_stop, const double current_gf,
+ const gas_t *gas)
{
double stoplen = 0;
@@ -119,7 +103,7 @@ double deco_stop(decostate_t *ds, const double depth, const double current_gf, c
for (;;) {
double tmp = add_segment_const(&ds_, depth, STOPLEN_ROUGH, gas);
- if (ceiling(&ds_, current_gf) != depth)
+ if (ceiling(&ds_, current_gf) <= next_stop)
break;
stoplen += tmp;
@@ -129,33 +113,15 @@ double deco_stop(decostate_t *ds, const double depth, const double current_gf, c
add_segment_const(ds, depth, stoplen, gas);
/* fine steps */
- while (ceiling(ds, current_gf) == depth)
+ while (ceiling(ds, current_gf) > next_stop)
stoplen += add_segment_const(ds, depth, STOPLEN_FINE, gas);
return stoplen;
}
-int should_switch(const gas_t **next, double *switch_depth, const decostate_t *ds, const double depth,
- const double next_stop, const gas_t *deco_gasses, const int nof_gasses)
+static int surfaced(const double depth)
{
- /* check if we switch at MOD or just at stops */
- if (!SWITCH_INTERMEDIATE)
- return 0;
-
- /* check if there is a gas to switch to */
- *next = next_gas(depth, deco_gasses, nof_gasses);
-
- if (*next == NULL)
- return 0;
-
- /* check if the switch happens before the current ceiling */
- *switch_depth = round_ceiling(ds, (*next)->mod) - ds->ceil_multiple;
- assert(*switch_depth <= (*next)->mod);
-
- if (*switch_depth <= next_stop)
- return 0;
-
- return 1;
+ return fabs(depth - SURFACE_PRESSURE) < 1E-2;
}
decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *start_gas, const gas_t *deco_gasses,
@@ -175,44 +141,20 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta
return ret;
}
- /* determine first stop */
- double current_gf = get_gf(ds, depth);
+ double next_stop = abs_depth(ds->ceil_multiple * (ceil(gauge_depth(depth) / ds->ceil_multiple) - 1));
+ double current_gf = get_gf(ds, next_stop);
- if (ds->firststop == -1)
- ds->firststop = ceiling(ds, current_gf);
-
- /* switch to best deco gas if there is one available */
- const gas_t *best = best_gas(depth, deco_gasses, nof_gasses);
-
- if (best)
- gas = best;
-
- /* alternate between ascending and stopping */
for (;;) {
/* extra bookkeeping because waypoints and segments do not match 1:1 */
double last_waypoint_depth = depth;
double waypoint_time;
- /* ascend */
- for (;;) {
- /* determine next stop */
- double next_stop = ceiling(ds, current_gf);
-
- /* find out if we need to switch gas on the way */
- const gas_t *next;
- double switch_depth;
-
- if (should_switch(&next, &switch_depth, ds, depth, next_stop, deco_gasses, nof_gasses)) {
- /* ascend to gas switch */
- ret.tts += add_segment_ascdec(ds, depth, switch_depth, fabs(depth - switch_depth) / asc_per_min, gas);
- depth = switch_depth;
- current_gf = get_gf(ds, depth);
-
- /*
- * since we're stopping for a switch next, this is the last of
- * any number of consecutive travel segments and the waypoint
- * callback should be called.
- */
+ while (ceiling(ds, current_gf) < next_stop && !surfaced(depth)) {
+ /* switch to better gas if available */
+ const gas_t *best = best_gas(depth, deco_gasses, nof_gasses);
+
+ if (SWITCH_INTERMEDIATE && best && best != gas) {
+ /* emit waypoint */
waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min;
if (wp_cb)
@@ -221,9 +163,9 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta
last_waypoint_depth = depth;
/* switch gas */
- gas = next;
+ gas = best;
- ret.tts += add_segment_const(ds, switch_depth, 1, gas);
+ ret.tts += add_segment_const(ds, depth, 1, gas);
if (wp_cb)
wp_cb(ds, (waypoint_t){.depth = depth, .time = 1, .gas = gas}, SEG_GAS_SWITCH);
@@ -231,32 +173,40 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta
continue;
}
- /* ascend to current ceiling */
+ /* ascend to next stop */
ret.tts += add_segment_ascdec(ds, depth, next_stop, fabs(depth - next_stop) / asc_per_min, gas);
depth = next_stop;
- current_gf = get_gf(ds, depth);
- /* if the ceiling moved while we ascended, keep ascending */
- if (depth > ceiling(ds, current_gf))
- continue;
+ /* make next stop shallower */
+ next_stop -= ds->ceil_multiple;
+
+ if (LAST_STOP_AT_SIX && next_stop < abs_depth(msw_to_bar(6)))
+ next_stop = SURFACE_PRESSURE;
+
+ /* recalculate gf */
+ current_gf = get_gf(ds, next_stop);
+ }
+
+ if (ds->firststop == -1) {
+ ds->firststop = depth;
/*
- * since we've actually reached the ceiling, this is the last of
- * any number of consecutive travel segments and the waypoint
- * callback should be called.
+ * if the first stop wasn't know yet during the previous call to
+ * get_gf, the result was inaccurate and needs to be recalculated
*/
- waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min;
- enum segtype_t segtype = depth <= abs_depth(0) ? SEG_SURFACE : SEG_TRAVEL;
+ current_gf = get_gf(ds, next_stop);
+ }
- if (wp_cb)
- wp_cb(ds, (waypoint_t){.depth = depth, .time = waypoint_time, .gas = gas}, segtype);
+ /* emit waypoint */
+ waypoint_time = fabs(last_waypoint_depth - depth) / asc_per_min;
+ enum segtype_t segtype = surfaced(depth) ? SEG_SURFACE : SEG_TRAVEL;
- break;
- }
+ if (wp_cb && waypoint_time)
+ wp_cb(ds, (waypoint_t){.depth = depth, .time = waypoint_time, .gas = gas}, segtype);
/* terminate if we surfaced */
- if (depth <= abs_depth(0))
- break;
+ if (surfaced(depth))
+ return ret;
/* switch to better gas if available */
const gas_t *best = best_gas(depth, deco_gasses, nof_gasses);
@@ -264,13 +214,12 @@ decoinfo_t calc_deco(decostate_t *ds, const double start_depth, const gas_t *sta
if (best)
gas = best;
- /* stop */
- double stoplen = deco_stop(ds, depth, current_gf, gas);
+ /* stop until ceiling rises above next stop */
+ double stoplen = deco_stop(ds, depth, next_stop, current_gf, gas);
+
ret.tts += stoplen;
if (wp_cb)
wp_cb(ds, (waypoint_t){.depth = depth, .time = stoplen, .gas = gas}, SEG_DECO_STOP);
}
-
- return ret;
}