44
55from app .models .profile import UserTasteProfile
66from app .services .tmdb .countries import COUNTRY_ADJECTIVES
7- from app .services .tmdb .genre import GENRE_ADJECTIVES , movie_genres , series_genres
7+ from app .services .tmdb .genre import movie_genres , series_genres
88from app .services .tmdb_service import TMDBService
99
1010
11+ def normalize_keyword (kw ):
12+ return kw .strip ().replace ("-" , " " ).replace ("_" , " " ).title ()
13+
14+
1115class RowDefinition (BaseModel ):
1216 """
1317 Defines a dynamic catalog row.
@@ -42,7 +46,7 @@ async def generate_rows(self, profile: UserTasteProfile, content_type: str = "mo
4246
4347 # Extract features
4448 top_genres = profile .get_top_genres (limit = 3 ) # [(id, score), ...]
45- top_keywords = profile .get_top_keywords (limit = 3 ) # [(id, score), ...]
49+ top_keywords = profile .get_top_keywords (limit = 4 ) # [(id, score), ...]
4650 top_countries = profile .get_top_countries (limit = 1 ) # [(code, score)]
4751 top_years = profile .years .get_top_features (limit = 1 ) # [(decade_start, score)]
4852
@@ -58,41 +62,53 @@ def get_cname(code):
5862 return random .choice (adjectives )
5963 return ""
6064
61- # Strategy 1: Genre + Mood (Adjective)
62- if top_genres :
63- g_id = top_genres [0 ][0 ]
64- adj = random .choice (GENRE_ADJECTIVES .get (g_id , ["Essential" ]))
65- rows .append (
66- RowDefinition (
67- title = f"{ adj } { get_gname (g_id )} " ,
68- id = f"watchly.theme.g{ g_id } .sort-vote" , # Use sort-vote for quality
69- genres = [g_id ],
70- )
71- )
72-
73- # Strategy 2: Genre + Keyword ("Time-Travel Adventures")
74- if len (top_genres ) > 0 and top_keywords :
75- g_id = top_genres [0 ][0 ] # Use top genre
65+ # Strategy 1: Pure Keyword Row (Top Priority)
66+ if top_keywords :
7667 k_id = top_keywords [0 ][0 ]
77-
7868 kw_name = await self ._get_keyword_name (k_id )
7969 if kw_name :
8070 rows .append (
8171 RowDefinition (
82- title = f"{ kw_name .title ()} { get_gname (g_id )} " ,
83- id = f"watchly.theme.g{ g_id } .k{ k_id } " ,
84- genres = [g_id ],
72+ title = f"{ normalize_keyword (kw_name )} " ,
73+ id = f"watchly.theme.k{ k_id } " ,
8574 keywords = [k_id ],
8675 )
8776 )
8877
89- # Strategy 3: Genre + Country ("Korean Thrillers")
90- if len (top_genres ) > 0 and top_countries :
91- # Pick a genre (maybe 2nd top to vary)
78+ # Strategy 2: Keyword + Genre (Specific Niche)
79+ if top_genres and len (top_keywords ) > 1 :
80+ g_id = top_genres [0 ][0 ]
81+ # get random keywords: Just to surprise user in every refresh
82+ k_id = random .choice (top_keywords [1 :])[0 ]
83+
84+ if k_id :
85+ kw_name = await self ._get_keyword_name (k_id )
86+ if kw_name :
87+ title = f"{ normalize_keyword (kw_name )} { get_gname (g_id )} "
88+ # keyword and genre can have same name sometimes, remove if so
89+ words = title .split ()
90+ seen_words = set ()
91+ unique_words = []
92+ for word in words :
93+ if word not in seen_words :
94+ unique_words .append (word )
95+ seen_words .add (word )
96+ title = " " .join (unique_words )
97+
98+ rows .append (
99+ RowDefinition (
100+ title = title ,
101+ id = f"watchly.theme.g{ g_id } .k{ k_id } " ,
102+ genres = [g_id ],
103+ keywords = [k_id ],
104+ )
105+ )
106+
107+ # Strategy 3: Genre + Country (e.g. "Bollywood Action")
108+ if top_countries and len (top_genres ) > 0 :
92109 g_id = top_genres [0 ][0 ] if len (top_genres ) == 1 else top_genres [1 ][0 ]
93110 c_code = top_countries [0 ][0 ]
94111 c_adj = get_cname (c_code )
95-
96112 if c_adj :
97113 rows .append (
98114 RowDefinition (
@@ -111,7 +127,7 @@ def get_cname(code):
111127 g_id = top_genres [2 ][0 ]
112128
113129 decade_start = top_years [0 ][0 ]
114- # Only do this if decade is valid and somewhat old (nostalgia factor)
130+ # # Only do this if decade is valid and somewhat old (nostalgia factor)
115131 if 1970 <= decade_start <= 2010 :
116132 decade_str = str (decade_start )[2 :] + "s" # "90s"
117133 rows .append (
0 commit comments