def _update_ranking(self, locked=False): benchmark = Benchmark() if not locked: self.acquire() seed_track = None if self._lastplayed_track: seed_track = self._lastplayed_track elif self._playing_track: seed_track = self._playing_track if not self._relation_resetted: benchmark.start() self._relation_resetted = True for track in TrackFactory.active_tracks(): track.relation_old = track.relation track.relation_sum = 0.0 track.relation_cnt = 0 for artist in ArtistFactory.active_artists(): artist.relation_old = artist.relation artist.relation_sum = 0.0 artist.relation_cnt = 0 self._logger.info(u"update ranking: resetting took %s" % benchmark) has_active_tracks = False for track in TrackFactory.active_tracks(): has_active_tracks = True break benchmark.start() # new relation = old relation * decay # e.g. for decay = 0.5 (0.75) # decfacA = 0.5 * 0.5 = 0.25 (0.75 * 0.5 = 0.375) # decfacB = 1.0 - 0.5 = 0.5 (1.0 - 0.75 = 0.25) # relation_old=0.75 -> 0.25+0.5*0.75=0.625 (0.375+0.25*0.75=0.5625) decfacA = self._relation_decay * 0.5 decfacB = 1.0 - self._relation_decay for track in TrackFactory.active_tracks(): if (track.relation_old > 0.501) or (track.relation_old < 0.499): track.relation = (decfacA + decfacB * track.relation_old) else: track.relation = 0.5 for artist in ArtistFactory.active_artists(): if (artist.relation_old > 0.501) or (artist.relation_old < 0.499): artist.relation = (decfacA + decfacB * artist.relation_old) else: artist.relation = 0.5 self._logger.info(u"update ranking: set old relation + decay took %s" % benchmark) if has_active_tracks: self._ranking_updated = True self.seed(seed_track, True) benchmark.start() at = [] tt = [] for track in TrackFactory.active_tracks(): """ so we have: ranking [0-1.0] (old) rating [0-1.0] relation [0-1.0] random [0-1.0] and: factor min(track_lastplayed/started,artist_lastplayed/started) [0-1.0] ? moved to next_file() """ artist = track.artist r = random() # calculate new ranking if track.boost: self._logger.info(u"pre boost: %s" % track) track.relation = (track.relation + 99.0) / 100.0 self._logger.info(u"post boost: %s" % track) elif track.ban: track.relation = 0.0 # mix with artist relation if we don't have a track relation if track.relation_cnt == 0: if artist.relation_cnt > 0: track.relation = (0.75 * track.relation + 0.25 * artist.relation) top_ten(at, u'relation cnt = {} with {} now {} to {}'.format( artist.relation_cnt, scale_rating(artist.relation), scale_rating(track.relation), artist), track.relation) else: top_ten(tt, u'relation cnt = {} with {} to {}'.format( track.relation_cnt, scale_rating(track.relation), track), track.relation) track.ranking = ( self._factor_ranking['rating'] * track.get_rating() + self._factor_ranking['relation'] * track.relation + self._factor_ranking['random'] * r ) self._logger.info(u"update ranking: took %s" % benchmark) self._update_queued = False if not locked: self.release()
def seed(self, track, locked=False): """Calculate relations based on track as seed. """ if not locked: self.acquire() benchmark = Benchmark() timestamp = now() seed_track = set() seed_artist = set() if track: seed_track.add(track) seed_artist.add(track.artist) self.lookup(track, True) # check artist relations cnt = 0 benchmark.start() tt = [] for seed_a in seed_artist.union(self._seed_artists): self._logger.info(u'check artist relations for {}'.format(seed_a)) for artist_relation in ArtistRelationFactory.by_artist(seed_a): cnt += 1 other_artist = artist_relation.artistA if artist_relation.artistA.name == seed_a.name: other_artist = artist_relation.artistB other_artist.relation_sum += artist_relation.rating other_artist.relation_cnt += 1 other_artist.relation = (other_artist.relation_sum / other_artist.relation_cnt) top_ten(tt, u'artist related with {}({}/{}={}) to {}'.format( scale_rating(artist_relation.rating), scale_rating(other_artist.relation_sum), scale_rating(other_artist.relation_cnt), scale_rating(other_artist.relation), other_artist), artist_relation.rating) artist_relation.lastused = timestamp top_ten_dump(tt, self._logger.info) self._logger.info(u"update ranking: check artist took %s" % benchmark) self._logger.info(u"updated %d artist(s)" % cnt) cnt = 0 benchmark.start() tt = [] for seed_t in seed_track.union(self._seed_tracks): self._logger.info(u'check track relations for {}'.format(seed_t)) for track_relation in TrackRelationFactory.by_track(seed_t): other_track = track_relation.trackA if track_relation.trackA.title == seed_t.title and \ track_relation.trackA.artist.name == seed_t.artist.name: other_track = track_relation.trackB cnt += 1 if not track.ban: other_track.relation_sum += track_relation.rating other_track.relation_cnt += 1 other_track.relation = (other_track.relation_sum / other_track.relation_cnt) top_ten(tt, u'track related with {} to {}'.format( scale_rating(track_relation.rating), other_track), track_relation.rating) track_relation.lastused = timestamp top_ten_dump(tt, self._logger.info) self._logger.info(u"update ranking: check track took %s" % benchmark) self._logger.info(u"updated %d track(s)" % cnt) if not locked: self.release()