a personalized learning app
To upload files, please first save the app
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, Boolean, Text
from sqlalchemy.orm import DeclarativeBase, Session
# Database setup
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True, nullable=False)
learning_style = Column(String(20)) # visual, auditory, kinesthetic, reading
difficulty_preference = Column(String(20)) # beginner, intermediate, advanced
created_at = Column(DateTime, default=datetime.utcnow)
class Topic(Base):
__tablename__ = 'topics'
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
category = Column(String(50))
difficulty = Column(String(20))
description = Column(Text)
class UserProgress(Base):
__tablename__ = 'user_progress'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, nullable=False)
topic_id = Column(Integer, nullable=False)
score = Column(Float)
completed = Column(Boolean, default=False)
time_spent = Column(Integer) # minutes
last_accessed = Column(DateTime, default=datetime.utcnow)
class Quiz(Base):
__tablename__ = 'quizzes'
id = Column(Integer, primary_key=True)
topic_id = Column(Integer, nullable=False)
question = Column(Text, nullable=False)
correct_answer = Column(String(200))
options = Column(Text) # JSON string of options
difficulty = Column(String(20))
# Create database
engine = create_engine("sqlite:///learning.db")
Base.metadata.create_all(bind=engine)
# Initialize sample data
def init_sample_data():
with Session(engine) as session:
# Check if data already exists
if session.query(Topic).count() > 0:
return
# Sample topics
topics = [
Topic(name="Python Basics", category="Programming", difficulty="beginner",
description="Learn fundamental Python concepts like variables, loops, and functions."),
Topic(name="Data Structures", category="Programming", difficulty="intermediate",
description="Understand lists, dictionaries, sets, and their applications."),
Topic(name="Machine Learning", category="AI", difficulty="advanced",
description="Introduction to ML algorithms and their implementations."),
Topic(name="Web Development", category="Programming", difficulty="intermediate",
description="Build web applications using modern frameworks."),
Topic(name="Database Design", category="Data", difficulty="intermediate",
description="Learn to design efficient database schemas."),
]
# Sample quizzes
quizzes = [
Quiz(topic_id=1, question="What is a variable in Python?",
correct_answer="A container for storing data values",
options='["A container for storing data values", "A function", "A loop", "A class"]',
difficulty="beginner"),
Quiz(topic_id=1, question="Which keyword is used to define a function in Python?",
correct_answer="def",
options='["def", "function", "func", "define"]',
difficulty="beginner"),
Quiz(topic_id=2, question="Which data structure allows duplicate values?",
correct_answer="List",
options='["Set", "List", "Dictionary", "Tuple"]',
difficulty="intermediate"),
]
session.add_all(topics + quizzes)
session.commit()
init_sample_data()
# Streamlit App
st.set_page_config(page_title="Personalized Learning App", page_icon="🎓", layout="wide")
# Navigation
pages = {
"🏠 Dashboard": "dashboard",
"📚 Learn": "learn",
"📊 Progress": "progress",
"👤 Profile": "profile"
}
if 'current_user' not in st.session_state:
st.session_state.current_user = None
if 'current_page' not in st.session_state:
st.session_state.current_page = 'dashboard'
# Sidebar navigation
with st.sidebar:
st.title("🎓 Learning Hub")
# User authentication
if st.session_state.current_user is None:
st.subheader("Login / Register")
username = st.text_input("Username")
col1, col2 = st.columns(2)
with col1:
if st.button("Login"):
with Session(engine) as session:
user = session.query(User).filter(User.username == username).first()
if user:
st.session_state.current_user = user.id
st.success("Logged in!")
st.rerun()
else:
st.error("User not found")
with col2:
if st.button("Register"):
if username:
with Session(engine) as session:
existing = session.query(User).filter(User.username == username).first()
if not existing:
new_user = User(username=username, learning_style="visual", difficulty_preference="beginner")
session.add(new_user)
session.commit()
st.session_state.current_user = new_user.id
st.success("Registered and logged in!")
st.rerun()
else:
st.error("Username already exists")
else:
with Session(engine) as session:
user = session.query(User).filter(User.id == st.session_state.current_user).first()
st.write(f"Welcome, **{user.username}**!")
if st.button("Logout"):
st.session_state.current_user = None
st.rerun()
st.divider()
# Navigation
for page_name, page_key in pages.items():
if st.button(page_name, use_container_width=True):
st.session_state.current_page = page_key
st.rerun()
# Main content
if st.session_state.current_user is None:
st.title("🎓 Welcome to Personalized Learning")
st.markdown("""
### Your AI-Powered Learning Companion
- **Adaptive Learning**: Content adapts to your learning style and pace
- **Progress Tracking**: Monitor your learning journey with detailed analytics
- **Personalized Recommendations**: Get topics suggested based on your interests
- **Interactive Quizzes**: Test your knowledge with tailored assessments
**Get started by creating an account or logging in!**
""")
# Demo metrics
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Active Learners", "1,234")
with col2:
st.metric("Learning Paths", "56")
with col3:
st.metric("Completed Courses", "8,901")
with col4:
st.metric("Success Rate", "94%")
else:
# Dashboard
if st.session_state.current_page == 'dashboard':
st.title("📊 Learning Dashboard")
with Session(engine) as session:
user = session.query(User).filter(User.id == st.session_state.current_user).first()
progress_data = session.query(UserProgress).filter(UserProgress.user_id == st.session_state.current_user).all()
topics = session.query(Topic).all()
# Metrics
total_topics = len(topics)
completed_topics = len([p for p in progress_data if p.completed])
avg_score = np.mean([p.score for p in progress_data if p.score]) if progress_data else 0
total_time = sum([p.time_spent for p in progress_data if p.time_spent]) if progress_data else 0
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Topics Completed", f"{completed_topics}/{total_topics}")
with col2:
st.metric("Average Score", f"{avg_score:.1f}%")
with col3:
st.metric("Time Spent", f"{total_time} min")
with col4:
st.metric("Streak", "7 days 🔥")
# Recent activity and recommendations
col1, col2 = st.columns(2)
with col1:
st.subheader("📈 Progress Overview")
if progress_data:
progress_df = pd.DataFrame([{
'Topic': next((t.name for t in topics if t.id == p.topic_id), 'Unknown'),
'Score': p.score or 0,
'Completed': p.completed,
'Time': p.time_spent or 0
} for p in progress_data])
fig = px.bar(progress_df, x='Topic', y='Score',
title="Scores by Topic", color='Completed')
st.plotly_chart(fig, use_container_width=True)
else:
st.info("Start learning to see your progress!")
with col2:
st.subheader("🎯 Recommended for You")
st.markdown(f"**Learning Style**: {user.learning_style.title()}")
st.markdown(f"**Preference**: {user.difficulty_preference.title()}")
# Filter recommendations based on user preference
recommended = [t for t in topics if t.difficulty == user.difficulty_preference][:3]
for topic in recommended:
with st.container():
st.markdown(f"**{topic.name}** ({topic.difficulty})")
st.markdown(f"*{topic.description}*")
if st.button(f"Start Learning", key=f"rec_{topic.id}"):
st.session_state.current_page = 'learn'
st.session_state.selected_topic = topic.id
st.rerun()
st.divider()
# Learning Page
elif st.session_state.current_page == 'learn':
st.title("📚 Learning Center")
with Session(engine) as session:
topics = session.query(Topic).all()
# Topic selection
if 'selected_topic' not in st.session_state:
st.subheader("Choose a Topic")
# Filter options
col1, col2 = st.columns(2)
with col1:
category_filter = st.selectbox("Category", ["All"] + list(set(t.category for t in topics)))
with col2:
difficulty_filter = st.selectbox("Difficulty", ["All", "beginner", "intermediate", "advanced"])
# Filter topics
filtered_topics = topics
if category_filter != "All":
filtered_topics = [t for t in filtered_topics if t.category == category_filter]
if difficulty_filter != "All":
filtered_topics = [t for t in filtered_topics if t.difficulty == difficulty_filter]
# Display topics
for topic in filtered_topics:
with st.container():
col1, col2 = st.columns([3, 1])
with col1:
st.markdown(f"### {topic.name}")
st.markdown(f"**Category**: {topic.category} | **Difficulty**: {topic.difficulty}")
st.markdown(topic.description)
with col2:
if st.button("Start", key=f"start_{topic.id}"):
st.session_state.selected_topic = topic.id
st.rerun()
st.divider()
else:
# Learning interface
topic = session.query(Topic).filter(Topic.id == st.session_state.selected_topic).first()
st.subheader(f"Learning: {topic.name}")
if st.button("← Back to Topics"):
del st.session_state.selected_topic
st.rerun()
# Learning content
tab1, tab2 = st.tabs(["📖 Content", "❓ Quiz"])
with tab1:
st.markdown(f"""
## {topic.name}
{topic.description}
### Key Concepts:
- Interactive learning materials
- Hands-on examples
- Practice exercises
- Real-world applications
*This is where the actual learning content would be displayed based on the topic.*
""")
# Simulate learning time
if st.button("Mark as Studied"):
progress = session.query(UserProgress).filter(
UserProgress.user_id == st.session_state.current_user,
UserProgress.topic_id == topic.id
).first()
if not progress:
progress = UserProgress(
user_id=st.session_state.current_user,
topic_id=topic.id,
time_spent=30,
last_accessed=datetime.utcnow()
)
session.add(progress)
else:
progress.time_spent = (progress.time_spent or 0) + 30
progress.last_accessed = datetime.utcnow()
session.commit()
st.success("Progress saved!")
with tab2:
quizzes = session.query(Quiz).filter(Quiz.topic_id == topic.id).all()
if quizzes:
st.markdown("### Test Your Knowledge")
for i, quiz in enumerate(quizzes):
st.markdown(f"**Question {i+1}**: {quiz.question}")
import json
options = json.loads(quiz.options)
selected = st.radio(f"Choose your answer:", options, key=f"quiz_{quiz.id}")
if st.button(f"Submit Answer", key=f"submit_{quiz.id}"):
if selected == quiz.correct_answer:
st.success("Correct! ✅")
score = 100
else:
st.error(f"Incorrect. The correct answer is: {quiz.correct_answer}")
score = 0
# Update progress
progress = session.query(UserProgress).filter(
UserProgress.user_id == st.session_state.current_user,
UserProgress.topic_id == topic.id
).first()
if not progress:
progress = UserProgress(
user_id=st.session_state.current_user,
topic_id=topic.id,
score=score,
completed=True,
last_accessed=datetime.utcnow()
)
session.add(progress)
else:
progress.score = score
progress.completed = True
progress.last_accessed = datetime.utcnow()
session.commit()
st.divider()
else:
st.info("No quizzes available for this topic yet.")
# Progress Page
elif st.session_state.current_page == 'progress':
st.title("📊 Learning Progress")
with Session(engine) as session:
progress_data = session.query(UserProgress).filter(UserProgress.user_id == st.session_state.current_user).all()
topics = session.query(Topic).all()
if progress_data:
# Progress overview
progress_df = pd.DataFrame([{
'Topic': next((t.name for t in topics if t.id == p.topic_id), 'Unknown'),
'Category': next((t.category for t in topics if t.id == p.topic_id), 'Unknown'),
'Score': p.score or 0,
'Completed': p.completed,
'Time Spent': p.time_spent or 0,
'Last Accessed': p.last_accessed.strftime('%Y-%m-%d') if p.last_accessed else 'Never'
} for p in progress_data])
# Charts
col1, col2 = st.columns(2)
with col1:
fig = px.pie(progress_df, names='Category', title="Time by Category", values='Time Spent')
st.plotly_chart(fig, use_container_width=True)
with col2:
fig = px.scatter(progress_df, x='Time Spent', y='Score',
title="Score vs Time Spent", hover_data=['Topic'])
st.plotly_chart(fig, use_container_width=True)
# Progress table
st.subheader("Detailed Progress")
st.dataframe(progress_df, use_container_width=True)
# Learning streak simulation
st.subheader("🔥 Learning Streak")
dates = pd.date_range(end=datetime.now(), periods=30, freq='D')
activity = np.random.choice([0, 1], size=30, p=[0.3, 0.7])
streak_df = pd.DataFrame({'Date': dates, 'Active': activity})
fig = px.bar(streak_df, x='Date', y='Active', title="Daily Learning Activity")
st.plotly_chart(fig, use_container_width=True)
else:
st.info("Start learning to track your progress!")
# Profile Page
elif st.session_state.current_page == 'profile':
st.title("👤 User Profile")
with Session(engine) as session:
user = session.query(User).filter(User.id == st.session_state.current_user).first()
col1, col2 = st.columns(2)
with col1:
st.subheader("Profile Information")
# Editable profile
username = st.text_input("Username", value=user.username)
learning_style = st.selectbox("Learning Style",
["visual", "auditory", "kinesthetic", "reading"],
index=["visual", "auditory", "kinesthetic", "reading"].index(user.learning_style))
difficulty_pref = st.selectbox("Difficulty Preference",
["beginner", "intermediate", "advanced"],
index=["beginner", "intermediate", "advanced"].index(user.difficulty_preference))
if st.button("Update Profile"):
user.username = username
user.learning_style = learning_style
user.difficulty_preference = difficulty_pref
session.commit()
st.success("Profile updated!")
with col2:
st.subheader("Learning Statistics")
progress_data = session.query(UserProgress).filter(UserProgress.user_id == st.session_state.current_user).all()
st.metric("Member Since", user.created_at.strftime('%B %Y'))
st.metric("Topics Attempted", len(progress_data))
st.metric("Average Score", f"{np.mean([p.score for p in progress_data if p.score]):.1f}%" if progress_data else "0%")
st.metric("Total Study Time", f"{sum([p.time_spent for p in progress_data if p.time_spent])} minutes" if progress_data else "0 minutes")
# Achievements
st.subheader("🏆 Achievements")
achievements = []
if len(progress_data) >= 1:
achievements.append("🎯 First Step - Started learning")
if len([p for p in progress_data if p.completed]) >= 3:
achievements.append("📚 Knowledge Seeker - Completed 3 topics")
if any(p.score and p.score >= 90 for p in progress_data):
achievements.append("⭐ Excellence - Scored 90% or higher")
if achievements:
for achievement in achievements:
st.markdown(f"• {achievement}")
else:
st.info("Complete topics to earn achievements!")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?