Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 56 additions & 15 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import os
from flask import Flask, render_template, request
from flask import Flask, render_template, request, jsonify
from flask_cors import CORS
import pandas as pd
import html
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

app = Flask(__name__)
CORS(app)
Expand All @@ -11,9 +13,43 @@
csv_file_path = 'data/semicleanedbg.csv'
data_df = pd.read_csv(csv_file_path)

# for cosine sim
data_df['processed_description'] = data_df['description'].apply(lambda x: x.lower() if isinstance(x, str) else '')
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(data_df['processed_description'].values.astype('U')) # 'U' for Unicode



@app.route("/")
def home():
return render_template('base.html', title="sample html")

#for the suggestions box pls do not touch; it checks all the games for games with the query in it (not accounting for typos)
# this then returns the top 5 matching titles
@app.route("/suggestions")
def suggestions():
query_partial = request.args.get("query", "")
if not query_partial:
return jsonify([])
matching_games = data_df[data_df['name'].str.contains(query_partial, case = False)]['name'].unique().tolist()
suggestions = matching_games[:5]
return jsonify(suggestions)


@app.route("/games")
def search():
text = request.args.get("title")
min_age = request.args.get("min_age", type=int)
min_players = request.args.get("min_players", type=int)
max_players = request.args.get("max_players", type=int)
category = request.args.get("category")
mode = request.args.get("mode")

if mode == 'recommendation':
matches = recommendation_search(text)
else:
matches = matches = data_df[data_df['name'].str.lower().str.contains(text.lower())]

def csv_search(query, min_age, min_players, max_players, category):
matches = data_df[data_df['name'].str.lower().str.contains(query.lower())]
if min_age is not None:
matches = matches[matches['minage'] >= min_age]
if min_players is not None:
Expand All @@ -22,25 +58,30 @@ def csv_search(query, min_age, min_players, max_players, category):
matches = matches[matches['maxplayers'] <= max_players]
if category:
matches = matches[matches['boardgamecategory'].str.contains(category, case=False, na=False)]

matches_filtered = matches[['name', 'description', 'average', 'objectid']]
matches_filtered['name'] = matches_filtered['name'].apply(html.unescape)
matches_filtered['description'] = matches_filtered['description'].apply(html.unescape)
matches_filtered_json = matches_filtered.to_json(orient='records')

return matches_filtered_json

@app.route("/")
def home():
return render_template('base.html', title="sample html")
def recommendation_search(query):
if query:
#some preprocessing: 1- fetch the game 2- get its processed desc
game_row = data_df[data_df['name'].str.lower() == query.lower()].iloc[0]
game_description = game_row['processed_description']
#cos sim
query_vector = tfidf_vectorizer.transform([game_description])
cosine_similarities = cosine_similarity(query_vector, tfidf_matrix).flatten()
#get the top 1000
similar_indices = cosine_similarities.argsort()[-(1000+1):][::-1]
# game itself is the most similar one, so we exclude it if so.
similar_indices = similar_indices[1:]

@app.route("/games")
def episodes_search():
text = request.args.get("title")
min_age = request.args.get("min_age", type=int)
min_players = request.args.get("min_players", type=int)
max_players = request.args.get("max_players", type=int)
category = request.args.get("category")
return csv_search(text, min_age, min_players, max_players, category)
# Fetch the details of the top N similar games then return
similar_games = data_df.iloc[similar_indices]
return similar_games


@app.route("/about/<game_id>")
def about(game_id):
Expand Down
Loading