team-1/backend/src/room.py

127 lines
4 KiB
Python
Raw Normal View History

2025-08-01 22:10:59 +02:00
import random
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
2025-08-01 22:10:59 +02:00
@dataclass
class Rank:
user_score: float
tag: float
artist: float
random: float
recent_penalty: float
def total(self) -> float:
return self.user_score + self.tag + self.artist + self.random - self.recent_penalty
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 22:07:39 +02:00
playing_idx: int
2025-08-01 19:13:09 +02:00
2025-08-01 22:10:59 +02:00
def rank_song_from_id(self, id: str) -> Rank:
scored = self.songs[id]
return self.rank_song(scored[0], scored[1])
def rank_song(self, song: Song, user_score: int) -> Rank:
2025-08-01 19:13:09 +02:00
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]
2025-08-01 22:10:59 +02:00
highest_score = max(song_items, key=lambda item: item[1][1])[1][1]
2025-08-01 19:31:47 +02:00
2025-08-01 22:10:59 +02:00
score_rank = translate(user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT)
2025-08-01 19:31:47 +02:00
recent_songs = self.history[-RECENT_COUNT:]
tag_counts = {}
artist_counts = {}
2025-08-01 22:10:59 +02:00
for recent_song in recent_songs:
for tag in recent_song.tags:
2025-08-01 19:31:47 +02:00
if tag not in tag_counts:
tag_counts[tag] = 0
tag_counts[tag] += 1
2025-08-01 22:10:59 +02:00
if recent_song.artist not in artist_counts:
artist_counts[recent_song.artist] = 0
artist_counts[recent_song.artist] += 1
2025-08-01 19:31:47 +02:00
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 22:10:59 +02:00
artist_total = artist_counts[song.artist] if song.artist in artist_counts else 0
2025-08-01 19:13:09 +02:00
2025-08-01 22:10:59 +02:00
tag_value = min(RECENT_COUNT, len(self.history)) - tag_total
artist_value = min(RECENT_COUNT, len(self.history)) - artist_total
2025-08-01 19:13:09 +02:00
2025-08-01 22:10:59 +02:00
tag_rank = translate(tag_value, 0, min(RECENT_COUNT, len(self.history)), 0, TAG_WEIGHT)
artist_rank = translate(artist_value, 0, min(RECENT_COUNT, len(self.history)), 0, ARTIST_WEIGHT)
random_rank = translate(random.random(), 0, 1, 0.0, RANDOM_WEIGHT)
recent_penalty = RECENT_PENALTY if song in recent_songs else 0
return Rank(score_rank, tag_rank, artist_rank, random_rank, recent_penalty)
2025-08-01 19:13:09 +02:00
def translate(value: float, in_min: float, in_max: float, out_min: float, out_max: float):
2025-08-01 22:10:59 +02:00
if in_max == in_min:
return out_min
2025-08-01 19:13:09 +02:00
return (value - in_min) / (in_max - in_min) * (out_max - out_min) + out_min
2025-08-01 22:10:59 +02:00
def test_algo():
songs = [
Song("paulham", "Io e i miei banchi", "Paul Ham", ["pop"], "", ""),
Song("cisco", "CiscoPT", "Cantarex", ["rap"], "", ""),
Song("vpn", "VPN", "Cantarex", ["rap"], "", ""),
Song("gang", "Gang Gang Gang", "Cantarex", ["rap"], "", ""),
Song("bertha1", "Rindondantha", "Berthanetti", ["rock"], "", ""),
Song("bertha2", "Ragatthi", "Berthanetti", ["rock"], "", ""),
Song("bertha3", "Tranthathione", "Berthanetti", ["rock"], "", ""),
Song("cexx", "Spritz", "Cex", ["kpop"], "", ""),
]
room = Room(
123,
(0.0, 0.0),
"test",
None,
set(["rock", "rap"]),
{
"paulham": (songs[0], 2),
"cisco": (songs[1], 1),
"vpn": (songs[2], 5),
"gang": (songs[3], 1),
"bertha1": (songs[4], 1),
"bertha2": (songs[5], 1),
"bertha3": (songs[6], 1),
"cexx": (songs[7], -123123),
},
[songs[4], songs[5], songs[0]],
)
print(room.rank_song_from_id("paulham"), room.rank_song_from_id("paulham").total())
print(room.rank_song_from_id("vpn"), room.rank_song_from_id("vpn").total())
print(room.rank_song_from_id("cexx"), room.rank_song_from_id("cexx").total())