from dataclasses import dataclass from .song import Song USER_SCORE_WEIGHT = 0.7 ARTIST_WEIGHT = 0.1 TAG_WEIGHT = 0.1 RANDOM_WEIGHT = 0.1 RECENT_PENALTY = 0.5 RECENT_COUNT = 10 type UserScoredSong = tuple[Song, int] @dataclass class Room: id: int coord: tuple[float, float] name: str pin: int | None tags: set[str] songs: dict[str, UserScoredSong] # canzoni + voto history: list[Song] # canzoni riprodotte (in ordine) playing: list[Song] # canzoni che sono i riproduzione def rank_song(self, song: Song, user_score: int) -> float: rank = 0.0 song_items = self.songs.items() lowest_score = min(song_items, key=lambda item: item[1][1])[1][1] highest_score = min(song_items, key=lambda item: item[1][1])[1][1] rank += translate(user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT) recent_songs = self.history[-RECENT_COUNT:] tag_counts = {} artist_counts = {} for song in recent_songs: for tag in song.tags: if tag not in tag_counts: tag_counts[tag] = 0 tag_counts[tag] += 1 if song.artist not in artist_counts: artist_counts[song.artist] = 0 artist_counts[song.artist] += 1 tag_total = 0 for tag in song.tags: if tag in tag_counts: tag_total += tag_counts[tag] rank += translate(tag_total, 0, RECENT_COUNT, 0, TAG_WEIGHT) rank += translate(artist_counts[song.artist], 0, RECENT_COUNT, 0, ARTIST_WEIGHT) if song in recent_songs: rank -= RECENT_PENALTY return rank def translate(value: float, in_min: float, in_max: float, out_min: float, out_max: float): return (value - in_min) / (in_max - in_min) * (out_max - out_min) + out_min