From a1da421ffe8d9ba18a92c1a42743de525ee4a00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phillip=20K=C3=BChne?= Date: Wed, 4 Oct 2023 18:37:08 +0000 Subject: [PATCH] Add suggestions --- backend/app.py | 33 +++++++-- backend/database.py | 57 +++++++++++++++ backend/templates/played_list.html | 22 ++++-- backend/templates/songlist.html | 112 +++++++++++++++++------------ 4 files changed, 167 insertions(+), 57 deletions(-) diff --git a/backend/app.py b/backend/app.py index 263dbb4..d10585c 100644 --- a/backend/app.py +++ b/backend/app.py @@ -170,6 +170,22 @@ def query_songs_with_details(input_string=""): return jsonify(result) +@app.route("/api/songs/suggest") +@nocache +def query_songs_with_details_suggest(input_string=""): + input_string = request.args.get("count", input_string) + if input_string == "": + return Response(status=400) + result = [] + if not input_string.isnumeric(): + return Response(status=400) + count: int = int(input_string) + for x in database.get_song_suggestions(count): + # Turn row into dict. Add field labels. + result.append(dict(zip(['karafun_id', 'title', 'artist', 'year', 'duo', 'explicit', 'styles', 'languages'], x))) + return jsonify(result) + + @app.route("/api/songs/details/") def get_song_details(song_id): result = database.get_song_details(song_id) @@ -261,14 +277,20 @@ def get_accept_entries(): return Response('{"status": "OK", "value": ' + str(int(accept_entries)) + '}', mimetype='text/json') -@app.route("/api/played/clear") +@app.route("/api/event/close") @nocache @basic_auth.required -def clear_played_songs(): - if database.clear_played_songs(): +def close_event(): + try: + database.transfer_playbacks() + database.clear_played_songs() + database.delete_all_entries() + helpers.reset_current_event_id(app) return Response('{"status": "OK"}', mimetype='text/json') - else: - return Response('{"status": "FAIL"}', mimetype='text/json') + except Exception as e: + response = jsonify({"status": "FAIL", "exception": e}) + response.status_code = 400 + return response @app.route("/api/entries/delete_all") @@ -298,6 +320,7 @@ def activate_job(): with app.app_context(): helpers.load_dbconfig(app) helpers.load_version(app) + database.create_schema() database.create_entry_table() database.create_song_table() database.create_done_song_table() diff --git a/backend/database.py b/backend/database.py index d5f90f8..25cd81a 100644 --- a/backend/database.py +++ b/backend/database.py @@ -40,6 +40,17 @@ def import_songs(song_csv): return ("Imported songs ({} in Database)".format(num_songs)) +def create_schema(): + create_song_table() + create_entry_table() + create_done_song_table() + create_config_table() + create_long_term_stats_table() + create_list_view() + create_done_song_view() + init_event_id() + + def create_entry_table(): with get_db_engine().connect() as conn: stmt = text( @@ -75,6 +86,17 @@ def create_song_table(): conn.commit() +def create_long_term_stats_table(): + with get_db_engine().connect() as conn: + stmt = text("""CREATE TABLE IF NOT EXISTS `long_term_stats` ( + `Id` INTEGER, + `Playbacks` INTEGER, + PRIMARY KEY (`Id`) + )""") + conn.execute(stmt) + conn.commit() + + def create_list_view(): with get_db_engine().connect() as conn: stmt = text("""CREATE OR REPLACE VIEW `Liste` AS @@ -121,6 +143,24 @@ def get_played_list(): return cur.fetchall() +def get_song_suggestions(count: int): + with get_db_engine().connect() as conn: + # Get the top 10 songs with the most plays from the long_term_stats table and join them with the songs table to get the song details. + # Exclude songs that are already in the queue, or in the done_songs table. + stmt = text(""" + SELECT s.Id, s.Title, s.Artist, s.Year, s.Duo, s.Explicit, s.Styles, s.Languages + FROM long_term_stats lts + LEFT JOIN songs s ON lts.Id = s.Id + LEFT JOIN entries e ON lts.Id = e.Song_Id + LEFT JOIN done_songs ds ON lts.Id = ds.Song_Id + WHERE e.Id IS NULL AND ds.Song_Id IS NULL + ORDER BY lts.Playbacks DESC + LIMIT :count; + """) + cur = conn.execute(stmt, {"count": count}) + return cur.fetchall() + + def get_song_list(): with get_db_engine().connect() as conn: stmt = text("SELECT Artist || \" - \" || Title AS Song, Id FROM songs;") @@ -224,6 +264,23 @@ def check_queue_length(): return cur.fetchall()[0][0] +def transfer_playbacks(): + with get_db_engine().connect() as conn: + # Use SQL to update the long_term_stats table. Add the playbacks of the songs in the done_songs table to the playbacks of the songs in the long_term_stats table. + stmt = text(""" + INSERT INTO long_term_stats(Id, Playbacks) + SELECT ds.Song_Id, ds.Plays + FROM done_songs ds + LEFT JOIN long_term_stats lts ON ds.Song_Id = lts.Id + ON DUPLICATE KEY + UPDATE Playbacks = lts.Playbacks + VALUES(Playbacks); + """) + result = conn.execute(stmt) + print(result) + conn.commit() + return True + + def clear_played_songs(): with get_db_engine().connect() as conn: conn.execute(text("DELETE FROM done_songs")) diff --git a/backend/templates/played_list.html b/backend/templates/played_list.html index 8c4f7e3..79b3842 100644 --- a/backend/templates/played_list.html +++ b/backend/templates/played_list.html @@ -2,8 +2,8 @@ {% block title %}Abspielliste{% endblock %} {% block content %}
- +