Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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