From: Andre Noll <maan@tuebingen.mpg.de>
Date: Sun, 20 Mar 2022 18:22:29 +0000 (+0100)
Subject: mood.c: Move struct statistics into struct mood.
X-Git-Tag: v0.7.2~14^2~14
X-Git-Url: https://git.tuebingen.mpg.de/?a=commitdiff_plain;h=c2245032a47304586180cb64bfa00dc6974467a7;p=paraslash.git

mood.c: Move struct statistics into struct mood.

Because it's part of the state of an open mood. Expand and improve
the documentation of struct mood and current_mood while at it, and
kill the pointless return value of update_afs_statistics().
---

diff --git a/mood.c b/mood.c
index a2c3d099..39871343 100644
--- a/mood.c
+++ b/mood.c
@@ -47,18 +47,27 @@ struct afs_statistics {
 	/** Number of admissible files */
 	unsigned num;
 };
-static struct afs_statistics statistics = {.normalization_divisor = 1};
 
+/**
+ * Stores an instance of an open mood (parser and statistics).
+ *
+ * A structure of this type is allocated and initialized at mood open time.
+ */
 struct mood {
-	/** The name of this mood. */
+	/** NULL means that this is the "dummy" mood. */
 	char *name;
-	/** Info for the bison parser. */
+	/** Bison's abstract syntax tree, used to determine admissibility. */
 	struct mp_context *parser_context;
+	/** To compute the score. */
+	struct afs_statistics stats;
 };
 
 /*
  * If current_mood is NULL then no mood is currently open. If
  * current_mood->name is NULL, the dummy mood is currently open.
+ *
+ * The statistics are adjusted dynamically through this pointer as files are
+ * added, removed or played.
  */
 static struct mood *current_mood;
 
@@ -133,6 +142,7 @@ static struct mood *alloc_new_mood(const char *name)
 	struct mood *m = zalloc(sizeof(struct mood));
 	if (name)
 		m->name = para_strdup(name);
+	m->stats.normalization_divisor = 1;
 	return m;
 }
 
@@ -250,10 +260,11 @@ static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd)
 
 static long compute_score(struct afs_info *afsi)
 {
-	long score = -normalized_value(afsi->num_played, statistics.num,
-		statistics.num_played_sum, statistics.num_played_qd);
-	score -= normalized_value(afsi->last_played, statistics.num,
-		statistics.last_played_sum, statistics.last_played_qd);
+	const struct afs_statistics *stats = &current_mood->stats;
+	long score = -normalized_value(afsi->num_played, stats->num,
+		stats->num_played_sum, stats->num_played_qd);
+	score -= normalized_value(afsi->last_played, stats->num,
+		stats->last_played_sum, stats->last_played_qd);
 	return score / 2;
 }
 
@@ -262,63 +273,65 @@ static int add_afs_statistics(const struct osl_row *row)
 	uint64_t n, x, s, q;
 	struct afs_info afsi;
 	int ret;
+	struct afs_statistics *stats = &current_mood->stats;
 
 	ret = get_afsi_of_row(row, &afsi);
 	if (ret < 0)
 		return ret;
-	n = statistics.num;
+	n = stats->num;
 	x = afsi.last_played;
-	s = statistics.last_played_sum;
+	s = stats->last_played_sum;
 	if (n > 0) {
 		q = (x > s / n)? x - s / n : s / n - x;
-		statistics.last_played_qd += q * q * n / (n + 1);
+		stats->last_played_qd += q * q * n / (n + 1);
 	}
-	statistics.last_played_sum += x;
+	stats->last_played_sum += x;
 
 	x = afsi.num_played;
-	s = statistics.num_played_sum;
+	s = stats->num_played_sum;
 	if (n > 0) {
 		q = (x > s / n)? x - s / n : s / n - x;
-		statistics.num_played_qd += q * q * n / (n + 1);
+		stats->num_played_qd += q * q * n / (n + 1);
 	}
-	statistics.num_played_sum += x;
-	statistics.num++;
+	stats->num_played_sum += x;
+	stats->num++;
 	return 1;
 }
 
 static int del_afs_statistics(const struct osl_row *row)
 {
+	struct afs_statistics *stats = &current_mood->stats;
 	uint64_t n, s, q, a, new_s;
 	struct afs_info afsi;
 	int ret;
 	ret = get_afsi_of_row(row, &afsi);
 	if (ret < 0)
 		return ret;
-	n = statistics.num;
+	n = stats->num;
 	assert(n);
 	if (n == 1) {
-		memset(&statistics, 0, sizeof(statistics));
-		statistics.normalization_divisor = 1;
+		memset(stats, 0, sizeof(*stats));
+		stats->normalization_divisor = 1;
 		return 1;
 	}
 
-	s = statistics.last_played_sum;
-	q = statistics.last_played_qd;
+	s = stats->last_played_sum;
+	q = stats->last_played_qd;
 	a = afsi.last_played;
 	new_s = s - a;
-	statistics.last_played_sum = new_s;
-	statistics.last_played_qd = q + s * s / n - a * a
+	stats->last_played_sum = new_s;
+	stats->last_played_qd = q + s * s / n - a * a
 		- new_s * new_s / (n - 1);
 
-	s = statistics.num_played_sum;
-	q = statistics.num_played_qd;
+	s = stats->num_played_sum;
+	q = stats->num_played_qd;
 	a = afsi.num_played;
 	new_s = s - a;
-	statistics.num_played_sum = new_s;
-	statistics.num_played_qd = q + s * s / n - a * a
+	stats->num_played_sum = new_s;
+	stats->num_played_qd = q + s * s / n - a * a
 		- new_s * new_s / (n - 1);
 
-	statistics.num--;
+	stats->num--;
 	return 1;
 }
 
@@ -346,17 +359,18 @@ struct admissible_array {
  */
 static int add_if_admissible(struct osl_row *aft_row, void *data)
 {
+	const struct afs_statistics *stats = &current_mood->stats;
 	struct admissible_array *aa = data;
 
 	if (!mp_eval_row(aft_row, aa->m->parser_context))
 		return 0;
-	if (statistics.num >= aa->size) {
+	if (stats->num >= aa->size) {
 		aa->size *= 2;
 		aa->size += 100;
 		aa->array = arr_realloc(aa->array, aa->size,
 			sizeof(struct osl_row *));
 	}
-	aa->array[statistics.num] = aft_row;
+	aa->array[stats->num] = aft_row;
 	return add_afs_statistics(aft_row);
 }
 
@@ -402,22 +416,21 @@ _static_inline_ int64_t update_quadratic_deviation(int64_t n, int64_t old_qd,
 	return old_qd + delta * (sigma - 2 * old_sum / n - delta / n);
 }
 
-static int update_afs_statistics(struct afs_info *old_afsi,
+static void update_afs_statistics(struct afs_info *old_afsi,
 		struct afs_info *new_afsi)
 {
-	unsigned n = statistics.num;
-	assert(n);
-
-	statistics.last_played_qd = update_quadratic_deviation(n,
-		statistics.last_played_qd, old_afsi->last_played,
-		new_afsi->last_played, statistics.last_played_sum);
-	statistics.last_played_sum += new_afsi->last_played - old_afsi->last_played;
-
-	statistics.num_played_qd = update_quadratic_deviation(n,
-		statistics.num_played_qd, old_afsi->num_played,
-		new_afsi->num_played, statistics.num_played_sum);
-	statistics.num_played_sum += new_afsi->num_played - old_afsi->num_played;
-	return 1;
+	struct afs_statistics *stats = &current_mood->stats;
+
+	assert(stats->num > 0);
+	stats->last_played_qd = update_quadratic_deviation(stats->num,
+		stats->last_played_qd, old_afsi->last_played,
+		new_afsi->last_played, stats->last_played_sum);
+	stats->last_played_sum += new_afsi->last_played - old_afsi->last_played;
+
+	stats->num_played_qd = update_quadratic_deviation(stats->num,
+		stats->num_played_qd, old_afsi->num_played,
+		new_afsi->num_played, stats->num_played_sum);
+	stats->num_played_sum += new_afsi->num_played - old_afsi->num_played;
 }
 
 static int add_to_score_table(const struct osl_row *aft_row)
@@ -502,11 +515,8 @@ static int mood_update_audio_file(const struct osl_row *aft_row,
 	ret = get_afsi_of_row(aft_row, &afsi);
 	if (ret < 0)
 		return ret;
-	if (old_afsi) {
-		ret = update_afs_statistics(old_afsi, &afsi);
-		if (ret < 0)
-			return ret;
-	}
+	if (old_afsi)
+		update_afs_statistics(old_afsi, &afsi);
 	score = compute_score(&afsi);
 	PARA_DEBUG_LOG("score: %li\n", score);
 	percent = (score + 100) / 3;
@@ -521,7 +531,8 @@ static int mood_update_audio_file(const struct osl_row *aft_row,
 /* sse: seconds since epoch. */
 static void log_statistics(int64_t sse)
 {
-	unsigned n = statistics.num;
+	const struct afs_statistics *stats = &current_mood->stats;
+	unsigned n = stats->num;
 	int mean_days, sigma_days;
 
 	assert(current_mood);
@@ -531,19 +542,19 @@ static void log_statistics(int64_t sse)
 		PARA_WARNING_LOG("no admissible files\n");
 		return;
 	}
-	PARA_NOTICE_LOG("%u admissible files\n", statistics.num);
-	mean_days = (sse - statistics.last_played_sum / n) / 3600 / 24;
-	sigma_days = int_sqrt(statistics.last_played_qd / n) / 3600 / 24;
+	PARA_NOTICE_LOG("%u admissible files\n", stats->num);
+	mean_days = (sse - stats->last_played_sum / n) / 3600 / 24;
+	sigma_days = int_sqrt(stats->last_played_qd / n) / 3600 / 24;
 	PARA_NOTICE_LOG("last_played mean/sigma: %d/%d days\n", mean_days, sigma_days);
 	PARA_NOTICE_LOG("num_played mean/sigma: %" PRId64 "/%" PRIu64 "\n",
-		statistics.num_played_sum / n,
-		int_sqrt(statistics.num_played_qd / n));
+		stats->num_played_sum / n,
+		int_sqrt(stats->num_played_qd / n));
 	PARA_NOTICE_LOG("num_played correction factor: %" PRId64 "\n",
-		statistics.num_played_correction);
+		stats->num_played_correction);
 	PARA_NOTICE_LOG("last_played correction factor: %" PRId64 "\n",
-		statistics.last_played_correction);
+		stats->last_played_correction);
 	PARA_NOTICE_LOG("normalization divisor: %" PRId64 "\n",
-		statistics.normalization_divisor);
+		stats->normalization_divisor);
 }
 
 /**
@@ -555,13 +566,11 @@ void close_current_mood(void)
 {
 	destroy_mood(current_mood);
 	current_mood = NULL;
-	memset(&statistics, 0, sizeof(statistics));
-	statistics.normalization_divisor = 1;
 }
 
 static void compute_correction_factors(int64_t sse)
 {
-	struct afs_statistics *s = &statistics;
+	struct afs_statistics *s = &current_mood->stats;
 
 	if (s->num > 0) {
 		s->normalization_divisor = int_sqrt(s->last_played_qd)
@@ -646,7 +655,7 @@ int change_current_mood(const char *mood_name, char **errmsg)
 	clock_get_realtime(&rnow);
 	compute_correction_factors(rnow.tv_sec);
 	log_statistics(rnow.tv_sec);
-	for (i = 0; i < statistics.num; i++) {
+	for (i = 0; i < current_mood->stats.num; i++) {
 		ret = add_to_score_table(aa.array[i]);
 		if (ret < 0) {
 			if (errmsg)
@@ -655,7 +664,7 @@ int change_current_mood(const char *mood_name, char **errmsg)
 			goto out;
 		}
 	}
-	ret = statistics.num;
+	ret = current_mood->stats.num;
 out:
 	free(aa.array);
 	if (ret < 0)