shikharyashmaurya's picture
Rename user-authenticated-revision-app5.py to app.py
62080fb verified
raw
history blame
10.5 kB
import streamlit as st
import networkx as nx
import matplotlib.pyplot as plt
import textwrap
from io import BytesIO
import uuid
class RevisionApp:
def __init__(self):
self.initialize_session_state()
self.handle_user_selection()
self.create_ui()
def initialize_session_state(self):
if 'users' not in st.session_state:
st.session_state.users = {}
if 'current_user' not in st.session_state:
st.session_state.current_user = None
if 'user_sessions' not in st.session_state:
st.session_state.user_sessions = {}
def handle_user_selection(self):
st.sidebar.title("User Selection")
user_name = st.sidebar.text_input("Enter your name:")
if st.sidebar.button("Set User"):
if user_name:
# Check if the username is already in use in this session
if user_name in st.session_state.user_sessions:
st.sidebar.error(f"The name '{user_name}' is already in use. Please choose a different name.")
else:
# Generate a unique session ID for this user
session_id = str(uuid.uuid4())
st.session_state.current_user = f"{user_name}_{session_id}"
st.session_state.user_sessions[user_name] = session_id
if st.session_state.current_user not in st.session_state.users:
st.session_state.users[st.session_state.current_user] = {}
st.success(f"User set to: {user_name}")
st.experimental_rerun()
def create_ui(self):
if st.session_state.current_user:
display_name = st.session_state.current_user.split('_')[0] # Extract the user's name without the session ID
st.title(f"Concept Revision App - Welcome, {display_name}!")
# Navigation
page = st.sidebar.selectbox("Choose a page", ["Tree View", "Mind Map", "Search"])
if page == "Tree View":
self.show_tree_view()
elif page == "Mind Map":
self.show_mind_map()
elif page == "Search":
self.show_search()
else:
st.title("Concept Revision App")
st.write("Please enter your name in the sidebar to begin.")
# The rest of the methods (show_tree_view, show_concept_details, show_mind_map, show_search, search_data, custom_tree_layout)
# remain the same as in the previous version, just ensure you're using st.session_state.current_user
# to access the correct user data in st.session_state.users
# Example of how to modify a method to use the new user identifier:
def show_tree_view(self):
st.header("Tree View")
# Input for new concept
new_key = st.text_input("Enter a new concept:")
if st.button("Add Concept"):
if new_key and new_key not in st.session_state.users[st.session_state.current_user]:
st.session_state.users[st.session_state.current_user][new_key] = {'next': [], 'text': []}
st.success(f"Added new concept: {new_key}")
st.experimental_rerun()
# Display concepts
user_data = st.session_state.users[st.session_state.current_user]
selected_concept = st.selectbox("Select a concept to view details:",
options=[""] + list(user_data.keys()))
if selected_concept:
self.show_concept_details(selected_concept)
# ... (other methods remain the same, just ensure you're using st.session_state.current_user consistently)
# def show_tree_view(self):
# st.header("Tree View")
# # Input for new concept
# new_key = st.text_input("Enter a new concept:")
# if st.button("Add Concept"):
# if new_key and new_key not in st.session_state.users[st.session_state.current_user]:
# st.session_state.users[st.session_state.current_user][new_key] = {'next': [], 'text': []}
# st.success(f"Added new concept: {new_key}")
# st.experimental_rerun()
# # Display concepts
# user_data = st.session_state.users[st.session_state.current_user]
# selected_concept = st.selectbox("Select a concept to view details:",
# options=[""] + list(user_data.keys()))
# if selected_concept:
# self.show_concept_details(selected_concept)
def show_concept_details(self, key):
user_data = st.session_state.users[st.session_state.current_user]
st.subheader(f"Concept: {key}")
# Display related concepts
st.write("Related Concepts:")
for next_item in user_data[key]['next']:
if st.button(f"Go to {next_item}", key=f"goto_{next_item}"):
self.show_concept_details(next_item)
return
# Add related concept
new_related = st.text_input(f"Add related concept to {key}:", key=f"related_{key}")
if st.button(f"Add related to {key}", key=f"add_related_{key}"):
if new_related and new_related not in user_data[key]['next']:
if new_related not in user_data:
user_data[new_related] = {'next': [], 'text': []}
user_data[key]['next'].append(new_related)
st.success(f"Added {new_related} as related to {key}")
st.experimental_rerun()
# Display information
st.write("Information:")
for i, text_item in enumerate(user_data[key]['text']):
st.text_area(f"Info {i+1}", value=text_item, key=f"info_{key}_{i}", height=100, disabled=True)
# Add information
new_info = st.text_area(f"Add information to {key}:", key=f"new_info_{key}")
if st.button(f"Add info to {key}", key=f"add_info_{key}"):
if new_info:
user_data[key]['text'].append(new_info)
st.success(f"Added new information to {key}")
st.experimental_rerun()
def show_mind_map(self):
st.header("Mind Map")
user_data = st.session_state.users[st.session_state.current_user]
G = nx.Graph()
for key, value in user_data.items():
G.add_node(key)
for next_item in value['next']:
if next_item in user_data:
G.add_edge(key, next_item)
pos = self.custom_tree_layout(G)
plt.figure(figsize=(12, 8))
nx.draw(G, pos, with_labels=False, node_color='lightblue', node_size=3000, alpha=0.8)
for node, (x, y) in pos.items():
lines = textwrap.wrap(node, width=10)
plt.annotate('\n'.join(lines), (x, y), horizontalalignment='center', verticalalignment='center')
plt.axis('off')
buf = BytesIO()
plt.savefig(buf, format="png")
buf.seek(0)
st.image(buf, caption='Mind Map', use_column_width=True)
def show_search(self):
st.header("Search")
query = st.text_input("Enter search term:")
if st.button("Search"):
results = self.search_data(query)
if results:
for key in results:
with st.expander(f"Concept: {key}"):
st.write("Related Concepts:")
for related in st.session_state.users[st.session_state.current_user][key]['next']:
st.write(f"- {related}")
st.write("Information:")
for info in st.session_state.users[st.session_state.current_user][key]['text']:
st.write(f"- {info}")
else:
st.write("No results found.")
def search_data(self, query):
query = query.lower()
user_data = st.session_state.users[st.session_state.current_user]
results = set()
for key, value in user_data.items():
if query in key.lower():
results.add(key)
for next_item in value['next']:
if query in next_item.lower():
results.add(key)
for text_item in value['text']:
if query in text_item.lower():
results.add(key)
return list(results)
def custom_tree_layout(self, G):
if not G.nodes():
return {}
def bfs_tree(root):
tree = nx.bfs_tree(G, root)
return tree
def assign_positions(tree, root):
pos = {}
level_width = {}
max_depth = 0
def dfs(node, depth, order):
nonlocal max_depth
max_depth = max(max_depth, depth)
if depth not in level_width:
level_width[depth] = 0
level_width[depth] += 1
children = list(tree.successors(node))
if not children:
pos[node] = (order, -depth)
return order + 1
start = order
for child in children:
order = dfs(child, depth + 1, order)
pos[node] = (start + (order - start - 1) / 2, -depth)
return order
dfs(root, 0, 0)
# Normalize positions
max_width = max(level_width.values()) if level_width else 1
for node in pos:
x, y = pos[node]
pos[node] = (x / max_width, y / max_depth if max_depth != 0 else 0)
return pos
# Handle disconnected components
components = list(nx.connected_components(G))
if not components:
return {}
pos = {}
y_offset = 0
for component in components:
subgraph = G.subgraph(component)
root = max(subgraph.nodes(), key=lambda n: subgraph.degree(n))
tree = bfs_tree(root)
component_pos = assign_positions(tree, root)
# Adjust y-positions for each component
for node, (x, y) in component_pos.items():
pos[node] = (x, y + y_offset)
y_offset -= 1.5 # Increase vertical separation between components
return pos
if __name__ == "__main__":
app = RevisionApp()