Shruttii/random_question_generator
0
1import streamlit as st
2import pandas as pd
3import random
4import io
5import os
6from docx import Document
7from docx.shared import Pt
8from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_LINE_SPACING
9
10# Streamlit Page Config
11st.set_page_config(page_title="Random Question Generator", page_icon="โ", layout="wide")
12
13# Page Title
14st.markdown("<h1 style='text-align: center; color: #1e88e5;'>๐ Random Question Paper Generator</h1>", unsafe_allow_html=True)
15
16# Input Fields
17st.markdown("### ๐ Enter Paper Details")
18paper_title = st.text_input("Enter the Heading of the Document")
19subject_name = st.text_input("Enter Subject Name")
20subject_code = st.text_input("Enter Subject Code")
21total_marks = st.number_input("Enter Total Marks", min_value=1, step=1)
22time_duration = st.text_input("Enter Time Duration (e.g., 3 Hours)")
23
24# Upload Section with Instructions
25st.markdown("### ๐ Upload Your Excel Files")
26
27with st.expander("๐ Important Instructions Before Uploading Excel Files", expanded=True):
28 st.markdown("""
29 - ๐น Each Excel file should contain *only one sheet* with the following column headers:
30 - Sr. No
31 - Questions
32 - Option 1
33 - Option 2
34 - Option 3
35 - Option 4
36 - Correct Answer
37 - ๐น Ensure that all cells under these columns are *filled* and there are *no missing values*.
38 - ๐น File names should be meaningful as the system uses the file name as the *section/topic title*.
39 - ๐น To *exclude questions*, provide their Sr. No in the respective exclusion field (comma-separated).
40 - ๐น Avoid using *special characters or merged cells* in your Excel files.
41 - ๐น Each file should contain at least as many questions as you plan to select.
42 - ๐น Maximum file size should not exceed *10MB* per file.
43 """)
44
45uploaded_files = st.file_uploader("Upload multiple Excel files", type=['xlsx'], accept_multiple_files=True)
46
47num_questions_per_sheet = {}
48marks_per_section = {}
49excluded_questions_per_file = {}
50used_questions = set()
51column_names = ["Sr. No", "Questions", "Option 1", "Option 2", "Option 3", "Option 4", "Correct Answer"]
52
53if uploaded_files:
54 st.markdown("### ๐ข Select Number of Questions and Marks Per Section")
55 for file in uploaded_files:
56 df = pd.read_excel(file)
57 if not all(col in df.columns for col in column_names):
58 st.error(f"โ Invalid columns in {file.name}. Expected: {column_names}")
59 continue
60 max_questions = len(df)
61 topic_name = os.path.splitext(file.name)[0] # Remove file extension
62 num_questions_per_sheet[topic_name] = st.number_input(
63 f"Questions from {topic_name} (Max: {max_questions})", 1, max_questions, 1, key=topic_name
64 )
65 marks_per_section[topic_name] = st.number_input(
66 f"Marks for {topic_name}", 1, step=1, key=f"marks_{topic_name}"
67 )
68 excluded_questions_input = st.text_area(
69 f"Enter question numbers to exclude for {topic_name} (comma-separated):", key=f"exclude_{topic_name}"
70 )
71 excluded_questions_per_file[topic_name] = set(excluded_questions_input.split(",")) if excluded_questions_input else set()
72
73# Generate Button
74if st.button("๐ Generate Question Paper"):
75 if not uploaded_files:
76 st.warning("โ Please upload at least one Excel file.")
77 else:
78 doc = Document()
79
80 # Title Formatting
81 title = doc.add_paragraph()
82 title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
83 title_run = title.add_run(paper_title.upper())
84 title_run.bold = True
85 title_run.font.size = Pt(18)
86
87 doc.add_paragraph("\n") # Space after title
88
89 # Table for Details
90 table = doc.add_table(rows=1, cols=4)
91 table.style = 'Table Grid'
92 hdr_cells = table.rows[0].cells
93 hdr_cells[0].text = f"Subject: {subject_name}"
94 hdr_cells[1].text = f"Subject Code: {subject_code}"
95 hdr_cells[2].text = f"Total Marks: {total_marks}"
96 hdr_cells[3].text = f"Time: {time_duration}"
97
98 doc.add_paragraph("\n") # Space after table
99
100 final_data = []
101 for file in uploaded_files:
102 df = pd.read_excel(file)
103 topic_name = os.path.splitext(file.name)[0]
104 excluded_set = excluded_questions_per_file[topic_name]
105 df = df[~df["Sr. No"].astype(str).isin(excluded_set)]
106 if topic_name in num_questions_per_sheet:
107 num_questions = num_questions_per_sheet[topic_name]
108 df = df[~df["Questions"].isin(used_questions)]
109 if len(df) >= num_questions:
110 selected_questions = df.sample(num_questions, random_state=random.randint(1, 100))
111
112 # Section Title
113 section_title = doc.add_paragraph()
114 section_title.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
115 section_run = section_title.add_run(f"Section: {topic_name} (Marks: {marks_per_section[topic_name]})")
116 section_run.bold = True
117 section_run.font.size = Pt(14)
118
119 final_data.append([topic_name, "", "", "", "", "", ""]) # Topic name row
120
121 # Reset question counter for this section
122 q_number = 1
123
124 for _, row in selected_questions.iterrows():
125 # Question
126 question_paragraph = doc.add_paragraph()
127 question_run = question_paragraph.add_run(f"{q_number}. {row['Questions']}")
128 question_run.bold = True
129 question_run.font.size = Pt(12)
130
131 # Options in one line
132 options_text = f"a) {row['Option 1']} b) {row['Option 2']} c) {row['Option 3']} d) {row['Option 4']}"
133 options_paragraph = doc.add_paragraph(options_text)
134 options_paragraph.paragraph_format.line_spacing_rule = WD_LINE_SPACING.SINGLE
135
136 final_data.append(row.tolist()) # Store original row
137 used_questions.add(row['Questions'])
138 q_number += 1
139 else:
140 st.warning(f"โ Not enough unique questions in {topic_name}. Skipping.")
141
142 # Save Excel File
143 if final_data:
144 output_df = pd.DataFrame(final_data, columns=column_names)
145 excel_buffer = io.BytesIO()
146 with pd.ExcelWriter(excel_buffer, engine="openpyxl") as writer:
147 output_df.to_excel(writer, index=False, sheet_name="Question Paper")
148 excel_buffer.seek(0)
149 st.session_state["excel_file"] = excel_buffer
150
151 # Save Word File
152 word_buffer = io.BytesIO()
153 doc.save(word_buffer)
154 word_buffer.seek(0)
155 st.session_state["word_file"] = word_buffer
156 st.success("โ
Question paper generated successfully!")
157
158# Download Buttons
159if "excel_file" in st.session_state and "word_file" in st.session_state:
160 st.download_button("๐ฅ Download Question Paper (Excel)", st.session_state["excel_file"], "Generated_Question_Paper.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
161 st.download_button("๐ฅ Download Question Paper (Word)", st.session_state["word_file"], "Generated_Question_Paper.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")