def assemble_exam( exam: str, email: Optional[str], response: Dict[str, Union[str, List[str]]], template_questions: List[Dict], student_questions: List[Dict], name_question: str, sid_question: str, dispatch, substitute_in_question_text: bool = False, ): questions = [] exam = AssembledExam( exam=exam, email=email, name=response.get(name_question, "NO NAME"), sid=response.get(sid_question, "NO SID"), questions=questions, ) student_question_lookup = {q["id"]: q for q in student_questions} for question in template_questions: question_name = get_name(question) if substitute_in_question_text: question_text = Text( student_question_lookup.get(question["id"], question)) else: question_text = Text(question) autograde_output = ( grade( email, student_question_lookup[question["id"]], response, dispatch, ) if question["id"] in response and question["id"] in student_question_lookup else "STUDENT LEFT QUESTION BLANK" if question["id"] in student_question_lookup else "STUDENT DID NOT RECEIVE QUESTION") if question.get("type") in ["multiple_choice", "select_all"]: selected_options = response.get(question["id"], []) if question.get("type") == "multiple_choice" and not isinstance( selected_options, list): selected_options = [selected_options] available_options = [ Text(option) for option in question["options"] ] if question["id"] not in student_question_lookup: student_options = available_options else: student_options = [ option["text"] for option in sorted( student_question_lookup[question["id"]]["options"], key=lambda option: option.get("index", ""), ) ] assert len(available_options) == len(student_options) assembled_question = OptionQuestion( name=question_name, prompt=question_text, options=available_options, selected=([ option for option in available_options if option.text in selected_options ]), autograde_output=autograde_output, ) else: assembled_question = TextQuestion( name=question_name, prompt=question_text, autograde_output=autograde_output, response=response.get(question["id"], "").replace("\t", " " * 4), height=question.get("options") or 1, ) questions.append(assembled_question) return exam
def write_exam( response, exam, template_questions, student_questions, name_question, sid_question, dispatch, out=None, ): pdf = FPDF() pdf.add_page() pdf.set_font("Courier", size=16) pdf.multi_cell(200, 20, txt=exam, align="L") pdf.multi_cell(200, 20, txt=response.get(name_question, "NO NAME").encode( "latin-1", "replace").decode("latin-1"), align="L") pdf.multi_cell(200, 20, txt=response.get(sid_question, "NO SID").encode( "latin-1", "replace").decode("latin-1"), align="L") pdf.set_font("Courier", size=9) if out is None: def out(text): pdf.multi_cell(200, 5, txt=text.encode("latin-1", "replace").decode("latin-1"), align="L") student_question_lookup = {q["id"]: q for q in student_questions} for question in template_questions: pdf.add_page() out("\nQUESTION") for line in question["text"].split("\n"): out(line) out("\nANSWER") if question.get("type") in ["multiple_choice", "select_all"]: selected_options = response.get(question["id"], []) if question.get("type") == "multiple_choice" and not isinstance( selected_options, list): selected_options = [selected_options] available_options = sorted([ (i, option["text"]) for i, option in enumerate(question["options"]) ]) if question["id"] not in student_question_lookup: student_options = sorted([ (option.get("index", i), option["text"]) for i, option in enumerate(question["options"]) ]) else: student_options = sorted([ (option.get("index", i), option["text"]) for i, option in enumerate(student_question_lookup[ question["id"]]["options"]) ]) available_options = [ (*available_option, option) for available_option, ( j, option) in zip(available_options, student_options) ] available_options.sort(key=lambda x: x[1]) for i, template, option in available_options: if option in selected_options: template = template out("[X] " + template) else: out("[ ] " + template) else: for line in response.get(question["id"], "").split("\n"): out(line) out("\nAUTOGRADER") if question["id"] in student_question_lookup and question[ "id"] in response: out( grade(student_question_lookup[question["id"]], response, dispatch)) elif question["id"] not in student_question_lookup: out("STUDENT DID NOT RECEIVE QUESTION") else: out("") return pdf
def write_exam( response, exam, template_questions, student_questions, name_question, sid_question, compact, dispatch, ): pdf = FPDF() pdf.add_page() pdf.set_font("Courier", size=16) pdf.multi_cell(200, 20, txt=exam, align="L") pdf.multi_cell(200, 20, txt=response.get(name_question, "NO NAME"), align="L") pdf.multi_cell(200, 20, txt=response.get(sid_question, "NO SID"), align="L") pdf.set_font("Courier", size=9) def out(text): pdf.multi_cell(200, 5, txt=text, align="L") line_count = 0 force_new = True student_question_lookup = {q["id"]: q for q in student_questions} for question in template_questions: if line_count > 30 or force_new or not compact: pdf.add_page() line_count = 0 force_new = False out("\nQUESTION") for line in question["text"].split("\n"): out(line) line_count += 1 out("\nANSWER") if question.get("type") not in ["multiple_choice", "select_all"]: force_new = True if question.get("type") in ["multiple_choice", "select_all"]: selected_options = response.get(question["id"], []) if question.get("type") == "multiple_choice" and not isinstance( selected_options, list): selected_options = [selected_options] available_options = sorted( [option["text"] for option in question["options"]]) if question["id"] not in student_question_lookup: out("STUDENT DID NOT RECEIVE QUESTION") line_count += 1 else: student_options = sorted([ option["text"] for option in student_question_lookup[ question["id"]]["options"] ]) for template, option in zip(available_options, student_options): if option in selected_options: out("[X] " + template) else: out("[ ] " + template) line_count += 1 else: for line in (response.get(question["id"], "").encode( "latin-1", "replace").decode("latin-1").split("\n")): out(line) line_count += 1 out("\nAUTOGRADER") if question["id"] in student_question_lookup and question[ "id"] in response: out( grade(student_question_lookup[question["id"]], response, dispatch)) return pdf