Spaces:
Sleeping
Sleeping
| """ | |
| DOCX document generation using python-docx | |
| """ | |
| from docx import Document | |
| from docx.shared import Inches | |
| from docx.enum.text import WD_ALIGN_PARAGRAPH | |
| from typing import Dict, Any, List | |
| import os | |
| class DocxBuilder: | |
| """Builds DOCX outputs for question papers, answers, and OBE reports""" | |
| def __init__(self): | |
| self.doc = None | |
| def build_question_paper(self, data: Dict[str, Any], subject: str, stream: str) -> Document: | |
| """Build question paper DOCX""" | |
| self.doc = Document() | |
| # Title section | |
| title = self.doc.add_heading(f'{subject} - Question Paper', 0) | |
| title.alignment = WD_ALIGN_PARAGRAPH.CENTER | |
| # Metadata | |
| self.doc.add_paragraph(f'Stream: {stream}') | |
| self.doc.add_paragraph(f'Total Marks: {self._calculate_total_marks(data)}') | |
| self.doc.add_paragraph('') | |
| # Instructions | |
| self._add_instructions(stream) | |
| # Questions by part | |
| self._add_part_questions(data, "A", "Part A - Answer ALL Questions") | |
| self._add_part_questions(data, "B", "Part B - Answer ALL Questions (Either/Or)") | |
| self._add_part_questions(data, "C", "Part C - Case Study (Answer ALL Questions)") | |
| return self.doc | |
| def build_answer_key(self, data: Dict[str, Any], subject: str) -> Document: | |
| """Build answer key DOCX""" | |
| self.doc = Document() | |
| title = self.doc.add_heading(f'{subject} - Model Answer Key', 0) | |
| title.alignment = WD_ALIGN_PARAGRAPH.CENTER | |
| if "answers" in data: | |
| for answer in data["answers"]: | |
| self.doc.add_heading(f'Question {answer["question_ref"]}', level=2) | |
| self.doc.add_paragraph(f'Model Answer: {answer.get("model_answer", "N/A")}') | |
| if "marking_scheme" in answer: | |
| self.doc.add_paragraph("Marking Scheme:") | |
| for point in answer["marking_scheme"]: | |
| self.doc.add_paragraph(point, style='List Bullet') | |
| self.doc.add_paragraph('') | |
| return self.doc | |
| def build_obe_summary(self, data: Dict[str, Any], subject: str) -> Document: | |
| """Build OBE summary report DOCX""" | |
| self.doc = Document() | |
| title = self.doc.add_heading(f'{subject} - OBE Summary Report', 0) | |
| title.alignment = WD_ALIGN_PARAGRAPH.CENTER | |
| if "obe" in data: | |
| obe_data = data["obe"] | |
| # Course Outcomes | |
| self.doc.add_heading('Course Outcome Mapping', level=2) | |
| if "course_outcomes" in obe_data: | |
| for co, info in obe_data["course_outcomes"].items(): | |
| self.doc.add_paragraph(f'{co}: {info.get("coverage", "N/A")} coverage') | |
| if "questions" in info: | |
| self.doc.add_paragraph(f'Questions: {", ".join(info["questions"])}') | |
| # Bloom's Distribution | |
| self.doc.add_heading("Bloom's Taxonomy Distribution", level=2) | |
| if "bloom_distribution" in obe_data: | |
| for level, percentage in obe_data["bloom_distribution"].items(): | |
| self.doc.add_paragraph(f'{level}: {percentage}') | |
| # Analysis | |
| self.doc.add_heading('Quality Analysis', level=2) | |
| self.doc.add_paragraph(f'Difficulty Index: {obe_data.get("difficulty_index", "N/A")}') | |
| self.doc.add_paragraph(f'Unit Coverage: {obe_data.get("unit_coverage", "N/A")}') | |
| if "recommendations" in obe_data: | |
| self.doc.add_paragraph(f'Recommendations: {obe_data["recommendations"]}') | |
| return self.doc | |
| def _calculate_total_marks(self, data: Dict[str, Any]) -> int: | |
| """Calculate total marks from questions""" | |
| total = 0 | |
| if "final_qp" in data and "questions" in data["final_qp"]: | |
| for question in data["final_qp"]["questions"]: | |
| total += question.get("marks", 0) | |
| return total | |
| def _add_instructions(self, stream: str): | |
| """Add stream-specific instructions""" | |
| instructions = self.doc.add_paragraph('INSTRUCTIONS:') | |
| instructions.bold = True | |
| if stream == "CSE": | |
| self.doc.add_paragraph('• Part A: Answer ALL questions (2 marks each)') | |
| self.doc.add_paragraph('• Part B: Answer ALL questions (13 marks each) - Choose either (a) or (b)') | |
| self.doc.add_paragraph('• Part C: Case study (14 marks) - Answer ALL sub-questions') | |
| self.doc.add_paragraph('• Questions are tagged with relevant company standards (MAANGO BIG15)') | |
| else: | |
| self.doc.add_paragraph('• Part A: Answer ALL questions (2 marks each)') | |
| self.doc.add_paragraph('• Part B: Answer ALL questions (13 marks each) - Choose either (a) or (b)') | |
| self.doc.add_paragraph('• Part C: Case study (14 marks) - Answer ALL sub-questions') | |
| self.doc.add_paragraph('• Questions follow GATE examination patterns') | |
| self.doc.add_paragraph('') | |
| def _add_part_questions(self, data: Dict[str, Any], part: str, heading: str): | |
| """Add questions for specific part""" | |
| self.doc.add_heading(heading, level=1) | |
| if "final_qp" in data and "questions" in data["final_qp"]: | |
| part_questions = [q for q in data["final_qp"]["questions"] if q.get("part") == part] | |
| for question in part_questions: | |
| # Question header | |
| q_header = f'Q{question["question_no"]}' | |
| if question.get("sub_no"): | |
| q_header += f'({question["sub_no"]})' | |
| q_header += f' [{question["marks"]} marks]' | |
| self.doc.add_paragraph(q_header).bold = True | |
| # Question text | |
| self.doc.add_paragraph(question["question_text"]) | |
| # Metadata | |
| meta = self.doc.add_paragraph() | |
| meta.add_run(f'Unit: {question["unit"]} | ') | |
| meta.add_run(f'Bloom: {question["bloom_level"]} | ') | |
| meta.add_run(f'CO: {question["course_outcome"]} | ') | |
| meta.add_run(f'Tags: {", ".join(question["tags"])}') | |
| meta.style.font.italic = True | |
| self.doc.add_paragraph('') | |
| def save_document(self, doc: Document, filename: str): | |
| """Save document to file""" | |
| doc.save(filename) | |
| def generate_all_documents(final_output: Dict[str, Any], subject: str, stream: str, output_dir: str = "."): | |
| """Generate all three DOCX files""" | |
| builder = DocxBuilder() | |
| # Question Paper | |
| qp_doc = builder.build_question_paper(final_output, subject, stream) | |
| qp_filename = f"{output_dir}/{subject}_QuestionPaper.docx" | |
| builder.save_document(qp_doc, qp_filename) | |
| # Answer Key | |
| ak_doc = builder.build_answer_key(final_output, subject) | |
| ak_filename = f"{output_dir}/{subject}_KeyAnswers.docx" | |
| builder.save_document(ak_doc, ak_filename) | |
| # OBE Summary | |
| obe_doc = builder.build_obe_summary(final_output, subject) | |
| obe_filename = f"{output_dir}/{subject}_OBE_Summary.docx" | |
| builder.save_document(obe_doc, obe_filename) | |
| return { | |
| "question_paper": qp_filename, | |
| "answer_key": ak_filename, | |
| "obe_summary": obe_filename | |
| } |