autotag: Can now compute the distance for incomplete albums

If the user has some songs from a specific album, but not all of them,
the real solution is immediately discarded. This commit is the first of a
series that will implement support for these incomplete albums.

The point of this patch is to make sure missing commits are taken into
account when calculating the distance between an album and its canonical
data.

Note that in order not to break API compatibility, the album_distance
call for the plugins receives a purged version of both the items and the
album info, resulting in some potential accuracy if the plugin bases
itself on the index of a track in album_info.tracks.
This commit is contained in:
Simon Chopin 2011-11-22 12:25:10 +01:00
parent 78dca315d4
commit 4dc4025b5f
2 changed files with 36 additions and 5 deletions

View file

@ -17,6 +17,7 @@ releases and tracks.
"""
import logging
import re
import copy
from munkres import Munkres
from unidecode import unidecode
@ -31,6 +32,8 @@ ARTIST_WEIGHT = 3.0
ALBUM_WEIGHT = 3.0
# The weight of the entire distance calculated for a given track.
TRACK_WEIGHT = 1.0
# The weight of a missing track.
MISSING_WEIGHT = 0.3
# These distances are components of the track distance (that is, they
# compete against each other but not ARTIST_WEIGHT and ALBUM_WEIGHT;
# the overall TRACK_WEIGHT does that).
@ -161,7 +164,7 @@ def current_metadata(items):
likelies = {}
consensus = {}
for key in keys:
values = [getattr(item, key) for item in items]
values = [getattr(item, key) for item in items if item]
likelies[key], freq = plurality(values)
consensus[key] = (freq == len(values))
return likelies['artist'], likelies['album'], consensus['artist']
@ -269,12 +272,25 @@ def distance(items, album_info):
# Track distances.
for i, (item, track_info) in enumerate(zip(items, album_info.tracks)):
dist += track_distance(item, track_info, i+1, album_info.va) * \
TRACK_WEIGHT
dist_max += TRACK_WEIGHT
if item:
dist += track_distance(item, track_info, i+1, album_info.va) * \
TRACK_WEIGHT
dist_max += TRACK_WEIGHT
else:
dist += MISSING_WEIGHT
dist_max += MISSING_WEIGHT
# Plugin distances.
plugin_d, plugin_dm = plugins.album_distance(items, album_info)
# In order not to break compatibility, send purged lists
purged_items, purged_tracks = [], []
for i, t in zip(items, album_info.tracks):
if i:
purged_items.append(i)
purged_tracks.append(t)
purged_album_info = copy.copy(album_info)
purged_album_info.tracks = purged_tracks
plugin_d, plugin_dm = plugins.album_distance(purged_items, purged_album_info)
dist += plugin_d
dist_max += plugin_dm

View file

@ -94,6 +94,21 @@ class AlbumDistanceTest(unittest.TestCase):
)
self.assertEqual(match.distance(items, info), 0)
def test_incomplete_album(self):
items = []
items.append(self.item('one', 1))
items.append(self.item('three', 3))
info = AlbumInfo(
artist = 'some artist',
album = 'some album',
tracks = self.trackinfo(),
va = False,
album_id = None, artist_id = None,
)
self.assertNotEqual(match.distance(items, info), 0)
# Make sure the distance is not too great
self.assertTrue(match.distance(items, info) < 0.2)
def test_global_artists_differ(self):
items = []
items.append(self.item('one', 1))