//TODO: C Code. static functions are not good if we plan to have a test for them.
static bool merge_locations_into_dives(void)
{
	int i, nr = 0, changed = 0;
	struct dive *gpsfix, *last_named_fix = NULL, *dive;

	sort_table(&gps_location_table);

	for_each_gps_location (i, gpsfix) {
		if (is_automatic_fix(gpsfix)) {
			dive = find_dive_including(gpsfix->when);
			if (dive && !dive_has_gps_location(dive)) {
#if DEBUG_WEBSERVICE
				struct tm tm;
				utc_mkdate(gpsfix->when, &tm);
				printf("found dive named %s @ %04d-%02d-%02d %02d:%02d:%02d\n",
				       gpsfix->location,
				       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
				       tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif
				changed++;
				copy_gps_location(gpsfix, dive);
			}
		} else {
			if (last_named_fix && dive_within_time_range(last_named_fix, gpsfix->when, SAME_GROUP)) {
				nr++;
			} else {
				nr = 1;
				last_named_fix = gpsfix;
			}
			dive = find_dive_n_near(gpsfix->when, nr, SAME_GROUP);
			if (dive) {
				if (!dive_has_gps_location(dive)) {
					copy_gps_location(gpsfix, dive);
					changed++;
				}
				if (!dive->location) {
					dive->location = strdup(gpsfix->location);
					changed++;
				}
			} else {
				struct tm tm;
				utc_mkdate(gpsfix->when, &tm);
#if DEBUG_WEBSERVICE
				printf("didn't find dive matching gps fix named %s @ %04d-%02d-%02d %02d:%02d:%02d\n",
				       gpsfix->location,
				       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
				       tm.tm_hour, tm.tm_min, tm.tm_sec);
#endif
			}
		}
	}
	return changed > 0;
}
Exemple #2
0
static void save_dive(FILE *f, struct dive *dive)
{
	int i;
	struct tm tm;

	utc_mkdate(dive->when, &tm);

	fputs("<dive", f);
	if (dive->number)
		fprintf(f, " number='%d'", dive->number);
	if (dive->tripflag != TF_NONE)
		fprintf(f, " tripflag='%s'", tripflag_names[dive->tripflag]);
	if (dive->rating)
		fprintf(f, " rating='%d'", dive->rating);
	fprintf(f, " date='%04u-%02u-%02u'",
		tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
	fprintf(f, " time='%02u:%02u:%02u'",
		tm.tm_hour, tm.tm_min, tm.tm_sec);
	fprintf(f, " duration='%u:%02u min'>\n",
		FRACTION(dive->duration.seconds, 60));
	save_overview(f, dive);
	save_cylinder_info(f, dive);
	save_weightsystem_info(f, dive);
	save_events(f, dive->events);
	for (i = 0; i < dive->samples; i++)
		save_sample(f, dive->sample+i);
	fprintf(f, "</dive>\n");
}
Exemple #3
0
static void show_date(struct membuffer *b, timestamp_t when)
{
	struct tm tm;

	utc_mkdate(when, &tm);

	put_format(b, "date %04u-%02u-%02u\n",
		   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
	put_format(b, "time %02u:%02u:%02u\n",
		   tm.tm_hour, tm.tm_min, tm.tm_sec);
}
Exemple #4
0
QString get_short_dive_date_string(timestamp_t when)
{
	struct tm tm;
	utc_mkdate(when, &tm);
	return translate("gettextFromC", "%1 %2, %3\n%4:%5")
		.arg(monthname(tm.tm_mon))
		.arg(tm.tm_mday)
		.arg(tm.tm_year + 1900)
		.arg(tm.tm_hour, 2, 10, QChar('0'))
		.arg(tm.tm_min, 2, 10, QChar('0'));
}
Exemple #5
0
QString get_dive_date_string(timestamp_t when)
{
	struct tm tm;
	utc_mkdate(when, &tm);
	return translate("gettextFromC", "%1, %2 %3, %4 %5:%6")
		.arg(weekday(tm.tm_wday))
		.arg(monthname(tm.tm_mon))
		.arg(tm.tm_mday)
		.arg(tm.tm_year + 1900)
		.arg(tm.tm_hour, 2, 10, QChar('0'))
		.arg(tm.tm_min, 2, 10, QChar('0'));
}
Exemple #6
0
static void update_date(timestamp_t *when, const char *line)
{
	unsigned yyyy, mm, dd;
	struct tm tm;

	if (sscanf(line, "%04u-%02u-%02u", &yyyy, &mm, &dd) != 3)
		return;
	utc_mkdate(*when, &tm);
	tm.tm_year = yyyy - 1900;
	tm.tm_mon = mm - 1;
	tm.tm_mday = dd;
	*when = utc_mktime(&tm);
}
Exemple #7
0
static void update_time(timestamp_t *when, const char *line)
{
	unsigned h, m, s = 0;
	struct tm tm;

	if (sscanf(line, "%02u:%02u:%02u", &h, &m, &s) < 2)
		return;
	utc_mkdate(*when, &tm);
	tm.tm_hour = h;
	tm.tm_min = m;
	tm.tm_sec = s;
	*when = utc_mktime(&tm);
}
Exemple #8
0
QString get_trip_date_string(timestamp_t when, int nr)
{
	struct tm tm;
	utc_mkdate(when, &tm);
	if (nr != 1)
		return translate("gettextFromC", "%1 %2 (%3 dives)")
			.arg(monthname(tm.tm_mon))
			.arg(tm.tm_year + 1900)
			.arg(nr);
	else
		return translate("gettextFromC", "%1 %2 (1 dive)")
			.arg(monthname(tm.tm_mon))
			.arg(tm.tm_year + 1900);
}
Exemple #9
0
/*
 * The name of a dive is the date and the dive number (and possibly
 * the uniqueness suffix).
 *
 * Note that the time of the dive may not be the same as the
 * time of the directory structure it is created in: the dive
 * might be part of a trip that straddles a month (or even a
 * year).
 *
 * We do *not* want to use localized weekdays and cause peoples save
 * formats to depend on their locale.
 */
static void create_dive_name(struct dive *dive, struct membuffer *name, struct tm *dirtm)
{
	struct tm tm;
	static const char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

	utc_mkdate(dive->when, &tm);
	if (tm.tm_year != dirtm->tm_year)
		put_format(name, "%04u-", tm.tm_year + 1900);
	if (tm.tm_mon != dirtm->tm_mon)
		put_format(name, "%02u-", tm.tm_mon+1);

	put_format(name, "%02u-%s-%02u:%02u:%02u",
		tm.tm_mday, weekday[tm.tm_wday],
		tm.tm_hour, tm.tm_min, tm.tm_sec);
}
Exemple #10
0
static void save_trip(FILE *f, dive_trip_t *trip)
{
	struct tm tm;

	utc_mkdate(trip->when, &tm);

	fprintf(f, "<trip");
	fprintf(f, " date='%04u-%02u-%02u'",
		tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
	fprintf(f, " time='%02u:%02u:%02u'",
		tm.tm_hour, tm.tm_min, tm.tm_sec);
	if (trip->location)
		show_utf8(f, trip->location, " location=\'","\'", 1);
	fprintf(f, " />\n");
}
Exemple #11
0
void dump_plan(struct diveplan *diveplan)
{
	struct divedatapoint *dp;
	struct tm tm;

	if (!diveplan) {
		printf("Diveplan NULL\n");
		return;
	}
	utc_mkdate(diveplan->when, &tm);

	printf("\nDiveplan @ %04d-%02d-%02d %02d:%02d:%02d (surfpres %dmbar):\n",
	       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
	       tm.tm_hour, tm.tm_min, tm.tm_sec,
	       diveplan->surface_pressure);
	dp = diveplan->dp;
	while (dp) {
		printf("\t%3u:%02u: %dmm gas: %d o2 %d h2\n", FRACTION(dp->time, 60), dp->depth, get_o2(&dp->gasmix), get_he(&dp->gasmix));
		dp = dp->next;
	}
}
Exemple #12
0
static void save_dive(FILE *f, struct dive *dive)
{
	int i;
	struct tm tm;

	utc_mkdate(dive->when, &tm);

	fputs("<dive", f);
	if (dive->number)
		fprintf(f, " number='%d'", dive->number);
	/*
	 * TF_NONE is the default for dives with no trips
	 * IN_TRIP is the default for dives with trips
	 * ASSIGNED_TRIP is an in-memory thing and gets converted
	 *    to IN_TRIP by the save code.
	 */
	if (dive->tripflag != TF_NONE && dive->tripflag != IN_TRIP && dive->tripflag != ASSIGNED_TRIP)
		fprintf(f, " tripflag='%s'", tripflag_names[dive->tripflag]);
	if (dive->rating)
		fprintf(f, " rating='%d'", dive->rating);
	if (dive->visibility)
		fprintf(f, " visibility='%d'", dive->visibility);
	fprintf(f, " date='%04u-%02u-%02u'",
		tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
	fprintf(f, " time='%02u:%02u:%02u'",
		tm.tm_hour, tm.tm_min, tm.tm_sec);
	fprintf(f, " duration='%u:%02u min'>\n",
		FRACTION(dive->duration.seconds, 60));
	save_overview(f, dive);
	save_cylinder_info(f, dive);
	save_weightsystem_info(f, dive);
	save_events(f, dive->events);
	for (i = 0; i < dive->samples; i++)
		save_sample(f, dive->sample+i);
	fprintf(f, "</dive>\n");
}
Exemple #13
0
static void show_single_dive_stats(struct dive *dive)
{
    char buf[80];
    double value;
    int decimals;
    const char *unit;
    int idx, offset, gas_used;
    struct dive *prev_dive;
    struct tm tm;

    process_all_dives(dive, &prev_dive);

    utc_mkdate(dive->when, &tm);
    snprintf(buf, sizeof(buf),
             /*++GETTEXT 80 chars: weekday, monthname, day, year, hour, min */
             _("%1$s, %2$s %3$d, %4$d %5$2d:%6$02d"),
             weekday(tm.tm_wday),
             monthname(tm.tm_mon),
             tm.tm_mday, tm.tm_year + 1900,
             tm.tm_hour, tm.tm_min);

    set_label(single_w.date, buf);
    set_label(single_w.dive_time, _("%d min"), (dive->duration.seconds + 30) / 60);
    if (prev_dive)
        set_label(single_w.surf_intv,
                  get_time_string(dive->when - (prev_dive->when + prev_dive->duration.seconds), 4));
    else
        set_label(single_w.surf_intv, _("unknown"));
    value = get_depth_units(dive->maxdepth.mm, &decimals, &unit);
    set_label(single_w.max_depth, "%.*f %s", decimals, value, unit);
    value = get_depth_units(dive->meandepth.mm, &decimals, &unit);
    set_label(single_w.avg_depth, "%.*f %s", decimals, value, unit);
    if (dive->watertemp.mkelvin) {
        value = get_temp_units(dive->watertemp.mkelvin, &unit);
        set_label(single_w.water_temp, "%.1f %s", value, unit);
    } else
        set_label(single_w.water_temp, "");
    value = get_volume_units(dive->sac, &decimals, &unit);
    if (value > 0) {
        set_label(single_w.sac, _("%.*f %s/min"), decimals, value, unit);
    } else
        set_label(single_w.sac, "");
    set_label(single_w.otu, "%d", dive->otu);
    offset = 0;
    gas_used = 0;
    buf[0] = '\0';
    /* for the O2/He readings just create a list of them */
    for (idx = 0; idx < MAX_CYLINDERS; idx++) {
        cylinder_t *cyl = &dive->cylinder[idx];
        unsigned int start, end;

        start = cyl->start.mbar ? : cyl->sample_start.mbar;
        end = cyl->end.mbar ? : cyl->sample_end.mbar;
        if (!cylinder_none(cyl)) {
            /* 0% O2 strangely means air, so 21% - I don't like that at all */
            int o2 = cyl->gasmix.o2.permille ? : AIR_PERMILLE;
            if (offset > 0) {
                snprintf(buf+offset, 80-offset, ", ");
                offset += 2;
            }
            snprintf(buf+offset, 80-offset, "%d/%d", (o2 + 5) / 10,
                     (cyl->gasmix.he.permille + 5) / 10);
            offset = strlen(buf);
        }
        /* and if we have size, start and end pressure, we can
         * calculate the total gas used */
        if (cyl->type.size.mliter && start && end)
            gas_used += cyl->type.size.mliter / 1000.0 * (start - end);
    }
Exemple #14
0
static void process_all_dives(struct dive *dive, struct dive **prev_dive)
{
    int idx;
    struct dive *dp;
    struct tm tm;
    int current_year = 0;
    int current_month = 0;
    int year_iter = 0;
    int month_iter = 0;
    int prev_month = 0, prev_year = 0;
    unsigned int size;

    *prev_dive = NULL;
    memset(&stats, 0, sizeof(stats));
    if (dive_table.nr > 0) {
        stats.shortest_time.seconds = dive_table.dives[0]->duration.seconds;
        stats.min_depth.mm = dive_table.dives[0]->maxdepth.mm;
        stats.selection_size = dive_table.nr;
    }

    /* allocate sufficient space to hold the worst
     * case (one dive per year or all dives during
     * one month) for yearly and monthly statistics*/

    if (stats_yearly != NULL) {
        free(stats_yearly);
        free(stats_monthly);
    }
    size = sizeof(stats_t) * (dive_table.nr + 1);
    stats_yearly = malloc(size);
    stats_monthly = malloc(size);
    if (!stats_yearly || !stats_monthly)
        return;
    memset(stats_yearly, 0, size);
    memset(stats_monthly, 0, size);

    /* this relies on the fact that the dives in the dive_table
     * are in chronological order */
    for (idx = 0; idx < dive_table.nr; idx++) {
        dp = dive_table.dives[idx];
        if (dp->when == dive->when) {
            /* that's the one we are showing */
            if (idx > 0)
                *prev_dive = dive_table.dives[idx-1];
        }
        process_dive(dp, &stats);

        /* yearly statistics */
        utc_mkdate(dp->when, &tm);
        if (current_year == 0)
            current_year = tm.tm_year + 1900;

        if (current_year != tm.tm_year + 1900) {
            current_year = tm.tm_year + 1900;
            process_dive(dp, &(stats_yearly[++year_iter]));
        } else
            process_dive(dp, &(stats_yearly[year_iter]));

        stats_yearly[year_iter].selection_size++;
        stats_yearly[year_iter].period = current_year;

        /* monthly statistics */
        if (current_month == 0) {
            current_month = tm.tm_mon + 1;
        } else {
            if (current_month != tm.tm_mon + 1)
                current_month = tm.tm_mon + 1;
            if (prev_month != current_month || prev_year != current_year)
                month_iter++;
        }

        process_dive(dp, &(stats_monthly[month_iter]));
        stats_monthly[month_iter].selection_size++;
        stats_monthly[month_iter].period = current_month;
        prev_month = current_month;
        prev_year = current_year;
    }
    if (yearly_tree)
        update_yearly_stats();
}
Exemple #15
0
void process_all_dives(struct dive *dive, struct dive **prev_dive)
{
	int idx;
	struct dive *dp;
	struct tm tm;
	int current_year = 0;
	int current_month = 0;
	int year_iter = 0;
	int month_iter = 0;
	int prev_month = 0, prev_year = 0;
	int trip_iter = 0;
	dive_trip_t *trip_ptr = 0;
	unsigned int size;

	*prev_dive = NULL;
	memset(&stats, 0, sizeof(stats));
	if (dive_table.nr > 0) {
		stats.shortest_time.seconds = dive_table.dives[0]->duration.seconds;
		stats.min_depth.mm = dive_table.dives[0]->maxdepth.mm;
		stats.selection_size = dive_table.nr;
	}

	/* allocate sufficient space to hold the worst
	 * case (one dive per year or all dives during
	 * one month) for yearly and monthly statistics*/

	free(stats_yearly);
	free(stats_monthly);
	free(stats_by_trip);

	size = sizeof(stats_t) * (dive_table.nr + 1);
	stats_yearly = malloc(size);
	stats_monthly = malloc(size);
	stats_by_trip = malloc(size);
	if (!stats_yearly || !stats_monthly || !stats_by_trip)
		return;
	memset(stats_yearly, 0, size);
	memset(stats_monthly, 0, size);
	memset(stats_by_trip, 0, size);
	stats_yearly[0].is_year = true;

	/* this relies on the fact that the dives in the dive_table
	 * are in chronological order */
	for_each_dive (idx, dp) {
		if (dive && dp->when == dive->when) {
			/* that's the one we are showing */
			if (idx > 0)
				*prev_dive = dive_table.dives[idx - 1];
		}
		process_dive(dp, &stats);

		/* yearly statistics */
		utc_mkdate(dp->when, &tm);
		if (current_year == 0)
			current_year = tm.tm_year + 1900;

		if (current_year != tm.tm_year + 1900) {
			current_year = tm.tm_year + 1900;
			process_dive(dp, &(stats_yearly[++year_iter]));
			stats_yearly[year_iter].is_year = true;
		} else {
			process_dive(dp, &(stats_yearly[year_iter]));
		}
		stats_yearly[year_iter].selection_size++;
		stats_yearly[year_iter].period = current_year;

		if (dp->divetrip != NULL) {
			if (trip_ptr != dp->divetrip) {
				trip_ptr = dp->divetrip;
				trip_iter++;
			}

			/* stats_by_trip[0] is all the dives combined */
			stats_by_trip[0].selection_size++;
			process_dive(dp, &(stats_by_trip[0]));
			stats_by_trip[0].is_trip = true;
			stats_by_trip[0].location = strdup("All (by trip stats)");

			process_dive(dp, &(stats_by_trip[trip_iter]));
			stats_by_trip[trip_iter].selection_size++;
			stats_by_trip[trip_iter].is_trip = true;
			stats_by_trip[trip_iter].location = dp->divetrip->location;
		}

		/* monthly statistics */
		if (current_month == 0) {
			current_month = tm.tm_mon + 1;
		} else {
			if (current_month != tm.tm_mon + 1)
				current_month = tm.tm_mon + 1;
			if (prev_month != current_month || prev_year != current_year)
				month_iter++;
		}
		process_dive(dp, &(stats_monthly[month_iter]));
		stats_monthly[month_iter].selection_size++;
		stats_monthly[month_iter].period = current_month;
		prev_month = current_month;
		prev_year = current_year;
	}
}
Exemple #16
0
/* we try to show the data from the currently selected divecomputer
 * right now for some values (e.g., surface pressure) we could fall back
 * to dive data, but for consistency we don't. */
static void show_single_dive_stats(struct dive *dive)
{
	char buf[256];
	double value;
	int decimals;
	const char *unit;
	int idx, offset, gas_used, mbar;
	struct dive *prev_dive;
	struct tm tm;
	struct divecomputer *dc;

	process_all_dives(dive, &prev_dive);
	if (!dive)
		return;
	dc = select_dc(&dive->dc);
	utc_mkdate(dive->when, &tm);
	snprintf(buf, sizeof(buf),
		/*++GETTEXT 80 chars: weekday, monthname, day, year, hour, min */
		_("%1$s, %2$s %3$d, %4$d %5$2d:%6$02d"),
		weekday(tm.tm_wday),
		monthname(tm.tm_mon),
		tm.tm_mday, tm.tm_year + 1900,
		tm.tm_hour, tm.tm_min);

	set_label(single_w.date, buf);
	set_label(single_w.dive_time, _("%d min"), (dive->duration.seconds + 30) / 60);
	if (prev_dive)
		set_label(single_w.surf_intv,
			get_time_string(dive->when - (prev_dive->when + prev_dive->duration.seconds), 4));
	else
		set_label(single_w.surf_intv, _("unknown"));
	value = get_depth_units(dc->maxdepth.mm, &decimals, &unit);
	set_label(single_w.max_depth, "%.*f %s", decimals, value, unit);
	value = get_depth_units(dc->meandepth.mm, &decimals, &unit);
	set_label(single_w.avg_depth, "%.*f %s", decimals, value, unit);
	set_label(single_w.viz, star_strings[dive->visibility]);
	if (dc->watertemp.mkelvin) {
		value = get_temp_units(dc->watertemp.mkelvin, &unit);
		set_label(single_w.water_temp, "%.1f %s", value, unit);
	} else {
		set_label(single_w.water_temp, "");
	}
	if (dc->airtemp.mkelvin) {
		value = get_temp_units(dc->airtemp.mkelvin, &unit);
		set_label(single_w.air_temp, "%.1f %s", value, unit);
	} else {
		if (dive->airtemp.mkelvin) {
			value = get_temp_units(dive->airtemp.mkelvin, &unit);
			set_label(single_w.air_temp, "%.1f %s", value, unit);
		} else {
				set_label(single_w.air_temp, "");
		}
	}
	mbar = dc->surface_pressure.mbar;
	/* it would be easy to get dive data here:
	 *	if (!mbar)
	 *		mbar = get_surface_pressure_in_mbar(dive, FALSE);
	 */
	if (mbar) {
		set_label(single_w.air_press, "%d mbar", mbar);
	} else {
		set_label(single_w.air_press, "");
	}
	value = get_volume_units(dive->sac, &decimals, &unit);
	if (value > 0)
		set_label(single_w.sac, _("%.*f %s/min"), decimals, value, unit);
	else
		set_label(single_w.sac, "");
	set_label(single_w.otu, "%d", dive->otu);
	offset = 0;
	gas_used = 0;
	buf[0] = '\0';
	/* for the O2/He readings just create a list of them */
	for (idx = 0; idx < MAX_CYLINDERS; idx++) {
		cylinder_t *cyl = &dive->cylinder[idx];
		pressure_t start, end;

		start = cyl->start.mbar ? cyl->start : cyl->sample_start;
		end = cyl->end.mbar ?cyl->sample_end : cyl->sample_end;
		if (!cylinder_none(cyl)) {
			/* 0% O2 strangely means air, so 21% - I don't like that at all */
			int o2 = get_o2(&cyl->gasmix);
			int he = get_he(&cyl->gasmix);
			if (offset > 0) {
				snprintf(buf+offset, 80-offset, ", ");
				offset += 2;
			}
			snprintf(buf+offset, 80-offset, "%d/%d", (o2 + 5) / 10, (he + 5) / 10);
			offset = strlen(buf);
		}
		/* and if we have size, start and end pressure, we can
		 * calculate the total gas used */
		if (start.mbar && end.mbar)
			gas_used += gas_volume(cyl, start) - gas_volume(cyl, end);
	}
	set_label(single_w.o2he, buf);
	if (gas_used) {
		value = get_volume_units(gas_used, &decimals, &unit);
		set_label(single_w.gas_used, "%.*f %s", decimals, value, unit);
	} else {
		set_label(single_w.gas_used, "");
	}
}