CoolFace
Apppublic

Shruttii/random_question_generator

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py161 linesDownload Raw Back to root
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")