summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.c2
-rw-r--r--dive.h5
-rw-r--r--planner.c55
3 files changed, 44 insertions, 18 deletions
diff --git a/dive.c b/dive.c
index 528172a40..e337ca319 100644
--- a/dive.c
+++ b/dive.c
@@ -281,7 +281,7 @@ static void sanitize_gasmix(struct gasmix *mix)
if (!o2)
return;
/* 20.8% to 21% O2 is just air */
- if (o2 >= (O2_IN_AIR - 1) && o2 <= (O2_IN_AIR + 1)) {
+ if (is_air(o2, he)) {
mix->o2.permille = 0;
return;
}
diff --git a/dive.h b/dive.h
index 84133a424..246521554 100644
--- a/dive.h
+++ b/dive.h
@@ -213,6 +213,11 @@ static inline int mbar_to_PSI(int mbar)
return to_PSI(p);
}
+static inline gboolean is_air(int o2, int he)
+{
+ return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
+}
+
/* Linear interpolation between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
static inline int interpolate(int a, int b, int part, int whole)
{
diff --git a/planner.c b/planner.c
index 6d7814abf..244fece53 100644
--- a/planner.c
+++ b/planner.c
@@ -12,6 +12,11 @@
#include "divelist.h"
#include "display-gtk.h"
+/* while we normally track gases with permille precision, in the planner
+ * we want to treat gases as identical based on percent granularity.
+ * The reason for this is that the gaschange event only deals with
+ * percent (this is inherited from libdivecomputer). */
+#define O2_IN_AIR_PERCENT 210
int decostoplevels[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 27000,
30000, 33000, 36000, 39000, 42000, 45000, 48000, 51000, 54000, 57000,
@@ -57,21 +62,30 @@ void get_gas_from_events(struct divecomputer *dc, int time, int *o2, int *he)
}
}
+/* simple helper function to compare two permille values with
+ * (rounded) percent granularity */
+static inline gboolean match_percent(int a, int b)
+{
+ return (a + 5) / 10 == (b + 5) / 10;
+}
static int get_gasidx(struct dive *dive, int o2, int he)
{
int gasidx = -1;
+ /* we treat air as 0/0 because it is special */
+ if (is_air(o2, he))
+ o2 = 0;
while (++gasidx < MAX_CYLINDERS)
- if (dive->cylinder[gasidx].gasmix.o2.permille == o2 &&
- dive->cylinder[gasidx].gasmix.he.permille == he)
+ if (match_percent(dive->cylinder[gasidx].gasmix.o2.permille, o2) &&
+ match_percent(dive->cylinder[gasidx].gasmix.he.permille, he))
return gasidx;
return -1;
}
static void get_gas_string(int o2, int he, char *text, int len)
{
- if (he == 0 && (o2 == 0 || (o2 >= O2_IN_AIR - 1 && o2 <= O2_IN_AIR + 1)))
+ if (is_air(o2, he))
snprintf(text, len, _("air"));
else if (he == 0)
snprintf(text, len, _("EAN%d"), (o2 + 5) / 10);
@@ -105,7 +119,7 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
t1 = sample->time.seconds;
get_gas_from_events(&dive->dc, t0, &o2, &he);
if ((gasidx = get_gasidx(dive, o2, he)) == -1) {
- printf("can't find gas %d/%d\n", o2/10, he/10);
+ printf("can't find gas %d/%d\n", (o2 + 5) / 10, (he + 5) / 10);
gasidx = 0;
}
if (i > 0)
@@ -153,19 +167,21 @@ int add_gas(struct dive *dive, int o2, int he)
for (i = 0; i < MAX_CYLINDERS; i++) {
cyl = dive->cylinder + i;
+ mix = &cyl->gasmix;
if (cylinder_nodata(cyl))
break;
- mix = &cyl->gasmix;
- if (o2 == mix->o2.permille && he == mix->he.permille)
+ if (match_percent(o2, mix->o2.permille) && match_percent(he, mix->he.permille))
return i;
}
if (i == MAX_CYLINDERS) {
printf("too many cylinders\n");
return -1;
}
- mix = &cyl->gasmix;
mix->o2.permille = o2;
mix->he.permille = he;
+ /* since air is stored as 0/0 we need to set a name or an air cylinder
+ * would be seen as unset (by cylinder_nodata()) */
+ cyl->type.description = strdup("Cylinder for planning");
return i;
}
@@ -175,7 +191,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan)
struct divedatapoint *dp;
struct divecomputer *dc;
struct sample *sample;
- int oldo2 = O2_IN_AIR, oldhe = 0;
+ int oldo2 = O2_IN_AIR_PERCENT, oldhe = 0;
int oldpo2 = 0;
int lasttime = 0;
@@ -226,14 +242,18 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan)
oldpo2 = po2;
}
- /* Create new gas, and gas change event if necessary */
+ /* Create new gas, and gas change event if necessary;
+ * Sadly, we inherited our gaschange event from libdivecomputer which only
+ * support percentage values, so round the entries */
if (o2 != oldo2 || he != oldhe) {
- int value = (o2 / 10) | (he / 10 << 16);
- add_gas(dive, o2, he);
+ int plano2 = (o2 + 5) / 10 * 10;
+ int planhe = (he + 5) / 10 * 10;
+ int value;
+ add_gas(dive, plano2, planhe);
+ value = (plano2 / 10) | (planhe << 16);
add_event(dc, lasttime, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2
oldo2 = o2; oldhe = he;
}
-
/* Create sample */
sample = prepare_sample(dc);
/* set po2 at beginning of this segment */
@@ -395,8 +415,8 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
#if DEBUG_PLAN & 16
for (nr = 0; nr < *gaschangenr; nr++)
printf("gaschange nr %d: @ %5.2lfm gasidx %d (%d/%d)\n", nr, gaschanges[nr].depth / 1000.0,
- gaschanges[nr].gasidx, dive->cylinder[gaschanges[nr].gasidx].gasmix.o2.permille / 10,
- dive->cylinder[gaschanges[nr].gasidx].gasmix.he.permille / 10);
+ gaschanges[nr].gasidx, (dive->cylinder[gaschanges[nr].gasidx].gasmix.o2.permille + 5) / 10,
+ (dive->cylinder[gaschanges[nr].gasidx].gasmix.he.permille + 5) / 10);
#endif
return gaschanges;
}
@@ -521,7 +541,8 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
FRACTION(dp->time, 60),
gas);
}
- consumption[gasidx] += used;
+ if (gasidx != -1)
+ consumption[gasidx] += used;
get_gas_string(newo2, newhe, gas, sizeof(gas));
if (o2 != newo2 || he != newhe) {
len = strlen(buffer);
@@ -619,7 +640,7 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep)
he = dive->cylinder[gaschanges[gi].gasidx].gasmix.he.permille;
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
- o2 / 10, he / 10, gaschanges[gi].depth / 1000.0);
+ (o2 + 5) / 10, (he + 5) / 10, gaschanges[gi].depth / 1000.0);
#endif
gi--;
}
@@ -730,7 +751,7 @@ static int validate_gas(const char *text, int *o2_p, int *he_p)
return 0;
if (!strcasecmp(text, _("air"))) {
- o2 = O2_IN_AIR; he = 0; text += strlen(_("air"));
+ o2 = O2_IN_AIR_PERCENT; he = 0; text += strlen(_("air"));
} else if (!strncasecmp(text, _("ean"), 3)) {
o2 = get_permille(text+3, &text); he = 0;
} else {