QuizGenerator 0.3.0__tar.gz → 0.4.0__tar.gz

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.
Files changed (76) hide show
  1. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/PKG-INFO +1 -1
  2. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/misc.py +2 -2
  3. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/languages.py +9 -13
  4. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/persistence_questions.py +78 -23
  5. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/cnns.py +1 -1
  6. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/text.py +4 -2
  7. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/weight_counting.py +1 -1
  8. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/pyproject.toml +2 -1
  9. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/pyproject_prev.toml +1 -1
  10. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/uv.lock +1 -1
  11. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/.envrc +0 -0
  12. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/.github/pull_request_template.md +0 -0
  13. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/.github/workflows/release.yaml +0 -0
  14. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/.gitignore +0 -0
  15. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/CLAUDE.md +0 -0
  16. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/CODEOWNERS +0 -0
  17. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/LICENSE +0 -0
  18. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/README.md +0 -0
  19. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/__init__.py +0 -0
  20. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/__main__.py +0 -0
  21. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/canvas/__init__.py +0 -0
  22. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/canvas/canvas_interface.py +0 -0
  23. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/canvas/classes.py +0 -0
  24. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/constants.py +0 -0
  25. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/contentast.py +0 -0
  26. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/generate.py +0 -0
  27. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/logging.yaml +0 -0
  28. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/mixins.py +0 -0
  29. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/performance.py +0 -0
  30. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/__init__.py +0 -0
  31. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/basic.py +0 -0
  32. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/__init__.py +0 -0
  33. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/math_questions.py +0 -0
  34. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/memory_questions.py +0 -0
  35. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/ostep13_vsfs.py +0 -0
  36. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst334/process.py +0 -0
  37. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/__init__.py +0 -0
  38. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py +0 -0
  39. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +0 -0
  40. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +0 -0
  41. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +0 -0
  42. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +0 -0
  43. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/math_and_data/__init__.py +0 -0
  44. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +0 -0
  45. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +0 -0
  46. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/__init__.py +0 -0
  47. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/attention.py +0 -0
  48. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/matrices.py +0 -0
  49. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/models/rnns.py +0 -0
  50. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py +0 -0
  51. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +0 -0
  52. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py +0 -0
  53. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +0 -0
  54. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/qrcode_generator.py +0 -0
  55. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/question.py +0 -0
  56. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/quiz.py +0 -0
  57. /quizgenerator-0.3.0/grade_from_qr.py → /quizgenerator-0.4.0/QuizGenerator/regenerate.py +0 -0
  58. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/QuizGenerator/typst_utils.py +0 -0
  59. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/README.md +0 -0
  60. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/documentation/GRADING_GUIDE.md +0 -0
  61. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/documentation/LESSONS_LEARNED-adding_questions.md +0 -0
  62. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/documentation/PARAMETER_STANDARDS.md +0 -0
  63. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/documentation/README.md +0 -0
  64. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/documentation/WEB_UI_INTEGRATION.md +0 -0
  65. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/all_classes.yaml +0 -0
  66. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/cst334.yaml +0 -0
  67. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/cst463.yaml +0 -0
  68. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/exam_generation.yaml +0 -0
  69. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/scratch.yaml +0 -0
  70. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/specific_generators/cst334.caching.yaml +0 -0
  71. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/example_files/specific_generators/cst334.lab-address_translation.yaml +0 -0
  72. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/examples/README.md +0 -0
  73. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/examples/web_ui_integration_example.py +0 -0
  74. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/scripts/generate_practice_yaml.sh +0 -0
  75. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/scripts/print.sh +0 -0
  76. {quizgenerator-0.3.0 → quizgenerator-0.4.0}/scripts/vendor_lms_interface.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuizGenerator
3
- Version: 0.3.0
3
+ Version: 0.4.0
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
@@ -564,9 +564,9 @@ class MatrixAnswer(Answer):
564
564
  value=self.value[i,j]
565
565
  )
566
566
  )
567
- for i in range(self.value.shape[0])
567
+ for j in range(self.value.shape[1])
568
568
  ]
569
- for j in range(self.value.shape[1])
569
+ for i in range(self.value.shape[0])
570
570
  ]
571
571
  table = ContentAST.Table(data)
572
572
 
@@ -60,11 +60,9 @@ class BNF:
60
60
 
61
61
  def get_grammar_string(self):
62
62
  lines = []
63
- lines.append('```')
64
63
  for symbol in self.symbols:
65
64
  lines.append(f"{symbol.get_full_str()}")
66
-
67
- lines.append('```')
65
+
68
66
  return '\n'.join(lines)
69
67
 
70
68
  class Symbol:
@@ -342,25 +340,23 @@ class ValidStringsInLanguageQuestion(LanguageQuestion):
342
340
  def get_body(self, *args, **kwargs) -> ContentAST.Section:
343
341
  body = ContentAST.Section()
344
342
 
345
- body.add_element(
343
+ body.add_elements([
346
344
  ContentAST.Paragraph([
347
- ContentAST.OnlyHtml(
345
+ ContentAST.OnlyHtml([
348
346
  ContentAST.Text("Given the following grammar, which of the below strings are part of the language?")
349
- ),
350
- ContentAST.OnlyLatex(
347
+ ]),
348
+ ContentAST.OnlyLatex([
351
349
  ContentAST.Text(
352
350
  "Given the following grammar "
353
351
  "please circle any provided strings that are part of the language (or indicate clearly if there are none), "
354
352
  "and on each blank line provide generate a new, unique string that is part of the language."
355
353
  )
356
- )
354
+ ])
357
355
  ])
358
- )
356
+ ])
359
357
 
360
358
  body.add_element(
361
- ContentAST.Paragraph([
362
- self.grammar_good.get_grammar_string()
363
- ])
359
+ ContentAST.Code(self.grammar_good.get_grammar_string())
364
360
  )
365
361
 
366
362
  # Add in some answers as latex-only options to be circled
@@ -374,7 +370,7 @@ class ValidStringsInLanguageQuestion(LanguageQuestion):
374
370
  # For Latex-only, ask students to generate some more.
375
371
  body.add_element(
376
372
  ContentAST.OnlyLatex([
377
- ContentAST.AnswerBlock([ContentAST.Answer() for _ in range(self.num_answer_blanks)])
373
+ ContentAST.AnswerBlock([ContentAST.Answer(Answer.string(f"blank_line_{i}", f"blank_line_{i}"), label=f"blank_line_{i}") for i in range(self.num_answer_blanks)])
378
374
  ])
379
375
  )
380
376
 
@@ -2,6 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import abc
5
+ import difflib
5
6
  import logging
6
7
 
7
8
  from QuizGenerator.question import Question, Answer, QuestionRegistry
@@ -365,31 +366,85 @@ class VSFS_states(IOQuestion):
365
366
  def get_explanation(self) -> ContentAST.Section:
366
367
  explanation = ContentAST.Section()
367
368
 
368
- explanation.add_element(
369
+ log.debug(f"self.start_state: {self.start_state}")
370
+ log.debug(f"self.end_state: {self.end_state}")
371
+
372
+ explanation.add_elements([
369
373
  ContentAST.Paragraph([
370
- "These questions are based on the VSFS simulator that our book mentions. "
371
- "We will be discussing the interpretation of this in class, but you can also find information "
372
- "<a href=\"https://github.com/chyyuu/os_tutorial_lab/blob/master/ostep/ostep13-vsfs.md\">here</a>, "
373
- "as well as simulator code. Please note that the code uses python 2.",
374
- "",
375
- "In general, I recommend looking for differences between the two outputs. Recommended steps would be:",
376
- "<ol>"
377
-
378
- "<li> Check to see if there are differences between the bitmaps "
379
- "that could indicate a file/directroy were created or removed.</li>",
380
-
381
- "<li>Check the listed inodes to see if any entries have changed. "
382
- "This might be a new entry entirely or a reference count changing. "
383
- "If the references increased then this was likely a link or creation, "
384
- "and if it decreased then it is likely an unlink.</li>",
385
-
386
- "<li>Look at the data blocks to see if a new entry has "
387
- "been added to a directory or a new block has been mapped.</li>",
388
-
389
- "</ol>",
390
- "These steps can usually help you quickly identify "
391
- "what has occured in the simulation and key you in to the right answer."
374
+ "The key thing to pay attention to when solving these problems is where there are differences between the start state and the end state.",
375
+ "In this particular problem, we can see that these lines are different:"
392
376
  ])
377
+ ])
378
+
379
+ chunk_to_add = []
380
+ lines_that_changed = []
381
+ for start_line, end_line in zip(self.start_state.split('\n'), self.end_state.split('\n')):
382
+ if start_line == end_line:
383
+ continue
384
+ lines_that_changed.append((start_line, end_line))
385
+ chunk_to_add.append(
386
+ f" - `{start_line}` -> `{end_line}`"
387
+ )
388
+
389
+ explanation.add_element(
390
+ ContentAST.Paragraph(chunk_to_add)
391
+ )
392
+
393
+ chunk_to_add = [
394
+ "A great place to start is to check to see if the bitmaps have changed as this can quickly tell us a lot of information"
395
+ ]
396
+
397
+ inode_bitmap_lines = list(filter(lambda s: "inode bitmap" in s[0], lines_that_changed))
398
+ data_bitmap_lines = list(filter(lambda s: "data bitmap" in s[0], lines_that_changed))
399
+
400
+ def get_bitmap(line: str) -> str:
401
+ log.debug(f"line: {line}")
402
+ return line.split()[-1]
403
+
404
+ def highlight_changes(a: str, b: str) -> str:
405
+ matcher = difflib.SequenceMatcher(None, a, b)
406
+ result = []
407
+
408
+ for tag, i1, i2, j1, j2 in matcher.get_opcodes():
409
+ if tag == "equal":
410
+ result.append(b[j1:j2])
411
+ elif tag in ("insert", "replace"):
412
+ result.append(f"***{b[j1:j2]}***")
413
+ # for "delete", do nothing since text is removed
414
+
415
+ return "".join(result)
416
+
417
+ if len(inode_bitmap_lines) > 0:
418
+ inode_bitmap_lines = inode_bitmap_lines[0]
419
+ chunk_to_add.append(f"The inode bitmap lines have changed from {get_bitmap(inode_bitmap_lines[0])} to {get_bitmap(inode_bitmap_lines[1])}.")
420
+ if get_bitmap(inode_bitmap_lines[0]).count('1') < get_bitmap(inode_bitmap_lines[1]).count('1'):
421
+ chunk_to_add.append("We can see that we have added an inode, so we have either called `creat` or `mkdir`.")
422
+ else:
423
+ chunk_to_add.append("We can see that we have removed an inode, so we have called `unlink`.")
424
+
425
+ if len(data_bitmap_lines) > 0:
426
+ data_bitmap_lines = data_bitmap_lines[0]
427
+ chunk_to_add.append(f"The inode bitmap lines have changed from {get_bitmap(data_bitmap_lines[0])} to {get_bitmap(data_bitmap_lines[1])}.")
428
+ if get_bitmap(data_bitmap_lines[0]).count('1') < get_bitmap(data_bitmap_lines[1]).count('1'):
429
+ chunk_to_add.append("We can see that we have added a data block, so we have either called `mkdir` or `write`.")
430
+ else:
431
+ chunk_to_add.append("We can see that we have removed a data block, so we have `unlink`ed a file.")
432
+
433
+ if len(data_bitmap_lines) == 0 and len(inode_bitmap_lines) == 0:
434
+ chunk_to_add.append("If they have not changed, then we know we must have eithered called `link` or `unlink` and must check the references.")
435
+
436
+ explanation.add_element(
437
+ ContentAST.Paragraph(chunk_to_add)
438
+ )
439
+
440
+ explanation.add_elements([
441
+ ContentAST.Paragraph(["The overall changes are highlighted with `*` symbols below"])
442
+ ])
443
+
444
+ explanation.add_element(
445
+ ContentAST.Code(
446
+ highlight_changes(self.start_state, self.end_state)
447
+ )
393
448
  )
394
449
 
395
450
  return explanation
@@ -28,7 +28,7 @@ class ConvolutionCalculation(MatrixQuestion):
28
28
 
29
29
  # Add padding
30
30
  if padding > 0:
31
- image = np.pad(image, ((padding, padding), (padding, padding), (0, 0)), mode='constant')
31
+ image = np.pad(image, ((padding, padding), (padding, padding)), mode='constant')
32
32
  H, W = H + 2 * padding, W + 2 * padding
33
33
 
34
34
  # Output dimensions
@@ -60,7 +60,9 @@ class word2vec__skipgram(MatrixQuestion, TableQuestionMixin):
60
60
  ## Answers:
61
61
  # center_word, center_emb, context_words, context_embs, logits, probs
62
62
  self.answers["logits"] = Answer.vector_value(key="logits", value=self.logits)
63
- self.answers["center_word"] = Answer.string(key="center_word", value=self.center_word)
63
+ most_likely_idx = np.argmax(self.probs)
64
+ most_likely_word = self.context_words[most_likely_idx]
65
+ self.answers["center_word"] = Answer.string(key="center_word", value=most_likely_word)
64
66
 
65
67
 
66
68
  return True
@@ -81,7 +83,7 @@ class word2vec__skipgram(MatrixQuestion, TableQuestionMixin):
81
83
  ContentAST.LineBreak(),
82
84
  self.answers["logits"].get_ast_element("Logits"),
83
85
  ContentAST.LineBreak(),
84
- self.answers["center_word"].get_ast_element("Center word")
86
+ self.answers["center_word"].get_ast_element("Most likely context word")
85
87
  ])
86
88
 
87
89
 
@@ -194,7 +194,7 @@ class WeightCounting_CNN(WeightCounting):
194
194
  )
195
195
  ]
196
196
  )
197
- return model, ["filters", "kernel_size", "strides", "padding", "pool_size"]
197
+ return model, ["units", "filters", "kernel_size", "strides", "padding", "pool_size"]
198
198
 
199
199
 
200
200
  @QuestionRegistry.register("cst463.WeightCounting-RNN")
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "QuizGenerator"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "Generate randomized quiz questions for Canvas LMS and PDF exams"
9
9
  readme = "README.md"
10
10
  license = {text = "GPL-3.0-or-later"}
@@ -51,6 +51,7 @@ Repository = "https://github.com/OtterDen-Lab/QuizGenerator"
51
51
 
52
52
  [project.scripts]
53
53
  quizgen = "QuizGenerator.generate:main"
54
+ quizregen = "QuizGenerator.regenerate:main"
54
55
 
55
56
  [project.optional-dependencies]
56
57
  grading = [
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "QuizGenerator"
7
- version = "0.1.4"
7
+ version = "0.3.1"
8
8
  description = "Generate randomized quiz questions for Canvas LMS and PDF exams"
9
9
  readme = "README.md"
10
10
  license = {text = "GPL-3.0-or-later"}
@@ -1214,7 +1214,7 @@ wheels = [
1214
1214
 
1215
1215
  [[package]]
1216
1216
  name = "quizgenerator"
1217
- version = "0.3.0"
1217
+ version = "0.4.0"
1218
1218
  source = { editable = "." }
1219
1219
  dependencies = [
1220
1220
  { name = "canvasapi" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes