Pianod/X Music Selection Biasing
================================

When playing music from Pianod-managed sources, Pianod can bias selection.  Biasing factors include:
- Rating (average user rating for authenticated users)
- Time since last played

Biasing factors do not include:
- Play count.  Including this factor cold counter-influence with time since last played.

When selecting items for the random queue, Pianod will calculate a biasing factor for each song among those currently in play, and sum up those biasing factors, T.  Each song will receive a discrete, non-overlapping floating-point bias range in [0, T).  It will then select songs by:

	random_bias = fmod ((double) random(), T)

Pianod will then locate the song to which that applies and queue it.

The bias for a track is calculated:

	track_bias = rating_bias * aging_bias

The biasing will be adjustable.  `User_bias` will be a setting as presented to users, a number in the range 0–100, from which a `scale` factor will be calculated:

	scale = (0.09 * user_bias) + 1

Alternately, for the range 1–100:

	scale = (user_bias + 10) / 11

However, 0–100 seems sane, as 0 = no influence.  The scale factor is then used in the calculation of both `rating bias` and `aging bias`, which will have independent settings.

Rating Bias
-----------
User ratings are stored as an enum, with values 1 - 10 as valid ratings (higher = better; value÷2 = “star rating”).  Pianod will average these values floating-point to compute a song rating.  Rating bias for the song can then be calculated:

	rating_bias = scale^((rating - neutral) ÷ (maximum - neutral))

Where `neutral` is 6, the neutral rating, and `maximum` is 10, the maximum rating.

Aging Bias
----------
Pianod records time of last play.  To appropriately bias aging, Pianod will use last play to calculate an `average age`, in seconds; songs that have never been played will be ignored for average calculation.

The aging bias can then be calculated:

	aging_bias = scale^log10(min(10, song_age÷average_age))

To limit excess bias, pianod will limit song_age ÷ average_age to 10.  Songs that have not been played will be assigned this limit.

Performance
-----------
Both rating and aging biases produce:

	0 < bias ≤ 10

One-star ratings (enum value 2) at maximum bias (user setting 100) will provide 1/10 risk of play, whereas rating 10 will be preferenced 10x over neutral songs.  Neutral songs provide unity (1) bias at all bias settings.  Behavior is linear with the user setting for good ratings, but less so for low values.  Rating 2 reduces play likelihood less than rating 10 increases, whereas rating 1 reduces likelihood more than rating 10 increases, achieving 1/20 at maximum bias.  This seems sufficient and sane.

For aging, with maximum bias old songs are 10 times more likely to be chosen over the average.  Recently played asymptotically approaches 0 probability; the average produces unity bias.

The combined effect is up to 100x (or 1/200 reduction) likelihood a song will play.  These seem high on the surface, but reflecting these are a much-liked song that hasn’t played in a very long time, and a much-disliked song that has just played, these again seem sane.

