subsurface/core/equipment.c
Dirk Hohndel 7be962bfc2 Move subsurface-core to core and qt-mobile to mobile-widgets
Having subsurface-core as a directory name really messes with
autocomplete and is obviously redundant. Simmilarly, qt-mobile caused an
autocomplete conflict and also was inconsistent with the desktop-widget
name for the directory containing the "other" UI.

And while cleaning up the resulting change in the path name for include
files, I decided to clean up those even more to make them consistent
overall.

This could have been handled in more commits, but since this requires a
make clean before the build, it seemed more sensible to do it all in one.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2016-04-04 22:33:58 -07:00

238 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Clang has a bug on zero-initialization of C structs.
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
/* 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) {
// FIXME: leaked on exit
tank_info[i].name = strdup(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) {
// FIXME: leaked on exit
ws_info[i].name = strdup(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 &&
!cyl->deco_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);
}
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 && get_o2(gasmix) < 1000)
snprintf(text, len, translate("gettextFromC", "EAN%d"), (get_o2(gasmix) + 5) / 10);
else if (get_he(gasmix) == 0 && get_o2(gasmix) == 1000)
snprintf(text, len, "%s", translate("gettextFromC", "oxygen"));
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", .ml = 10000 },
{ "11.1", .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 },
/* Metric AL cylinders */
{ "ALU7", .ml = 7000, .bar = 200 },
/* 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 */
{ "3 232 bar", .ml = 3000, .bar = 232 },
{ "3 300 bar", .ml = 3000, .bar = 300 },
{ "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 },
{ "D7 300 bar", .ml = 14000, .bar = 300 },
{ "D8.5 232 bar", .ml = 17000, .bar = 232 },
{ "D12 232 bar", .ml = 24000, .bar = 232 },
{ "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 },
/* 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 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)
{
int i;
pressure_t decopo2 = {.mbar = prefs.decopo2};
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, calculate based on prefs */
cyl->depth = gas_mod(&cyl->gasmix, decopo2, dive, M_OR_FT(3,10));
if (track_gas)
cyl->start.mbar = cyl->end.mbar = cyl->type.workingpressure.mbar;
cyl->gas_used.mliter = 0;
cyl->deco_gas_used.mliter = 0;
}
}