diff --git a/backend/requirements.txt b/backend/requirements.txt
index 7623d9f..57b0b9d 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -1,4 +1,5 @@
Flask==3.1.0
flask-cors
+flask-socketio
dotenv
requests
\ No newline at end of file
diff --git a/backend/src/app.py b/backend/src/app.py
index 1abebfb..6902f7c 100644
--- a/backend/src/app.py
+++ b/backend/src/app.py
@@ -1,6 +1,8 @@
import dotenv
from flask import Flask, Response, jsonify, request
+
from flask_cors import CORS
+from flask_socketio import SocketIO, emit
from .room import Room
from .song import Song, init_db
@@ -11,6 +13,8 @@ dotenv.load_dotenv()
app = Flask(__name__)
+app.config["SECRET_KEY"] = "your_secret_key"
+socketio = SocketIO(app)
CORS(app)
@@ -24,6 +28,7 @@ ROOMS: dict[int, Room] = {
{},
[],
[Song(mbid="test", title="
", artist="", tags=["Metal"], image_id="img-id", youtube_id="yt-id")],
+ playing_idx=1,
)
} # { room_id: room, ... }
@@ -63,13 +68,27 @@ def queue():
@app.post("/api/queue/next")
-def queue_next(): ...
+def queue_next():
+ if (room_id := request.args.get("room")) is None:
+ return error("Missing room id")
+ if (room := ROOMS.get(int(room_id))) is None:
+ return error("Invalid room")
-@app.post("/api/queue/renew")
-def queue_renew(): ...
+ room.playing_idx += 1
+
+ if room.playing_idx >= len(room.playing):
+ ## queue ended
+
+ # room.renew_queue()
+ emit("update_songs", {"songs": [1, 2, 3]}, broadcast=True, namespace="/")
+
+ return {"success": True, "ended": True, "index": room.playing_idx, "queue": []}
+
+ return {"success": True, "ended": False, "index": room.playing_idx}
init_db()
+exit()
if __name__ == "__main__":
- app.run(debug=True)
+ socketio.run(app, debug=True)
diff --git a/backend/src/room.py b/backend/src/room.py
index e6ebd4b..7fc051d 100644
--- a/backend/src/room.py
+++ b/backend/src/room.py
@@ -1,3 +1,4 @@
+import random
from dataclasses import dataclass
from .song import Song
@@ -13,6 +14,18 @@ RECENT_COUNT = 10
type UserScoredSong = tuple[Song, int]
+@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
+
+
@dataclass
class Room:
id: int
@@ -24,42 +37,90 @@ class Room:
songs: dict[str, UserScoredSong] # canzoni + voto
history: list[Song] # canzoni riprodotte (in ordine)
playing: list[Song] # canzoni che sono i riproduzione
+ playing_idx: int
- def rank_song(self, song: Song, user_score: int) -> float:
- rank = 0.0
+ 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:
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]
+ highest_score = max(song_items, key=lambda item: item[1][1])[1][1]
- rank += translate(user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT)
+ score_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:
+ for recent_song in recent_songs:
+ for tag in recent_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
+ if recent_song.artist not in artist_counts:
+ artist_counts[recent_song.artist] = 0
+ artist_counts[recent_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)
+ artist_total = artist_counts[song.artist] if song.artist in artist_counts else 0
- if song in recent_songs:
- rank -= RECENT_PENALTY
+ tag_value = min(RECENT_COUNT, len(self.history)) - tag_total
+ artist_value = min(RECENT_COUNT, len(self.history)) - artist_total
- return rank
+ 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)
def translate(value: float, in_min: float, in_max: float, out_min: float, out_max: float):
+ if in_max == in_min:
+ return out_min
return (value - in_min) / (in_max - in_min) * (out_max - out_min) + out_min
+
+
+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())