2025-08-01 18:46:38 +02:00
|
|
|
from dataclasses import dataclass
|
|
|
|
|
2025-08-01 19:16:20 +02:00
|
|
|
from .song import Song
|
2025-08-01 18:46:38 +02:00
|
|
|
|
2025-08-01 19:13:09 +02:00
|
|
|
USER_SCORE_WEIGHT = 0.7
|
2025-08-01 19:31:47 +02:00
|
|
|
ARTIST_WEIGHT = 0.1
|
|
|
|
TAG_WEIGHT = 0.1
|
2025-08-01 19:13:09 +02:00
|
|
|
RANDOM_WEIGHT = 0.1
|
|
|
|
RECENT_PENALTY = 0.5
|
|
|
|
RECENT_COUNT = 10
|
|
|
|
|
|
|
|
|
2025-08-01 19:31:47 +02:00
|
|
|
type UserScoredSong = tuple[Song, int]
|
2025-08-01 18:46:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class Room:
|
|
|
|
id: int
|
|
|
|
coord: tuple[float, float]
|
|
|
|
name: str
|
|
|
|
pin: int | None
|
|
|
|
tags: set[str]
|
|
|
|
|
2025-08-01 21:39:46 +02:00
|
|
|
songs: dict[str, UserScoredSong] # canzoni + voto
|
|
|
|
history: list[Song] # canzoni riprodotte (in ordine)
|
|
|
|
playing: list[Song] # canzoni che sono i riproduzione
|
2025-08-01 19:13:09 +02:00
|
|
|
|
2025-08-01 19:31:47 +02:00
|
|
|
def rank_song(self, song: Song, user_score: int) -> float:
|
2025-08-01 19:13:09 +02:00
|
|
|
rank = 0.0
|
|
|
|
song_items = self.songs.items()
|
|
|
|
|
2025-08-01 19:31:47 +02:00
|
|
|
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]
|
2025-08-01 19:13:09 +02:00
|
|
|
|
2025-08-01 19:31:47 +02:00
|
|
|
rank += translate(tag_total, 0, RECENT_COUNT, 0, TAG_WEIGHT)
|
|
|
|
rank += translate(artist_counts[song.artist], 0, RECENT_COUNT, 0, ARTIST_WEIGHT)
|
2025-08-01 19:13:09 +02:00
|
|
|
|
2025-08-01 19:31:47 +02:00
|
|
|
if song in recent_songs:
|
|
|
|
rank -= RECENT_PENALTY
|
2025-08-01 19:13:09 +02:00
|
|
|
|
|
|
|
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
|