shriramprabhu commited on
Commit
28aef2a
Β·
verified Β·
1 Parent(s): bccc33a

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +488 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,490 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import pandas as pd
3
+ import os
4
+
5
+ # Configure the page
6
+ st.set_page_config(
7
+ page_title="NVIDIA GENL Mock Test",
8
+ page_icon="🧠",
9
+ layout="wide",
10
+ initial_sidebar_state="expanded"
11
+ )
12
+
13
+ # Initialize session state
14
+ if 'current_sheet' not in st.session_state:
15
+ st.session_state.current_sheet = None
16
+ if 'current_question' not in st.session_state:
17
+ st.session_state.current_question = 0
18
+ if 'user_answers' not in st.session_state:
19
+ st.session_state.user_answers = {}
20
+ if 'show_answers' not in st.session_state:
21
+ st.session_state.show_answers = {}
22
+ if 'sheets_data' not in st.session_state:
23
+ st.session_state.sheets_data = {}
24
+ if 'show_results' not in st.session_state:
25
+ st.session_state.show_results = False
26
+
27
+ def load_excel_file(file_path):
28
+ """Load the Excel file from the specified path"""
29
+ try:
30
+ excel_file = pd.read_excel(file_path, sheet_name=None)
31
+ return excel_file
32
+ except Exception as e:
33
+ st.error(f"Error loading Excel file: {e}")
34
+ return None
35
+
36
+ def clean_data(value):
37
+ """Clean and format data values"""
38
+ if pd.isna(value) or value == '':
39
+ return None
40
+ return str(value).strip()
41
+
42
+ def display_question(question_data, question_num, total_questions):
43
+ """Display a single question and options with instant feedback"""
44
+
45
+ # Create columns for better layout
46
+ col1, col2 = st.columns([3, 1])
47
+
48
+ with col1:
49
+ st.markdown(f"### Question {question_num + 1} of {total_questions}")
50
+
51
+ with col2:
52
+ progress = (question_num + 1) / total_questions
53
+ st.progress(progress)
54
+ st.caption(f"Progress: {question_num + 1}/{total_questions}")
55
+
56
+ # Display the question
57
+ st.markdown(
58
+ f"""
59
+ <div style='
60
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
61
+ padding: 2rem;
62
+ border-radius: 15px;
63
+ margin-bottom: 2rem;
64
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
65
+ '>
66
+ <h3 style='margin:0; color: white; font-weight: 500;'>{question_data['Question']}</h3>
67
+ </div>
68
+ """,
69
+ unsafe_allow_html=True
70
+ )
71
+
72
+ # Get available choices
73
+ choices = []
74
+ for i in range(1, 7):
75
+ choice_col = f'Choice{i}'
76
+ if choice_col in question_data.index:
77
+ choice_val = clean_data(question_data[choice_col])
78
+ if choice_val:
79
+ choices.append(choice_val)
80
+
81
+ question_key = f"q_{question_num}"
82
+
83
+ # Get current answer (None if not answered yet)
84
+ current_answer = st.session_state.user_answers.get(question_key, None)
85
+
86
+ # Display options
87
+ if choices:
88
+ # Radio button with no default selection
89
+ selected_option = st.radio(
90
+ "**Select your answer:**",
91
+ options=[""] + choices, # Add empty option at start
92
+ format_func=lambda x: "-- Select an option --" if x == "" else x,
93
+ key=f"radio_{question_key}",
94
+ index=0 if current_answer is None else (choices.index(current_answer) + 1 if current_answer in choices else 0)
95
+ )
96
+
97
+ # Only store if a real choice is selected
98
+ if selected_option != "":
99
+ st.session_state.user_answers[question_key] = selected_option
100
+
101
+ # Get correct answer
102
+ correct_answer = clean_data(question_data['Answer'])
103
+
104
+ # Show instant feedback
105
+ st.markdown("<br>", unsafe_allow_html=True)
106
+ if selected_option == correct_answer:
107
+ st.markdown(
108
+ """
109
+ <div style='
110
+ background: #d4edda;
111
+ border-left: 5px solid #28a745;
112
+ padding: 1rem;
113
+ border-radius: 8px;
114
+ margin-top: 1rem;
115
+ '>
116
+ <span style='color: #155724; font-size: 1.1rem; font-weight: 600;'>
117
+ βœ… Correct! Well done.
118
+ </span>
119
+ </div>
120
+ """,
121
+ unsafe_allow_html=True
122
+ )
123
+ else:
124
+ st.markdown(
125
+ """
126
+ <div style='
127
+ background: #f8d7da;
128
+ border-left: 5px solid #dc3545;
129
+ padding: 1rem;
130
+ border-radius: 8px;
131
+ margin-top: 1rem;
132
+ '>
133
+ <span style='color: #721c24; font-size: 1.1rem; font-weight: 600;'>
134
+ ❌ Incorrect
135
+ </span>
136
+ </div>
137
+ """,
138
+ unsafe_allow_html=True
139
+ )
140
+
141
+ # Show correct answer button
142
+ if st.session_state.show_answers.get(question_key, False):
143
+ st.markdown(
144
+ f"""
145
+ <div style='
146
+ background: #d1ecf1;
147
+ border-left: 5px solid #0c5460;
148
+ padding: 1rem;
149
+ border-radius: 8px;
150
+ margin-top: 0.5rem;
151
+ '>
152
+ <span style='color: #0c5460; font-weight: 600;'>
153
+ πŸ’‘ Correct answer: {correct_answer}
154
+ </span>
155
+ </div>
156
+ """,
157
+ unsafe_allow_html=True
158
+ )
159
+ else:
160
+ if st.button("πŸ” Show Correct Answer", key=f"show_{question_num}"):
161
+ st.session_state.show_answers[question_key] = True
162
+ st.rerun()
163
+ else:
164
+ # Remove answer if user deselects
165
+ if question_key in st.session_state.user_answers:
166
+ del st.session_state.user_answers[question_key]
167
+ else:
168
+ st.warning("⚠️ No choices found for this question.")
169
+
170
+ def calculate_score(sheet_data):
171
+ """Calculate the score for the test"""
172
+ total_score = 0
173
+ max_score = 0
174
+ results = []
175
+
176
+ for i in range(len(sheet_data)):
177
+ question_data = sheet_data.iloc[i]
178
+ question_key = f"q_{i}"
179
+ user_answer = st.session_state.user_answers.get(question_key, "")
180
+ correct_answer = clean_data(question_data['Answer'])
181
+
182
+ is_correct = user_answer == correct_answer if correct_answer else False
183
+
184
+ try:
185
+ marks = float(question_data.get('Marks', 1.0))
186
+ except:
187
+ marks = 1.0
188
+
189
+ if is_correct:
190
+ total_score += marks
191
+
192
+ max_score += marks
193
+
194
+ results.append({
195
+ 'question': i + 1,
196
+ 'question_text': question_data['Question'],
197
+ 'user_answer': user_answer,
198
+ 'correct_answer': correct_answer,
199
+ 'is_correct': is_correct,
200
+ 'marks': marks
201
+ })
202
+
203
+ return total_score, max_score, results
204
+
205
+ def main():
206
+ # Enhanced CSS
207
+ st.markdown("""
208
+ <style>
209
+ /* Import Google Fonts */
210
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
211
+
212
+ /* Global Styles */
213
+ * {
214
+ font-family: 'Inter', sans-serif;
215
+ }
216
+
217
+ .main-header {
218
+ font-size: 3rem;
219
+ font-weight: 700;
220
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
221
+ -webkit-background-clip: text;
222
+ -webkit-text-fill-color: transparent;
223
+ text-align: center;
224
+ margin-bottom: 2rem;
225
+ animation: fadeIn 1s ease-in;
226
+ }
227
+
228
+ @keyframes fadeIn {
229
+ from { opacity: 0; transform: translateY(-20px); }
230
+ to { opacity: 1; transform: translateY(0); }
231
+ }
232
+
233
+ /* Sidebar Styling */
234
+ [data-testid="stSidebar"] {
235
+ background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
236
+ }
237
+
238
+ /* Metric Cards */
239
+ .metric-card {
240
+ background: white;
241
+ padding: 1.5rem;
242
+ border-radius: 15px;
243
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
244
+ text-align: center;
245
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
246
+ }
247
+
248
+ .metric-card:hover {
249
+ transform: translateY(-5px);
250
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
251
+ }
252
+
253
+ /* Button Styling */
254
+ .stButton>button {
255
+ border-radius: 10px;
256
+ font-weight: 600;
257
+ transition: all 0.3s ease;
258
+ border: none;
259
+ }
260
+
261
+ .stButton>button:hover {
262
+ transform: scale(1.02);
263
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
264
+ }
265
+
266
+ /* Radio Button Styling */
267
+ .stRadio > div {
268
+ background: white;
269
+ padding: 1.5rem;
270
+ border-radius: 12px;
271
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
272
+ }
273
+
274
+ /* Progress Bar */
275
+ .stProgress > div > div > div {
276
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
277
+ }
278
+
279
+ /* Expander Styling */
280
+ .streamlit-expanderHeader {
281
+ background: white;
282
+ border-radius: 10px;
283
+ font-weight: 600;
284
+ }
285
+
286
+ /* Custom Scrollbar */
287
+ ::-webkit-scrollbar {
288
+ width: 10px;
289
+ }
290
+
291
+ ::-webkit-scrollbar-track {
292
+ background: #f1f1f1;
293
+ }
294
+
295
+ ::-webkit-scrollbar-thumb {
296
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
297
+ border-radius: 5px;
298
+ }
299
+
300
+ ::-webkit-scrollbar-thumb:hover {
301
+ background: #764ba2;
302
+ }
303
+ </style>
304
+ """, unsafe_allow_html=True)
305
+
306
+ # Header
307
+ st.markdown('<h1 class="main-header">🧠 NVIDIA GENL Mock Test</h1>', unsafe_allow_html=True)
308
+
309
+ # File path
310
+ excel_file_path = "E:/nvidiatest/Nvidia GENL 1.xlsx"
311
+
312
+ # Load data
313
+ if not st.session_state.sheets_data:
314
+ with st.spinner("πŸ“š Loading test data..."):
315
+ sheets_data = load_excel_file(excel_file_path)
316
+ if sheets_data:
317
+ st.session_state.sheets_data = sheets_data
318
+ st.success("βœ… Test data loaded successfully!")
319
+ else:
320
+ st.error(f"❌ Could not load Excel file from: {excel_file_path}")
321
+ st.info("πŸ’‘ Please make sure the file exists at the specified path.")
322
+ return
323
+
324
+ sheets_data = st.session_state.sheets_data
325
+
326
+ # Sidebar
327
+ with st.sidebar:
328
+ st.markdown("## 🧭 Navigation")
329
+
330
+ available_sheets = list(sheets_data.keys())
331
+ selected_sheet = st.selectbox(
332
+ "**Select Test Sheet:**",
333
+ options=available_sheets,
334
+ index=0
335
+ )
336
+
337
+ if selected_sheet != st.session_state.current_sheet:
338
+ st.session_state.current_sheet = selected_sheet
339
+ st.session_state.current_question = 0
340
+ st.session_state.user_answers = {}
341
+ st.session_state.show_answers = {}
342
+ st.session_state.show_results = False
343
+ st.rerun()
344
+
345
+ st.markdown("---")
346
+
347
+ current_data = sheets_data[selected_sheet]
348
+
349
+ if 'Type' in current_data.columns:
350
+ objective_questions = current_data[current_data['Type'] == 'Objective']
351
+ else:
352
+ objective_questions = current_data
353
+
354
+ total_questions = len(objective_questions)
355
+
356
+ # Info cards
357
+ st.markdown(f"**πŸ“„ Sheet:** {selected_sheet}")
358
+ st.markdown(f"**πŸ“ Total Questions:** {total_questions}")
359
+
360
+ answered_count = len([k for k in st.session_state.user_answers if st.session_state.user_answers[k]])
361
+ st.markdown(f"**βœ… Answered:** {answered_count}/{total_questions}")
362
+
363
+ st.markdown("---")
364
+ st.markdown("### 🎯 Quick Navigation")
365
+
366
+ col1, col2 = st.columns(2)
367
+ with col1:
368
+ if st.button("β—€ Prev", use_container_width=True,
369
+ disabled=st.session_state.current_question == 0):
370
+ st.session_state.current_question -= 1
371
+ st.rerun()
372
+
373
+ with col2:
374
+ if st.button("Next β–Ά", use_container_width=True,
375
+ disabled=st.session_state.current_question >= total_questions - 1):
376
+ st.session_state.current_question += 1
377
+ st.rerun()
378
+
379
+ selected_q = st.selectbox(
380
+ "**Go to question:**",
381
+ options=list(range(1, total_questions + 1)),
382
+ index=st.session_state.current_question
383
+ )
384
+
385
+ if selected_q - 1 != st.session_state.current_question:
386
+ st.session_state.current_question = selected_q - 1
387
+ st.rerun()
388
+
389
+ st.markdown("---")
390
+
391
+ if st.button("πŸ”„ Reset Test", use_container_width=True, type="secondary"):
392
+ st.session_state.user_answers = {}
393
+ st.session_state.current_question = 0
394
+ st.session_state.show_answers = {}
395
+ st.session_state.show_results = False
396
+ st.rerun()
397
+
398
+ if st.button("πŸ“Š View Results", use_container_width=True, type="primary"):
399
+ if answered_count > 0:
400
+ st.session_state.show_results = True
401
+ st.rerun()
402
+ else:
403
+ st.warning("⚠️ Please answer some questions first!")
404
+
405
+ # Main content
406
+ if total_questions == 0:
407
+ st.warning("⚠️ No questions found in this sheet.")
408
+ return
409
+
410
+ # Display question or results
411
+ if st.session_state.show_results:
412
+ st.markdown("---")
413
+ st.markdown("## πŸ“Š Test Results")
414
+
415
+ total_score, max_score, results = calculate_score(objective_questions)
416
+
417
+ col1, col2, col3, col4 = st.columns(4)
418
+
419
+ with col1:
420
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
421
+ st.metric("Total Score", f"{total_score:.1f}/{max_score:.1f}")
422
+ st.markdown('</div>', unsafe_allow_html=True)
423
+
424
+ with col2:
425
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
426
+ percentage = (total_score / max_score) * 100 if max_score > 0 else 0
427
+ st.metric("Percentage", f"{percentage:.1f}%")
428
+ st.markdown('</div>', unsafe_allow_html=True)
429
+
430
+ with col3:
431
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
432
+ correct_count = sum(1 for r in results if r['is_correct'])
433
+ st.metric("Correct", f"{correct_count}/{total_questions}")
434
+ st.markdown('</div>', unsafe_allow_html=True)
435
+
436
+ with col4:
437
+ st.markdown('<div class="metric-card">', unsafe_allow_html=True)
438
+ incorrect_count = total_questions - correct_count
439
+ st.metric("Incorrect", f"{incorrect_count}")
440
+ st.markdown('</div>', unsafe_allow_html=True)
441
+
442
+ st.markdown("---")
443
+ st.subheader("πŸ“‹ Question-wise Results")
444
+
445
+ for result in results:
446
+ icon = "βœ…" if result['is_correct'] else "❌"
447
+
448
+ with st.expander(f"{icon} Question {result['question']} ({result['marks']} mark{'s' if result['marks'] > 1 else ''})", expanded=False):
449
+ st.write(f"**Question:** {result['question_text']}")
450
+
451
+ col_a, col_b = st.columns(2)
452
+
453
+ with col_a:
454
+ st.write("**Your Answer:**")
455
+ if result['user_answer']:
456
+ if result['is_correct']:
457
+ st.success(result['user_answer'])
458
+ else:
459
+ st.error(result['user_answer'])
460
+ else:
461
+ st.warning("Not answered")
462
+
463
+ with col_b:
464
+ st.write("**Correct Answer:**")
465
+ st.success(result['correct_answer'])
466
+
467
+ if st.button("← Back to Test", use_container_width=True, type="primary"):
468
+ st.session_state.show_results = False
469
+ st.rerun()
470
+ else:
471
+ current_q_data = objective_questions.iloc[st.session_state.current_question]
472
+ display_question(current_q_data, st.session_state.current_question, total_questions)
473
+
474
+ st.markdown("---")
475
+ col1, col2, col3 = st.columns([1, 2, 1])
476
+
477
+ with col1:
478
+ if st.button("β—€ Previous Question", use_container_width=True,
479
+ disabled=st.session_state.current_question == 0):
480
+ st.session_state.current_question -= 1
481
+ st.rerun()
482
+
483
+ with col3:
484
+ if st.button("Next Question β–Ά", use_container_width=True,
485
+ disabled=st.session_state.current_question >= total_questions - 1):
486
+ st.session_state.current_question += 1
487
+ st.rerun()
488
 
489
+ if __name__ == "__main__":
490
+ main()