//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; }
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"); }
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); }
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')); }
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')); }
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); }
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); }
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); }
/* * 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); }
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"); }
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; } }
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"); }
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); }
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(); }
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; } }
/* 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, ""); } }