diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2016-04-04 22:02:03 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2016-04-04 22:33:58 -0700 |
commit | 7be962bfc2879a72c32ff67518731347dcdff6de (patch) | |
tree | d05bf7ab234a448ee37a15b608e2b939f2285d07 /subsurface-core/statistics.c | |
parent | 2d760a7bff71c46c5aeba37c40d236ea16eefea2 (diff) | |
download | subsurface-7be962bfc2879a72c32ff67518731347dcdff6de.tar.gz |
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>
Diffstat (limited to 'subsurface-core/statistics.c')
-rw-r--r-- | subsurface-core/statistics.c | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/subsurface-core/statistics.c b/subsurface-core/statistics.c deleted file mode 100644 index 6a05cffc1..000000000 --- a/subsurface-core/statistics.c +++ /dev/null @@ -1,404 +0,0 @@ -/* statistics.c - * - * core logic for the Info & Stats page - - * char *get_time_string(int seconds, int maxdays); - * char *get_minutes(int seconds); - * void process_all_dives(struct dive *dive, struct dive **prev_dive); - * void get_selected_dives_text(char *buffer, int size); - */ -#include "gettext.h" -#include <string.h> -#include <ctype.h> - -#include "dive.h" -#include "display.h" -#include "divelist.h" -#include "statistics.h" - -static stats_t stats; -stats_t stats_selection; -stats_t *stats_monthly = NULL; -stats_t *stats_yearly = NULL; -stats_t *stats_by_trip = NULL; -stats_t *stats_by_type = NULL; - -static void process_temperatures(struct dive *dp, stats_t *stats) -{ - int min_temp, mean_temp, max_temp = 0; - - max_temp = dp->maxtemp.mkelvin; - if (max_temp && (!stats->max_temp || max_temp > stats->max_temp)) - stats->max_temp = max_temp; - - min_temp = dp->mintemp.mkelvin; - if (min_temp && (!stats->min_temp || min_temp < stats->min_temp)) - stats->min_temp = min_temp; - - if (min_temp || max_temp) { - mean_temp = min_temp; - if (mean_temp) - mean_temp = (mean_temp + max_temp) / 2; - else - mean_temp = max_temp; - stats->combined_temp += get_temp_units(mean_temp, NULL); - stats->combined_count++; - } -} - -static void process_dive(struct dive *dp, stats_t *stats) -{ - int old_tt, sac_time = 0; - uint32_t duration = dp->duration.seconds; - - old_tt = stats->total_time.seconds; - stats->total_time.seconds += duration; - if (duration > stats->longest_time.seconds) - stats->longest_time.seconds = duration; - if (stats->shortest_time.seconds == 0 || duration < stats->shortest_time.seconds) - stats->shortest_time.seconds = duration; - if (dp->maxdepth.mm > stats->max_depth.mm) - stats->max_depth.mm = dp->maxdepth.mm; - if (stats->min_depth.mm == 0 || dp->maxdepth.mm < stats->min_depth.mm) - stats->min_depth.mm = dp->maxdepth.mm; - - process_temperatures(dp, stats); - - /* Maybe we should drop zero-duration dives */ - if (!duration) - return; - stats->avg_depth.mm = (1.0 * old_tt * stats->avg_depth.mm + - duration * dp->meandepth.mm) / - stats->total_time.seconds; - if (dp->sac > 100) { /* less than .1 l/min is bogus, even with a pSCR */ - sac_time = stats->total_sac_time + duration; - stats->avg_sac.mliter = (1.0 * stats->total_sac_time * stats->avg_sac.mliter + - duration * dp->sac) / - sac_time; - if (dp->sac > stats->max_sac.mliter) - stats->max_sac.mliter = dp->sac; - if (stats->min_sac.mliter == 0 || dp->sac < stats->min_sac.mliter) - stats->min_sac.mliter = dp->sac; - stats->total_sac_time = sac_time; - } -} - -char *get_minutes(int seconds) -{ - static char buf[80]; - snprintf(buf, sizeof(buf), "%d:%.2d", FRACTION(seconds, 60)); - return buf; -} - -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, tsize; - - *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); - free(stats_by_type); - - size = sizeof(stats_t) * (dive_table.nr + 1); - tsize = sizeof(stats_t) * (NUM_DC_TYPE + 1); - stats_yearly = malloc(size); - stats_monthly = malloc(size); - stats_by_trip = malloc(size); - stats_by_type = malloc(tsize); - if (!stats_yearly || !stats_monthly || !stats_by_trip || !stats_by_type) - return; - memset(stats_yearly, 0, size); - memset(stats_monthly, 0, size); - memset(stats_by_trip, 0, size); - memset(stats_by_type, 0, tsize); - stats_yearly[0].is_year = true; - - /* Setting the is_trip to true to show the location as first - * field in the statistics window */ - stats_by_type[0].location = strdup("All (by type stats)"); - stats_by_type[0].is_trip = true; - stats_by_type[1].location = strdup("OC"); - stats_by_type[1].is_trip = true; - stats_by_type[2].location = strdup("CCR"); - stats_by_type[2].is_trip = true; - stats_by_type[3].location = strdup("pSCR"); - stats_by_type[3].is_trip = true; - stats_by_type[4].location = strdup("Freedive"); - stats_by_type[4].is_trip = 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; - - /* stats_by_type[0] is all the dives combined */ - stats_by_type[0].selection_size++; - process_dive(dp, &(stats_by_type[0])); - - process_dive(dp, &(stats_by_type[dp->dc.divemode + 1])); - stats_by_type[dp->dc.divemode + 1].selection_size++; - - 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; - } -} - -/* make sure we skip the selected summary entries */ -void process_selected_dives(void) -{ - struct dive *dive; - unsigned int i, nr; - - memset(&stats_selection, 0, sizeof(stats_selection)); - - nr = 0; - for_each_dive(i, dive) { - if (dive->selected) { - process_dive(dive, &stats_selection); - nr++; - } - } - stats_selection.selection_size = nr; -} - -char *get_time_string_s(int seconds, int maxdays, bool freediving) -{ - static char buf[80]; - if (maxdays && seconds > 3600 * 24 * maxdays) { - snprintf(buf, sizeof(buf), translate("gettextFromC", "more than %d days"), maxdays); - } else { - int days = seconds / 3600 / 24; - int hours = (seconds - days * 3600 * 24) / 3600; - int minutes = (seconds - days * 3600 * 24 - hours * 3600) / 60; - int secs = (seconds - days * 3600 * 24 - hours * 3600 - minutes*60); - if (days > 0) - snprintf(buf, sizeof(buf), translate("gettextFromC", "%dd %dh %dmin"), days, hours, minutes); - else - if (freediving && seconds < 3600) - snprintf(buf, sizeof(buf), translate("gettextFromC", "%dmin %dsecs"), minutes, secs); - else - snprintf(buf, sizeof(buf), translate("gettextFromC", "%dh %dmin"), hours, minutes); - } - return buf; -} - -/* this gets called when at least two but not all dives are selected */ -static void get_ranges(char *buffer, int size) -{ - int i, len; - int first = -1, last = -1; - struct dive *dive; - - snprintf(buffer, size, "%s", translate("gettextFromC", "for dives #")); - for_each_dive (i, dive) { - if (!dive->selected) - continue; - if (dive->number < 1) { - /* uhh - weird numbers - bail */ - snprintf(buffer, size, "%s", translate("gettextFromC", "for selected dives")); - return; - } - len = strlen(buffer); - if (last == -1) { - snprintf(buffer + len, size - len, "%d", dive->number); - first = last = dive->number; - } else { - if (dive->number == last + 1) { - last++; - continue; - } else { - if (first == last) - snprintf(buffer + len, size - len, ", %d", dive->number); - else if (first + 1 == last) - snprintf(buffer + len, size - len, ", %d, %d", last, dive->number); - else - snprintf(buffer + len, size - len, "-%d, %d", last, dive->number); - first = last = dive->number; - } - } - } - len = strlen(buffer); - if (first != last) { - if (first + 1 == last) - snprintf(buffer + len, size - len, ", %d", last); - else - snprintf(buffer + len, size - len, "-%d", last); - } -} - -void get_selected_dives_text(char *buffer, size_t size) -{ - if (amount_selected == 1) { - if (current_dive) - snprintf(buffer, size, translate("gettextFromC", "for dive #%d"), current_dive->number); - else - snprintf(buffer, size, "%s", translate("gettextFromC", "for selected dive")); - } else if (amount_selected == (unsigned int)dive_table.nr) { - snprintf(buffer, size, "%s", translate("gettextFromC", "for all dives")); - } else if (amount_selected == 0) { - snprintf(buffer, size, "%s", translate("gettextFromC", "(no dives)")); - } else { - get_ranges(buffer, size); - if (strlen(buffer) == size - 1) { - /* add our own ellipse... the way Pango does this is ugly - * as it will leave partial numbers there which I don't like */ - size_t offset = 4; - while (offset < size && isdigit(buffer[size - offset])) - offset++; - strcpy(buffer + size - offset, "..."); - } - } -} - -#define SOME_GAS 5000 // 5bar drop in cylinder pressure makes cylinder used - -bool is_cylinder_used(struct dive *dive, int idx) -{ - struct divecomputer *dc; - bool firstGasExplicit = false; - if (cylinder_none(&dive->cylinder[idx])) - return false; - - if ((dive->cylinder[idx].start.mbar - dive->cylinder[idx].end.mbar) > SOME_GAS) - return true; - for_each_dc(dive, dc) { - struct event *event = get_next_event(dc->events, "gaschange"); - while (event) { - if (dc->sample && (event->time.seconds == 0 || - (dc->samples && dc->sample[0].time.seconds == event->time.seconds))) - firstGasExplicit = true; - if (get_cylinder_index(dive, event) == idx) - return true; - event = get_next_event(event->next, "gaschange"); - } - if (dc->divemode == CCR && (idx == dive->diluent_cylinder_index || idx == dive->oxygen_cylinder_index)) - return true; - } - if (idx == 0 && !firstGasExplicit) - return true; - return false; -} - -void get_gas_used(struct dive *dive, volume_t gases[MAX_CYLINDERS]) -{ - int idx; - for (idx = 0; idx < MAX_CYLINDERS; idx++) { - cylinder_t *cyl = &dive->cylinder[idx]; - pressure_t start, end; - - if (!is_cylinder_used(dive, idx)) - continue; - - start = cyl->start.mbar ? cyl->start : cyl->sample_start; - end = cyl->end.mbar ? cyl->end : cyl->sample_end; - if (end.mbar && start.mbar > end.mbar) - gases[idx].mliter = gas_volume(cyl, start) - gas_volume(cyl, end); - } -} - -/* Quite crude reverse-blender-function, but it produces a approx result */ -static void get_gas_parts(struct gasmix mix, volume_t vol, int o2_in_topup, volume_t *o2, volume_t *he) -{ - volume_t air = {}; - - if (gasmix_is_air(&mix)) { - o2->mliter = 0; - he->mliter = 0; - return; - } - - air.mliter = rint(((double)vol.mliter * (1000 - get_he(&mix) - get_o2(&mix))) / (1000 - o2_in_topup)); - he->mliter = rint(((double)vol.mliter * get_he(&mix)) / 1000.0); - o2->mliter += vol.mliter - he->mliter - air.mliter; -} - -void selected_dives_gas_parts(volume_t *o2_tot, volume_t *he_tot) -{ - int i, j; - struct dive *d; - for_each_dive (i, d) { - if (!d->selected) - continue; - volume_t diveGases[MAX_CYLINDERS] = {}; - get_gas_used(d, diveGases); - for (j = 0; j < MAX_CYLINDERS; j++) { - if (diveGases[j].mliter) { - volume_t o2 = {}, he = {}; - get_gas_parts(d->cylinder[j].gasmix, diveGases[j], O2_IN_AIR, &o2, &he); - o2_tot->mliter += o2.mliter; - he_tot->mliter += he.mliter; - } - } - } -} |