X-Git-Url: http://git.tdb.fi/?p=ext%2Fsubsurface.git;a=blobdiff_plain;f=dive.c;h=54784cdbabfb01fbb5c5a8db539cdc481f20c613;hp=3fa09bd10c05982a9972c0db8a58a76314543f59;hb=HEAD;hpb=95cc317b087e863f6e0a4ab4db7ab68f06a9d969 diff --git a/dive.c b/dive.c index 3fa09bd..54784cd 100644 --- a/dive.c +++ b/dive.c @@ -120,6 +120,28 @@ double get_depth_units(unsigned int mm, int *frac, const char **units) return d; } +double get_weight_units(unsigned int grams, int *frac, const char **units) +{ + int decimals; + double value; + const char* unit; + + if (output_units.weight == LBS) { + value = grams_to_lbs(grams); + unit = "lbs"; + decimals = 0; + } else { + value = grams / 1000.0; + unit = "kg"; + decimals = 1; + } + if (frac) + *frac = decimals; + if (units) + *units = unit; + return value; +} + struct dive *alloc_dive(void) { const int initial_samples = 5; @@ -160,7 +182,7 @@ struct sample *prepare_sample(struct dive **divep) return NULL; } -void finish_sample(struct dive *dive, struct sample *sample) +void finish_sample(struct dive *dive) { dive->samples++; } @@ -234,6 +256,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 +384,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; @@ -333,8 +472,21 @@ struct dive *fixup_dive(struct dive *dive) cyl->sample_end.mbar = 0; } } - if (end < 0) + if (end < 0) { + /* Assume an ascent/descent rate of 9 m/min */ + int depth = dive->maxdepth.mm; + int asc_desc_time = depth*60/9000; + int duration = dive->duration.seconds; + + /* Some sanity checks against insane dives */ + if (duration < 2) + duration = 2; + if (asc_desc_time * 2 >= duration) + asc_desc_time = duration/2; + + dive->meandepth.mm = depth*(duration-asc_desc_time)/duration; return dive; + } update_duration(&dive->duration, end - start); if (start != end) @@ -347,6 +499,7 @@ struct dive *fixup_dive(struct dive *dive) add_people(dive->buddy); add_people(dive->divemaster); add_location(dive->location); + add_suit(dive->suit); for (i = 0; i < MAX_CYLINDERS; i++) { cylinder_t *cyl = dive->cylinder + i; add_cylinder_description(&cyl->type); @@ -355,6 +508,10 @@ struct dive *fixup_dive(struct dive *dive) if (same_rounded_pressure(cyl->sample_end, cyl->end)) cyl->end.mbar = 0; } + for (i = 0; i < MAX_WEIGHTSYSTEMS; i++) { + weightsystem_t *ws = dive->weightsystem + i; + add_weightsystem_description(ws); + } return dive; } @@ -373,7 +530,7 @@ static struct dive *add_sample(struct sample *sample, int time, struct dive *div return NULL; *p = *sample; p->time.seconds = time; - finish_sample(dive, p); + finish_sample(dive); return dive; } @@ -560,6 +717,7 @@ struct dive *try_to_merge(struct dive *a, struct dive *b) MERGE_TXT(res, a, b, buddy); MERGE_TXT(res, a, b, divemaster); MERGE_MAX(res, a, b, rating); + MERGE_TXT(res, a, b, suit); MERGE_MAX(res, a, b, number); MERGE_MAX(res, a, b, maxdepth.mm); res->meandepth.mm = 0;