From 3cd9dad5963c5c39ff341b2e43811eae24b885d7 Mon Sep 17 00:00:00 2001 From: Joshua Shorenstein Date: Fri, 28 Mar 2025 18:43:47 -0600 Subject: [PATCH 1/2] make query weighted --- movienightbot/db/controllers.py | 56 ++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/movienightbot/db/controllers.py b/movienightbot/db/controllers.py index 5f7c799..776af0e 100644 --- a/movienightbot/db/controllers.py +++ b/movienightbot/db/controllers.py @@ -1,4 +1,5 @@ import logging +import random from collections import defaultdict from string import ascii_lowercase from typing import Any, Dict, List, Optional, Union @@ -129,15 +130,19 @@ def update_imdb_id(self, server_id: int, movie_name: str, imdb_id: str): .execute() ) - def get_random_movies(self, server_id: int, num_movies: int, genres: Optional[List[str]] = None) -> List[Movie]: - if genres is None: - return ( - Movie.select() - .order_by(pw.fn.Random()) - .where((Movie.server == server_id) & Movie.watched_on.is_null(True)) + def _weighted_movie_selection(self, server_id: int, num_movies: int) -> List[int]: + # weighted score so it's random but has the movie avg score taken into account + return ( + Movie.select(Movie, ((Movie.total_score / Movie.num_votes_entered) * pw.fn.Random()).alias('weight_score')) + .order_by(pw.SQL("weight_score").desc()) + .where((Movie.server == server_id) + & Movie.watched_on.is_null(True) + & (Movie.num_votes_entered > 0)) .limit(num_movies) - ) - else: + ) + + def get_random_movies(self, server_id: int, num_movies: int, genres: Optional[List[str]] = None) -> List[Movie]: + if genres is not None: return ( Movie.select() .join(MovieGenre) @@ -148,6 +153,41 @@ def get_random_movies(self, server_id: int, num_movies: int, genres: Optional[Li .limit(num_movies) ) + # calculate the new vs old split + counts_by_votes_entered = ( + Movie.select(Movie.num_votes_entered, pw.fn.COUNT(Movie.num_votes_entered).alias("count_value")) + .group_by(Movie.num_votes_entered) + .where(Movie.server == server_id) + .order_by(Movie.num_votes_entered.asc()) + ) + if counts_by_votes_entered[0].num_votes_entered != 0: + # We have some weird case where every movie has been in at least one vote + # so short circuit and just choose at random weighted + return self._weighted_movie_selection(server_id, num_movies) + + total_count = sum(c.count_value for c in counts_by_votes_entered) + new_count = counts_by_votes_entered[0].count_value + + # prevent errors by limiting the total number if db has too few options + if total_count < num_movies: + num_movies = total_count + + # calculate the actual split counts, making sure at least one new movie is in the split + new_split = max(1, round((new_count / total_count) * num_movies)) + old_split = num_movies - new_split + + # query the movies based on the split + # for the sake of not knowing how to coax sql into doing this, I'll do this with python + new_movies = (Movie.select() + .order_by(pw.fn.Random()) + .where((Movie.server == server_id) + & Movie.watched_on.is_null(True) + & (Movie.num_votes_entered == 0)) + .limit(new_split)) + + # Shuffle so it isn't ordered new -> old always + return random.shuffle(new_movies + self._weighted_movie_selection(server_id, old_split)) + def movie_score_weightings(server_id: int) -> Dict[int, float]: num_votes_allowed = ServerController().get_by_id(server_id).num_votes_per_user From 462fbdc7b336c418a3d060fed3d29a2a971eed67 Mon Sep 17 00:00:00 2001 From: Chopknee Date: Sat, 29 Mar 2025 00:59:48 +0000 Subject: [PATCH 2/2] Update controllers.py Delete redundant comment --- movienightbot/db/controllers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/movienightbot/db/controllers.py b/movienightbot/db/controllers.py index 776af0e..29e6eed 100644 --- a/movienightbot/db/controllers.py +++ b/movienightbot/db/controllers.py @@ -177,7 +177,6 @@ def get_random_movies(self, server_id: int, num_movies: int, genres: Optional[Li old_split = num_movies - new_split # query the movies based on the split - # for the sake of not knowing how to coax sql into doing this, I'll do this with python new_movies = (Movie.select() .order_by(pw.fn.Random()) .where((Movie.server == server_id)