2017-04-27 18:24:53 +00:00
|
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2017-03-11 20:08:31 +00:00
|
|
|
|
#ifdef __clang__
|
2016-03-09 18:17:17 +00:00
|
|
|
|
// Clang has a bug on zero-initialization of C structs.
|
|
|
|
|
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
2017-03-11 20:08:31 +00:00
|
|
|
|
#endif
|
2016-03-09 18:17:17 +00:00
|
|
|
|
|
2011-09-20 19:40:34 +00:00
|
|
|
|
/* equipment.c */
|
2011-09-09 15:38:48 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <time.h>
|
2019-06-04 11:52:48 +00:00
|
|
|
|
#include <limits.h>
|
2019-05-30 18:51:30 +00:00
|
|
|
|
#include "equipment.h"
|
2013-10-06 15:55:58 +00:00
|
|
|
|
#include "gettext.h"
|
2011-09-09 15:38:48 +00:00
|
|
|
|
#include "dive.h"
|
|
|
|
|
#include "display.h"
|
|
|
|
|
#include "divelist.h"
|
2019-07-15 20:16:56 +00:00
|
|
|
|
#include "subsurface-string.h"
|
2019-06-26 15:21:03 +00:00
|
|
|
|
#include "table.h"
|
|
|
|
|
|
|
|
|
|
static void free_weightsystem(weightsystem_t w)
|
|
|
|
|
{
|
|
|
|
|
free((void *)w.description);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d)
|
|
|
|
|
{
|
|
|
|
|
clear_weightsystem_table(d);
|
|
|
|
|
for (int i = 0; i < s->nr; i++)
|
|
|
|
|
add_cloned_weightsystem(d, s->weightsystems[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* weightsystem table functions */
|
|
|
|
|
//static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems)
|
|
|
|
|
static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems)
|
|
|
|
|
//static MAKE_GET_INSERTION_INDEX(weightsystem_table, weightsystem_t, weightsystems, weightsystem_less_than)
|
|
|
|
|
MAKE_ADD_TO(weightsystem_table, weightsystem_t, weightsystems)
|
|
|
|
|
MAKE_REMOVE_FROM(weightsystem_table, weightsystems)
|
|
|
|
|
//MAKE_SORT(weightsystem_table, weightsystem_t, weightsystems, comp_weightsystems)
|
|
|
|
|
//MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem)
|
|
|
|
|
MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem)
|
2019-07-15 20:16:56 +00:00
|
|
|
|
|
|
|
|
|
const char *cylinderuse_text[NUM_GAS_USE] = {
|
|
|
|
|
QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int cylinderuse_from_text(const char *text)
|
|
|
|
|
{
|
|
|
|
|
for (enum cylinderuse i = 0; i < NUM_GAS_USE; i++) {
|
|
|
|
|
if (same_string(text, cylinderuse_text[i]) || same_string(text, translate("gettextFromC", cylinderuse_text[i])))
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2011-09-09 15:38:48 +00:00
|
|
|
|
|
2013-05-03 18:04:51 +00:00
|
|
|
|
/* placeholders for a few functions that we need to redesign for the Qt UI */
|
2019-06-05 18:26:51 +00:00
|
|
|
|
void add_cylinder_description(const cylinder_type_t *type)
|
2013-05-03 18:04:51 +00:00
|
|
|
|
{
|
|
|
|
|
const char *desc;
|
2013-12-28 22:56:01 +00:00
|
|
|
|
int i;
|
2013-05-03 18:04:51 +00:00
|
|
|
|
|
|
|
|
|
desc = type->description;
|
|
|
|
|
if (!desc)
|
|
|
|
|
return;
|
2018-06-19 01:02:02 +00:00
|
|
|
|
for (i = 0; i < MAX_TANK_INFO && tank_info[i].name != NULL; i++) {
|
2013-12-28 22:56:01 +00:00
|
|
|
|
if (strcmp(tank_info[i].name, desc) == 0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-06-19 01:02:02 +00:00
|
|
|
|
if (i < MAX_TANK_INFO) {
|
2014-12-18 07:47:58 +00:00
|
|
|
|
// FIXME: leaked on exit
|
2014-11-14 21:33:12 +00:00
|
|
|
|
tank_info[i].name = strdup(desc);
|
2013-12-28 22:56:01 +00:00
|
|
|
|
tank_info[i].ml = type->size.mliter;
|
|
|
|
|
tank_info[i].bar = type->workingpressure.mbar / 1000;
|
|
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
|
}
|
2019-06-26 15:21:03 +00:00
|
|
|
|
|
2019-06-05 18:26:51 +00:00
|
|
|
|
void add_weightsystem_description(const weightsystem_t *weightsystem)
|
2013-05-03 18:04:51 +00:00
|
|
|
|
{
|
|
|
|
|
const char *desc;
|
2013-09-10 18:42:26 +00:00
|
|
|
|
int i;
|
2013-05-03 18:04:51 +00:00
|
|
|
|
|
|
|
|
|
desc = weightsystem->description;
|
|
|
|
|
if (!desc)
|
|
|
|
|
return;
|
2018-06-19 00:59:33 +00:00
|
|
|
|
for (i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
|
2013-09-10 18:42:26 +00:00
|
|
|
|
if (strcmp(ws_info[i].name, desc) == 0) {
|
|
|
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-19 00:59:33 +00:00
|
|
|
|
if (i < MAX_WS_INFO) {
|
2014-12-18 07:47:58 +00:00
|
|
|
|
// FIXME: leaked on exit
|
2014-11-14 21:33:12 +00:00
|
|
|
|
ws_info[i].name = strdup(desc);
|
2013-09-10 18:42:26 +00:00
|
|
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-26 15:21:03 +00:00
|
|
|
|
/* Add a clone of a weightsystem to the end of a weightsystem table.
|
|
|
|
|
* Cloned in means that the description-string is copied. */
|
|
|
|
|
void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws)
|
|
|
|
|
{
|
|
|
|
|
weightsystem_t w_clone = { ws.weight, copy_string(ws.description) };
|
|
|
|
|
add_to_weightsystem_table(t, t->nr, w_clone);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 19:26:51 +00:00
|
|
|
|
bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
|
|
|
|
|
{
|
2019-06-26 15:21:03 +00:00
|
|
|
|
return w1.weight.grams == w2.weight.grams &&
|
|
|
|
|
same_string(w1.description, w2.description);
|
2019-06-25 19:26:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-02 18:50:17 +00:00
|
|
|
|
bool cylinder_nodata(const cylinder_t *cyl)
|
2011-12-24 03:41:16 +00:00
|
|
|
|
{
|
2014-02-28 04:09:57 +00:00
|
|
|
|
return !cyl->type.size.mliter &&
|
|
|
|
|
!cyl->type.workingpressure.mbar &&
|
|
|
|
|
!cyl->type.description &&
|
|
|
|
|
!cyl->gasmix.o2.permille &&
|
|
|
|
|
!cyl->gasmix.he.permille &&
|
|
|
|
|
!cyl->start.mbar &&
|
2014-06-01 16:59:38 +00:00
|
|
|
|
!cyl->end.mbar &&
|
2014-07-01 07:37:49 +00:00
|
|
|
|
!cyl->gas_used.mliter &&
|
|
|
|
|
!cyl->deco_gas_used.mliter;
|
2011-10-02 20:13:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-18 10:53:48 +00:00
|
|
|
|
static bool cylinder_nosamples(const cylinder_t *cyl)
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
|
{
|
2014-02-28 04:09:57 +00:00
|
|
|
|
return !cyl->sample_start.mbar &&
|
|
|
|
|
!cyl->sample_end.mbar;
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-18 10:53:48 +00:00
|
|
|
|
bool cylinder_none(const cylinder_t *cyl)
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
|
{
|
|
|
|
|
return cylinder_nodata(cyl) && cylinder_nosamples(cyl);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-16 17:10:10 +00:00
|
|
|
|
void get_gas_string(struct gasmix gasmix, char *text, int len)
|
2014-06-02 03:56:29 +00:00
|
|
|
|
{
|
|
|
|
|
if (gasmix_is_air(gasmix))
|
|
|
|
|
snprintf(text, len, "%s", translate("gettextFromC", "air"));
|
2015-01-05 19:09:30 +00:00
|
|
|
|
else if (get_he(gasmix) == 0 && get_o2(gasmix) < 1000)
|
2014-06-02 03:56:29 +00:00
|
|
|
|
snprintf(text, len, translate("gettextFromC", "EAN%d"), (get_o2(gasmix) + 5) / 10);
|
2015-01-05 19:09:30 +00:00
|
|
|
|
else if (get_he(gasmix) == 0 && get_o2(gasmix) == 1000)
|
|
|
|
|
snprintf(text, len, "%s", translate("gettextFromC", "oxygen"));
|
2014-06-02 03:56:29 +00:00
|
|
|
|
else
|
|
|
|
|
snprintf(text, len, "(%d/%d)", (get_o2(gasmix) + 5) / 10, (get_he(gasmix) + 5) / 10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a static char buffer - only good for immediate use by printf etc */
|
2018-08-16 17:10:10 +00:00
|
|
|
|
const char *gasname(struct gasmix gasmix)
|
2014-06-02 03:56:29 +00:00
|
|
|
|
{
|
|
|
|
|
static char gas[64];
|
|
|
|
|
get_gas_string(gasmix, gas, sizeof(gas));
|
|
|
|
|
return gas;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 11:52:48 +00:00
|
|
|
|
int gas_volume(const cylinder_t *cyl, pressure_t p)
|
|
|
|
|
{
|
|
|
|
|
double bar = p.mbar / 1000.0;
|
|
|
|
|
double z_factor = gas_compressibility_factor(cyl->gasmix, bar);
|
|
|
|
|
return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-05 18:31:35 +00:00
|
|
|
|
int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[])
|
2019-06-04 11:52:48 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int best = -1, score = INT_MAX;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_CYLINDERS; i++) {
|
|
|
|
|
const cylinder_t *match;
|
|
|
|
|
int distance;
|
|
|
|
|
|
|
|
|
|
match = array + i;
|
|
|
|
|
if (cylinder_nodata(match))
|
|
|
|
|
continue;
|
|
|
|
|
distance = gasmix_distance(mix, match->gasmix);
|
|
|
|
|
if (distance >= score)
|
|
|
|
|
continue;
|
|
|
|
|
best = i;
|
|
|
|
|
score = distance;
|
|
|
|
|
}
|
|
|
|
|
return best;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-18 10:53:48 +00:00
|
|
|
|
bool weightsystem_none(const weightsystem_t *ws)
|
2011-12-24 03:41:16 +00:00
|
|
|
|
{
|
|
|
|
|
return !ws->weight.grams && !ws->description;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-11 00:14:07 +00:00
|
|
|
|
/*
|
|
|
|
|
* We hardcode the most common standard cylinders,
|
|
|
|
|
* we should pick up any other names from the dive
|
|
|
|
|
* logs directly.
|
|
|
|
|
*/
|
2018-06-19 01:02:02 +00:00
|
|
|
|
struct tank_info_t tank_info[MAX_TANK_INFO] = {
|
2011-09-11 00:14:07 +00:00
|
|
|
|
/* Need an empty entry for the no-cylinder case */
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
|
{ "", },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
|
|
/* Size-only metric cylinders */
|
2014-06-22 13:47:25 +00:00
|
|
|
|
{ "10.0ℓ", .ml = 10000 },
|
|
|
|
|
{ "11.1ℓ", .ml = 11100 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
|
|
/* Most common AL cylinders */
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ "AL40", .cuft = 40, .psi = 3000 },
|
|
|
|
|
{ "AL50", .cuft = 50, .psi = 3000 },
|
|
|
|
|
{ "AL63", .cuft = 63, .psi = 3000 },
|
|
|
|
|
{ "AL72", .cuft = 72, .psi = 3000 },
|
|
|
|
|
{ "AL80", .cuft = 80, .psi = 3000 },
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
|
{ "AL100", .cuft = 100, .psi = 3300 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
2014-06-25 08:43:03 +00:00
|
|
|
|
/* Metric AL cylinders */
|
|
|
|
|
{ "ALU7", .ml = 7000, .bar = 200 },
|
|
|
|
|
|
2011-09-11 00:14:07 +00:00
|
|
|
|
/* Somewhat common LP steel cylinders */
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ "LP85", .cuft = 85, .psi = 2640 },
|
|
|
|
|
{ "LP95", .cuft = 95, .psi = 2640 },
|
2012-04-01 22:38:52 +00:00
|
|
|
|
{ "LP108", .cuft = 108, .psi = 2640 },
|
|
|
|
|
{ "LP121", .cuft = 121, .psi = 2640 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
|
|
/* Somewhat common HP steel cylinders */
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ "HP65", .cuft = 65, .psi = 3442 },
|
|
|
|
|
{ "HP80", .cuft = 80, .psi = 3442 },
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
|
{ "HP100", .cuft = 100, .psi = 3442 },
|
2016-08-10 03:32:44 +00:00
|
|
|
|
{ "HP117", .cuft = 117, .psi = 3442 },
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
|
{ "HP119", .cuft = 119, .psi = 3442 },
|
|
|
|
|
{ "HP130", .cuft = 130, .psi = 3442 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
2011-12-11 20:03:55 +00:00
|
|
|
|
/* Common European steel cylinders */
|
2014-06-22 13:47:25 +00:00
|
|
|
|
{ "3ℓ 232 bar", .ml = 3000, .bar = 232 },
|
|
|
|
|
{ "3ℓ 300 bar", .ml = 3000, .bar = 300 },
|
2017-03-20 16:17:05 +00:00
|
|
|
|
{ "10ℓ 200 bar", .ml = 10000, .bar = 200 },
|
|
|
|
|
{ "10ℓ 232 bar", .ml = 10000, .bar = 232 },
|
2014-06-22 13:47:25 +00:00
|
|
|
|
{ "10ℓ 300 bar", .ml = 10000, .bar = 300 },
|
|
|
|
|
{ "12ℓ 200 bar", .ml = 12000, .bar = 200 },
|
|
|
|
|
{ "12ℓ 232 bar", .ml = 12000, .bar = 232 },
|
|
|
|
|
{ "12ℓ 300 bar", .ml = 12000, .bar = 300 },
|
|
|
|
|
{ "15ℓ 200 bar", .ml = 15000, .bar = 200 },
|
|
|
|
|
{ "15ℓ 232 bar", .ml = 15000, .bar = 232 },
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ "D7 300 bar", .ml = 14000, .bar = 300 },
|
2011-12-11 20:03:55 +00:00
|
|
|
|
{ "D8.5 232 bar", .ml = 17000, .bar = 232 },
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ "D12 232 bar", .ml = 24000, .bar = 232 },
|
2014-08-05 15:05:07 +00:00
|
|
|
|
{ "D13 232 bar", .ml = 26000, .bar = 232 },
|
|
|
|
|
{ "D15 232 bar", .ml = 30000, .bar = 232 },
|
|
|
|
|
{ "D16 232 bar", .ml = 32000, .bar = 232 },
|
|
|
|
|
{ "D18 232 bar", .ml = 36000, .bar = 232 },
|
|
|
|
|
{ "D20 232 bar", .ml = 40000, .bar = 232 },
|
2011-12-11 20:03:55 +00:00
|
|
|
|
|
2011-09-11 00:14:07 +00:00
|
|
|
|
/* We'll fill in more from the dive log dynamically */
|
2011-09-09 15:38:48 +00:00
|
|
|
|
{ NULL, }
|
|
|
|
|
};
|
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
|
/*
|
|
|
|
|
* We hardcode the most common weight system types
|
|
|
|
|
* This is a bit odd as the weight system types don't usually encode weight
|
|
|
|
|
*/
|
2018-06-19 00:59:33 +00:00
|
|
|
|
struct ws_info_t ws_info[MAX_WS_INFO] = {
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "integrated"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "belt"), 0 },
|
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "ankle"), 0 },
|
2017-03-07 07:15:07 +00:00
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "backplate"), 0 },
|
2014-02-28 04:09:57 +00:00
|
|
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "clip-on"), 0 },
|
2011-12-24 03:41:16 +00:00
|
|
|
|
};
|
|
|
|
|
|
2013-05-22 17:02:28 +00:00
|
|
|
|
void remove_cylinder(struct dive *dive, int idx)
|
|
|
|
|
{
|
|
|
|
|
cylinder_t *cyl = dive->cylinder + idx;
|
|
|
|
|
int nr = MAX_CYLINDERS - idx - 1;
|
|
|
|
|
memmove(cyl, cyl + 1, nr * sizeof(*cyl));
|
|
|
|
|
memset(cyl + nr, 0, sizeof(*cyl));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void remove_weightsystem(struct dive *dive, int idx)
|
|
|
|
|
{
|
2019-06-26 15:21:03 +00:00
|
|
|
|
remove_from_weightsystem_table(&dive->weightsystems, idx);
|
2013-05-22 17:02:28 +00:00
|
|
|
|
}
|
2014-05-29 21:36:14 +00:00
|
|
|
|
|
2014-05-30 16:10:35 +00:00
|
|
|
|
/* when planning a dive we need to make sure that all cylinders have a sane depth assigned
|
2014-07-04 18:40:02 +00:00
|
|
|
|
* and if we are tracking gas consumption the pressures need to be reset to start = end = workingpressure */
|
|
|
|
|
void reset_cylinders(struct dive *dive, bool track_gas)
|
2014-05-29 21:36:14 +00:00
|
|
|
|
{
|
2014-12-04 19:56:17 +00:00
|
|
|
|
pressure_t decopo2 = {.mbar = prefs.decopo2};
|
2014-05-30 16:10:35 +00:00
|
|
|
|
|
2017-11-27 19:37:19 +00:00
|
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
2014-05-30 16:10:35 +00:00
|
|
|
|
cylinder_t *cyl = &dive->cylinder[i];
|
|
|
|
|
if (cylinder_none(cyl))
|
|
|
|
|
continue;
|
2014-12-04 19:56:17 +00:00
|
|
|
|
if (cyl->depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */
|
2018-08-16 17:10:10 +00:00
|
|
|
|
cyl->depth = gas_mod(cyl->gasmix, decopo2, dive, M_OR_FT(3,10));
|
2014-07-17 06:04:30 +00:00
|
|
|
|
if (track_gas)
|
2014-05-30 16:10:35 +00:00
|
|
|
|
cyl->start.mbar = cyl->end.mbar = cyl->type.workingpressure.mbar;
|
2014-06-01 16:59:38 +00:00
|
|
|
|
cyl->gas_used.mliter = 0;
|
2014-07-05 14:49:06 +00:00
|
|
|
|
cyl->deco_gas_used.mliter = 0;
|
2014-05-29 21:36:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-27 11:36:20 +00:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_CYL
|
|
|
|
|
void dump_cylinders(struct dive *dive, bool verbose)
|
|
|
|
|
{
|
|
|
|
|
printf("Cylinder list:\n");
|
|
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
|
|
|
|
cylinder_t *cyl = &dive->cylinder[i];
|
|
|
|
|
|
|
|
|
|
printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description, cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0);
|
|
|
|
|
printf(" Gasmix O2 %2.0f%% He %2.0f%%\n", cyl->gasmix.o2.permille / 10.0, cyl->gasmix.he.permille / 10.0);
|
|
|
|
|
printf(" Pressure Start %3.0fbar End %3.0fbar Sample start %3.0fbar Sample end %3.0fbar\n", cyl->start.mbar / 1000.0, cyl->end.mbar / 1000.0, cyl->sample_start.mbar / 1000.0, cyl->sample_end.mbar / 1000.0);
|
|
|
|
|
if (verbose) {
|
|
|
|
|
printf(" Depth %3.0fm\n", cyl->depth.mm / 1000.0);
|
|
|
|
|
printf(" Added %s\n", (cyl->manually_added ? "manually" : ""));
|
|
|
|
|
printf(" Gas used Bottom %5.0fl Deco %5.0fl\n", cyl->gas_used.mliter / 1000.0, cyl->deco_gas_used.mliter / 1000.0);
|
|
|
|
|
printf(" Use %d\n", cyl->cylinder_use);
|
|
|
|
|
printf(" Bestmix %s %s\n", (cyl->bestmix_o2 ? "O2" : " "), (cyl->bestmix_he ? "He" : " "));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|