Spaces:
Runtime error
Runtime error
added from github repo, branch ~peter, added chatbot
Browse files- Home.py +169 -0
- README.md +3 -3
- module/__custom__.py +157 -23
- module/__selectpage__.py +5 -10
- Overall.py β pages/01 Overall.py +0 -0
- pages/{01 Category.py β 02 Category.py} +3 -1
- pages/03 DLC_Counts.py +4 -1
- pages/{02 Genre.py β 04 Genre.py} +11 -1
- pages/{04 Price.py β 05 Price.py} +3 -1
- pages/{05 Age_Restriction.py β 06 Age_Restriction.py} +5 -2
- pages/{06 Settings.py β 07 Settings.py} +9 -1
- pages/{07 OS.py β 08 OS.py} +11 -1
- pages/{08 Publisher.py β 09 Publisher.py} +3 -1
- pages/{09 Developer.py β 10 Developer.py} +3 -1
Home.py
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import os
|
3 |
+
import random
|
4 |
+
import time
|
5 |
+
from module.__custom__ import *
|
6 |
+
from streamlit_extras.switch_page_button import switch_page
|
7 |
+
|
8 |
+
# Openai API Key
|
9 |
+
import openai
|
10 |
+
import json
|
11 |
+
def read_api_key_from_secrets(file_path='secrets.json'):
|
12 |
+
try:
|
13 |
+
with open(file_path, 'r') as secrets_file:
|
14 |
+
secrets_data = json.load(secrets_file)
|
15 |
+
openai_api_key = secrets_data.get('openai_api_key')
|
16 |
+
|
17 |
+
if openai_api_key is not None:
|
18 |
+
return openai_api_key
|
19 |
+
else:
|
20 |
+
raise KeyError("'openai_api_key' not found in secrets.json")
|
21 |
+
except FileNotFoundError:
|
22 |
+
raise FileNotFoundError(f"The file {file_path} was not found.")
|
23 |
+
except json.JSONDecodeError:
|
24 |
+
raise ValueError(f"Error decoding JSON in {file_path}. Please check the file format.")
|
25 |
+
|
26 |
+
# Example usage
|
27 |
+
try:
|
28 |
+
key = read_api_key_from_secrets()
|
29 |
+
openai.api_key = key
|
30 |
+
os.environ['OPENAI_API_KEY'] = key
|
31 |
+
print(f"OpenAI API Key Found")
|
32 |
+
except (FileNotFoundError, ValueError, KeyError) as e:
|
33 |
+
print(f"Error: {e}")
|
34 |
+
|
35 |
+
from langchain.vectorstores import Chroma
|
36 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
37 |
+
from langchain.chains.query_constructor.base import AttributeInfo
|
38 |
+
from langchain.retrievers.self_query.base import SelfQueryRetriever
|
39 |
+
embedding = OpenAIEmbeddings()
|
40 |
+
# from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings
|
41 |
+
# embedding = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
|
42 |
+
|
43 |
+
# LLM
|
44 |
+
from langchain.chat_models import ChatOpenAI
|
45 |
+
llm_name = "gpt-3.5-turbo"
|
46 |
+
llm = ChatOpenAI(model_name=llm_name, temperature=0)
|
47 |
+
|
48 |
+
# load from disk
|
49 |
+
db_cos = Chroma(
|
50 |
+
persist_directory="./data/docs/chroma_cos",
|
51 |
+
embedding_function=embedding
|
52 |
+
)
|
53 |
+
db_plot = Chroma(
|
54 |
+
persist_directory="./data/docs/chroma_plot",
|
55 |
+
embedding_function=embedding
|
56 |
+
)
|
57 |
+
|
58 |
+
metadata_field_info = [
|
59 |
+
AttributeInfo(
|
60 |
+
name="name",
|
61 |
+
description="The name of the video game on steam",
|
62 |
+
type="string",
|
63 |
+
)
|
64 |
+
]
|
65 |
+
document_content_description = "Brief summary of a video game on Steam"
|
66 |
+
|
67 |
+
|
68 |
+
with st.sidebar: is_plot = st.toggle('Enable Plot')
|
69 |
+
db_selected = db_cos
|
70 |
+
if is_plot: db_selected = db_plot
|
71 |
+
|
72 |
+
|
73 |
+
retriever = SelfQueryRetriever.from_llm(
|
74 |
+
llm,
|
75 |
+
db_selected,
|
76 |
+
document_content_description,
|
77 |
+
metadata_field_info,
|
78 |
+
enable_limit=True,
|
79 |
+
)
|
80 |
+
|
81 |
+
emoji = 'πΉοΈ GameInsightify'
|
82 |
+
st.header(emoji)
|
83 |
+
|
84 |
+
# Initialize chat history
|
85 |
+
if "messages" not in st.session_state:
|
86 |
+
st.session_state.messages = []
|
87 |
+
if 'gamenames' not in st.session_state:
|
88 |
+
st.session_state.gamenames = []
|
89 |
+
|
90 |
+
# Slider on range and button to clear chat history
|
91 |
+
col1, col2= st.columns([8,2])
|
92 |
+
with col1:
|
93 |
+
st.title("Game Recommender")
|
94 |
+
with col2:
|
95 |
+
if st.button("Clear chat"):
|
96 |
+
st.session_state.messages = []
|
97 |
+
st.session_state.gamenames = []
|
98 |
+
|
99 |
+
|
100 |
+
# Display chat messages from history on app rerun
|
101 |
+
tab1, tab2= st.tabs(['Chatbot', ' '])
|
102 |
+
with tab1: # this tab exist becasue i have to limit the height of chatbot
|
103 |
+
for message in st.session_state.messages:
|
104 |
+
with st.chat_message(message["role"]):
|
105 |
+
st.markdown(message["content"])
|
106 |
+
with tab2: pass # this tab exist becasue i have to limit the height of chatbot
|
107 |
+
|
108 |
+
|
109 |
+
# Accept user input
|
110 |
+
if prompt := st.chat_input("Need a game recommendation?"):
|
111 |
+
st.session_state.messages.append({"role": "user", "content": prompt}) # Add user message to chat history
|
112 |
+
with st.chat_message("user"): # Display user message in chat message container
|
113 |
+
st.markdown(prompt)
|
114 |
+
|
115 |
+
|
116 |
+
with st.chat_message("assistant"): # Display assistant response in chat message container
|
117 |
+
message_placeholder = st.empty()
|
118 |
+
|
119 |
+
# docs = db.max_marginal_relevance_search(prompt,k=query_num, fetch_k=10) # Sending query to db
|
120 |
+
docs = retriever.invoke(prompt) # retrieve response from chatgpt
|
121 |
+
full_response = random.choice( # 1st sentence of response
|
122 |
+
["I recommend the following games:\n",
|
123 |
+
f"Hi, human! These are the {len(docs)} best games:\n",
|
124 |
+
f"I bet you will love these {len(docs)} games:\n",]
|
125 |
+
)
|
126 |
+
|
127 |
+
# formatting response from db
|
128 |
+
top_games = []
|
129 |
+
assistant_response = ""
|
130 |
+
for idx, doc in enumerate(docs):
|
131 |
+
gamename = doc.metadata['name']
|
132 |
+
top_games.append(gamename)
|
133 |
+
assistant_response += f"{idx+1}. {gamename}\n"
|
134 |
+
|
135 |
+
# separating response into chunk of words
|
136 |
+
chunks = []
|
137 |
+
for line in assistant_response.splitlines():
|
138 |
+
for word in line.split() : chunks.append(word)
|
139 |
+
chunks.append('\n')
|
140 |
+
chunks = chunks[0:-1]
|
141 |
+
|
142 |
+
# Simulate stream of response with milliseconds delay
|
143 |
+
for chunk in chunks:
|
144 |
+
full_response += chunk + " "
|
145 |
+
time.sleep(0.05)
|
146 |
+
message_placeholder.markdown(full_response + "β") # Add a blinking cursor to simulate typing
|
147 |
+
message_placeholder.markdown(full_response)
|
148 |
+
|
149 |
+
# Add assistant response to chat history
|
150 |
+
st.session_state.messages.append({"role": "assistant", "content": full_response})
|
151 |
+
if is_plot: st.session_state.gamenames.append(top_games)
|
152 |
+
|
153 |
+
col1, col2, col3= st.columns([4,2,4])
|
154 |
+
with col2:
|
155 |
+
if is_plot and db_selected==db_plot:
|
156 |
+
if st.button("Plot Games"): # button in center column
|
157 |
+
switch_page('Overall')
|
158 |
+
|
159 |
+
|
160 |
+
# Styling on Tabs
|
161 |
+
css=f'''
|
162 |
+
div.stTabs {{
|
163 |
+
height: 40vh;
|
164 |
+
overflow-y: scroll;
|
165 |
+
overflow-x: hidden;
|
166 |
+
}}
|
167 |
+
</style>
|
168 |
+
'''
|
169 |
+
st.markdown(f'<style>{css}</style>', unsafe_allow_html=True)
|
README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
---
|
2 |
title: Streamlit
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
colorTo: green
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.27.0
|
8 |
-
app_file:
|
9 |
pinned: false
|
10 |
---
|
|
|
1 |
---
|
2 |
title: Streamlit
|
3 |
+
emoji: πΉοΈ
|
4 |
+
colorFrom: blue
|
5 |
colorTo: green
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.27.0
|
8 |
+
app_file: Home.py
|
9 |
pinned: false
|
10 |
---
|
module/__custom__.py
CHANGED
@@ -39,13 +39,36 @@ def name(target):
|
|
39 |
# Appending favorite game selected by user to filtered list
|
40 |
"""use after search box
|
41 |
"""
|
42 |
-
def add_top_games(top_games,
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
47 |
return top_games
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
# Linear search over all gamenames
|
50 |
def search(target):
|
51 |
gamenames = df['gamename'].unique() # all unique gamenames
|
@@ -65,16 +88,39 @@ def searchbox():
|
|
65 |
)
|
66 |
return selected_game
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
########## PAGE SECTION ##########
|
70 |
# Datafram Section
|
71 |
"""Dataframe
|
72 |
together with Title
|
73 |
"""
|
74 |
-
def dfbox(ax_name, y_name, df_ax):
|
75 |
-
title = f"1.
|
76 |
-
st.
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
# plot 1 Section
|
80 |
"""Plot contains the top ranked games
|
@@ -89,10 +135,15 @@ def plot1_box(ax, y, order_name, ranges, df_ax, top_games):
|
|
89 |
st.subheader(title)
|
90 |
|
91 |
# Plot 1 - select box
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
94 |
options = top_games
|
95 |
-
|
|
|
96 |
|
97 |
# Plot 1
|
98 |
title_names = ','.join(selected_options)
|
@@ -178,6 +229,81 @@ def plot2_box(theme, y, genres, df_bx):
|
|
178 |
with tab3:
|
179 |
st.plotly_chart(fig_sc)
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
|
182 |
##### Execute Page #####
|
183 |
def exec_page(emoji, theme, page_genres):
|
@@ -217,7 +343,7 @@ def exec_page(emoji, theme, page_genres):
|
|
217 |
max = len(max)-1
|
218 |
ranges = st.slider(
|
219 |
label=f'Select range of the {order_name.lower()} games',
|
220 |
-
value = (1,
|
221 |
min_value=1, max_value=30,
|
222 |
# min_value=1, max_value=max,
|
223 |
)
|
@@ -225,7 +351,8 @@ def exec_page(emoji, theme, page_genres):
|
|
225 |
|
226 |
|
227 |
# Dataframe preview
|
228 |
-
|
|
|
229 |
|
230 |
##### PLOT 1 #####
|
231 |
# Plot 1 - markdown
|
@@ -242,7 +369,7 @@ def exec_page_home(theme):
|
|
242 |
st_page_selectbox(theme)
|
243 |
|
244 |
# Header
|
245 |
-
st.header(
|
246 |
st.title("Customized Plot on :blue[General Features]")
|
247 |
|
248 |
##### FILTER #####
|
@@ -266,14 +393,15 @@ def exec_page_home(theme):
|
|
266 |
max = len(max)-1
|
267 |
ranges = st.slider(
|
268 |
label=f'Select range of the {order_name.lower()} games',
|
269 |
-
value = (1,
|
270 |
min_value=1, max_value=30,
|
271 |
# min_value=1, max_value=max,
|
272 |
)
|
273 |
top_games = df_ax.gamename.unique()[ranges[0]-1:ranges[1]]
|
274 |
|
275 |
# Dataframe preview
|
276 |
-
|
|
|
277 |
|
278 |
|
279 |
##### PLOT 1 #####
|
@@ -284,10 +412,15 @@ def exec_page_home(theme):
|
|
284 |
|
285 |
|
286 |
# Plot 1 - select box
|
287 |
-
|
288 |
-
|
|
|
|
|
|
|
|
|
289 |
options = top_games
|
290 |
-
|
|
|
291 |
|
292 |
# Plot 1
|
293 |
title_names = ','.join(selected_options)
|
@@ -359,11 +492,12 @@ def exec_page_pub(emoji, theme, main_genre):
|
|
359 |
top_games = df_ax.gamename.unique()[ranges[0]-1:ranges[1]]
|
360 |
|
361 |
# Dataframe preview
|
362 |
-
|
|
|
363 |
|
364 |
-
title = f"1.2
|
365 |
st.subheader(title)
|
366 |
-
st.
|
367 |
|
368 |
|
369 |
|
|
|
39 |
# Appending favorite game selected by user to filtered list
|
40 |
"""use after search box
|
41 |
"""
|
42 |
+
def add_top_games(top_games, fav_games, ranges, df_ax):
|
43 |
+
ranges_last = ranges[1]
|
44 |
+
for fav in fav_games:
|
45 |
+
if fav in top_games:
|
46 |
+
range_last+=1
|
47 |
+
top_games = df_ax.gamename.unique()[ranges[0]-1:range_last]
|
48 |
+
elif fav!=None:
|
49 |
+
top_games = np.append(top_games, fav)
|
50 |
return top_games
|
51 |
|
52 |
+
def add_list(favorite_game, rec_games):
|
53 |
+
fav_games = []
|
54 |
+
if favorite_game[0]: fav_games = favorite_game
|
55 |
+
if rec_games:
|
56 |
+
fav_games = list(set(fav_games + rec_games))
|
57 |
+
return fav_games
|
58 |
+
|
59 |
+
# fav_games = []
|
60 |
+
# if favorite_game: fav_games = [favorite_game]
|
61 |
+
# if st.session_state.gamenames[-1]:
|
62 |
+
# rec_games = st.session_state.gamenames[-1]
|
63 |
+
# fav_games = list(set(fav_games + rec_games))
|
64 |
+
|
65 |
+
# def add_top_games(top_games, favorite_game, ranges, df_ax):
|
66 |
+
# if favorite_game in top_games:
|
67 |
+
# top_games = df_ax.gamename.unique()[ranges[0]-1:ranges[1]+1]
|
68 |
+
# elif favorite_game!=None:
|
69 |
+
# top_games = np.append(top_games, favorite_game)
|
70 |
+
# return top_games
|
71 |
+
|
72 |
# Linear search over all gamenames
|
73 |
def search(target):
|
74 |
gamenames = df['gamename'].unique() # all unique gamenames
|
|
|
88 |
)
|
89 |
return selected_game
|
90 |
|
91 |
+
# Overloaded with target name
|
92 |
+
def searchbox(target):
|
93 |
+
col1, col2= st.columns([1,1])
|
94 |
+
with col1:
|
95 |
+
selected_game = st_searchbox(
|
96 |
+
search_function=search,
|
97 |
+
key="gamename_searchbox",
|
98 |
+
default_options=target,
|
99 |
+
placeholder="Compare with your Favorite Game...",
|
100 |
+
)
|
101 |
+
return selected_game
|
102 |
|
103 |
########## PAGE SECTION ##########
|
104 |
# Datafram Section
|
105 |
"""Dataframe
|
106 |
together with Title
|
107 |
"""
|
108 |
+
def dfbox(ax_name, y_name, df_ax, ranges, order_name):
|
109 |
+
title = f"1.2 :blue[{ax_name}] Games with the {order_name} :blue[{y_name}]:"
|
110 |
+
with st.sidebar:
|
111 |
+
gamenames = df_ax.gamename.unique()
|
112 |
+
df_names = pd.DataFrame(gamenames, columns=['gamename'])
|
113 |
+
st.write(title)
|
114 |
+
st.dataframe(df_names[ranges[0]:ranges[1]+1])
|
115 |
+
|
116 |
+
def rec_dfbox():
|
117 |
+
title = f"1.1 :blue[Recommended] by :green[GameInsightify]"
|
118 |
+
if len(st.session_state.gamenames) > 0:
|
119 |
+
with st.sidebar:
|
120 |
+
rec_games = st.session_state.gamenames[-1]
|
121 |
+
df_names = pd.DataFrame(rec_games, columns=['gamename'])
|
122 |
+
st.write(title)
|
123 |
+
st.dataframe(df_names[0:len(rec_games)])
|
124 |
|
125 |
# plot 1 Section
|
126 |
"""Plot contains the top ranked games
|
|
|
135 |
st.subheader(title)
|
136 |
|
137 |
# Plot 1 - select box
|
138 |
+
rec_games = []
|
139 |
+
if len(st.session_state.gamenames) > 0 : rec_games = st.session_state.gamenames[-1]
|
140 |
+
favorite_game = searchbox(None) # search box to add a user favorite game on Plot 1
|
141 |
+
fav_games = add_list([favorite_game], rec_games)
|
142 |
+
fav_options = st.multiselect('Select Recommended Games', fav_games)
|
143 |
+
|
144 |
options = top_games
|
145 |
+
selected_tops = st.multiselect('Select Video Games', options)
|
146 |
+
selected_options = add_top_games(selected_tops, fav_options, ranges, df_ax)
|
147 |
|
148 |
# Plot 1
|
149 |
title_names = ','.join(selected_options)
|
|
|
229 |
with tab3:
|
230 |
st.plotly_chart(fig_sc)
|
231 |
|
232 |
+
# Plot 3 - Pie chart
|
233 |
+
import plotly.express as px
|
234 |
+
def plot3_box(theme, labels):
|
235 |
+
title = f"2.1 Ratio of Games Among :blue[{theme}]"
|
236 |
+
st.subheader(title)
|
237 |
+
|
238 |
+
if (type(labels)==str):
|
239 |
+
values = []
|
240 |
+
index = df[labels].unique().tolist()
|
241 |
+
for idx, value in enumerate(index):
|
242 |
+
count = len(df[df[labels] == value])
|
243 |
+
values.append(count)
|
244 |
+
if(count/len(df) < 0.02): index[idx] = 'Other'
|
245 |
+
|
246 |
+
df_p = pd.DataFrame(data = values,
|
247 |
+
index = index,
|
248 |
+
columns = ['counts'])
|
249 |
+
df_p = df_p.reset_index().rename(columns={'index':labels})
|
250 |
+
fig_ratio = px.pie(df_p, values='counts', names=labels)
|
251 |
+
st.plotly_chart(fig_ratio)
|
252 |
+
|
253 |
+
else:
|
254 |
+
values = []
|
255 |
+
for label in labels:
|
256 |
+
value = len(df[df[label]==1])
|
257 |
+
values.append(value)
|
258 |
+
|
259 |
+
fig_ratio = go.Figure(data=[go.Pie(labels=labels, values=values)])
|
260 |
+
st.plotly_chart(fig_ratio)
|
261 |
+
|
262 |
+
# Could not overload function, so renamed it
|
263 |
+
def plot3_box_limit(theme, labels, limit_perc):
|
264 |
+
title = f"2.1 Ratio of Games Among :blue[{theme}] over :blue[{limit_perc*100}%]"
|
265 |
+
st.subheader(title)
|
266 |
+
|
267 |
+
values = []
|
268 |
+
index = df[labels].unique().tolist()
|
269 |
+
for idx, value in enumerate(index):
|
270 |
+
count = len(df[df[labels] == value])
|
271 |
+
values.append(count)
|
272 |
+
if(count/len(df) < limit_perc): index[idx] = 'Other'
|
273 |
+
|
274 |
+
df_p = pd.DataFrame(data = values,
|
275 |
+
index = index,
|
276 |
+
columns = ['counts'])
|
277 |
+
df_p = df_p.reset_index().rename(columns={'index':labels})
|
278 |
+
fig_ratio = px.pie(df_p, values='counts', names=labels)
|
279 |
+
st.plotly_chart(fig_ratio)
|
280 |
+
|
281 |
+
def plot_chat_box(y, query_num, top_games):
|
282 |
+
y_name = name(y) # formeting strings
|
283 |
+
|
284 |
+
title = f"1.2 Comparison on The {query_num} Best Recommended Games on :blue[{y_name}]"
|
285 |
+
st.subheader(title)
|
286 |
+
|
287 |
+
# Plot 1 - select box # search box to add a user favorite game on Plot 1
|
288 |
+
options = top_games
|
289 |
+
selected_options = st.multiselect('Select Video Games', options)
|
290 |
+
|
291 |
+
# Plot 1
|
292 |
+
title_names = ','.join(selected_options)
|
293 |
+
plot_title = f"Monthly {y_name} of {title_names} Over Time"
|
294 |
+
gb = df.sort_values(by='date')
|
295 |
+
gb_list = {game: gb[gb["gamename"] == game] for game in selected_options}
|
296 |
+
|
297 |
+
fig_1 = go.Figure()
|
298 |
+
fig_1.update_layout(
|
299 |
+
title = plot_title,
|
300 |
+
xaxis_title = 'Date',
|
301 |
+
yaxis_title = y_name,
|
302 |
+
)
|
303 |
+
for game, gb in gb_list.items():
|
304 |
+
fig_1 = fig_1.add_trace(go.Scatter(x=gb["date"], y=gb[y], name=game, mode='lines'))
|
305 |
+
st.plotly_chart(fig_1)
|
306 |
+
|
307 |
|
308 |
##### Execute Page #####
|
309 |
def exec_page(emoji, theme, page_genres):
|
|
|
343 |
max = len(max)-1
|
344 |
ranges = st.slider(
|
345 |
label=f'Select range of the {order_name.lower()} games',
|
346 |
+
value = (1, 3),
|
347 |
min_value=1, max_value=30,
|
348 |
# min_value=1, max_value=max,
|
349 |
)
|
|
|
351 |
|
352 |
|
353 |
# Dataframe preview
|
354 |
+
rec_dfbox()
|
355 |
+
dfbox(ax_name, y_name, df_ax, ranges, order_name)
|
356 |
|
357 |
##### PLOT 1 #####
|
358 |
# Plot 1 - markdown
|
|
|
369 |
st_page_selectbox(theme)
|
370 |
|
371 |
# Header
|
372 |
+
st.header("π")
|
373 |
st.title("Customized Plot on :blue[General Features]")
|
374 |
|
375 |
##### FILTER #####
|
|
|
393 |
max = len(max)-1
|
394 |
ranges = st.slider(
|
395 |
label=f'Select range of the {order_name.lower()} games',
|
396 |
+
value = (1, 3),
|
397 |
min_value=1, max_value=30,
|
398 |
# min_value=1, max_value=max,
|
399 |
)
|
400 |
top_games = df_ax.gamename.unique()[ranges[0]-1:ranges[1]]
|
401 |
|
402 |
# Dataframe preview
|
403 |
+
rec_dfbox()
|
404 |
+
dfbox("", y_name, df_ax, ranges, order_name)
|
405 |
|
406 |
|
407 |
##### PLOT 1 #####
|
|
|
412 |
|
413 |
|
414 |
# Plot 1 - select box
|
415 |
+
rec_games = []
|
416 |
+
if len(st.session_state.gamenames)>0: rec_games = st.session_state.gamenames[-1]
|
417 |
+
favorite_game = searchbox(None) # search box to add a user favorite game on Plot 1
|
418 |
+
fav_games = add_list([favorite_game], rec_games)
|
419 |
+
fav_options = st.multiselect('Select Recommended Games', fav_games)
|
420 |
+
|
421 |
options = top_games
|
422 |
+
selected_tops = st.multiselect('Select Video Games', options)
|
423 |
+
selected_options = add_top_games(selected_tops, fav_options, ranges, df_ax)
|
424 |
|
425 |
# Plot 1
|
426 |
title_names = ','.join(selected_options)
|
|
|
492 |
top_games = df_ax.gamename.unique()[ranges[0]-1:ranges[1]]
|
493 |
|
494 |
# Dataframe preview
|
495 |
+
rec_dfbox()
|
496 |
+
dfbox(ax_name, y_name, df_ax, ranges, order_name)
|
497 |
|
498 |
+
title = f"1.2 5 :blue[{theme}s] with the :red[{order_name}] Monthly :blue[{y_name}]:"
|
499 |
st.subheader(title)
|
500 |
+
st.dataframe(genres[0:5])
|
501 |
|
502 |
|
503 |
|
module/__selectpage__.py
CHANGED
@@ -2,18 +2,13 @@ import streamlit as st
|
|
2 |
from streamlit_extras.switch_page_button import switch_page
|
3 |
import os
|
4 |
|
5 |
-
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
|
12 |
-
pages = [
|
13 |
-
"Overall",
|
14 |
-
"Category", "Genre", "DLC Counts", "Price", "Age Restriction",
|
15 |
-
"Settings", "OS", "Publisher", "Developer",
|
16 |
-
]
|
17 |
|
18 |
def st_page_selectbox(current_page):
|
19 |
current_index = pages.index(current_page)
|
|
|
2 |
from streamlit_extras.switch_page_button import switch_page
|
3 |
import os
|
4 |
|
5 |
+
pages = ["Overall"]
|
6 |
|
7 |
+
files = os.listdir('.\pages')
|
8 |
+
for name in files:
|
9 |
+
name = name.split()[1].replace('.py', '').replace('_', ' ')
|
10 |
+
pages.append(name)
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
def st_page_selectbox(current_page):
|
14 |
current_index = pages.index(current_page)
|
Overall.py β pages/01 Overall.py
RENAMED
File without changes
|
pages/{01 Category.py β 02 Category.py}
RENAMED
@@ -5,6 +5,8 @@ from module.__custom__ import *
|
|
5 |
theme = "Category"
|
6 |
page_genres = ['multi_player', 'pvp', 'co-op', 'single_player']
|
7 |
add_genre = ['single_player', 'multi_player']
|
|
|
8 |
|
9 |
add_opp_features(add_genre)
|
10 |
-
exec_page('π€Ό', theme, page_genres)
|
|
|
|
5 |
theme = "Category"
|
6 |
page_genres = ['multi_player', 'pvp', 'co-op', 'single_player']
|
7 |
add_genre = ['single_player', 'multi_player']
|
8 |
+
labels = ['pvp', 'co-op', 'single_player']
|
9 |
|
10 |
add_opp_features(add_genre)
|
11 |
+
exec_page('π€Ό', theme, page_genres)
|
12 |
+
plot3_box(theme, labels)
|
pages/03 DLC_Counts.py
CHANGED
@@ -11,8 +11,11 @@ add_genres = [[0, 1, 'dlc_0', 'dlc_count'],
|
|
11 |
[41, 101, 'dlc_100', 'dlc_count'],
|
12 |
[101, 301, 'dlc_300', 'dlc_count'],
|
13 |
[301, 9999, 'dlc_most', 'dlc_count']]
|
|
|
|
|
14 |
|
15 |
# ### adding single-player feature ###
|
16 |
for add in add_genres:
|
17 |
add_range_features(add)
|
18 |
-
exec_page('πͺ', theme, page_genres)
|
|
|
|
11 |
[41, 101, 'dlc_100', 'dlc_count'],
|
12 |
[101, 301, 'dlc_300', 'dlc_count'],
|
13 |
[301, 9999, 'dlc_most', 'dlc_count']]
|
14 |
+
labels = 'dlc_count'
|
15 |
+
|
16 |
|
17 |
# ### adding single-player feature ###
|
18 |
for add in add_genres:
|
19 |
add_range_features(add)
|
20 |
+
exec_page('πͺ', theme, page_genres)
|
21 |
+
plot3_box(theme, labels)
|
pages/{02 Genre.py β 04 Genre.py}
RENAMED
@@ -7,6 +7,16 @@ page_genres = ['genre_action', 'genre_adventure', 'genre_casual',
|
|
7 |
'genre_sexual_content', 'genre_strategy', 'genre_sports',
|
8 |
'genre_racing', 'genre_rpg', 'genre_simulation', 'indie', 'mainstream']
|
9 |
add_genre = ['mainstream', 'indie']
|
|
|
|
|
|
|
|
|
10 |
|
11 |
add_opp_features(add_genre)
|
12 |
-
exec_page('π¦ΉββοΈ', theme, page_genres)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
'genre_sexual_content', 'genre_strategy', 'genre_sports',
|
8 |
'genre_racing', 'genre_rpg', 'genre_simulation', 'indie', 'mainstream']
|
9 |
add_genre = ['mainstream', 'indie']
|
10 |
+
labels = ['genre_action', 'genre_adventure', 'genre_casual',
|
11 |
+
'genre_sexual_content', 'genre_strategy', 'genre_sports',
|
12 |
+
'genre_racing', 'genre_rpg', 'genre_simulation']
|
13 |
+
labels_2 = add_genre
|
14 |
|
15 |
add_opp_features(add_genre)
|
16 |
+
exec_page('π¦ΉββοΈ', theme, page_genres)
|
17 |
+
|
18 |
+
tab1, tab2= st.tabs(['Genre ratio', 'Indie versus mainstream ratio'])
|
19 |
+
with tab1:
|
20 |
+
plot3_box(theme, labels)
|
21 |
+
with tab2:
|
22 |
+
plot3_box(theme, labels_2)
|
pages/{04 Price.py β 05 Price.py}
RENAMED
@@ -12,8 +12,10 @@ add_genres = [[0, 0.001, 'price_free', 'price'],
|
|
12 |
[20.001, 40.001, 'price_40', 'price'],
|
13 |
[40.001, 60.001, 'price_60', 'price'],
|
14 |
[60.001, 9999, 'price_most', 'price']]
|
|
|
15 |
|
16 |
# ### adding single-player feature ###
|
17 |
for add in add_genres:
|
18 |
add_range_features(add)
|
19 |
-
exec_page('πΈ', theme, page_genres)
|
|
|
|
12 |
[20.001, 40.001, 'price_40', 'price'],
|
13 |
[40.001, 60.001, 'price_60', 'price'],
|
14 |
[60.001, 9999, 'price_most', 'price']]
|
15 |
+
labels = 'price'
|
16 |
|
17 |
# ### adding single-player feature ###
|
18 |
for add in add_genres:
|
19 |
add_range_features(add)
|
20 |
+
exec_page('πΈ', theme, page_genres)
|
21 |
+
plot3_box(theme, labels)
|
pages/{05 Age_Restriction.py β 06 Age_Restriction.py}
RENAMED
@@ -1,7 +1,10 @@
|
|
1 |
import streamlit as st
|
2 |
|
3 |
-
from module.__custom__ import
|
4 |
|
5 |
theme = "Age Restriction"
|
6 |
page_genres = ['age_0_plus', 'age_13_plus', 'age_18_plus']
|
7 |
-
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
|
3 |
+
from module.__custom__ import *
|
4 |
|
5 |
theme = "Age Restriction"
|
6 |
page_genres = ['age_0_plus', 'age_13_plus', 'age_18_plus']
|
7 |
+
labels = page_genres
|
8 |
+
|
9 |
+
exec_page('π΄', theme, page_genres)
|
10 |
+
plot3_box(theme, labels)
|
pages/{06 Settings.py β 07 Settings.py}
RENAMED
@@ -5,8 +5,16 @@ from module.__custom__ import *
|
|
5 |
theme = "Settings"
|
6 |
page_genres = ['full_audio', 'full_controller_support', 'not_full_audio', 'not_full_controller']
|
7 |
add_genres = [['not_full_audio', 'full_audio'], ['not_full_controller', 'full_controller_support'] ]
|
|
|
|
|
8 |
|
9 |
# ### adding single-player feature ###
|
10 |
for add in add_genres:
|
11 |
add_opp_features(add)
|
12 |
-
exec_page('π§', theme, page_genres)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
theme = "Settings"
|
6 |
page_genres = ['full_audio', 'full_controller_support', 'not_full_audio', 'not_full_controller']
|
7 |
add_genres = [['not_full_audio', 'full_audio'], ['not_full_controller', 'full_controller_support'] ]
|
8 |
+
labels = ['not_full_controller', 'full_controller_support']
|
9 |
+
labels_2 = ['not_full_audio', 'full_audio']
|
10 |
|
11 |
# ### adding single-player feature ###
|
12 |
for add in add_genres:
|
13 |
add_opp_features(add)
|
14 |
+
exec_page('π§', theme, page_genres)
|
15 |
+
tab1, tab2= st.tabs(['Controller support ratio', 'Full audio ratio'])
|
16 |
+
with tab1:
|
17 |
+
plot3_box(theme, labels)
|
18 |
+
with tab2:
|
19 |
+
plot3_box(theme, labels_2)
|
20 |
+
|
pages/{07 OS.py β 08 OS.py}
RENAMED
@@ -5,8 +5,18 @@ from module.__custom__ import *
|
|
5 |
theme = "OS"
|
6 |
page_genres = ['windows', 'mac', 'linux', 'not_windows', 'not_mac', 'not_linux']
|
7 |
add_genres = [['not_windows', 'windows'], ['not_mac', 'mac'], ['not_linux', 'linux'] ]
|
|
|
|
|
|
|
8 |
|
9 |
# ### adding single-player feature ###
|
10 |
for add in add_genres:
|
11 |
add_opp_features(add)
|
12 |
-
exec_page('π₯', theme, page_genres)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
theme = "OS"
|
6 |
page_genres = ['windows', 'mac', 'linux', 'not_windows', 'not_mac', 'not_linux']
|
7 |
add_genres = [['not_windows', 'windows'], ['not_mac', 'mac'], ['not_linux', 'linux'] ]
|
8 |
+
labels = ['not_windows', 'windows']
|
9 |
+
labels_2 = ['not_mac', 'mac']
|
10 |
+
labels_3 = ['not_linux', 'linux']
|
11 |
|
12 |
# ### adding single-player feature ###
|
13 |
for add in add_genres:
|
14 |
add_opp_features(add)
|
15 |
+
exec_page('π₯', theme, page_genres)
|
16 |
+
tab1, tab2, tab3 = st.tabs(['Windows game ratio', 'Mac game ratio', 'Linux game ratio'])
|
17 |
+
with tab1:
|
18 |
+
plot3_box(theme, labels)
|
19 |
+
with tab2:
|
20 |
+
plot3_box(theme, labels_2)
|
21 |
+
with tab3:
|
22 |
+
plot3_box(theme, labels_3)
|
pages/{08 Publisher.py β 09 Publisher.py}
RENAMED
@@ -4,5 +4,7 @@ from module.__custom__ import *
|
|
4 |
|
5 |
theme = "Publisher"
|
6 |
main_genre = "publishers"
|
|
|
7 |
|
8 |
-
exec_page_pub('π', theme, main_genre)
|
|
|
|
4 |
|
5 |
theme = "Publisher"
|
6 |
main_genre = "publishers"
|
7 |
+
labels = main_genre
|
8 |
|
9 |
+
exec_page_pub('π', theme, main_genre)
|
10 |
+
plot3_box_limit(theme, labels, 0.01)
|
pages/{09 Developer.py β 10 Developer.py}
RENAMED
@@ -4,5 +4,7 @@ from module.__custom__ import *
|
|
4 |
|
5 |
theme = "Developer"
|
6 |
main_genre = "developers"
|
|
|
7 |
|
8 |
-
exec_page_pub('π½', theme, main_genre)
|
|
|
|
4 |
|
5 |
theme = "Developer"
|
6 |
main_genre = "developers"
|
7 |
+
labels = main_genre
|
8 |
|
9 |
+
exec_page_pub('π½', theme, main_genre)
|
10 |
+
plot3_box_limit(theme, labels, 0.005)
|