What happened to the depth being shown on profile?

Linus Torvalds torvalds at linux-foundation.org
Wed Apr 20 11:34:51 PDT 2016


On Wed, Apr 20, 2016 at 11:00 AM, Dirk Hohndel <dirk at hohndel.org> wrote:
>>
>> If it's just the min/max arrays, let me fix that for you. I'll make
>> them indices instead of pointers.
>
> That's it indeed. And your fix would be appreciated. Just make sure you
> also fix the "consumer" of this over in the profile widget code.

This ended up being a bit bigger than expected. When looking at that
code, I realized that the average was miscalculated (although it may
not be used anywhere any more), and I also ended up correcting and
adding comments.

I've not signed off on this, because I think somebody else needs to
take a look, but if you think it's ok, feel free to commit it and add
my sign-off. The changelog would be something like

  Fix 3-, 6- and 9-minute min/max calculations

  Make them use indices into the plot-info, fix calculation of average
depth, and fix and add comments.

Or something.

              Linus
-------------- next part --------------
 core/profile.c                     | 81 ++++++++++++++++++++++++--------------
 core/profile.h                     |  6 +--
 profile-widget/diveprofileitem.cpp | 10 +++--
 3 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/core/profile.c b/core/profile.c
index b4f7279a0a9f..7d72508a1a61 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -196,46 +196,69 @@ static int get_local_sac(struct plot_data *entry1, struct plot_data *entry2, str
 	return airuse / atm * 60 / duration;
 }
 
-static void analyze_plot_info_minmax_minute(struct plot_data *entry, struct plot_data *first, struct plot_data *last, int index)
+/*
+ * We do three min/max/avg calculations: over 3, 6 and 9 minutes
+ * around the entry point (indices 0, 1, 2 respectively).
+ */
+static void analyze_plot_info_minmax_minute(struct plot_info *pi, int entry, int index)
 {
-	struct plot_data *p = entry;
-	int time = entry->sec;
+	struct plot_data *plot_entry = pi->entry + entry;  // fixed
+	struct plot_data *p = plot_entry;  // moves with 'entry'
 	int seconds = 90 * (index + 1);
-	struct plot_data *min, *max;
-	int avg, nr;
+	int start = p->sec - seconds, end = p->sec + seconds;
+	int min, max;
+	int firsttime, lasttime, lastdepth;
+	int depth_time_2;
 
 	/* Go back 'seconds' in time */
-	while (p > first) {
-		if (p[-1].sec < time - seconds)
+	while (entry > 0) {
+		if (p[-1].sec < start)
 			break;
+		entry--;
 		p--;
 	}
 
+	// indexes to the min/max entries
+	min = max = entry;
+	// accumulated depth*time*2
+	depth_time_2 = 0;
+	firsttime = lasttime = p->sec;
+	lastdepth = p->depth;
+
 	/* Then go forward until we hit an entry past the time */
-	min = max = p;
-	avg = p->depth;
-	nr = 1;
-	while (++p < last) {
+	while (entry < pi->nr) {
+		int time = p->sec;
 		int depth = p->depth;
-		if (p->sec > time + seconds)
+
+		if (time > end)
 			break;
-		avg += depth;
-		nr++;
-		if (depth < min->depth)
-			min = p;
-		if (depth > max->depth)
-			max = p;
+
+		depth_time_2 += (time - lasttime) * (depth + lastdepth);
+		lasttime = time;
+		lastdepth = depth;
+
+		if (depth < pi->entry[min].depth)
+			min = entry;
+		if (depth > pi->entry[max].depth)
+			max = entry;
+
+		p++;
+		entry++;
 	}
-	entry->min[index] = min;
-	entry->max[index] = max;
-	entry->avg[index] = (avg + nr / 2) / nr;
+
+	plot_entry->min[index] = min;
+	plot_entry->max[index] = max;
+	if (firsttime == lasttime)
+		plot_entry->avg[index] = pi->entry[min].depth;
+	else
+		plot_entry->avg[index] = depth_time_2 / 2 / (lasttime - firsttime);
 }
 
-static void analyze_plot_info_minmax(struct plot_data *entry, struct plot_data *first, struct plot_data *last)
+static void analyze_plot_info_minmax(struct plot_info *pi, int entry)
 {
-	analyze_plot_info_minmax_minute(entry, first, last, 0);
-	analyze_plot_info_minmax_minute(entry, first, last, 1);
-	analyze_plot_info_minmax_minute(entry, first, last, 2);
+	analyze_plot_info_minmax_minute(pi, entry, 0);
+	analyze_plot_info_minmax_minute(pi, entry, 1);
+	analyze_plot_info_minmax_minute(pi, entry, 2);
 }
 
 static velocity_t velocity(int speed)
@@ -299,11 +322,9 @@ struct plot_info *analyze_plot_info(struct plot_info *pi)
 		}
 	}
 
-	/* One-, two- and three-minute minmax data */
-	for (i = 0; i < nr; i++) {
-		struct plot_data *entry = pi->entry + i;
-		analyze_plot_info_minmax(entry, pi->entry, pi->entry + nr);
-	}
+	/* 3, 6 and 9-minute minmax data */
+	for (i = 0; i < nr; i++)
+		analyze_plot_info_minmax(pi, i);
 
 	return pi;
 }
diff --git a/core/profile.h b/core/profile.h
index abac9dd490f0..21cc263b7373 100644
--- a/core/profile.h
+++ b/core/profile.h
@@ -50,9 +50,9 @@ struct plot_data {
 	double mod, ead, end, eadd;
 	velocity_t velocity;
 	int speed;
-	struct plot_data *min[3];
-	struct plot_data *max[3];
-	int avg[3];
+	// stats over 3, 6, 9 minute windows:
+	int min[3], max[3];	// indices into pi->entry[]
+	int avg[3];		// actual depth average
 	/* values calculated by us */
 	unsigned int in_deco_calc : 1;
 	int ndl_calc;
diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp
index d62c35f938c2..9ea90ea2f33b 100644
--- a/profile-widget/diveprofileitem.cpp
+++ b/profile-widget/diveprofileitem.cpp
@@ -225,17 +225,21 @@ void DiveProfileItem::modelDataChanged(const QModelIndex &topLeft, const QModelI
 
 	int last = -1;
 	for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
+		struct plot_data *pd = dataModel->data().entry;
+		struct plot_data *entry =  pd + i;
+		// "min/max[2]" are the 9-minute window min/max indices
+		struct plot_data *min_entry = pd + entry->min[2];
+		struct plot_data *max_entry = pd + entry->max[2];
 
-		struct plot_data *entry = dataModel->data().entry + i;
 		if (entry->depth < 2000)
 			continue;
 
-		if ((entry == entry->max[2]) && entry->depth / 100 != last) {
+		if ((entry == max_entry) && entry->depth / 100 != last) {
 			plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignBottom, getColor(SAMPLE_DEEP));
 			last = entry->depth / 100;
 		}
 
-		if ((entry == entry->min[2]) && entry->depth / 100 != last) {
+		if ((entry == min_entry) && entry->depth / 100 != last) {
 			plot_depth_sample(entry, Qt::AlignHCenter | Qt::AlignTop, getColor(SAMPLE_SHALLOW));
 			last = entry->depth / 100;
 		}


More information about the subsurface mailing list