Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import difflib | |
| from sklearn.feature_extraction.text import TfidfVectorizer | |
| from sklearn.metrics.pairwise import cosine_similarity | |
| import gradio as gr | |
| import numpy as np | |
| # Load the data | |
| def load_data(): | |
| try: | |
| data = pd.read_csv('games_march2025_cleaned.csv', nrows=20000, on_bad_lines='skip', engine='python') | |
| return data | |
| except Exception as e: | |
| print(f"Error loading data: {e}") | |
| return None | |
| # Prepare the feature vectors for similarity calculation | |
| def prepare_features(data): | |
| selected_features = ['genres', 'price', 'average_playtime_2weeks', 'tags'] | |
| for feature in selected_features: | |
| data[feature] = data[feature].fillna('') | |
| combined_features = ( | |
| data['genres'] + ' ' + | |
| data['price'].astype(str) + ' ' + | |
| data['average_playtime_2weeks'].astype(str) + ' ' + | |
| data['tags'].astype(str) | |
| ) | |
| vectorizer = TfidfVectorizer() | |
| feature_vectors = vectorizer.fit_transform(combined_features) | |
| return feature_vectors | |
| # Function to get game recommendations | |
| def get_recommendations(game_name, data, feature_vectors): | |
| titles = data['name'].tolist() | |
| close_matches = difflib.get_close_matches(game_name, titles) | |
| if not close_matches: | |
| print(f"Couldn't find a close match for: '{game_name}'") | |
| return "No match found. Try typing a more complete or accurate title." | |
| match = close_matches[0] | |
| print(f"Using closest match: {match}") | |
| game_idx = data[data['name'] == match].index[0] | |
| similarity = cosine_similarity(feature_vectors) | |
| scores = list(enumerate(similarity[game_idx])) | |
| similar_games = sorted(scores, key=lambda x: x[1], reverse=True) | |
| html = "" | |
| for i, (idx, score) in enumerate(similar_games[1:10], 1): # skip the first one (it's the same game) | |
| game = data.loc[idx] | |
| name = game['name'] | |
| desc = game['short_description'] or "No description provided." | |
| if len(desc) > 180: | |
| desc = desc[:180] + "..." | |
| img = game.get('header_image', '') or "" | |
| # Detect supported platforms | |
| platforms = [] | |
| if game.get('windows') == 1: | |
| platforms.append('Windows') | |
| if game.get('mac') == 1: | |
| platforms.append('Mac') | |
| if game.get('linux') == 1: | |
| platforms.append('Linux') | |
| platforms_str = ", ".join(platforms) if platforms else "Unknown" | |
| price = game['price'] | |
| meta_score = game.get('metacritic_score') | |
| meta_display = int(meta_score) if pd.notnull(meta_score) else "N/A" | |
| pos = game.get('positive', 0) | |
| neg = game.get('negative', 0) | |
| total = pos + neg | |
| pos_pct = f"{(pos / total * 100):.1f}%" if total > 0 else "N/A" | |
| # Build the card HTML | |
| html += f''' | |
| <div style="display:flex; margin-bottom:16px;"> | |
| <img src="{img}" width="130" style="margin-right:12px; border-radius:4px;"> | |
| <div> | |
| <h4>{i}. {name}</h4> | |
| <p><b>Platforms:</b> {platforms_str}</p> | |
| <p><b>Price:</b> ${price}</p> | |
| <p><b>Metacritic:</b> {meta_display}</p> | |
| <p><b>Positive Reviews:</b> {pos_pct}</p> | |
| <p>{desc}</p> | |
| </div> | |
| </div> | |
| <hr> | |
| ''' | |
| return html | |
| # Gradio interface function | |
| def recommend_games(game_name, max_age, max_price, min_metacritic): | |
| data = load_data() | |
| if data is None: | |
| return "Failed to load data." | |
| # Apply filters BEFORE feature preparation | |
| data = data[ | |
| (data['required_age'] <= max_age) & | |
| (data['price'] <= max_price) & | |
| ((data['metacritic_score'].fillna(0) >= min_metacritic) | data['metacritic_score'].isna()) | |
| ].reset_index(drop=True) | |
| if data.empty: | |
| return "No games found." | |
| feature_vectors = prepare_features(data) | |
| recommendations_html = get_recommendations(game_name, data, feature_vectors) | |
| return recommendations_html | |
| # Create the Gradio interface | |
| with gr.Blocks(title="Steam Game Recommender") as demo: | |
| gr.Markdown("Steam Game Recommender") | |
| gr.Markdown("Enter a game you like and customize filters to get similar suggestions.") | |
| with gr.Row(): | |
| input_text = gr.Textbox(label="Input Steam Game") | |
| with gr.Row(): | |
| max_age_slider = gr.Slider(0, 21, value=17, label="Max Age Rating (Avoid Adult Games)") | |
| max_price_slider = gr.Slider(0.0, 100.0, value=60.0, step=0.5, label="Maximum Price ($)") | |
| min_metacritic_slider = gr.Slider(0, 100, value=50, step=1, label="Minimum Metacritic Score") | |
| with gr.Row(): | |
| submit_btn = gr.Button("Get Recommendations") | |
| with gr.Row(): | |
| output_text = gr.Markdown(label="Recommendations") | |
| submit_btn.click( | |
| fn=recommend_games, | |
| inputs=[input_text, max_age_slider, max_price_slider, min_metacritic_slider], | |
| outputs=output_text | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch() |