Passed
Push — main ( 33f2ac...d83075 )
by Máté
01:16
created

quiz   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 96
dl 0
loc 139
rs 10
c 0
b 0
f 0
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A Quiz.__str__() 0 11 3
A Quiz.__init__() 0 8 1
B Quiz.import_files() 0 12 6
B Quiz.add_question_no_duplicates() 0 28 5
A Quiz.import_questions() 0 13 3
A Quiz.import_question() 0 25 4
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_files(self, path: Path, recursively: bool) -> None:
57
        if os.path.isfile(path):
58
            self.import_questions(path, path.parent)
59
            return
60
        for subdir, dirs, files in os.walk(path):
61
            for file in files:
62
                self.import_questions(file, subdir)
63
            if not recursively:
64
                break
65
        if not self.questions:
66
            raise ValueError(
67
                "No questions were imported from the provided source path!"
68
            )
69
70
    def import_questions(self, file: Path | str, subdir: Path | str) -> None:
71
        file_path = os.path.join(subdir, file)
72
        with open(file_path, "rb") as source_file:
73
            webpage = BeautifulSoup(source_file, "html.parser")
74
75
            multi_or_single_choice_questions = webpage.find_all(
76
                "div", class_=re.compile(r"multichoice|calculatedmulti|truefalse")
77
            )
78
            for question in multi_or_single_choice_questions:
79
                self.import_question(
80
                    question=question, filename=os.path.basename(file_path)
81
                )
82
                clear_terminal()  # type: ignore
83
84
    def import_question(self, question: Tag, filename: str) -> None:
85
        with contextlib.suppress(NotImplementedError):
86
            question_type = get_question_type(question)  # type: ignore
87
        correctly_answered, grade, maximum_points = get_grading_of_question(question)  # type: ignore
88
        question_text = get_question_text(question)  # type: ignore
89
        answer_texts, id_of_correct_answers, all_correct_answers_known = get_answers(  # type: ignore
90
            question, grade, maximum_points
91
        )
92
        if not correctly_answered and not all_correct_answers_known:
93
            complete_correct_answers(  # type: ignore
94
                answer_texts,
95
                id_of_correct_answers,
96
                grade,
97
                maximum_points,
98
                question_text,
99
                question_type,
100
                filename,
101
            )
102
        has_illustration = get_if_has_illustration(question)  # type: ignore
103
        self.add_question_no_duplicates(
104
            question_type,
105
            question_text,
106
            has_illustration,
107
            answer_texts,
108
            id_of_correct_answers,
109
        )
110
111
    def add_question_no_duplicates(
112
        self,
113
        question_type: QuestionType,
114
        question_text: str,
115
        has_illustration: bool,
116
        answer_texts: list[str],
117
        correct_answers: set[int],
118
    ) -> None:
119
        for existing_question in self.questions:
120
            if question_already_exists(existing_question, question_text):  # type: ignore
121
                add_answers_to_existing_question(  # type: ignore
122
                    answer_texts, correct_answers, existing_question
123
                )
124
                break
125
        else:
126
            try:
127
                self.questions.add(
128
                    Question(
129
                        q_type=question_type,
130
                        text=question_text,
131
                        illustration=has_illustration,
132
                        answers=answer_texts,
133
                        correct_answers=correct_answers,
134
                    )
135
                )
136
            except AssertionError:
137
                print(
138
                    f"Error: question '{question_text}' was not added to the quiz because it wasn't processed correctly!"
139
                )
140