Sina Media Lab commited on
Commit
74a6085
Β·
1 Parent(s): 2eb2833
app.py CHANGED
@@ -41,7 +41,7 @@ def generate_pdf_report():
41
  pdf.set_fill_color(211, 211, 211) # Light gray
42
  pdf.cell(0, 10, txt="Magic Math Quiz!", ln=True, align="C", fill=True)
43
  pdf.ln(5)
44
- pdf.set_font("Arial", size=10)
45
  pdf.cell(0, 10, txt="by Ghassem Tofighi", ln=True, align="C", link="https://ghassem.com")
46
  pdf.ln(10)
47
 
@@ -86,23 +86,36 @@ def generate_pdf_report():
86
 
87
  def load_modules():
88
  modules = {}
89
- module_dir = "modules"
90
- for filename in os.listdir(module_dir):
91
- if filename.endswith(".py") and filename != "__init__.py":
92
- module_name = filename[:-3]
93
- # Dynamically import the module only when needed
94
- module = __import__(f"{module_dir}.{module_name}", fromlist=[''])
95
- modules[module_name] = {
96
- "title": getattr(module, "title", module_name.replace("_", " ").title()),
97
- "description": getattr(module, "description", "No description available."),
98
- "generate_question": module.generate_question # Access the generate_question function
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
100
  return modules
101
 
102
- def generate_new_question(module_name, module):
103
  question_data = module['generate_question']()
104
  # Ensure 'answered' is initialized to False and add the 'module' and 'selected' keys
105
  question_data['answered'] = False
 
106
  question_data['module'] = module_name # Add the module name to the question data
107
  question_data['module_title'] = module['title'] # Add the module title to the question data
108
  question_data['selected'] = None # Initialize 'selected' to None
@@ -116,59 +129,65 @@ def generate_new_question(module_name, module):
116
  modules = load_modules()
117
 
118
  # Streamlit interface
119
- st.sidebar.title("Quiz Modules")
120
- module_name = st.sidebar.radio("Choose a module:", [modules[module]["title"] for module in modules], index=0)
121
-
122
- selected_module = None
123
- for module in modules:
124
- if modules[module]["title"] == module_name:
125
- selected_module = module
126
- break
127
-
128
- if selected_module != st.session_state.current_module:
129
- st.session_state.current_module = selected_module
130
- st.session_state.current_index = len(st.session_state.questions) # Continue numbering from previous questions
131
- st.session_state.selected_answer = None
132
- st.session_state.button_label = "Submit/New"
133
- st.session_state.start_time = time.time() # Start the timer for the new question
134
- # Initialize question count and correct count if not already done
135
- if selected_module not in st.session_state.module_question_count:
136
- st.session_state.module_question_count[selected_module] = 0
137
- if selected_module not in st.session_state.module_correct_count:
138
- st.session_state.module_correct_count[selected_module] = 0
139
- # Generate a new question without adding it to the answered list yet
140
- st.session_state.current_question = generate_new_question(selected_module, modules[selected_module])
 
 
141
 
142
  current_question = st.session_state.current_question
143
 
144
  # Title header with rounded corners and margin
145
  st.markdown(
146
  """
147
- <div style='background-color: #D3D3D3; padding: 10px; border-radius: 10px; text-align: center; color: black; margin-top: 20px;'>
148
  <h3 style='margin: 0;'>Magic Math Quiz!</h3>
149
- <h6 style='margin: 0;'><a href="https://ghassem.com" target="_blank" style="color: black; text-decoration: none;">By Ghassem Tofighi</a></h6>
 
 
 
 
 
150
  </div>
151
  """, unsafe_allow_html=True)
152
 
153
- # Display the PDF report button next to the title header if at least one question is answered
154
- if any(q['answered'] for q in st.session_state.questions):
 
 
 
155
  pdf = generate_pdf_report()
156
  st.session_state.pdf_data = pdf # Reset PDF cache
157
- st.markdown(
158
- """
159
- <div style='text-align: right; margin-top: -30px;'>
160
- """, unsafe_allow_html=True)
161
  st.download_button(
162
  label="Download PDF Report πŸ“„",
163
  data=st.session_state.pdf_data,
164
  file_name="quiz_report.pdf",
165
- mime="application/pdf"
 
166
  )
167
- st.markdown("</div>", unsafe_allow_html=True)
168
 
169
  # Display module title and description with a larger font for description
170
- st.markdown(f"### {modules[selected_module]['title']}")
171
- st.markdown(f"<span style='font-size: 14px;'>{modules[selected_module]['description']}</span>", unsafe_allow_html=True)
172
 
173
  # Display the current question with larger font
174
  st.markdown(f"<span style='font-size: 18px;'><b>Q{st.session_state.current_index + 1}: {current_question['question']}</b></span>", unsafe_allow_html=True)
@@ -204,24 +223,27 @@ if submit_button:
204
  st.session_state.module_correct_count[selected_module] += 1
205
 
206
  # Show correct/incorrect feedback, explanation, and step-by-step solution
207
- for i, option in enumerate(current_question['options']):
208
- option_text = f"{options[i]}. {option}"
209
- if option == current_question['correct_answer']:
210
- st.markdown(f"<span style='color:green;'>{option_text} βœ…</span>", unsafe_allow_html=True)
211
- elif option == selected_answer_text:
212
- st.markdown(f"<span style='color:red;'>{option_text} ❌</span>", unsafe_allow_html=True)
213
- else:
214
- st.markdown(f"{option_text}", unsafe_allow_html=True)
 
 
215
 
216
- st.markdown(f"<span style='font-size: 14px;'><b>Explanation:</b> {current_question['explanation']}</span>", unsafe_allow_html=True)
217
- st.markdown(f"<span style='font-size: 14px;'><b>Step-by-Step Solution:</b></span>", unsafe_allow_html=True)
218
- for step in current_question['step_by_step_solution']:
219
- st.markdown(f"<span style='font-size: 14px;'>{step}</span>", unsafe_allow_html=True)
 
220
 
221
  # Add the question to the answered list only after submission
222
  st.session_state.questions.append(current_question)
223
  st.session_state.current_index = len(st.session_state.questions)
224
 
225
  # Generate a new question after submission
226
- st.session_state.current_question = generate_new_question(selected_module, modules[selected_module])
227
  st.session_state.start_time = time.time() # Reset the timer for the new question
 
41
  pdf.set_fill_color(211, 211, 211) # Light gray
42
  pdf.cell(0, 10, txt="Magic Math Quiz!", ln=True, align="C", fill=True)
43
  pdf.ln(5)
44
+ pdf.set_font("Arial", size=8)
45
  pdf.cell(0, 10, txt="by Ghassem Tofighi", ln=True, align="C", link="https://ghassem.com")
46
  pdf.ln(10)
47
 
 
86
 
87
  def load_modules():
88
  modules = {}
89
+ base_dir = "modules"
90
+ for category in os.listdir(base_dir):
91
+ category_dir = os.path.join(base_dir, category)
92
+ if os.path.isdir(category_dir):
93
+ config_path = os.path.join(category_dir, "config.py")
94
+ if os.path.exists(config_path):
95
+ config = {}
96
+ with open(config_path) as f:
97
+ exec(f.read(), config)
98
+ category_title = config.get("title", category.title().replace("_", " "))
99
+ else:
100
+ category_title = category.title().replace("_", " ")
101
+
102
+ modules[category_title] = {}
103
+ for filename in os.listdir(category_dir):
104
+ if filename.endswith(".py") and filename != "__init__.py" and filename != "config.py":
105
+ module_name = filename[:-3]
106
+ module = __import__(f"{category_dir.replace('/', '.')}.{module_name}", fromlist=[''])
107
+ modules[category_title][module_name] = {
108
+ "title": getattr(module, "title", module_name.replace("_", " ").title()),
109
+ "description": getattr(module, "description", "No description available."),
110
+ "generate_question": module.generate_question # Access the generate_question function
111
+ }
112
  return modules
113
 
114
+ def generate_new_question(category_name, module_name, module):
115
  question_data = module['generate_question']()
116
  # Ensure 'answered' is initialized to False and add the 'module' and 'selected' keys
117
  question_data['answered'] = False
118
+ question_data['category'] = category_name # Add the category name to the question data
119
  question_data['module'] = module_name # Add the module name to the question data
120
  question_data['module_title'] = module['title'] # Add the module title to the question data
121
  question_data['selected'] = None # Initialize 'selected' to None
 
129
  modules = load_modules()
130
 
131
  # Streamlit interface
132
+ st.sidebar.title("Quiz Categories")
133
+ selected_category = st.sidebar.selectbox("Choose a category:", list(modules.keys()))
134
+
135
+ if selected_category:
136
+ selected_module = st.sidebar.radio("Choose a module:", [modules[selected_category][module]["title"] for module in modules[selected_category]])
137
+
138
+ for module_name, module_data in modules[selected_category].items():
139
+ if module_data["title"] == selected_module:
140
+ selected_module_data = module_data
141
+ break
142
+
143
+ if selected_module != st.session_state.current_module:
144
+ st.session_state.current_module = selected_module
145
+ st.session_state.current_index = len(st.session_state.questions) # Continue numbering from previous questions
146
+ st.session_state.selected_answer = None
147
+ st.session_state.button_label = "Submit/New"
148
+ st.session_state.start_time = time.time() # Start the timer for the new question
149
+ # Initialize question count and correct count if not already done
150
+ if selected_module not in st.session_state.module_question_count:
151
+ st.session_state.module_question_count[selected_module] = 0
152
+ if selected_module not in st.session_state.module_correct_count:
153
+ st.session_state.module_correct_count[selected_module] = 0
154
+ # Generate a new question without adding it to the answered list yet
155
+ st.session_state.current_question = generate_new_question(selected_category, selected_module, selected_module_data)
156
 
157
  current_question = st.session_state.current_question
158
 
159
  # Title header with rounded corners and margin
160
  st.markdown(
161
  """
162
+ <div style='background-color: #D3D3D3; padding: 10px; border-radius: 10px; text-align: center; color: black; margin-top: 20px; position: relative;'>
163
  <h3 style='margin: 0;'>Magic Math Quiz!</h3>
164
+ <h6 style='margin: 0; font-size: 10px;'><a href="https://ghassem.com" target="_blank" style="color: black; text-decoration: none;'>By Ghassem Tofighi</a></h6>
165
+ <div style='position: absolute; right: 10px; top: 10px;'>
166
+ <button id="pdf-button" style='font-size: 10px;'>
167
+ Download PDF Report πŸ“„
168
+ </button>
169
+ </div>
170
  </div>
171
  """, unsafe_allow_html=True)
172
 
173
+ # Disable PDF download button initially if no questions have been answered
174
+ pdf_button_disabled = not any(q['answered'] for q in st.session_state.questions)
175
+ st.write('<script>document.getElementById("pdf-button").disabled = {};</script>'.format(pdf_button_disabled), unsafe_allow_html=True)
176
+
177
+ if not pdf_button_disabled:
178
  pdf = generate_pdf_report()
179
  st.session_state.pdf_data = pdf # Reset PDF cache
 
 
 
 
180
  st.download_button(
181
  label="Download PDF Report πŸ“„",
182
  data=st.session_state.pdf_data,
183
  file_name="quiz_report.pdf",
184
+ mime="application/pdf",
185
+ disabled=pdf_button_disabled
186
  )
 
187
 
188
  # Display module title and description with a larger font for description
189
+ st.markdown(f"### {selected_module_data['title']}")
190
+ st.markdown(f"<span style='font-size: 14px;'>{selected_module_data['description']}</span>", unsafe_allow_html=True)
191
 
192
  # Display the current question with larger font
193
  st.markdown(f"<span style='font-size: 18px;'><b>Q{st.session_state.current_index + 1}: {current_question['question']}</b></span>", unsafe_allow_html=True)
 
223
  st.session_state.module_correct_count[selected_module] += 1
224
 
225
  # Show correct/incorrect feedback, explanation, and step-by-step solution
226
+ col1, col2 = st.columns(2)
227
+ with col1:
228
+ for i, option in enumerate(current_question['options']):
229
+ option_text = f"{options[i]}. {option}"
230
+ if option == current_question['correct_answer']:
231
+ st.markdown(f"<span style='color:green;'>{option_text} βœ…</span>", unsafe_allow_html=True)
232
+ elif option == selected_answer_text:
233
+ st.markdown(f"<span style='color:red;'>{option_text} ❌</span>", unsafe_allow_html=True)
234
+ else:
235
+ st.markdown(f"{option_text}", unsafe_allow_html=True)
236
 
237
+ with col2:
238
+ st.markdown(f"<span style='font-size: 14px;'><b>Explanation:</b> {current_question['explanation']}</span>", unsafe_allow_html=True)
239
+ st.markdown(f"<span style='font-size: 14px;'><b>Step-by-Step Solution:</b></span>", unsafe_allow_html=True)
240
+ for step in current_question['step_by_step_solution']:
241
+ st.markdown(f"<span style='font-size: 14px;'>{step}</span>", unsafe_allow_html=True)
242
 
243
  # Add the question to the answered list only after submission
244
  st.session_state.questions.append(current_question)
245
  st.session_state.current_index = len(st.session_state.questions)
246
 
247
  # Generate a new question after submission
248
+ st.session_state.current_question = generate_new_question(selected_category, selected_module, selected_module_data)
249
  st.session_state.start_time = time.time() # Reset the timer for the new question
modules/{__init__.py β†’ numbering_system/__init__.py} RENAMED
File without changes
modules/{addition_bases.py β†’ numbering_system/addition_bases.py} RENAMED
@@ -1,4 +1,4 @@
1
- # modules/addition_bases.py
2
 
3
  title = "Addition in Various Bases"
4
  description = "This module covers addition operations in bases like binary, octal, and hexadecimal."
 
1
+ # modules/numbering_system/addition_bases.py
2
 
3
  title = "Addition in Various Bases"
4
  description = "This module covers addition operations in bases like binary, octal, and hexadecimal."
modules/numbering_system/config.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ title = "Numbering System"
2
+ description = "This category covers various operations and concepts in different numbering systems, including binary, octal, decimal, and hexadecimal."
modules/{conversion_bases.py β†’ numbering_system/conversion_bases.py} RENAMED
File without changes
modules/{grouping_techniques.py β†’ numbering_system/grouping_techniques.py} RENAMED
File without changes
modules/{negative_binary.py β†’ numbering_system/negative_binary.py} RENAMED
File without changes
modules/{presentation_bases.py β†’ numbering_system/presentation_bases.py} RENAMED
File without changes
modules/{subtraction_bases.py β†’ numbering_system/subtraction_bases.py} RENAMED
File without changes
modules/{twos_complement.py β†’ numbering_system/twos_complement.py} RENAMED
File without changes
modules/{valid_invalid_numbers.py β†’ numbering_system/valid_invalid_numbers.py} RENAMED
File without changes