lenawilli commited on
Commit
daef28a
Β·
verified Β·
1 Parent(s): e27b6a6

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +75 -79
src/streamlit_app.py CHANGED
@@ -1,88 +1,84 @@
1
- import React, { useState, useEffect } from "react";
2
- import { Card, CardContent } from "@/components/ui/card";
3
- import { Button } from "@/components/ui/button";
4
- import { Slider } from "@/components/ui/slider";
5
- import moviesData from "./movies.csv"; // Assume a CSV loader or API exposes this
6
 
7
- export default function MovieRecommender() {
8
- const [maxQuestions, setMaxQuestions] = useState(5);
9
- const [questionIndex, setQuestionIndex] = useState(0);
10
- const [ratedCount, setRatedCount] = useState(0);
11
- const [ratings, setRatings] = useState([]);
12
- const [shuffledMovies, setShuffledMovies] = useState([]);
13
- const [submitted, setSubmitted] = useState(false);
14
 
15
- useEffect(() => {
16
- const allTitles = moviesData.map((m) => m.title);
17
- const shuffled = [...allTitles].sort(() => 0.5 - Math.random());
18
- setShuffledMovies(shuffled);
19
- }, []);
20
 
21
- const handleRating = (choice) => {
22
- if (choice !== "skip") {
23
- setRatings([...ratings, { movie: shuffledMovies[questionIndex], rating: choice }]);
24
- setRatedCount(ratedCount + 1);
25
- }
 
 
 
 
26
 
27
- if ((choice !== "skip" && ratedCount + 1 >= maxQuestions) || questionIndex + 1 >= shuffledMovies.length) {
28
- setSubmitted(true);
29
- } else {
30
- setQuestionIndex(questionIndex + 1);
31
- }
32
- };
 
 
 
 
 
33
 
34
- const recommendations = shuffledMovies.filter(
35
- (movie) => !ratings.map((r) => r.movie).includes(movie)
36
- ).slice(0, 10).map((title) => ({ title, score: (Math.random() * 100).toFixed(1) }));
37
 
38
- return (
39
- <div className="min-h-screen bg-[#0d1b2a] text-white flex flex-col items-center justify-center px-4 py-10">
40
- <h1 className="text-3xl font-bold mb-8">🎬 Movie Recommender</h1>
 
41
 
42
- {!submitted && ratings.length === 0 && (
43
- <div className="w-full max-w-md">
44
- <p className="mb-4">How many movies would you like to rate?</p>
45
- <Slider
46
- defaultValue={[5]}
47
- min={1}
48
- max={15}
49
- step={1}
50
- onValueChange={(val) => setMaxQuestions(val[0])}
51
- />
52
- <div className="mt-2 text-center">Selected: {maxQuestions}</div>
53
- </div>
54
- )}
 
 
 
 
 
 
55
 
56
- {!submitted && ratings.length < maxQuestions && shuffledMovies.length > 0 && (
57
- <Card className="mt-10 w-full max-w-xl shadow-2xl transition-transform animate-in fade-in zoom-in rounded-2xl bg-[#1b263b]">
58
- <CardContent className="p-6 text-center">
59
- <div className="flex justify-between mb-4">
60
- <span className="text-sm text-gray-300">Rate the following movie</span>
61
- <span className="text-sm text-gray-300">#{ratedCount + 1}</span>
62
- </div>
63
- <h2 className="text-2xl font-semibold mb-6">{shuffledMovies[questionIndex]}</h2>
64
- <div className="flex justify-around gap-4">
65
- <Button onClick={() => handleRating("like")} className="bg-green-600 hover:bg-green-700">πŸ‘ Like</Button>
66
- <Button onClick={() => handleRating("dislike")} className="bg-red-600 hover:bg-red-700">πŸ‘Ž Dislike</Button>
67
- <Button onClick={() => handleRating("skip")} className="bg-gray-500 hover:bg-gray-600">⏭ Didn't Watch</Button>
68
- </div>
69
- </CardContent>
70
- </Card>
71
- )}
72
 
73
- {submitted && (
74
- <div className="mt-10 w-full max-w-2xl text-center">
75
- <h2 className="text-2xl font-semibold mb-4">🎯 Top 10 Recommendations</h2>
76
- <ul className="space-y-2">
77
- {recommendations.map((rec, i) => (
78
- <li key={i} className="bg-[#1e2a3c] rounded-lg px-4 py-3 flex justify-between items-center shadow">
79
- <span>{rec.title}</span>
80
- <span className="text-sm text-gray-300">Likelihood: {rec.score}%</span>
81
- </li>
82
- ))}
83
- </ul>
84
- </div>
85
- )}
86
- </div>
87
- );
88
- }
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import random
5
+ import os
6
 
7
+ # Load movie data
8
+ BASE_DIR = os.path.dirname(__file__)
9
+ MOVIES_PATH = os.path.join(BASE_DIR, "movies.csv")
 
 
 
 
10
 
11
+ @st.cache_data
12
+ def load_movies():
13
+ df = pd.read_csv(MOVIES_PATH)
14
+ return df["title"].dropna().unique().tolist()
 
15
 
16
+ # Initialize session state
17
+ if "movies" not in st.session_state:
18
+ st.session_state.movies = []
19
+ st.session_state.queue = []
20
+ st.session_state.index = 0
21
+ st.session_state.rated = []
22
+ st.session_state.skipped = 0
23
+ st.session_state.max_questions = 5
24
+ st.session_state.finished = False
25
 
26
+ st.markdown("""
27
+ <style>
28
+ body {
29
+ background-color: #0d1b2a;
30
+ color: white;
31
+ }
32
+ .stSlider > div {
33
+ background-color: #1b263b;
34
+ }
35
+ </style>
36
+ """, unsafe_allow_html=True)
37
 
38
+ st.title("🎬 Midnight Movie Recommender")
39
+ st.write("Rate a few movies to get personalized recommendations")
 
40
 
41
+ if not st.session_state.movies:
42
+ movie_titles = load_movies()
43
+ random.shuffle(movie_titles)
44
+ st.session_state.movies = movie_titles
45
 
46
+ if not st.session_state.queue:
47
+ with st.container():
48
+ st.subheader("How many movies do you want to rate?")
49
+ st.session_state.max_questions = st.slider("Select number of movies", 1, 15, 5)
50
+ if st.button("Start Rating"):
51
+ st.session_state.queue = st.session_state.movies.copy()
52
+ st.experimental_rerun()
53
+ else:
54
+ if st.session_state.finished or st.session_state.index >= len(st.session_state.queue):
55
+ st.subheader("🍿 Top 10 Recommendations")
56
+ st.write("Based on your preferences, we suggest:")
57
+ remaining = [m for m in st.session_state.movies if m not in [r["movie"] for r in st.session_state.rated]]
58
+ recommendations = random.sample(remaining, min(10, len(remaining)))
59
+ for i, movie in enumerate(recommendations, 1):
60
+ score = round(random.uniform(75, 100), 1)
61
+ st.markdown(f"**#{i}. {movie}** β€” Likelihood: `{score}%`")
62
+ else:
63
+ movie = st.session_state.queue[st.session_state.index]
64
+ card_number = len(st.session_state.rated) + 1
65
 
66
+ st.markdown(f"### 🎞️ Movie #{card_number} of {st.session_state.max_questions}")
67
+ st.markdown(f"## **{movie}**")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
+ col1, col2, col3 = st.columns([1, 1, 1])
70
+ with col1:
71
+ if st.button("πŸ‘ Like"):
72
+ st.session_state.rated.append({"movie": movie, "rating": "like"})
73
+ st.session_state.index += 1
74
+ with col2:
75
+ if st.button("πŸ‘Ž Dislike"):
76
+ st.session_state.rated.append({"movie": movie, "rating": "dislike"})
77
+ st.session_state.index += 1
78
+ with col3:
79
+ if st.button("⏭ Didn't Watch"):
80
+ st.session_state.index += 1
81
+
82
+ if len(st.session_state.rated) >= st.session_state.max_questions:
83
+ st.session_state.finished = True
84
+ st.experimental_rerun()