mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 13:10:19 +00:00
28093ae957
Also make gasname() and get_gas_string() global functions (which allows us to delete code elsewhere). Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
246 lines
6.7 KiB
C
246 lines
6.7 KiB
C
/* equipment.c */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
#include "gettext.h"
|
|
#include "dive.h"
|
|
#include "display.h"
|
|
#include "divelist.h"
|
|
|
|
/* placeholders for a few functions that we need to redesign for the Qt UI */
|
|
void add_cylinder_description(cylinder_type_t *type)
|
|
{
|
|
const char *desc;
|
|
int i;
|
|
|
|
desc = type->description;
|
|
if (!desc)
|
|
return;
|
|
for (i = 0; i < 100 && tank_info[i].name != NULL; i++) {
|
|
if (strcmp(tank_info[i].name, desc) == 0)
|
|
return;
|
|
}
|
|
if (i < 100) {
|
|
tank_info[i].name = desc;
|
|
tank_info[i].ml = type->size.mliter;
|
|
tank_info[i].bar = type->workingpressure.mbar / 1000;
|
|
}
|
|
}
|
|
void add_weightsystem_description(weightsystem_t *weightsystem)
|
|
{
|
|
const char *desc;
|
|
int i;
|
|
|
|
desc = weightsystem->description;
|
|
if (!desc)
|
|
return;
|
|
for (i = 0; i < 100 && ws_info[i].name != NULL; i++) {
|
|
if (strcmp(ws_info[i].name, desc) == 0) {
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
return;
|
|
}
|
|
}
|
|
if (i < 100) {
|
|
ws_info[i].name = desc;
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
}
|
|
}
|
|
|
|
bool cylinder_nodata(cylinder_t *cyl)
|
|
{
|
|
return !cyl->type.size.mliter &&
|
|
!cyl->type.workingpressure.mbar &&
|
|
!cyl->type.description &&
|
|
!cyl->gasmix.o2.permille &&
|
|
!cyl->gasmix.he.permille &&
|
|
!cyl->start.mbar &&
|
|
!cyl->end.mbar &&
|
|
!cyl->gas_used.mliter;
|
|
}
|
|
|
|
static bool cylinder_nosamples(cylinder_t *cyl)
|
|
{
|
|
return !cyl->sample_start.mbar &&
|
|
!cyl->sample_end.mbar;
|
|
}
|
|
|
|
bool cylinder_none(void *_data)
|
|
{
|
|
cylinder_t *cyl = _data;
|
|
return cylinder_nodata(cyl) && cylinder_nosamples(cyl);
|
|
}
|
|
|
|
/* look at all dive computers and figure out if this cylinder is used anywhere
|
|
* d has to be a valid dive (test before calling)
|
|
* cyl does not have to be a cylinder that is part of this dive structure */
|
|
bool cylinder_is_used(struct dive *d, cylinder_t *cyl)
|
|
{
|
|
struct divecomputer *dc = &d->dc;
|
|
bool same_as_first = gasmix_distance(&cyl->gasmix, &d->cylinder[0].gasmix) < 200;
|
|
while (dc) {
|
|
struct event *ev = get_next_event(dc->events, "gaschange");
|
|
if (same_as_first && (!ev || ev->time.seconds > 30)) {
|
|
// unless there is a gas change in the first 30 seconds we can
|
|
// always mark the first cylinder as used
|
|
return true;
|
|
}
|
|
while (ev) {
|
|
if (gasmix_distance(&cyl->gasmix, get_gasmix_from_event(ev)) < 200)
|
|
return true;
|
|
|
|
ev = get_next_event(ev->next, "gaschange");
|
|
}
|
|
dc = dc->next;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void get_gas_string(const struct gasmix *gasmix, char *text, int len)
|
|
{
|
|
if (gasmix_is_air(gasmix))
|
|
snprintf(text, len, "%s", translate("gettextFromC", "air"));
|
|
else if (get_he(gasmix) == 0)
|
|
snprintf(text, len, translate("gettextFromC", "EAN%d"), (get_o2(gasmix) + 5) / 10);
|
|
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 */
|
|
const char *gasname(const struct gasmix *gasmix)
|
|
{
|
|
static char gas[64];
|
|
get_gas_string(gasmix, gas, sizeof(gas));
|
|
return gas;
|
|
}
|
|
|
|
bool weightsystem_none(void *_data)
|
|
{
|
|
weightsystem_t *ws = _data;
|
|
return !ws->weight.grams && !ws->description;
|
|
}
|
|
|
|
bool no_weightsystems(weightsystem_t *ws)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_WEIGHTSYSTEMS; i++)
|
|
if (!weightsystem_none(ws + i))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static bool one_weightsystem_equal(weightsystem_t *ws1, weightsystem_t *ws2)
|
|
{
|
|
return ws1->weight.grams == ws2->weight.grams &&
|
|
same_string(ws1->description, ws2->description);
|
|
}
|
|
|
|
bool weightsystems_equal(weightsystem_t *ws1, weightsystem_t *ws2)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_WEIGHTSYSTEMS; i++)
|
|
if (!one_weightsystem_equal(ws1 + i, ws2 + i))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* We hardcode the most common standard cylinders,
|
|
* we should pick up any other names from the dive
|
|
* logs directly.
|
|
*/
|
|
struct tank_info_t tank_info[100] = {
|
|
/* Need an empty entry for the no-cylinder case */
|
|
{ "", },
|
|
|
|
/* Size-only metric cylinders */
|
|
{ "10.0 l", .ml = 10000 },
|
|
{ "11.1 l", .ml = 11100 },
|
|
|
|
/* Most common AL cylinders */
|
|
{ "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 },
|
|
{ "AL100", .cuft = 100, .psi = 3300 },
|
|
|
|
/* Somewhat common LP steel cylinders */
|
|
{ "LP85", .cuft = 85, .psi = 2640 },
|
|
{ "LP95", .cuft = 95, .psi = 2640 },
|
|
{ "LP108", .cuft = 108, .psi = 2640 },
|
|
{ "LP121", .cuft = 121, .psi = 2640 },
|
|
|
|
/* Somewhat common HP steel cylinders */
|
|
{ "HP65", .cuft = 65, .psi = 3442 },
|
|
{ "HP80", .cuft = 80, .psi = 3442 },
|
|
{ "HP100", .cuft = 100, .psi = 3442 },
|
|
{ "HP119", .cuft = 119, .psi = 3442 },
|
|
{ "HP130", .cuft = 130, .psi = 3442 },
|
|
|
|
/* Common European steel cylinders */
|
|
{ "3L 232 bar", .ml = 3000, .bar = 232 },
|
|
{ "3L 300 bar", .ml = 3000, .bar = 300 },
|
|
{ "10L 300 bar", .ml = 10000, .bar = 300 },
|
|
{ "12L 200 bar", .ml = 12000, .bar = 200 },
|
|
{ "12L 232 bar", .ml = 12000, .bar = 232 },
|
|
{ "12L 300 bar", .ml = 12000, .bar = 300 },
|
|
{ "15L 200 bar", .ml = 15000, .bar = 200 },
|
|
{ "15L 232 bar", .ml = 15000, .bar = 232 },
|
|
{ "D7 300 bar", .ml = 14000, .bar = 300 },
|
|
{ "D8.5 232 bar", .ml = 17000, .bar = 232 },
|
|
{ "D12 232 bar", .ml = 24000, .bar = 232 },
|
|
|
|
/* We'll fill in more from the dive log dynamically */
|
|
{ NULL, }
|
|
};
|
|
|
|
/*
|
|
* We hardcode the most common weight system types
|
|
* This is a bit odd as the weight system types don't usually encode weight
|
|
*/
|
|
struct ws_info_t ws_info[100] = {
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "integrated"), 0 },
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "belt"), 0 },
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "ankle"), 0 },
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "backplate weight"), 0 },
|
|
{ QT_TRANSLATE_NOOP("gettextFromC", "clip-on"), 0 },
|
|
};
|
|
|
|
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)
|
|
{
|
|
weightsystem_t *ws = dive->weightsystem + idx;
|
|
int nr = MAX_WEIGHTSYSTEMS - idx - 1;
|
|
memmove(ws, ws + 1, nr * sizeof(*ws));
|
|
memset(ws + nr, 0, sizeof(*ws));
|
|
}
|
|
|
|
/* when planning a dive we need to make sure that all cylinders have a sane depth assigned
|
|
* and that the pressures are reset to start = end = workingpressure */
|
|
void reset_cylinders(struct dive *dive)
|
|
{
|
|
int i;
|
|
pressure_t pO2 = {.mbar = 1400};
|
|
|
|
for (i = 0; i < MAX_CYLINDERS; i++) {
|
|
cylinder_t *cyl = &dive->cylinder[i];
|
|
if (cylinder_none(cyl))
|
|
continue;
|
|
if (cyl->depth.mm == 0) /* if the gas doesn't give a mod, assume conservative pO2 */
|
|
cyl->depth = gas_mod(&cyl->gasmix, pO2);
|
|
if (cyl->type.workingpressure.mbar)
|
|
cyl->start.mbar = cyl->end.mbar = cyl->type.workingpressure.mbar;
|
|
cyl->gas_used.mliter = 0;
|
|
}
|
|
}
|