summaryrefslogtreecommitdiffstats
path: root/core/dive.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/dive.c')
-rw-r--r--core/dive.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/core/dive.c b/core/dive.c
index c977183a3..da4b19346 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -4062,3 +4062,245 @@ fraction_t best_he(depth_t depth, struct dive *dive)
fhe.permille = 0;
return fhe;
}
+
+bool gasmix_is_air(const struct gasmix *gasmix)
+{
+ int o2 = gasmix->o2.permille;
+ int he = gasmix->he.permille;
+ return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
+}
+
+void invalidate_dive_cache(struct dive *dive)
+{
+ memset(dive->git_id, 0, 20);
+}
+
+bool dive_cache_is_valid(const struct dive *dive)
+{
+ static const unsigned char null_id[20] = { 0, };
+ return !!memcmp(dive->git_id, null_id, 20);
+}
+
+int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null)
+{
+ int mbar = dive->surface_pressure.mbar;
+ if (!mbar && non_null)
+ mbar = SURFACE_PRESSURE;
+ return mbar;
+}
+
+/* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m
+ * of water (and use standard salt water at 1.03kg per liter if we don't know salinity)
+ * and add that to the surface pressure (or to 1013 if that's unknown) */
+int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity)
+{
+ double specific_weight;
+ int mbar = surface_pressure.mbar;
+
+ if (!mbar)
+ mbar = SURFACE_PRESSURE;
+ if (!salinity)
+ salinity = SEAWATER_SALINITY;
+ if (salinity < 500)
+ salinity += FRESHWATER_SALINITY;
+ specific_weight = salinity / 10000.0 * 0.981;
+ mbar += lrint(depth / 10.0 * specific_weight);
+ return mbar;
+}
+
+int depth_to_mbar(int depth, struct dive *dive)
+{
+ return calculate_depth_to_mbar(depth, dive->surface_pressure, dive->salinity);
+}
+
+double depth_to_bar(int depth, struct dive *dive)
+{
+ return depth_to_mbar(depth, dive) / 1000.0;
+}
+
+double depth_to_atm(int depth, struct dive *dive)
+{
+ return mbar_to_atm(depth_to_mbar(depth, dive));
+}
+
+/* for the inverse calculation we use just the relative pressure
+ * (that's the one that some dive computers like the Uemis Zurich
+ * provide - for the other models that do this libdivecomputer has to
+ * take care of this, but the Uemis we support natively */
+int rel_mbar_to_depth(int mbar, struct dive *dive)
+{
+ int cm;
+ double specific_weight = 1.03 * 0.981;
+ if (dive->dc.salinity)
+ specific_weight = dive->dc.salinity / 10000.0 * 0.981;
+ /* whole mbar gives us cm precision */
+ cm = (int)lrint(mbar / specific_weight);
+ return cm * 10;
+}
+
+int mbar_to_depth(int mbar, struct dive *dive)
+{
+ pressure_t surface_pressure;
+ if (dive->surface_pressure.mbar)
+ surface_pressure = dive->surface_pressure;
+ else
+ surface_pressure.mbar = SURFACE_PRESSURE;
+ return rel_mbar_to_depth(mbar - surface_pressure.mbar, dive);
+}
+
+/* MOD rounded to multiples of roundto mm */
+depth_t gas_mod(struct gasmix *mix, pressure_t po2_limit, struct dive *dive, int roundto)
+{
+ depth_t rounded_depth;
+
+ double depth = (double) mbar_to_depth(po2_limit.mbar * 1000 / get_o2(mix), dive);
+ rounded_depth.mm = (int)lrint(depth / roundto) * roundto;
+ return rounded_depth;
+}
+
+/* Maximum narcotic depth rounded to multiples of roundto mm */
+depth_t gas_mnd(struct gasmix *mix, depth_t end, struct dive *dive, int roundto)
+{
+ depth_t rounded_depth;
+ pressure_t ppo2n2;
+ ppo2n2.mbar = depth_to_mbar(end.mm, dive);
+
+ int maxambient = (int)lrint(ppo2n2.mbar / (1 - get_he(mix) / 1000.0));
+ rounded_depth.mm = (int)lrint(((double)mbar_to_depth(maxambient, dive)) / roundto) * roundto;
+ return rounded_depth;
+}
+
+struct dive *get_dive(int nr)
+{
+ if (nr >= dive_table.nr || nr < 0)
+ return NULL;
+ return dive_table.dives[nr];
+}
+
+struct dive *get_dive_from_table(int nr, struct dive_table *dt)
+{
+ if (nr >= dt->nr || nr < 0)
+ return NULL;
+ return dt->dives[nr];
+}
+
+struct dive_site *get_dive_site_for_dive(struct dive *dive)
+{
+ if (dive)
+ return get_dive_site_by_uuid(dive->dive_site_uuid);
+ return NULL;
+}
+
+const char *get_dive_country(struct dive *dive)
+{
+ struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid);
+ if (ds) {
+ int idx = taxonomy_index_for_category(&ds->taxonomy, TC_COUNTRY);
+ if (idx >= 0)
+ return ds->taxonomy.category[idx].value;
+ }
+ return NULL;
+}
+
+char *get_dive_location(struct dive *dive)
+{
+ struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid);
+ if (ds && ds->name)
+ return ds->name;
+ return NULL;
+}
+
+unsigned int number_of_computers(struct dive *dive)
+{
+ unsigned int total_number = 0;
+ struct divecomputer *dc = &dive->dc;
+
+ if (!dive)
+ return 1;
+
+ do {
+ total_number++;
+ dc = dc->next;
+ } while (dc);
+ return total_number;
+}
+
+struct divecomputer *get_dive_dc(struct dive *dive, int nr)
+{
+ struct divecomputer *dc;
+ if (!dive)
+ return NULL;
+ dc = &dive->dc;
+
+ while (nr-- > 0) {
+ dc = dc->next;
+ if (!dc)
+ return &dive->dc;
+ }
+ return dc;
+}
+
+struct dive *get_dive_by_uniq_id(int id)
+{
+ int i;
+ struct dive *dive = NULL;
+
+ for_each_dive (i, dive) {
+ if (dive->id == id)
+ break;
+ }
+#ifdef DEBUG
+ if (dive == NULL) {
+ fprintf(stderr, "Invalid id %x passed to get_dive_by_diveid, try to fix the code\n", id);
+ exit(1);
+ }
+#endif
+ return dive;
+}
+
+int get_idx_by_uniq_id(int id)
+{
+ int i;
+ struct dive *dive = NULL;
+
+ for_each_dive (i, dive) {
+ if (dive->id == id)
+ break;
+ }
+#ifdef DEBUG
+ if (dive == NULL) {
+ fprintf(stderr, "Invalid id %x passed to get_dive_by_diveid, try to fix the code\n", id);
+ exit(1);
+ }
+#endif
+ return i;
+}
+
+bool dive_site_has_gps_location(struct dive_site *ds)
+{
+ return ds && (ds->latitude.udeg || ds->longitude.udeg);
+}
+
+int dive_has_gps_location(struct dive *dive)
+{
+ if (!dive)
+ return false;
+ return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid));
+}
+
+struct gasmix *get_gasmix(struct dive *dive, struct divecomputer *dc, int time, struct event **evp, struct gasmix *gasmix)
+{
+ struct event *ev = *evp;
+
+ if (!gasmix) {
+ int cyl = explicit_first_cylinder(dive, dc);
+ gasmix = &dive->cylinder[cyl].gasmix;
+ ev = dc ? get_next_event(dc->events, "gaschange") : NULL;
+ }
+ while (ev && ev->time.seconds < time) {
+ gasmix = get_gasmix_from_event(dive, ev);
+ ev = get_next_event(ev->next, "gaschange");
+ }
+ *evp = ev;
+ return gasmix;
+}