excel2moodle 0.3.4__py3-none-any.whl → 0.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,16 @@
1
- """This Module checks if the data inside the Spreadsheet is valid
1
+ """This Module checks if the data inside the Spreadsheet is valid.
2
2
 
3
3
  Those things are considered:
4
4
 
5
5
  #. The mandatory entries must not be ``Nan``
6
6
  #. All fields must have the right data-type
7
7
 
8
- If Those checks pass, a question is created, which can be accessed via ``Validator.question``
8
+ If Those checks pass, a question is created,
9
+ which can be accessed via ``Validator.question``
9
10
  """
10
11
 
11
12
  import logging
12
- from types import UnionType
13
+ from typing import TYPE_CHECKING
13
14
 
14
15
  import pandas as pd
15
16
 
@@ -17,10 +18,18 @@ from excel2moodle.core.exceptions import InvalidFieldException
17
18
  from excel2moodle.core.globals import DFIndex
18
19
  from excel2moodle.core.question import Question
19
20
 
21
+ if TYPE_CHECKING:
22
+ from types import UnionType
23
+
20
24
  logger = logging.getLogger(__name__)
21
25
 
22
26
 
23
27
  class Validator:
28
+ """Validate the question data from the spreadsheet.
29
+
30
+ Creates a dictionary with the data, for easier access later.
31
+ """
32
+
24
33
  def __init__(self, category) -> None:
25
34
  self.question: Question
26
35
  self.category = category
@@ -31,15 +40,16 @@ class Validator:
31
40
  }
32
41
  self.optional: dict[DFIndex, type | UnionType] = {
33
42
  DFIndex.BPOINTS: str,
34
- DFIndex.NAME: str,
35
43
  DFIndex.PICTURE: int | str,
36
44
  }
37
- self.nfOpt: dict[DFIndex, type | UnionType] = {
45
+ self.nfOpt: dict[DFIndex, type | UnionType] = {}
46
+ self.nfMand: dict[DFIndex, type | UnionType] = {
38
47
  DFIndex.RESULT: float | int,
39
48
  }
40
- self.nfMand: dict[DFIndex, type | UnionType] = {}
41
49
  self.nfmOpt: dict[DFIndex, type | UnionType] = {}
42
- self.nfmMand: dict[DFIndex, type | UnionType] = {}
50
+ self.nfmMand: dict[DFIndex, type | UnionType] = {
51
+ DFIndex.RESULT: str,
52
+ }
43
53
  self.mcOpt: dict[DFIndex, type | UnionType] = {}
44
54
  self.mcMand: dict[DFIndex, type | UnionType] = {
45
55
  DFIndex.TRUE: str,
@@ -70,7 +80,7 @@ class Validator:
70
80
  raise InvalidFieldException(msg, id, missing)
71
81
  checker, missing = self._typeCheck()
72
82
  if not checker:
73
- msg = f"Question {id} misses keys {missing}"
83
+ msg = f"Question {id} has wrong typed data {missing}"
74
84
  if missing is not None:
75
85
  raise InvalidFieldException(msg, id, missing)
76
86
  self._getQuestion()
@@ -81,7 +91,6 @@ class Validator:
81
91
  self.qdata: dict[str, str | float | int | list] = {}
82
92
  for idx, val in self.df.items():
83
93
  if not isinstance(idx, str):
84
- logger.debug(f"Got a non String key in the spreadsheet, skipping it")
85
94
  continue
86
95
  if idx in self.qdata:
87
96
  if isinstance(self.qdata[idx], list):
@@ -93,9 +102,9 @@ class Validator:
93
102
  self.qdata[idx] = val
94
103
 
95
104
  def _mandatory(self) -> tuple[bool, DFIndex | None]:
96
- """detects if all keys of mandatory are filled with values"""
105
+ """Detects if all keys of mandatory are filled with values."""
97
106
  checker = pd.Series.notna(self.df)
98
- for k in self.mandatory.keys():
107
+ for k in self.mandatory:
99
108
  try:
100
109
  c = checker[k]
101
110
  except KeyError:
@@ -112,24 +121,24 @@ class Validator:
112
121
  for field, typ in self.mandatory.items():
113
122
  if isinstance(self.df[field], pd.Series):
114
123
  for f in self.df[field]:
115
- if pd.notna(f):
116
- if not isinstance(f, typ):
117
- invalid.append(field)
124
+ if pd.notna(f) and not isinstance(f, typ):
125
+ invalid.append(field)
118
126
  elif not isinstance(self.df[field], typ):
119
127
  invalid.append(field)
120
128
  for field, typ in self.optional.items():
121
129
  if field in self.df:
122
- if not isinstance(self.df[field], typ):
130
+ if not isinstance(self.df[field], typ) and pd.notna(self.df[field]):
123
131
  invalid.append(field)
124
132
  if len(invalid) == 0:
125
133
  return True, None
126
- else:
127
- return False, invalid
134
+ return False, invalid
128
135
 
129
136
  def _getQuestion(self) -> None:
130
137
  name = self.df[DFIndex.NAME]
131
138
  qtype = self.df[DFIndex.TYPE]
132
139
  self.question = Question(
133
- self.category, name=str(name), number=self.index, qtype=str(qtype)
140
+ self.category,
141
+ name=str(name),
142
+ number=self.index,
143
+ qtype=str(qtype),
134
144
  )
135
- return None
@@ -1,174 +1,267 @@
1
- """This Module holds the related Functions for writing the Questions to an xml-File
1
+ """This Module holds the related Functions for writing the Questions to an xml-File.
2
2
 
3
3
  It is planned to rework those Functions, because they're not quite elegant.
4
4
  """
5
5
 
6
- from .stringHelpers import get_bullet_string
7
6
 
8
- def write_question_MC(save_dir, ID, name, s_1, s_2, s_3, points_avail, ans_type, true_ans, false_ans, pic):
9
- """Funktion schreibt MC-Frage auf Grundlage der übergebenen strings nach Pfad f_path"""
10
- perc = ['100', '50', '33.33333', '25', '20', '16.66667', '14.28571', '12.5', '11.11111', '10']
11
- num_true = int(len(true_ans))
12
- perc_true = perc[num_true-1]
13
- num_false = int(len(false_ans))
14
- perc_false = '-'+perc_true
15
- q_name = ID + '_' + name
16
- f_path = ( save_dir / q_name ).with_suffix('.xml')
7
+ def write_question_MC(
8
+ save_dir,
9
+ ID,
10
+ name,
11
+ s_1,
12
+ s_2,
13
+ s_3,
14
+ points_avail,
15
+ ans_type,
16
+ true_ans,
17
+ false_ans,
18
+ pic,
19
+ ) -> None:
20
+ """Funktion schreibt MC-Frage auf Grundlage der übergebenen strings nach Pfad f_path."""
21
+ perc = [
22
+ "100",
23
+ "50",
24
+ "33.33333",
25
+ "25",
26
+ "20",
27
+ "16.66667",
28
+ "14.28571",
29
+ "12.5",
30
+ "11.11111",
31
+ "10",
32
+ ]
33
+ num_true = len(true_ans)
34
+ perc_true = perc[num_true - 1]
35
+ num_false = len(false_ans)
36
+ perc_false = "-" + perc_true
37
+ q_name = ID + "_" + name
38
+ f_path = (save_dir / q_name).with_suffix(".xml")
17
39
 
18
- with open(f_path,'w', encoding='utf-8') as f:
19
- # Text schreiben
40
+ with open(f_path, "w", encoding="utf-8") as f:
41
+ # Text schreiben
20
42
  f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
21
- f.write('<quiz>\n')
43
+ f.write("<quiz>\n")
22
44
  f.write('<question type="multichoice">\n')
23
- f.write('<name>\n')
24
- f.write('<text>' + q_name + '</text>\n')
25
- f.write('</name>\n')
45
+ f.write("<name>\n")
46
+ f.write("<text>" + q_name + "</text>\n")
47
+ f.write("</name>\n")
26
48
  f.write('<questiontext format="html">\n')
27
49
  if pic != 0:
28
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID ' +str(ID)+ '</b> <br></p>'\
29
- '<p dir="ltr" style="text-align: left;">' + s_1 + '<br></p>'\
30
- '<p dir="ltr" style="text-align: left;">' + s_2 + '<br></p>'\
31
- '<p dir="ltr" style="text-align: left;">' + s_3 + '<br><br></p>'\
32
- '<br><img src="@@PLUGINFILE@@/'+ str(ID) + '.svg" alt="Bild" width="500"><br>'\
33
- '<br></p>]]></text>\n')
50
+ f.write(
51
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '
52
+ + str(ID)
53
+ + "</b> <br></p>"
54
+ '<p dir="ltr" style="text-align: left;">' + s_1 + "<br></p>"
55
+ '<p dir="ltr" style="text-align: left;">' + s_2 + "<br></p>"
56
+ '<p dir="ltr" style="text-align: left;">' + s_3 + "<br><br></p>"
57
+ '<br><img src="@@PLUGINFILE@@/'
58
+ + str(ID)
59
+ + '.svg" alt="Bild" width="500"><br>'
60
+ "<br></p>]]></text>\n",
61
+ )
34
62
  f.write(str(pic))
35
63
  else:
36
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '+q_name+' </b> <br></p>'\
37
- '<p dir="ltr" style="text-align: left;">' + s_1 + '<br></p>'\
38
- '<p dir="ltr" style="text-align: left;">' + s_2 + '<br></p>'\
39
- '<p dir="ltr" style="text-align: left;">' + s_3 + '<br></p>'\
40
- '<br></p>]]></text>\n')
41
-
42
- f.write('</questiontext>\n')
64
+ f.write(
65
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '
66
+ + q_name
67
+ + " </b> <br></p>"
68
+ '<p dir="ltr" style="text-align: left;">' + s_1 + "<br></p>"
69
+ '<p dir="ltr" style="text-align: left;">' + s_2 + "<br></p>"
70
+ '<p dir="ltr" style="text-align: left;">' + s_3 + "<br></p>"
71
+ "<br></p>]]></text>\n",
72
+ )
73
+
74
+ f.write("</questiontext>\n")
43
75
  f.write('<generalfeedback format="html">\n')
44
- f.write('<text></text>\n')
45
- f.write('</generalfeedback>\n')
46
- f.write('<defaultgrade>' +str(float(points_avail)) +'</defaultgrade>\n')
47
- f.write('<penalty>0.3333333</penalty>\n')
48
- f.write('<hidden>0</hidden>\n')
49
- f.write('<idnumber>' + ID +'</idnumber>\n')
50
- f.write('<single>false</single>\n')
51
- f.write('<shuffleanswers>true</shuffleanswers>\n')
52
- f.write('<answernumbering>abc</answernumbering>\n')
53
- f.write('<showstandardinstruction>0</showstandardinstruction>\n')
76
+ f.write("<text></text>\n")
77
+ f.write("</generalfeedback>\n")
78
+ f.write("<defaultgrade>" + str(float(points_avail)) + "</defaultgrade>\n")
79
+ f.write("<penalty>0.3333333</penalty>\n")
80
+ f.write("<hidden>0</hidden>\n")
81
+ f.write("<idnumber>" + ID + "</idnumber>\n")
82
+ f.write("<single>false</single>\n")
83
+ f.write("<shuffleanswers>true</shuffleanswers>\n")
84
+ f.write("<answernumbering>abc</answernumbering>\n")
85
+ f.write("<showstandardinstruction>0</showstandardinstruction>\n")
54
86
  f.write('<correctfeedback format="html">\n')
55
- f.write('<text>Die Frage wurde richtig beantwortet.</text>\n')
56
- f.write('</correctfeedback>\n')
87
+ f.write("<text>Die Frage wurde richtig beantwortet.</text>\n")
88
+ f.write("</correctfeedback>\n")
57
89
  f.write('<partiallycorrectfeedback format="html">\n')
58
- f.write('<text>Die Frage wurde teilweise richtig beantwortet.</text>\n')
59
- f.write('</partiallycorrectfeedback>\n')
90
+ f.write("<text>Die Frage wurde teilweise richtig beantwortet.</text>\n")
91
+ f.write("</partiallycorrectfeedback>\n")
60
92
  f.write('<incorrectfeedback format="html">\n')
61
- f.write('<text>Die Frage wurde falsch beantwortet.</text>\n')
62
- f.write('</incorrectfeedback>\n')
63
- f.write('<shownumcorrect/>\n')
64
-
93
+ f.write("<text>Die Frage wurde falsch beantwortet.</text>\n")
94
+ f.write("</incorrectfeedback>\n")
95
+ f.write("<shownumcorrect/>\n")
96
+
65
97
  # Alle richtigen Antworten
66
- for i in range (0, num_true):
67
-
68
- if ans_type=='unit':
69
- f.write('<answer fraction="' + perc_true +'" format="html">\n')
70
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(\\mathrm{' + true_ans[i] + '}\\)<br></p>]]></text>\n')
98
+ for i in range(num_true):
99
+ if ans_type == "unit":
100
+ f.write('<answer fraction="' + perc_true + '" format="html">\n')
101
+ f.write(
102
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(\\mathrm{'
103
+ + true_ans[i]
104
+ + "}\\)<br></p>]]></text>\n",
105
+ )
71
106
  f.write('<feedback format="html">\n')
72
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n')
73
- f.write('</feedback>\n')
74
- f.write('</answer>\n')
75
-
76
- elif ans_type=='math':
77
- f.write('<answer fraction="' + perc_true +'" format="html">\n')
78
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(' + true_ans[i] + '\\)<br></p>]]></text>\n')
107
+ f.write(
108
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n',
109
+ )
110
+ f.write("</feedback>\n")
111
+ f.write("</answer>\n")
112
+
113
+ elif ans_type == "math":
114
+ f.write('<answer fraction="' + perc_true + '" format="html">\n')
115
+ f.write(
116
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">\\('
117
+ + true_ans[i]
118
+ + "\\)<br></p>]]></text>\n",
119
+ )
79
120
  f.write('<feedback format="html">\n')
80
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n')
81
- f.write('</feedback>\n')
82
- f.write('</answer>\n')
83
-
84
-
85
- elif ans_type=='text':
86
- f.write('<answer fraction="' + perc_true +'" format="html">\n')
87
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">' + true_ans[i] + '<br></p>]]></text>\n')
121
+ f.write(
122
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n',
123
+ )
124
+ f.write("</feedback>\n")
125
+ f.write("</answer>\n")
126
+
127
+ elif ans_type == "text":
128
+ f.write('<answer fraction="' + perc_true + '" format="html">\n')
129
+ f.write(
130
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">'
131
+ + true_ans[i]
132
+ + "<br></p>]]></text>\n",
133
+ )
88
134
  f.write('<feedback format="html">\n')
89
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n')
90
- f.write('</feedback>\n')
91
- f.write('</answer>\n')
92
-
135
+ f.write(
136
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">richtig</span><br></p>]]></text>\n',
137
+ )
138
+ f.write("</feedback>\n")
139
+ f.write("</answer>\n")
140
+
93
141
  # Alle falschen Antworten
94
- for i in range (0, num_false):
95
- if ans_type=='unit':
96
- f.write('<answer fraction="' + perc_false +'" format="html">\n')
97
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(\\mathrm{' + false_ans[i] + '}\\)<br></p>]]></text>\n')
142
+ for i in range(num_false):
143
+ if ans_type == "unit":
144
+ f.write('<answer fraction="' + perc_false + '" format="html">\n')
145
+ f.write(
146
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(\\mathrm{'
147
+ + false_ans[i]
148
+ + "}\\)<br></p>]]></text>\n",
149
+ )
98
150
  f.write('<feedback format="html">\n')
99
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n')
100
- f.write('</feedback>\n')
101
- f.write('</answer>\n')
102
-
103
- elif ans_type=='math':
104
- f.write('<answer fraction="' + perc_false +'" format="html">\n')
105
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">\\(' + false_ans[i] + '\\)<br></p>]]></text>\n')
151
+ f.write(
152
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n',
153
+ )
154
+ f.write("</feedback>\n")
155
+ f.write("</answer>\n")
156
+
157
+ elif ans_type == "math":
158
+ f.write('<answer fraction="' + perc_false + '" format="html">\n')
159
+ f.write(
160
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">\\('
161
+ + false_ans[i]
162
+ + "\\)<br></p>]]></text>\n",
163
+ )
106
164
  f.write('<feedback format="html">\n')
107
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n')
108
- f.write('</feedback>\n')
109
- f.write('</answer>\n')
110
-
111
- elif ans_type=='text':
112
- f.write('<answer fraction="' + perc_false +'" format="html">\n')
113
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;">' + false_ans[i] + '<br></p>]]></text>\n')
165
+ f.write(
166
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n',
167
+ )
168
+ f.write("</feedback>\n")
169
+ f.write("</answer>\n")
170
+
171
+ elif ans_type == "text":
172
+ f.write('<answer fraction="' + perc_false + '" format="html">\n')
173
+ f.write(
174
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;">'
175
+ + false_ans[i]
176
+ + "<br></p>]]></text>\n",
177
+ )
114
178
  f.write('<feedback format="html">\n')
115
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n')
116
- f.write('</feedback>\n')
117
- f.write('</answer>\n')
118
-
119
- f.write('</question>\n')
120
- f.write('</quiz>\n')
121
- return None
122
-
123
- def write_question_NF(save_dir, ID, name, s_1, s_2, s_3, b_str, points_avail, result, pic, tol_abs, picID = None):
124
- """Funktion schreibt NF-Frage auf Grundlage der übergebenen strings nach Pfad f_path"""
125
- if picID == None:
179
+ f.write(
180
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(239, 69, 64);">falsch</span><br></p>]]></text>\n',
181
+ )
182
+ f.write("</feedback>\n")
183
+ f.write("</answer>\n")
184
+
185
+ f.write("</question>\n")
186
+ f.write("</quiz>\n")
187
+
188
+
189
+ def write_question_NF(
190
+ save_dir,
191
+ ID,
192
+ name,
193
+ s_1,
194
+ s_2,
195
+ s_3,
196
+ b_str,
197
+ points_avail,
198
+ result,
199
+ pic,
200
+ tol_abs,
201
+ picID=None,
202
+ ) -> None:
203
+ """Funktion schreibt NF-Frage auf Grundlage der übergebenen strings nach Pfad f_path."""
204
+ if picID is None:
126
205
  picID = ID
127
- q_name = ID + '_' + name
128
- f_path = (save_dir / q_name).with_suffix('.xml')
129
-
130
- with open(f_path,'w', encoding='utf-8') as f:
206
+ q_name = ID + "_" + name
207
+ f_path = (save_dir / q_name).with_suffix(".xml")
208
+
209
+ with open(f_path, "w", encoding="utf-8") as f:
131
210
  # Text schreiben
132
211
  f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
133
- f.write('<quiz>\n')
212
+ f.write("<quiz>\n")
134
213
  f.write('<question type="numerical">\n')
135
- f.write('<name>\n')
136
- f.write('<text>' + q_name + '</text>\n')
137
- f.write('</name>\n')
214
+ f.write("<name>\n")
215
+ f.write("<text>" + q_name + "</text>\n")
216
+ f.write("</name>\n")
138
217
  f.write('<questiontext format="html">\n')
139
218
  if pic != 0:
140
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '+ str(ID) +' </b> <br></p>'\
141
- '<p dir="ltr" style="text-align: left;">' + s_1 + '<br></p>'\
142
- '<p dir="ltr" style="text-align: left;">' + s_2 + '<br></p>'\
143
- '<p dir="ltr" style="text-align: left;">' + s_3 + b_str +'<br><br></p>'\
144
- '<br><img src="@@PLUGINFILE@@/'+ str(picID) + '.svg" alt="Bild" width="500"><br>'\
145
- '<br></p>]]></text>\n')
219
+ f.write(
220
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '
221
+ + str(ID)
222
+ + " </b> <br></p>"
223
+ '<p dir="ltr" style="text-align: left;">' + s_1 + "<br></p>"
224
+ '<p dir="ltr" style="text-align: left;">' + s_2 + "<br></p>"
225
+ '<p dir="ltr" style="text-align: left;">' + s_3 + b_str + "<br><br></p>"
226
+ '<br><img src="@@PLUGINFILE@@/'
227
+ + str(picID)
228
+ + '.svg" alt="Bild" width="500"><br>'
229
+ "<br></p>]]></text>\n",
230
+ )
146
231
  f.write(pic)
147
232
  else:
148
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '+ID+' </b> <br></p>'\
149
- '<p dir="ltr" style="text-align: left;">' + s_1 + '<br></p>'\
150
- '<p dir="ltr" style="text-align: left;">' + s_2 + '<br></p>'\
151
- '<p dir="ltr" style="text-align: left;">' + s_3 + b_str+ ']]></text>\n')
152
-
153
- f.write('</questiontext>\n')
233
+ f.write(
234
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"> <b>ID '
235
+ + ID
236
+ + " </b> <br></p>"
237
+ '<p dir="ltr" style="text-align: left;">' + s_1 + "<br></p>"
238
+ '<p dir="ltr" style="text-align: left;">' + s_2 + "<br></p>"
239
+ '<p dir="ltr" style="text-align: left;">'
240
+ + s_3
241
+ + b_str
242
+ + "]]></text>\n",
243
+ )
244
+
245
+ f.write("</questiontext>\n")
154
246
  f.write('<generalfeedback format="html">\n')
155
- f.write('<text></text>\n')
156
- f.write('</generalfeedback>\n')
157
- f.write('<defaultgrade>' +str(float(points_avail)) +'</defaultgrade>\n')
158
- f.write('<penalty>0.3333333</penalty>\n')
159
- f.write('<hidden>0</hidden>\n')
160
- f.write('<idnumber>' + ID +'</idnumber>\n')
247
+ f.write("<text></text>\n")
248
+ f.write("</generalfeedback>\n")
249
+ f.write("<defaultgrade>" + str(float(points_avail)) + "</defaultgrade>\n")
250
+ f.write("<penalty>0.3333333</penalty>\n")
251
+ f.write("<hidden>0</hidden>\n")
252
+ f.write("<idnumber>" + ID + "</idnumber>\n")
161
253
  f.write('<answer fraction="100" format="moodle_auto_format">\n')
162
- f.write('<text>'+ str(result) +'</text>\n')
254
+ f.write("<text>" + str(result) + "</text>\n")
163
255
  f.write('<feedback format="html">\n')
164
- f.write('<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">Das Ergebnis ist im Rahmen der 1%-Toleranz korrekt.</span><br></p>]]></text>\n')
165
- f.write('</feedback>\n')
166
- f.write('<tolerance>'+ str(tol_abs)+'</tolerance>\n')
167
- f.write('</answer>\n')
168
- f.write('<unitgradingtype>0</unitgradingtype>\n')
169
- f.write('<unitpenalty>0.1000000</unitpenalty>\n')
170
- f.write('<showunits>3</showunits>\n')
171
- f.write('<unitsleft>0</unitsleft>\n')
172
- f.write('</question>\n')
173
- f.write('</quiz>\n')
174
- return None
256
+ f.write(
257
+ '<text><![CDATA[<p dir="ltr" style="text-align: left;"><span class="" style="color: rgb(152, 202, 62);">Das Ergebnis ist im Rahmen der 1%-Toleranz korrekt.</span><br></p>]]></text>\n',
258
+ )
259
+ f.write("</feedback>\n")
260
+ f.write("<tolerance>" + str(tol_abs) + "</tolerance>\n")
261
+ f.write("</answer>\n")
262
+ f.write("<unitgradingtype>0</unitgradingtype>\n")
263
+ f.write("<unitpenalty>0.1000000</unitpenalty>\n")
264
+ f.write("<showunits>3</showunits>\n")
265
+ f.write("<unitsleft>0</unitsleft>\n")
266
+ f.write("</question>\n")
267
+ f.write("</quiz>\n")
@@ -1,6 +1,6 @@
1
- """This Module holds small Helperfunctions related to string manipulation"""
1
+ """This Module holds small Helperfunctions related to string manipulation."""
2
2
 
3
- import base64 as base64
3
+ import base64
4
4
  from pathlib import Path
5
5
 
6
6
  import lxml.etree as ET
@@ -21,7 +21,7 @@ def stringToFloat(string: str) -> float:
21
21
 
22
22
 
23
23
  def get_bullet_string(s):
24
- """Formatiert die Angaben zum Statischen System hübsch"""
24
+ """Formatiert die Angaben zum Statischen System hübsch."""
25
25
  split = s.split(";")
26
26
  s_spl = stripWhitespace(split)
27
27
  name = []
@@ -35,16 +35,12 @@ def get_bullet_string(s):
35
35
  quant.append(sc_split[3])
36
36
  unit.append(sc_split[4])
37
37
  bulletString = ['</p><ul dir="ltr">']
38
- for i in range(0, len(s_spl)):
38
+ for i in range(len(s_spl)):
39
39
  num = quant[i].split(",")
40
- if len(num) == 2:
41
- num_s = f"{str(num[0])},\\!{str(num[1])}~"
42
- else:
43
- num_s = f"{str(num[0])},\\!0~"
40
+ num_s = f"{num[0]!s},\\!{num[1]!s}~" if len(num) == 2 else f"{num[0]!s},\\!0~"
44
41
  bulletString.append('<li style="text-align: left;">')
45
42
  bulletString.append(
46
- f"{name[i]}: \\( {var[i]} = {
47
- num_s} \\mathrm{{ {unit[i]} }}\\) </li>\n"
43
+ f"{name[i]}: \\( {var[i]} = {num_s} \\mathrm{{ {unit[i]} }}\\) </li>\n",
48
44
  )
49
45
  bulletString.append("<br></ul>")
50
46
  return "\n".join(bulletString)
@@ -52,43 +48,40 @@ def get_bullet_string(s):
52
48
 
53
49
  def getBase64Img(imgPath):
54
50
  with open(imgPath, "rb") as img:
55
- img64 = base64.b64encode(img.read()).decode("utf-8")
56
- return img64
51
+ return base64.b64encode(img.read()).decode("utf-8")
57
52
 
58
53
 
59
- def getUnitsElementAsString(unit):
60
-
54
+ def getUnitsElementAsString(unit) -> None:
61
55
  def __getUnitEle__(name, multipl):
62
56
  unit = ET.Element("unit")
63
57
  ET.SubElement(unit, "multiplier").text = multipl
64
58
  ET.SubElement(unit, "unit_name").text = name
65
59
  return unit
66
60
 
67
- unitsEle = ET.Element("units")
61
+ ET.Element("units")
68
62
 
69
63
 
70
64
  def printDom(xmlElement: ET.Element, file: Path | None = None) -> None:
71
- """Prints the document tree of ``xmlTree`` to the ``file``, if specified, else dumps to stdout"""
65
+ """Prints the document tree of ``xmlTree`` to the ``file``, if specified, else dumps to stdout."""
72
66
  documentTree = ET.ElementTree(xmlElement)
73
67
  if file is not None:
74
68
  if file.parent.exists():
75
69
  documentTree.write(
76
- file, xml_declaration=True, encoding="utf-8", pretty_print=True
70
+ file,
71
+ xml_declaration=True,
72
+ encoding="utf-8",
73
+ pretty_print=True,
77
74
  )
78
75
  else:
79
- msg = "No output File specified, here is the Element:"
80
- print(f"\n{msg:=^80}")
81
- print(ET.tostring(xmlElement, encoding="utf-8", pretty_print=True))
82
- print(f'{" End of Element ":=^80}')
76
+ pass
83
77
 
84
78
 
85
79
  def texWrapper(text: str | list[str], style: str) -> list[str]:
86
- """Puts the strings inside ``text`` into a LaTex environment
80
+ r"""Puts the strings inside ``text`` into a LaTex environment.
87
81
 
88
82
  if ``style == unit``: inside ``\\mathrm{}``
89
83
  if ``style == math``: inside ``\\( \\)``
90
84
  """
91
-
92
85
  answers: list[str] = []
93
86
  begin = ""
94
87
  end = ""