[PATCH] Show statistics of selected dives

Dirk Hohndel dirk at hohndel.org
Thu Mar 15 10:45:19 PDT 2012


MUCH better. My only question is "why do we need the new .h file for
just that one function?"
We have other functions in dive.h. So either put process_selected_dives
in there as well - or put them ALL into statistics.h

I guess I could have fixed that up myself, couldn't I? :-)

/D


On Wed, 14 Mar 2012 19:01:34 +0200, Miika Turkia <miika.turkia at gmail.com> wrote:
> If at least 2 dives are selected, show statistics of these dives on
> Overall Stats. Otherwise, show the statistics of all dives. Temperature
> is also added to the shown statistics.
> 
> Signed-off-by: Miika Turkia <miika.turkia at gmail.com>
> ---
>  Makefile     |    4 +-
>  divelist.c   |    5 ++
>  statistics.c |  144 ++++++++++++++++++++++++++++++++++++++++++++--------------
>  statistics.h |    6 ++
>  4 files changed, 122 insertions(+), 37 deletions(-)
>  create mode 100644 statistics.h
> 
> diff --git a/Makefile b/Makefile
> index 20dff4c..19fccfc 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -179,10 +179,10 @@ info.o: info.c dive.h display.h display-gtk.h divelist.h
>  equipment.o: equipment.c dive.h display.h divelist.h
>  	$(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c equipment.c
>  
> -statistics.o: statistics.c dive.h display.h divelist.h
> +statistics.o: statistics.c dive.h display.h divelist.h statistics.h
>  	$(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c statistics.c
>  
> -divelist.o: divelist.c dive.h display.h divelist.h
> +divelist.o: divelist.c dive.h display.h divelist.h statistics.h
>  	$(CC) $(CFLAGS) $(GTK2CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c divelist.c
>  
>  print.o: print.c dive.h display.h display-gtk.h
> diff --git a/divelist.c b/divelist.c
> index b9388f8..2083cf4 100644
> --- a/divelist.c
> +++ b/divelist.c
> @@ -20,6 +20,7 @@
>  #include "dive.h"
>  #include "display.h"
>  #include "display-gtk.h"
> +#include "statistics.h"
>  
>  struct DiveList {
>  	GtkWidget    *tree_view;
> @@ -73,6 +74,7 @@ static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
>  		return;
>  	case 1:	
>  		/* just pick that dive as selected */
> +		amount_selected = 1;
>  		path = g_list_nth_data(selected_dives, 0);
>  		if (gtk_tree_model_get_iter(model, &iter, path)) {
>  			gtk_tree_model_get_value(model, &iter, DIVE_INDEX, &value);
> @@ -86,6 +88,9 @@ static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
>  		  * is the most intuitive solution.
>  		  * I do however want to keep around which dives have
>  		  * been selected */
> +		amount_selected = g_list_length(selected_dives);
> +		process_selected_dives(selected_dives, model);
> +		repaint_dive();
>  		return;
>  	}
>  }
> diff --git a/statistics.c b/statistics.c
> index 2669d53..9277aa5 100644
> --- a/statistics.c
> +++ b/statistics.c
> @@ -18,6 +18,7 @@
>  #include "display.h"
>  #include "display-gtk.h"
>  #include "divelist.h"
> +#include "statistics.h"
>  
>  typedef struct {
>  	GtkWidget *date,
> @@ -44,7 +45,11 @@ typedef struct {
>  		*avg_overall_depth,
>  		*min_sac,
>  		*avg_sac,
> -		*max_sac;
> +		*max_sac,
> +		*selection_size,
> +		*max_temp,
> +		*avg_temp,
> +		*min_temp;
>  } total_stats_widget_t;
>  
>  static total_stats_widget_t stats_w;
> @@ -60,21 +65,65 @@ typedef struct {
>  	volume_t max_sac;
>  	volume_t min_sac;
>  	volume_t avg_sac;
> +	int max_temp;
> +	int min_temp;
> +	unsigned int combined_temp;
> +	unsigned int combined_count;
> +	unsigned int selection_size;
>  } stats_t;
>  
>  static stats_t stats;
> +static stats_t stats_selection;
> +
> +
> +static void process_dive(struct dive *dp, stats_t *stats)
> +{
> +	int old_tt, sac_time = 0;
> +	const char *unit;
> +
> +	old_tt = stats->total_time.seconds;
> +	stats->total_time.seconds += dp->duration.seconds;
> +	if (dp->duration.seconds > stats->longest_time.seconds)
> +		stats->longest_time.seconds = dp->duration.seconds;
> +	if (stats->shortest_time.seconds == 0 || dp->duration.seconds < stats->shortest_time.seconds)
> +		stats->shortest_time.seconds = dp->duration.seconds;
> +	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;
> +	stats->avg_depth.mm = (1.0 * old_tt * stats->avg_depth.mm +
> +			dp->duration.seconds * dp->meandepth.mm) / stats->total_time.seconds;
> +	if (dp->sac > 2800) { /* less than .1 cuft/min (2800ml/min) is bogus */
> +		int old_sac_time = sac_time;
> +		sac_time += dp->duration.seconds;
> +		stats->avg_sac.mliter = (1.0 * old_sac_time * stats->avg_sac.mliter +
> +				dp->duration.seconds * 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;
> +	}
> +	if (dp->watertemp.mkelvin) {
> +		if (stats->min_temp == 0 || dp->watertemp.mkelvin < stats->min_temp)
> +			stats->min_temp = dp->watertemp.mkelvin;
> +		if (dp->watertemp.mkelvin > stats->max_temp)
> +			stats->max_temp = dp->watertemp.mkelvin;
> +		stats->combined_temp += get_temp_units(dp->watertemp.mkelvin, &unit);
> +		stats->combined_count++;
> +	}
> +}
>  
>  static void process_all_dives(struct dive *dive, struct dive **prev_dive)
>  {
>  	int idx;
>  	struct dive *dp;
> -	int old_tt, sac_time = 0;
>  
>  	*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;
>  	}
>  	/* this relies on the fact that the dives in the dive_table
>  	 * are in chronological order */
> @@ -85,28 +134,28 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
>  			if (idx > 0)
>  				*prev_dive = dive_table.dives[idx-1];
>  		}
> -		old_tt = stats.total_time.seconds;
> -		stats.total_time.seconds += dp->duration.seconds;
> -		if (dp->duration.seconds > stats.longest_time.seconds)
> -			stats.longest_time.seconds = dp->duration.seconds;
> -		if (dp->duration.seconds < stats.shortest_time.seconds)
> -			stats.shortest_time.seconds = dp->duration.seconds;
> -		if (dp->maxdepth.mm > stats.max_depth.mm)
> -			stats.max_depth.mm = dp->maxdepth.mm;
> -		if (dp->maxdepth.mm < stats.min_depth.mm)
> -			stats.min_depth.mm = dp->maxdepth.mm;
> -		stats.avg_depth.mm = (1.0 * old_tt * stats.avg_depth.mm +
> -				dp->duration.seconds * dp->meandepth.mm) / stats.total_time.seconds;
> -		if (dp->sac > 2800) { /* less than .1 cuft/min (2800ml/min) is bogus */
> -			int old_sac_time = sac_time;
> -			sac_time += dp->duration.seconds;
> -			stats.avg_sac.mliter = (1.0 * old_sac_time * stats.avg_sac.mliter +
> -						dp->duration.seconds * 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;
> +		process_dive(dp, &stats);
> +	}
> +}
> +
> +void process_selected_dives(GList *selected_dives, GtkTreeModel *model)
> +{
> +	struct dive *dp;
> +	unsigned int i;
> +	GtkTreeIter iter;
> +	GtkTreePath *path;
> +
> +	memset(&stats_selection, 0, sizeof(stats_selection));
> +	stats_selection.selection_size = amount_selected;
> +
> +	for (i = 0; i < amount_selected; ++i) {
> +		GValue value = {0, };
> +		path = g_list_nth_data(selected_dives, i);
> +		if (gtk_tree_model_get_iter(model, &iter, path)) {
> +			gtk_tree_model_get_value(model, &iter, 0, &value);
> +			dp = get_dive(g_value_get_int(&value));
>  		}
> +		process_dive(dp, &stats_selection);
>  	}
>  }
>  
> @@ -219,22 +268,39 @@ static void show_total_dive_stats(struct dive *dive)
>  	double value;
>  	int decimals;
>  	const char *unit;
> +	stats_t *stats_ptr;
> +
> +	if (amount_selected < 2)
> +		stats_ptr = &stats;
> +	else
> +		stats_ptr = &stats_selection;
>  
> -	set_label(stats_w.total_time, get_time_string(stats.total_time.seconds, 0));
> -	set_label(stats_w.avg_time, get_time_string(stats.total_time.seconds / dive_table.nr, 0));
> -	set_label(stats_w.longest_time, get_time_string(stats.longest_time.seconds, 0));
> -	set_label(stats_w.shortest_time, get_time_string(stats.shortest_time.seconds, 0));
> -	value = get_depth_units(stats.max_depth.mm, &decimals, &unit);
> +	set_label(stats_w.selection_size, "%d", stats_ptr->selection_size);
> +	if (stats_ptr->min_temp) {
> +		value = get_temp_units(stats_ptr->min_temp, &unit);
> +		set_label(stats_w.min_temp, "%.1f %s", value, unit);
> +	}
> +	if (stats_ptr->combined_temp && stats_ptr->combined_count)
> +		set_label(stats_w.avg_temp, "%.1f %s", stats_ptr->combined_temp / (stats_ptr->combined_count * 1.0), unit);
> +	if (stats_ptr->max_temp) {
> +		value = get_temp_units(stats_ptr->max_temp, &unit);
> +		set_label(stats_w.max_temp, "%.1f %s", value, unit);
> +	}
> +	set_label(stats_w.total_time, get_time_string(stats_ptr->total_time.seconds, 0));
> +	set_label(stats_w.avg_time, get_time_string(stats_ptr->total_time.seconds / stats_ptr->selection_size, 0));
> +	set_label(stats_w.longest_time, get_time_string(stats_ptr->longest_time.seconds, 0));
> +	set_label(stats_w.shortest_time, get_time_string(stats_ptr->shortest_time.seconds, 0));
> +	value = get_depth_units(stats_ptr->max_depth.mm, &decimals, &unit);
>  	set_label(stats_w.max_overall_depth, "%.*f %s", decimals, value, unit);
> -	value = get_depth_units(stats.min_depth.mm, &decimals, &unit);
> +	value = get_depth_units(stats_ptr->min_depth.mm, &decimals, &unit);
>  	set_label(stats_w.min_overall_depth, "%.*f %s", decimals, value, unit);
> -	value = get_depth_units(stats.avg_depth.mm, &decimals, &unit);
> +	value = get_depth_units(stats_ptr->avg_depth.mm, &decimals, &unit);
>  	set_label(stats_w.avg_overall_depth, "%.*f %s", decimals, value, unit);
> -	value = get_volume_units(stats.max_sac.mliter, &decimals, &unit);
> +	value = get_volume_units(stats_ptr->max_sac.mliter, &decimals, &unit);
>  	set_label(stats_w.max_sac, "%.*f %s/min", decimals, value, unit);
> -	value = get_volume_units(stats.min_sac.mliter, &decimals, &unit);
> +	value = get_volume_units(stats_ptr->min_sac.mliter, &decimals, &unit);
>  	set_label(stats_w.min_sac, "%.*f %s/min", decimals, value, unit);
> -	value = get_volume_units(stats.avg_sac.mliter, &decimals, &unit);
> +	value = get_volume_units(stats_ptr->avg_sac.mliter, &decimals, &unit);
>  	set_label(stats_w.avg_sac, "%.*f %s/min", decimals, value, unit);
>  }
>  
> @@ -278,13 +344,21 @@ GtkWidget *total_stats_widget(void)
>  	/* first row */
>  	hbox = gtk_hbox_new(FALSE, 3);
>  	gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
> +	stats_w.selection_size = new_info_label_in_frame(hbox, "Dives");
> +	stats_w.max_temp = new_info_label_in_frame(hbox, "Max Temp");
> +	stats_w.min_temp = new_info_label_in_frame(hbox, "Min Temp");
> +	stats_w.avg_temp = new_info_label_in_frame(hbox, "Avg Temp");
> +
> +	/* second row */
> +	hbox = gtk_hbox_new(FALSE, 3);
> +	gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
>  
>  	stats_w.total_time = new_info_label_in_frame(hbox, "Total Time");
>  	stats_w.avg_time = new_info_label_in_frame(hbox, "Avg Time");
>  	stats_w.longest_time = new_info_label_in_frame(hbox, "Longest Dive");
>  	stats_w.shortest_time = new_info_label_in_frame(hbox, "Shortest Dive");
>  
> -	/* second row */
> +	/* third row */
>  	hbox = gtk_hbox_new(FALSE, 3);
>  	gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
>  
> @@ -292,7 +366,7 @@ GtkWidget *total_stats_widget(void)
>  	stats_w.min_overall_depth = new_info_label_in_frame(hbox, "Min Depth");
>  	stats_w.avg_overall_depth = new_info_label_in_frame(hbox, "Avg Depth");
>  
> -	/* third row */
> +	/* fourth row */
>  	hbox = gtk_hbox_new(FALSE, 3);
>  	gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
>  
> diff --git a/statistics.h b/statistics.h
> new file mode 100644
> index 0000000..1293224
> --- /dev/null
> +++ b/statistics.h
> @@ -0,0 +1,6 @@
> +#ifndef STATISTICS_H
> +#define STATISTICS_H
> +unsigned int amount_selected;
> +
> +extern void process_selected_dives(GList *, GtkTreeModel *);
> +#endif
> -- 
> 1.7.5.4
> 
> _______________________________________________
> subsurface mailing list
> subsurface at hohndel.org
> http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface

-- 
Dirk Hohndel
Intel Open Source Technology Center


More information about the subsurface mailing list