Passed
Push — main ( d83075...11bea3 )
by Máté
01:58
created

quiz.Quiz.add_question()   A

Complexity

Conditions 2

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 18
nop 6
dl 0
loc 21
rs 9.5
c 0
b 0
f 0
1
import contextlib
2
3
# future: report false positive to JetBrains developers
4
# noinspection PyUnresolvedReferences
5
import os
6
from pathlib import Path
7
8
# future: report false positive to JetBrains developers
9
# noinspection PyUnresolvedReferences
10
import re
11
12
# future: report false positive to JetBrains developers
13
# noinspection PyUnresolvedReferences
14
from bs4 import BeautifulSoup, Tag
15
16
# future: report false positive to JetBrains developers
17
# noinspection PyPackages
18
# future: report false positive to mypy developers
19
from .grading_types import GradingType  # type: ignore
20
21
# noinspection PyPackages
22
# future: report false positive to mypy developers
23
from .question_types import QuestionType  # type: ignore
24
25
# noinspection PyPackages
26
# future: report false positive to mypy developers
27
from .quiz_helpers import *  # type: ignore
28
29
# noinspection PyPackages
30
# future: report false positive to mypy developers
31
from .question import Question  # type: ignore
32
33
34
class Quiz:
35
    def __init__(
36
        self, parent_article: str, title: str, grading: GradingType | None = None
37
    ):
38
        self.parent_article = parent_article
39
        self.title = title
40
        self.grading = grading
41
42
        self.questions: set[Question] = set()
43
44
    def __str__(self) -> str:
45
        text = f"{{{{Vissza | {self.parent_article}}}}}"
46
        text += f"""{{{{Kvízoldal
47
| cím = {self.title}"""
48
        if self.grading:
49
            text += f"\n| pontozás = {self.grading.value}"
50
        text += "\n}}"
51
        for question in self.questions:
52
            text += f"\n\n\n{question}"
53
        text += "\n"
54
        return text
55
56
    def import_file_or_files(self, path: Path, recursively: bool) -> None:
57
        if os.path.isfile(path):
58
            self.import_questions(path, path.parent)
59
        else:
60
            self.import_files(path, recursively)
61
        if not self.questions:
62
            raise ValueError(
63
                "No questions were imported from the provided source path!"
64
            )
65
66
    def import_files(self, path: Path, recursively: bool) -> None:
67
        for subdir, dirs, files in os.walk(path):
68
            for file in files:
69
                self.import_questions(file, subdir)
70
            if not recursively:
71
                break
72
73
    def import_questions(self, file: Path | str, subdir: Path | str) -> None:
74
        file_path = os.path.join(subdir, file)
75
        with open(file_path, "rb") as source_file:
76
            webpage = BeautifulSoup(source_file, "html.parser")
77
78
            multi_or_single_choice_questions = webpage.find_all(
79
                "div", class_=re.compile(r"multichoice|calculatedmulti|truefalse")
80
            )
81
            for question in multi_or_single_choice_questions:
82
                self.import_question(
83
                    question=question, filename=os.path.basename(file_path)
84
                )
85
                clear_terminal()  # type: ignore
86
87
    def import_question(self, question: Tag, filename: str) -> None:
88
        with contextlib.suppress(NotImplementedError):
89
            question_type = get_question_type(question)  # type: ignore
90
        correctly_answered, grade, maximum_points = get_grading_of_question(question)  # type: ignore
91
        question_text = get_question_text(question)  # type: ignore
92
        answer_texts, id_of_correct_answers, all_correct_answers_known = get_answers(  # type: ignore
93
            question, grade, maximum_points
94
        )
95
        if not correctly_answered and not all_correct_answers_known:
96
            complete_correct_answers(  # type: ignore
97
                answer_texts,
98
                id_of_correct_answers,
99
                grade,
100
                maximum_points,
101
                question_text,
102
                question_type,
103
                filename,
104
            )
105
        has_illustration = get_if_has_illustration(question)  # type: ignore
106
        self.add_question_no_duplicates(
107
            question_type,
108
            question_text,
109
            has_illustration,
110
            answer_texts,
111
            id_of_correct_answers,
112
        )
113
114
    def add_question_no_duplicates(
115
        self,
116
        question_type: QuestionType,
117
        question_text: str,
118
        has_illustration: bool,
119
        answer_texts: list[str],
120
        correct_answers: set[int],
121
    ) -> None:
122
        for existing_question in self.questions:
123
            if question_already_exists(existing_question, question_text):  # type: ignore
124
                add_answers_to_existing_question(  # type: ignore
125
                    answer_texts, correct_answers, existing_question
126
                )
127
                break
128
        else:
129
            self.add_question(
130
                answer_texts,
131
                correct_answers,
132
                has_illustration,
133
                question_text,
134
                question_type,
135
            )
136
137
    def add_question(
138
        self,
139
        answer_texts: list[str],
140
        correct_answers: set[int],
141
        has_illustration: bool,
142
        question_text: str,
143
        question_type: QuestionType,
144
    ) -> None:
145
        try:
146
            self.questions.add(
147
                Question(
148
                    q_type=question_type,
149
                    text=question_text,
150
                    illustration=has_illustration,
151
                    answers=answer_texts,
152
                    correct_answers=correct_answers,
153
                )
154
            )
155
        except AssertionError:
156
            print(
157
                f"Error: question '{question_text}' was not added to the quiz because it wasn't processed correctly!"
158
            )
159