QuizGenerator 0.7.1__py3-none-any.whl → 0.8.1__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.
- QuizGenerator/contentast.py +48 -15
- QuizGenerator/generate.py +2 -1
- QuizGenerator/mixins.py +14 -100
- QuizGenerator/premade_questions/basic.py +24 -29
- QuizGenerator/premade_questions/cst334/languages.py +100 -99
- QuizGenerator/premade_questions/cst334/math_questions.py +112 -122
- QuizGenerator/premade_questions/cst334/memory_questions.py +621 -621
- QuizGenerator/premade_questions/cst334/persistence_questions.py +137 -163
- QuizGenerator/premade_questions/cst334/process.py +312 -328
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +34 -35
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +41 -36
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +48 -41
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +285 -521
- QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +149 -126
- QuizGenerator/premade_questions/cst463/models/attention.py +44 -50
- QuizGenerator/premade_questions/cst463/models/cnns.py +43 -47
- QuizGenerator/premade_questions/cst463/models/matrices.py +61 -11
- QuizGenerator/premade_questions/cst463/models/rnns.py +48 -50
- QuizGenerator/premade_questions/cst463/models/text.py +65 -67
- QuizGenerator/premade_questions/cst463/models/weight_counting.py +47 -46
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +100 -156
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +93 -141
- QuizGenerator/question.py +310 -202
- QuizGenerator/quiz.py +8 -5
- QuizGenerator/regenerate.py +14 -6
- {quizgenerator-0.7.1.dist-info → quizgenerator-0.8.1.dist-info}/METADATA +30 -2
- {quizgenerator-0.7.1.dist-info → quizgenerator-0.8.1.dist-info}/RECORD +30 -30
- {quizgenerator-0.7.1.dist-info → quizgenerator-0.8.1.dist-info}/WHEEL +0 -0
- {quizgenerator-0.7.1.dist-info → quizgenerator-0.8.1.dist-info}/entry_points.txt +0 -0
- {quizgenerator-0.7.1.dist-info → quizgenerator-0.8.1.dist-info}/licenses/LICENSE +0 -0
QuizGenerator/quiz.py
CHANGED
|
@@ -206,10 +206,10 @@ class Quiz:
|
|
|
206
206
|
if check_typst_available():
|
|
207
207
|
try:
|
|
208
208
|
# Render question to Typst
|
|
209
|
-
|
|
209
|
+
instance = question.instantiate(**kwargs)
|
|
210
210
|
|
|
211
211
|
# Get just the content body (without the #question wrapper which adds spacing)
|
|
212
|
-
typst_body =
|
|
212
|
+
typst_body = instance.body.render("typst", **kwargs)
|
|
213
213
|
|
|
214
214
|
# Measure the content
|
|
215
215
|
measured_height = measure_typst_content(typst_body, page_width_cm=18.0)
|
|
@@ -236,7 +236,8 @@ class Quiz:
|
|
|
236
236
|
spacing_height = question.spacing # cm
|
|
237
237
|
|
|
238
238
|
# Estimate content height by rendering to LaTeX and analyzing structure
|
|
239
|
-
|
|
239
|
+
instance = question.instantiate(**kwargs)
|
|
240
|
+
question_ast = question._build_question_ast(instance)
|
|
240
241
|
latex_content = question_ast.render("latex")
|
|
241
242
|
|
|
242
243
|
# Count content that adds height (rough estimates in cm)
|
|
@@ -451,9 +452,11 @@ class Quiz:
|
|
|
451
452
|
# Generate a unique seed for this question from the master seed
|
|
452
453
|
if master_seed is not None:
|
|
453
454
|
question_seed = master_rng.randint(0, 2**31 - 1)
|
|
454
|
-
|
|
455
|
+
instance = question.instantiate(rng_seed=question_seed, **kwargs)
|
|
456
|
+
question_ast = question._build_question_ast(instance)
|
|
455
457
|
else:
|
|
456
|
-
|
|
458
|
+
instance = question.instantiate(**kwargs)
|
|
459
|
+
question_ast = question._build_question_ast(instance)
|
|
457
460
|
|
|
458
461
|
# Add question number to the AST for QR code generation
|
|
459
462
|
question_ast.question_number = question_number
|
QuizGenerator/regenerate.py
CHANGED
|
@@ -241,10 +241,14 @@ def regenerate_question_answer(
|
|
|
241
241
|
)
|
|
242
242
|
|
|
243
243
|
# Generate question with the specific seed
|
|
244
|
-
|
|
244
|
+
instance = question.instantiate(rng_seed=seed)
|
|
245
|
+
question_ast = question._build_question_ast(instance)
|
|
245
246
|
|
|
246
247
|
# Extract answers
|
|
247
|
-
answer_kind, canvas_answers = question.
|
|
248
|
+
answer_kind, canvas_answers = question._answers_for_canvas(
|
|
249
|
+
instance.answers,
|
|
250
|
+
instance.can_be_numerical
|
|
251
|
+
)
|
|
248
252
|
|
|
249
253
|
result['answers'] = {
|
|
250
254
|
'kind': answer_kind.value,
|
|
@@ -252,7 +256,7 @@ def regenerate_question_answer(
|
|
|
252
256
|
}
|
|
253
257
|
|
|
254
258
|
# Also store the raw answer objects for easier access
|
|
255
|
-
result['answer_objects'] =
|
|
259
|
+
result['answer_objects'] = instance.answers
|
|
256
260
|
|
|
257
261
|
resolved_upload_func = _resolve_upload_func(image_mode, upload_func)
|
|
258
262
|
|
|
@@ -400,10 +404,14 @@ def regenerate_from_metadata(
|
|
|
400
404
|
)
|
|
401
405
|
|
|
402
406
|
# Generate question with the specific seed
|
|
403
|
-
|
|
407
|
+
instance = question.instantiate(rng_seed=seed)
|
|
408
|
+
question_ast = question._build_question_ast(instance)
|
|
404
409
|
|
|
405
410
|
# Extract answers
|
|
406
|
-
answer_kind, canvas_answers = question.
|
|
411
|
+
answer_kind, canvas_answers = question._answers_for_canvas(
|
|
412
|
+
instance.answers,
|
|
413
|
+
instance.can_be_numerical
|
|
414
|
+
)
|
|
407
415
|
|
|
408
416
|
resolved_upload_func = _resolve_upload_func(image_mode, upload_func)
|
|
409
417
|
|
|
@@ -436,7 +444,7 @@ def regenerate_from_metadata(
|
|
|
436
444
|
"kind": answer_kind.value,
|
|
437
445
|
"data": canvas_answers
|
|
438
446
|
},
|
|
439
|
-
"answer_objects":
|
|
447
|
+
"answer_objects": instance.answers,
|
|
440
448
|
"answer_key_html": question_html,
|
|
441
449
|
"explanation_markdown": explanation_markdown,
|
|
442
450
|
"explanation_html": explanation_html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: QuizGenerator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Generate randomized quiz questions for Canvas LMS and PDF exams
|
|
5
5
|
Project-URL: Homepage, https://github.com/OtterDen-Lab/QuizGenerator
|
|
6
6
|
Project-URL: Documentation, https://github.com/OtterDen-Lab/QuizGenerator/tree/main/documentation
|
|
@@ -144,6 +144,34 @@ questions:
|
|
|
144
144
|
|
|
145
145
|
See [documentation/custom_questions.md](documentation/custom_questions.md) for complete guide.
|
|
146
146
|
|
|
147
|
+
### Question Authoring Pattern (New)
|
|
148
|
+
|
|
149
|
+
All questions follow the same three‑method flow:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
class MyQuestion(Question):
|
|
153
|
+
def _build_context(self, *, rng_seed=None, **kwargs):
|
|
154
|
+
context = super()._build_context(rng_seed=rng_seed, **kwargs)
|
|
155
|
+
rng = context["rng"]
|
|
156
|
+
context["value"] = rng.randint(1, 10)
|
|
157
|
+
return context
|
|
158
|
+
|
|
159
|
+
def _build_body(self, context):
|
|
160
|
+
body = ca.Section()
|
|
161
|
+
body.add_element(ca.Paragraph([f"Value: {context['value']}"]))
|
|
162
|
+
body.add_element(ca.AnswerTypes.Int(context["value"], label="Value"))
|
|
163
|
+
return body
|
|
164
|
+
|
|
165
|
+
def _build_explanation(self, context):
|
|
166
|
+
explanation = ca.Section()
|
|
167
|
+
explanation.add_element(ca.Paragraph([f"Answer: {context['value']}"]))
|
|
168
|
+
return explanation
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Notes:
|
|
172
|
+
- Always use `context["rng"]` for deterministic randomness.
|
|
173
|
+
- Avoid `refresh()`; it is no longer part of the API.
|
|
174
|
+
|
|
147
175
|
## Built-in Question Types
|
|
148
176
|
|
|
149
177
|
### Operating Systems (CST334)
|
|
@@ -262,4 +290,4 @@ If you use QuizGenerator in academic work, please cite:
|
|
|
262
290
|
|
|
263
291
|
---
|
|
264
292
|
|
|
265
|
-
**Note**: This tool is designed for educational use. Ensure compliance with your institution's academic integrity policies when using automated quiz generation.
|
|
293
|
+
**Note**: This tool is designed for educational use. Ensure compliance with your institution's academic integrity policies when using automated quiz generation.
|
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
QuizGenerator/__init__.py,sha256=8EV-k90A3PNC8Cm2-ZquwNyVyvnwW1gs6u-nGictyhs,840
|
|
2
2
|
QuizGenerator/__main__.py,sha256=Dd9w4R0Unm3RiXztvR4Y_g9-lkWp6FHg-4VN50JbKxU,151
|
|
3
3
|
QuizGenerator/constants.py,sha256=AO-UWwsWPLb1k2JW6KP8rl9fxTcdT0rW-6XC6zfnDOs,4386
|
|
4
|
-
QuizGenerator/contentast.py,sha256=
|
|
5
|
-
QuizGenerator/generate.py,sha256=
|
|
4
|
+
QuizGenerator/contentast.py,sha256=uTql3nvNg8DZnPxOg7S31vXbifSNfb3rFK5c_ihLsbg,87615
|
|
5
|
+
QuizGenerator/generate.py,sha256=dqF-WWmWxyJmPHl0gTYr3gNNxyF877fvXYaMvYA3uA8,15790
|
|
6
6
|
QuizGenerator/misc.py,sha256=MXrguUhhdrWSV4Hqdl4G21ktowODu1AcKy6-5mvy3aI,454
|
|
7
|
-
QuizGenerator/mixins.py,sha256=
|
|
7
|
+
QuizGenerator/mixins.py,sha256=B9Ee52wUCeclmBTgonasHNo0WHvVOcnILsz0iecrf78,15705
|
|
8
8
|
QuizGenerator/performance.py,sha256=CM3zLarJXN5Hfrl4-6JRBqD03j4BU1B2QW699HAr1Ds,7002
|
|
9
9
|
QuizGenerator/qrcode_generator.py,sha256=S3mzZDk2UiHiw6ipSCpWPMhbKvSRR1P5ordZJUTo6ug,10776
|
|
10
|
-
QuizGenerator/question.py,sha256=
|
|
11
|
-
QuizGenerator/quiz.py,sha256=
|
|
12
|
-
QuizGenerator/regenerate.py,sha256=
|
|
10
|
+
QuizGenerator/question.py,sha256=QsLKFEM8LzLkH1_5MOwMFRuqtTkEd7-a_eoaTKcttpU,33602
|
|
11
|
+
QuizGenerator/quiz.py,sha256=CEWy7FB7BZiK33s_wYs6MqGKDetc6htUaqvP3--2HzI,21621
|
|
12
|
+
QuizGenerator/regenerate.py,sha256=ZAs1mtERmO8JXza2tBqJpd-uJs9V7gS1jJ9A9gSb8jo,19764
|
|
13
13
|
QuizGenerator/typst_utils.py,sha256=JGQn_u5bEHd8HAtjAHuZoVJwLkx-Rd4ZCBWffwFZa3o,3136
|
|
14
14
|
QuizGenerator/canvas/__init__.py,sha256=TwFP_zgxPIlWtkvIqQ6mcvBNTL9swIH_rJl7DGKcvkQ,286
|
|
15
15
|
QuizGenerator/canvas/canvas_interface.py,sha256=StMcdXgLvTA1EayQ44m_le2GXGQpDQnduYXVeUYsqW0,24618
|
|
16
16
|
QuizGenerator/canvas/classes.py,sha256=v_tQ8t_JJplU9sv2p4YctX45Fwed1nQ2HC1oC9BnDNw,7594
|
|
17
17
|
QuizGenerator/premade_questions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
QuizGenerator/premade_questions/basic.py,sha256=
|
|
18
|
+
QuizGenerator/premade_questions/basic.py,sha256=F_Qsu14b2xERyibCAMP1NPgnmi1h2G2DDkKJoU_RS8g,3284
|
|
19
19
|
QuizGenerator/premade_questions/cst334/__init__.py,sha256=BTz-Os1XbwIRKqAilf2UIva2NlY0DbA_XbSIggO2Tdk,36
|
|
20
|
-
QuizGenerator/premade_questions/cst334/languages.py,sha256=
|
|
21
|
-
QuizGenerator/premade_questions/cst334/math_questions.py,sha256=
|
|
22
|
-
QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=
|
|
20
|
+
QuizGenerator/premade_questions/cst334/languages.py,sha256=ctemEAMkI8C6ASMIf59EHAW1ndFWi7hXzdEt-zOByUE,14114
|
|
21
|
+
QuizGenerator/premade_questions/cst334/math_questions.py,sha256=aUYbQxneL5MXE7Xo3tZX9-xcg71CXwvG3rrxcoh0l7A,8638
|
|
22
|
+
QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=g0EFJ2HUogYnOYMWYyn-z4lEv15Pfv5IdSvj0xGoKbI,51050
|
|
23
23
|
QuizGenerator/premade_questions/cst334/ostep13_vsfs.py,sha256=d9jjrynEw44vupAH_wKl57UoHooCNEJXaC5DoNYualk,16163
|
|
24
|
-
QuizGenerator/premade_questions/cst334/persistence_questions.py,sha256=
|
|
25
|
-
QuizGenerator/premade_questions/cst334/process.py,sha256=
|
|
24
|
+
QuizGenerator/premade_questions/cst334/persistence_questions.py,sha256=9mgsX-3oWDQgm_n2YwmFSil0QPyzsruHzuqB-hfGMuA,16220
|
|
25
|
+
QuizGenerator/premade_questions/cst334/process.py,sha256=0SqXkvdxaEJZXJA8fBqheh7F0PL8I6xgO5a8u2s2po4,37238
|
|
26
26
|
QuizGenerator/premade_questions/cst463/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py,sha256=sH2CUV6zK9FT3jWTn453ys6_JTrUKRtZnU8hK6RmImU,240
|
|
28
|
-
QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=
|
|
29
|
-
QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=
|
|
30
|
-
QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=
|
|
28
|
+
QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=laBeC0tMc2EaLzCotGHQNzePPPOKS1EGgQirigNyi9M,13479
|
|
29
|
+
QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=_2HlC0sqfGy__Qyzbw0PwMD_OkQiiQukl72LQFyPYx0,10939
|
|
30
|
+
QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=8GtJX1DNNox-AgMvABFkRgmHB-lvrxMZKzv-3Ils_Jg,22380
|
|
31
31
|
QuizGenerator/premade_questions/cst463/gradient_descent/misc.py,sha256=0R-nFeD3zsqJyde5CXWrF6Npjmpx6_HbzfCbThLi3os,2657
|
|
32
32
|
QuizGenerator/premade_questions/cst463/math_and_data/__init__.py,sha256=EbIaUrx7_aK9j3Gd8Mk08h9GocTq_0OoNu2trfNwaU8,202
|
|
33
|
-
QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=
|
|
34
|
-
QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=
|
|
33
|
+
QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=4DLdo_8XDS_xtPA8R-wH4K0cKnMn4r5727Vszz8keTc,15565
|
|
34
|
+
QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=VXQCLQEeNKxRDPn_fGW5nAPX-0betrZ8mURh0ElbNz0,12668
|
|
35
35
|
QuizGenerator/premade_questions/cst463/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
-
QuizGenerator/premade_questions/cst463/models/attention.py,sha256=
|
|
37
|
-
QuizGenerator/premade_questions/cst463/models/cnns.py,sha256=
|
|
38
|
-
QuizGenerator/premade_questions/cst463/models/matrices.py,sha256=
|
|
39
|
-
QuizGenerator/premade_questions/cst463/models/rnns.py,sha256=
|
|
40
|
-
QuizGenerator/premade_questions/cst463/models/text.py,sha256=
|
|
41
|
-
QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=
|
|
36
|
+
QuizGenerator/premade_questions/cst463/models/attention.py,sha256=iECxOoR0LEJAH_d7ZE3MoLOkdYVbGOKo4Dwf8Pww0tM,5443
|
|
37
|
+
QuizGenerator/premade_questions/cst463/models/cnns.py,sha256=_HSjgClNBBid5t52CDQfPUMdKOHFOXjy7VQ3sW-zW-Y,6030
|
|
38
|
+
QuizGenerator/premade_questions/cst463/models/matrices.py,sha256=21eNXUcIjFNZTGH18oH-x3MbCa4buNGQGer3a5yL85c,1938
|
|
39
|
+
QuizGenerator/premade_questions/cst463/models/rnns.py,sha256=5fKQuWnpSAoznZVJuCY4nICQ5KzB04Cz17hpccYiiVc,6673
|
|
40
|
+
QuizGenerator/premade_questions/cst463/models/text.py,sha256=BnW6qIB8pnQiFRyXxtX9cdsIfmjw99p6TI0WqI0AQzk,6605
|
|
41
|
+
QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=sFnEvSs7ZwR4RZPltiMEElKJgoxHTaY427_g8Abi2uk,6912
|
|
42
42
|
QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py,sha256=pmyCezO-20AFEQC6MR7KnAsaU9TcgZYsGQOMVkRZ-U8,149
|
|
43
|
-
QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=
|
|
43
|
+
QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=bit_HfAG4K6yh9SZZw_HAPhFUVFkOBdZ2odwt-Cdvmo,42868
|
|
44
44
|
QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py,sha256=G1gEHtG4KakYgi8ZXSYYhX6bQRtnm2tZVGx36d63Nmo,173
|
|
45
|
-
QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=
|
|
46
|
-
quizgenerator-0.
|
|
47
|
-
quizgenerator-0.
|
|
48
|
-
quizgenerator-0.
|
|
49
|
-
quizgenerator-0.
|
|
50
|
-
quizgenerator-0.
|
|
45
|
+
QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=jZRbEqb65BAtliv_V9VR4kvpwOt-o10ApN7RmOIg3XI,30464
|
|
46
|
+
quizgenerator-0.8.1.dist-info/METADATA,sha256=Ef_TPUm2UKYIXnBMiaip6SaAyRjMD4G1MNdVejagfRw,8113
|
|
47
|
+
quizgenerator-0.8.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
48
|
+
quizgenerator-0.8.1.dist-info/entry_points.txt,sha256=aOIdRdw26xY8HkxOoKHBnUPe2mwGv5Ti3U1zojb6zxQ,98
|
|
49
|
+
quizgenerator-0.8.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
50
|
+
quizgenerator-0.8.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|