Bharath370 commited on
Commit
7a07835
·
verified ·
1 Parent(s): b60840d
Files changed (1) hide show
  1. src/app.py +409 -0
src/app.py ADDED
@@ -0,0 +1,409 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ """TriviaVerse Enhanced - Advanced Quiz Application"""
3
+
4
+ import streamlit as st
5
+ import time
6
+ from datetime import datetime
7
+ from config.settings import (
8
+ APP_NAME,
9
+ APP_DESCRIPTION,
10
+ DIFFICULTY_LEVELS,
11
+ BADGES,
12
+ RANDOM_TOPICS,
13
+ )
14
+ from config.themes import THEMES
15
+ from modules.mcq_generator import generate_mcq
16
+ from modules.flashcard_generator import generate_flashcard
17
+ from modules.fact_game import generate_random_fact
18
+ from modules.adaptive_engine import AdaptiveEngine
19
+ from utils.ui_components import (
20
+ apply_custom_theme,
21
+ display_user_stats,
22
+ display_badges,
23
+ create_progress_chart,
24
+ animated_success,
25
+ create_quiz_card,
26
+ render_flashcard,
27
+ )
28
+ from utils.score_tracker import ScoreTracker
29
+ from utils.mobile_responsive import responsive_columns, responsive_css
30
+ from utils.user_auth import init_authentication, authenticate_user
31
+
32
+ # Page configuration
33
+ st.set_page_config(
34
+ page_title=f"{APP_NAME} - Enhanced Edition",
35
+ page_icon="🎯",
36
+ layout="wide",
37
+ initial_sidebar_state="expanded",
38
+ menu_items={
39
+ "Get Help": "https://github.com/yourusername/triviaverse",
40
+ "Report a bug": "https://github.com/yourusername/triviaverse/issues",
41
+ "About": f"{APP_NAME} - A gamified learning platform powered by Wikimedia",
42
+ },
43
+ )
44
+
45
+ # Initialize authentication
46
+ init_authentication()
47
+
48
+ # Check authentication
49
+ if not authenticate_user():
50
+ st.stop()
51
+
52
+ # Initialize session state
53
+ if "user_id" not in st.session_state:
54
+ st.session_state.user_id = st.session_state.get(
55
+ "username", f"user_{int(time.time())}"
56
+ )
57
+ if "score_tracker" not in st.session_state:
58
+ st.session_state.score_tracker = ScoreTracker(st.session_state.user_id)
59
+ if "theme" not in st.session_state:
60
+ st.session_state.theme = "default"
61
+ if "current_streak" not in st.session_state:
62
+ st.session_state.current_streak = 0
63
+ if "adaptive_engine" not in st.session_state:
64
+ st.session_state.adaptive_engine = AdaptiveEngine(st.session_state.user_id)
65
+ # Initialize topic in session state
66
+ if "topic" not in st.session_state:
67
+ st.session_state.topic = "Python programming"
68
+
69
+
70
+ # Apply theme and responsive CSS
71
+ apply_custom_theme(st.session_state.theme)
72
+ st.markdown(responsive_css(), unsafe_allow_html=True)
73
+
74
+ # Sidebar with enhanced features
75
+ with st.sidebar:
76
+ st.title(f"🎯 {APP_NAME}")
77
+ st.markdown("### 🎮 Game Settings")
78
+
79
+ # User info
80
+ st.info(f"👤 Welcome, {st.session_state.get('username', 'Guest')}!")
81
+
82
+ # Theme selector
83
+ theme_select = st.selectbox(
84
+ "🎨 Choose Theme",
85
+ list(THEMES.keys()),
86
+ index=list(THEMES.keys()).index(st.session_state.theme),
87
+ )
88
+ if theme_select != st.session_state.theme:
89
+ st.session_state.theme = theme_select
90
+ st.rerun()
91
+
92
+ st.divider()
93
+
94
+ # Game mode selection with icons
95
+ mode = st.radio(
96
+ "🎲 Select Game Mode",
97
+ ["🧩 MCQ Quiz", "📚 Flashcards", "💡 Fact Game"],
98
+ help="Choose your preferred learning mode",
99
+ )
100
+
101
+ # Adaptive difficulty
102
+ use_adaptive = st.checkbox("🤖 Use Adaptive Difficulty", value=True)
103
+
104
+ if use_adaptive:
105
+ difficulty = st.session_state.adaptive_engine.get_recommended_difficulty()
106
+ st.info(f"Recommended: {difficulty}")
107
+ else:
108
+ difficulty = st.selectbox(
109
+ "⚡ Difficulty Level",
110
+ list(DIFFICULTY_LEVELS.keys()),
111
+ format_func=lambda x: f"{x} - {DIFFICULTY_LEVELS[x]['description']}",
112
+ )
113
+
114
+ # Enhanced topic input
115
+ st.markdown("### 📖 Choose Topic")
116
+ col1, col2 = st.columns([3, 1])
117
+ with col1:
118
+ # Use st.session_state.topic for the text input
119
+ st.session_state.topic = st.text_input(
120
+ "Enter topic", value=st.session_state.topic, label_visibility="collapsed"
121
+ )
122
+ with col2:
123
+ if st.button("🎲", help="Random topic"):
124
+ import random # random is still needed here
125
+
126
+ st.session_state.topic = random.choice(RANDOM_TOPICS)
127
+ st.rerun()
128
+
129
+ # Popular topics
130
+ st.markdown("### 🔥 Trending Topics")
131
+ trending = [
132
+ "Machine Learning",
133
+ "Blockchain",
134
+ "Sustainability",
135
+ "Genetics",
136
+ "Cybersecurity",
137
+ ]
138
+ selected_trending = st.selectbox(
139
+ "Quick select", [""] + trending, label_visibility="collapsed"
140
+ )
141
+ if selected_trending:
142
+ st.session_state.topic = selected_trending
143
+ st.rerun()
144
+
145
+ st.divider()
146
+
147
+ # User stats in sidebar
148
+ st.markdown("### 📊 Your Stats")
149
+ stats = st.session_state.score_tracker.get_stats()
150
+
151
+ col1, col2 = st.columns(2)
152
+ with col1:
153
+ st.metric("Total Score", f"{stats['total_score']:,}")
154
+ st.metric("Current Streak", f"🔥 {stats['current_streak']}")
155
+ with col2:
156
+ st.metric("Quizzes", stats["quizzes_completed"])
157
+ st.metric("Best Streak", f"⭐ {stats['best_streak']}")
158
+
159
+ # Display badges in sidebar
160
+ if stats["badges"]:
161
+ st.markdown("### 🏆 Your Badges")
162
+ for badge_id in stats["badges"]:
163
+ badge = BADGES.get(badge_id, {})
164
+ st.write(f"{badge.get('icon', '🏆')} {badge.get('name', badge_id)}")
165
+
166
+ # Logout button
167
+ if st.button("🚪 Logout", type="secondary", use_container_width=True):
168
+ st.session_state.clear() # A more efficient way to clear the session state
169
+ st.rerun() # Rerun to go back to the login page
170
+
171
+
172
+ # Main content area
173
+ # Header with user dashboard
174
+ col1, col2 = st.columns([2, 1])
175
+ with col1:
176
+ st.title(f"🎮 {APP_NAME} - Enhanced Edition")
177
+ st.markdown(f"*{APP_DESCRIPTION}*")
178
+ with col2:
179
+ # Display current time and greeting
180
+ current_hour = datetime.now().hour
181
+ greeting = (
182
+ "Good morning"
183
+ if current_hour < 12
184
+ else "Good afternoon"
185
+ if current_hour < 18
186
+ else "Good evening"
187
+ )
188
+ st.markdown(f"### {greeting}, {st.session_state.get('username', 'Learner')}! 👋")
189
+ st.caption(f"{datetime.now().strftime('%B %d, %Y - %I:%M %p')}")
190
+
191
+ # Display user statistics dashboard
192
+ stats = st.session_state.score_tracker.get_stats()
193
+ display_user_stats(stats)
194
+
195
+ # Display badges
196
+ if stats["badges"]:
197
+ st.markdown("### 🏅 Your Achievements")
198
+ display_badges(stats["badges"])
199
+
200
+ # Progress chart
201
+ with st.expander("📈 View Detailed Progress", expanded=False):
202
+ if stats["quizzes_completed"] > 0:
203
+ fig = create_progress_chart(stats)
204
+ st.plotly_chart(fig, use_container_width=True)
205
+ else:
206
+ st.info("Complete some quizzes to see your progress chart!")
207
+
208
+ st.divider()
209
+
210
+ # Main game area
211
+ if "MCQ" in mode:
212
+ st.header("🧩 Multiple Choice Quiz")
213
+
214
+ # Quiz controls
215
+ col1, col2, col3 = responsive_columns([1, 1, 1], [1, 1, 1])
216
+
217
+ with col1:
218
+ if st.button("🎯 Generate Question", type="primary", use_container_width=True):
219
+ with st.spinner("🤔 Generating question..."):
220
+ mcq = generate_mcq(st.session_state.topic, difficulty)
221
+
222
+ if mcq.get("status"):
223
+ st.session_state.current_question = mcq
224
+ st.session_state.question_start_time = time.time()
225
+ st.session_state.hints_used = 0
226
+ st.session_state.answered = False
227
+
228
+ with col2:
229
+ time_limit = DIFFICULTY_LEVELS[difficulty]["time_limit"]
230
+ st.info(f"⏱️ Time Limit: {time_limit}s")
231
+
232
+ with col3:
233
+ hints_allowed = DIFFICULTY_LEVELS[difficulty]["hints_allowed"]
234
+ st.info(f"💡 Hints: {hints_allowed}")
235
+
236
+ # Display question if available
237
+ if hasattr(st.session_state, "current_question") and not st.session_state.get(
238
+ "answered", True
239
+ ):
240
+ mcq = st.session_state.current_question
241
+
242
+ # Timer
243
+ elapsed_time = int(time.time() - st.session_state.question_start_time)
244
+ remaining_time = max(0, time_limit - elapsed_time)
245
+
246
+ if remaining_time > 0:
247
+ progress = remaining_time / time_limit
248
+ st.progress(progress)
249
+ st.caption(f"⏱️ Time remaining: {remaining_time}s")
250
+
251
+ # Quiz card
252
+ answer = create_quiz_card(mcq["question"], mcq["options"])
253
+
254
+ # Hint system
255
+ if hints_allowed > st.session_state.hints_used:
256
+ if st.button(
257
+ f"💡 Get Hint ({hints_allowed - st.session_state.hints_used} left)"
258
+ ):
259
+ st.session_state.hints_used += 1
260
+ st.info(f"💡 Hint: {mcq['explanation'][:100]}...")
261
+
262
+ # Submit answer
263
+ col1, col2, col3 = st.columns([1, 2, 1])
264
+ with col2:
265
+ if st.button(
266
+ "✅ Submit Answer", type="primary", use_container_width=True
267
+ ):
268
+ is_correct = answer == mcq["correct_answer"]
269
+ st.session_state.answered = True
270
+
271
+ # Update adaptive engine
272
+ st.session_state.adaptive_engine.update_performance(
273
+ is_correct, difficulty, topic=mcq.get("topic")
274
+ )
275
+
276
+ # Update streak
277
+ if is_correct:
278
+ st.session_state.current_streak += 1
279
+ points = st.session_state.score_tracker.add_quiz_result(
280
+ "MCQ Quiz", 1, 1, difficulty
281
+ )
282
+ animated_success(f"Correct! +{points} points")
283
+ st.balloons()
284
+ else:
285
+ st.session_state.current_streak = 0
286
+ st.error(
287
+ f"❌ Incorrect. The answer was: {mcq['correct_answer']}"
288
+ )
289
+
290
+ st.info(f"📚 {mcq['explanation']}")
291
+ else:
292
+ st.error("⏱️ Time's up!")
293
+ st.session_state.answered = True
294
+ st.session_state.score_tracker.add_quiz_result("MCQ Quiz", 0, 1, difficulty)
295
+
296
+ elif "Flashcards" in mode:
297
+ st.header("📚 Interactive Flashcards")
298
+
299
+ # Flashcard controls
300
+ if st.button("📇 Generate Flashcard", type="primary"):
301
+ with st.spinner("Creating flashcard..."):
302
+ flashcard = generate_flashcard(st.session_state.topic)
303
+
304
+ if flashcard.get("status"):
305
+ st.session_state.current_flashcard = flashcard
306
+ st.session_state.card_flipped = False
307
+
308
+ # Display flashcard
309
+ if hasattr(st.session_state, "current_flashcard"):
310
+ flashcard = st.session_state.current_flashcard
311
+
312
+ # Create flashcard UI
313
+ col1, col2, col3 = st.columns([1, 2, 1])
314
+
315
+ with col2:
316
+ render_flashcard(
317
+ front_content=flashcard["front"],
318
+ back_content=flashcard["back"],
319
+ is_flipped=st.session_state.get("card_flipped", False),
320
+ )
321
+
322
+ if not st.session_state.get("card_flipped", False):
323
+ if st.button("🔄 Flip Card", use_container_width=True):
324
+ st.session_state.card_flipped = True
325
+ st.rerun()
326
+ else:
327
+ # Add a small spacer for the buttons
328
+ st.write("")
329
+ btn_col1, btn_col2 = st.columns(2)
330
+ with btn_col1:
331
+ if st.button("✅ Got it!", use_container_width=True):
332
+ points = st.session_state.score_tracker.add_quiz_result(
333
+ "Flashcards", 1, 1, difficulty
334
+ )
335
+ animated_success(f"Great! +{points} points")
336
+ st.session_state.card_flipped = False
337
+ with btn_col2:
338
+ if st.button("❌ Need Practice", use_container_width=True):
339
+ st.session_state.score_tracker.add_quiz_result(
340
+ "Flashcards", 0, 1, difficulty
341
+ )
342
+ st.session_state.card_flipped = False
343
+
344
+ elif "Fact" in mode:
345
+ st.header("💡 Random Fact Game")
346
+
347
+ # Fact game with timer
348
+ col1, col2 = st.columns([2, 1])
349
+
350
+ with col1:
351
+ if st.button("🎲 Get Random Fact", type="primary", use_container_width=True):
352
+ with st.spinner("Finding an interesting fact..."):
353
+ fact = generate_random_fact()
354
+
355
+ if fact.get("status"):
356
+ st.session_state.current_fact = fact
357
+ st.session_state.fact_start_time = time.time()
358
+
359
+ with col2:
360
+ st.info("⏱️ Quick Read Challenge: 15s")
361
+
362
+ # Display fact
363
+ if hasattr(st.session_state, "current_fact"):
364
+ fact = st.session_state.current_fact
365
+
366
+ # Timer for reading
367
+ elapsed = int(time.time() - st.session_state.fact_start_time)
368
+ remaining = max(0, 15 - elapsed)
369
+
370
+ if remaining > 0:
371
+ st.progress(remaining / 15)
372
+
373
+ st.markdown(
374
+ f"""
375
+ <div class="quiz-container">
376
+ <h3>🌟 Did you know?</h3>
377
+ <p style="font-size: 18px; line-height: 1.8;">{fact["fact"]}</p>
378
+ <p style="margin-top: 20px; color: #666;">Topic: <strong>{fact["topic"]}</strong></p>
379
+ </div>
380
+ """,
381
+ unsafe_allow_html=True,
382
+ )
383
+
384
+ if st.button("✅ Interesting! Next fact"):
385
+ points = st.session_state.score_tracker.add_quiz_result(
386
+ "Fact Game", 1, 1, difficulty
387
+ )
388
+ animated_success(f"Knowledge gained! +{points} points")
389
+ del st.session_state["current_fact"]
390
+ st.rerun()
391
+ else:
392
+ st.success("⏱️ Time's up! Ready for the next fact?")
393
+ if st.button("Next Fact"):
394
+ del st.session_state["current_fact"]
395
+ st.rerun()
396
+
397
+ # Footer
398
+ st.divider()
399
+ col1, col2, col3 = st.columns([1, 2, 1])
400
+ with col2:
401
+ st.markdown(
402
+ """
403
+ <div style='text-align: center'>
404
+ <p>Made with ❤️ using Streamlit and Wikimedia APIs</p>
405
+ <p style='opacity: 0.7; font-size: 0.9em;'>TriviaVerse v2.0 - Enhanced Edition</p>
406
+ </div>
407
+ """,
408
+ unsafe_allow_html=True,
409
+ )