diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-30 13:09:17 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-30 13:09:17 -0800 |
commit | e5b6bfc7ed03bb6649abcfbac79f06aafd235918 (patch) | |
tree | 43329e7061829c308c3c262650c82633c117b375 /dive.c | |
parent | 565736a471e9ba66cbc68ce76c90d5e0c2fa57cf (diff) | |
download | subsurface-e5b6bfc7ed03bb6649abcfbac79f06aafd235918.tar.gz |
Move the gasmix cleanups from XML parsing to the generic dive fixup stage
Right now we do certain cylinder info operations only when importing
from an XML file, which is wrong. In particular, we do the "is the
gasmix air" or "what is the standard cylinder name" only at XML read
time, which means that if you import a dive directly from the dive
computer, it won't have the air sanitization or the proper default
cylinder names.
Of course, most dive computers don't actually save enough cylinder
information for us to do the cylinder name lookup anyway, but some do.
And all Nitrox-capable dive computers do have that O2 percentage that
needs cleanup too.
Reported-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'dive.c')
-rw-r--r-- | dive.c | 117 |
1 files changed, 117 insertions, 0 deletions
@@ -234,6 +234,122 @@ static int same_rounded_pressure(pressure_t a, pressure_t b) return abs(a.mbar - b.mbar) <= 500; } +static void sanitize_gasmix(struct gasmix *mix) +{ + unsigned int o2, he; + + o2 = mix->o2.permille; + he = mix->he.permille; + + /* Regular air: leave empty */ + if (!he) { + if (!o2) + return; + /* 20.9% or 21% O2 is just air */ + if (o2 >= 209 && o2 <= 210) { + mix->o2.permille = 0; + return; + } + } + + /* Sane mix? */ + if (o2 <= 1000 && he <= 1000 && o2+he <= 1000) + return; + fprintf(stderr, "Odd gasmix: %d O2 %d He\n", o2, he); + memset(mix, 0, sizeof(*mix)); +} + +/* + * See if the size/workingpressure looks like some standard cylinder + * size, eg "AL80". + */ +static void match_standard_cylinder(cylinder_type_t *type) +{ + double cuft; + int psi, len; + const char *fmt; + char buffer[20], *p; + + /* Do we already have a cylinder description? */ + if (type->description) + return; + + cuft = ml_to_cuft(type->size.mliter); + cuft *= to_ATM(type->workingpressure); + psi = to_PSI(type->workingpressure); + + switch (psi) { + case 2300 ... 2500: /* 2400 psi: LP tank */ + fmt = "LP%d"; + break; + case 2600 ... 2700: /* 2640 psi: LP+10% */ + fmt = "LP%d"; + break; + case 2900 ... 3100: /* 3000 psi: ALx tank */ + fmt = "AL%d"; + break; + case 3400 ... 3500: /* 3442 psi: HP tank */ + fmt = "HP%d"; + break; + case 3700 ... 3850: /* HP+10% */ + fmt = "HP%d+"; + break; + default: + return; + } + len = snprintf(buffer, sizeof(buffer), fmt, (int) (cuft+0.5)); + p = malloc(len+1); + if (!p) + return; + memcpy(p, buffer, len+1); + type->description = p; +} + + +/* + * There are two ways to give cylinder size information: + * - total amount of gas in cuft (depends on working pressure and physical size) + * - physical size + * + * where "physical size" is the one that actually matters and is sane. + * + * We internally use physical size only. But we save the workingpressure + * so that we can do the conversion if required. + */ +static void sanitize_cylinder_type(cylinder_type_t *type) +{ + double volume_of_air, atm, volume; + + /* If we have no working pressure, it had *better* be just a physical size! */ + if (!type->workingpressure.mbar) + return; + + /* No size either? Nothing to go on */ + if (!type->size.mliter) + return; + + if (input_units.volume == CUFT) { + /* confusing - we don't really start from ml but millicuft !*/ + volume_of_air = cuft_to_l(type->size.mliter); + atm = to_ATM(type->workingpressure); /* working pressure in atm */ + volume = volume_of_air / atm; /* milliliters at 1 atm: "true size" */ + type->size.mliter = volume + 0.5; + } + + /* Ok, we have both size and pressure: try to match a description */ + match_standard_cylinder(type); +} + +static void sanitize_cylinder_info(struct dive *dive) +{ + int i; + + for (i = 0; i < MAX_CYLINDERS; i++) { + sanitize_gasmix(&dive->cylinder[i].gasmix); + sanitize_cylinder_type(&dive->cylinder[i].type); + } +} + struct dive *fixup_dive(struct dive *dive) { int i,j; @@ -246,6 +362,7 @@ struct dive *fixup_dive(struct dive *dive) int lasttemp = 0, lastpressure = 0; int pressure_delta[MAX_CYLINDERS] = {INT_MAX, }; + sanitize_cylinder_info(dive); for (i = 0; i < dive->samples; i++) { struct sample *sample = dive->sample + i; int time = sample->time.seconds; |