QuizGenerator 0.4.2__py3-none-any.whl → 0.6.0__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.
Files changed (33) hide show
  1. QuizGenerator/contentast.py +809 -117
  2. QuizGenerator/generate.py +219 -11
  3. QuizGenerator/misc.py +0 -556
  4. QuizGenerator/mixins.py +50 -29
  5. QuizGenerator/premade_questions/basic.py +3 -3
  6. QuizGenerator/premade_questions/cst334/languages.py +183 -175
  7. QuizGenerator/premade_questions/cst334/math_questions.py +81 -70
  8. QuizGenerator/premade_questions/cst334/memory_questions.py +262 -165
  9. QuizGenerator/premade_questions/cst334/persistence_questions.py +83 -60
  10. QuizGenerator/premade_questions/cst334/process.py +558 -79
  11. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +39 -13
  12. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +61 -36
  13. QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +29 -10
  14. QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +2 -2
  15. QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +60 -43
  16. QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +173 -326
  17. QuizGenerator/premade_questions/cst463/models/attention.py +29 -14
  18. QuizGenerator/premade_questions/cst463/models/cnns.py +32 -20
  19. QuizGenerator/premade_questions/cst463/models/rnns.py +28 -15
  20. QuizGenerator/premade_questions/cst463/models/text.py +29 -15
  21. QuizGenerator/premade_questions/cst463/models/weight_counting.py +38 -30
  22. QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +91 -111
  23. QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +128 -55
  24. QuizGenerator/question.py +114 -20
  25. QuizGenerator/quiz.py +81 -24
  26. QuizGenerator/regenerate.py +98 -29
  27. {quizgenerator-0.4.2.dist-info → quizgenerator-0.6.0.dist-info}/METADATA +1 -1
  28. {quizgenerator-0.4.2.dist-info → quizgenerator-0.6.0.dist-info}/RECORD +31 -33
  29. QuizGenerator/README.md +0 -5
  30. QuizGenerator/logging.yaml +0 -55
  31. {quizgenerator-0.4.2.dist-info → quizgenerator-0.6.0.dist-info}/WHEEL +0 -0
  32. {quizgenerator-0.4.2.dist-info → quizgenerator-0.6.0.dist-info}/entry_points.txt +0 -0
  33. {quizgenerator-0.4.2.dist-info → quizgenerator-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,8 +2,8 @@
2
2
  import abc
3
3
  import logging
4
4
 
5
- from QuizGenerator.question import Question, QuestionRegistry, Answer
6
- from QuizGenerator.contentast import ContentAST
5
+ from QuizGenerator.question import Question, QuestionRegistry
6
+ from QuizGenerator.contentast import ContentAST, AnswerTypes
7
7
  from QuizGenerator.mixins import MathOperationQuestion
8
8
 
9
9
  log = logging.getLogger(__name__)
@@ -21,7 +21,7 @@ class MatrixMathQuestion(MathOperationQuestion, Question):
21
21
  - ContentAST.Matrix for mathematical matrices
22
22
  - ContentAST.Equation.make_block_equation__multiline_equals for step-by-step solutions
23
23
  - ContentAST.OnlyHtml for Canvas-specific content
24
- - Answer.integer for numerical answers
24
+ - ContentAST.Answer.integer for numerical answers
25
25
  """
26
26
  def __init__(self, *args, **kwargs):
27
27
  kwargs["topic"] = kwargs.get("topic", Question.Topic.MATH)
@@ -36,15 +36,22 @@ class MatrixMathQuestion(MathOperationQuestion, Question):
36
36
  return [[f"{prefix}{matrix[i][j]}" for j in range(len(matrix[0]))] for i in range(len(matrix))]
37
37
 
38
38
  def _create_answer_table(self, rows, cols, answers_dict, answer_prefix="answer"):
39
- """Create a table with answer blanks for matrix results."""
39
+ """Create a table with answer blanks for matrix results.
40
+
41
+ Returns:
42
+ Tuple of (table, answers_list)
43
+ """
40
44
  table_data = []
45
+ answers = []
41
46
  for i in range(rows):
42
47
  row = []
43
48
  for j in range(cols):
44
49
  answer_key = f"{answer_prefix}_{i}_{j}"
45
- row.append(ContentAST.Answer(answer=answers_dict[answer_key]))
50
+ ans = answers_dict[answer_key]
51
+ row.append(ans)
52
+ answers.append(ans)
46
53
  table_data.append(row)
47
- return ContentAST.Table(data=table_data, padding=True)
54
+ return ContentAST.Table(data=table_data, padding=True), answers
48
55
 
49
56
  # Implement MathOperationQuestion abstract methods
50
57
 
@@ -64,23 +71,23 @@ class MatrixMathQuestion(MathOperationQuestion, Question):
64
71
  return f"{operand_a_latex} {self.get_operator()} {operand_b_latex}"
65
72
 
66
73
  def _add_single_question_answers(self, body):
67
- """Add Canvas-only answer fields for single questions."""
74
+ """Add Canvas-only answer fields for single questions.
75
+
76
+ Returns:
77
+ List of Answer objects that were added to the body.
78
+ """
79
+ answers = []
80
+
68
81
  # For matrices, we typically show result dimensions and answer table
69
82
  if hasattr(self, 'result_rows') and hasattr(self, 'result_cols'):
70
83
  # Matrix multiplication case with dimension answers
71
84
  if hasattr(self, 'answers') and "result_rows" in self.answers:
85
+ rows_ans = self.answers["result_rows"]
86
+ cols_ans = self.answers["result_cols"]
87
+ answers.extend([rows_ans, cols_ans])
72
88
  body.add_element(
73
89
  ContentAST.OnlyHtml([
74
- ContentAST.AnswerBlock([
75
- ContentAST.Answer(
76
- answer=self.answers["result_rows"],
77
- label="Number of rows in result"
78
- ),
79
- ContentAST.Answer(
80
- answer=self.answers["result_cols"],
81
- label="Number of columns in result"
82
- )
83
- ])
90
+ ContentAST.AnswerBlock([rows_ans, cols_ans])
84
91
  ])
85
92
  )
86
93
 
@@ -88,21 +95,27 @@ class MatrixMathQuestion(MathOperationQuestion, Question):
88
95
  if hasattr(self, 'result') and self.result:
89
96
  rows = len(self.result)
90
97
  cols = len(self.result[0])
98
+ table, table_answers = self._create_answer_table(rows, cols, self.answers)
99
+ answers.extend(table_answers)
91
100
  body.add_element(
92
101
  ContentAST.OnlyHtml([
93
102
  ContentAST.Paragraph(["Result matrix:"]),
94
- self._create_answer_table(rows, cols, self.answers)
103
+ table
95
104
  ])
96
105
  )
97
106
  elif hasattr(self, 'max_dim'):
98
107
  # Matrix multiplication with max dimensions
108
+ table, table_answers = self._create_answer_table(self.max_dim, self.max_dim, self.answers)
109
+ answers.extend(table_answers)
99
110
  body.add_element(
100
111
  ContentAST.OnlyHtml([
101
112
  ContentAST.Paragraph(["Result matrix (use '-' if cell doesn't exist):"]),
102
- self._create_answer_table(self.max_dim, self.max_dim, self.answers)
113
+ table
103
114
  ])
104
115
  )
105
116
 
117
+ return answers
118
+
106
119
  # Abstract methods that subclasses must implement
107
120
  @abc.abstractmethod
108
121
  def get_operator(self):
@@ -156,7 +169,7 @@ class MatrixAddition(MatrixMathQuestion):
156
169
  for i in range(rows):
157
170
  for j in range(cols):
158
171
  answer_key = f"answer_{i}_{j}"
159
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
172
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
160
173
  else:
161
174
  # For multipart questions, use subpart letter format
162
175
  letter = chr(ord('a') + subpart_index)
@@ -165,7 +178,7 @@ class MatrixAddition(MatrixMathQuestion):
165
178
  for i in range(rows):
166
179
  for j in range(cols):
167
180
  answer_key = f"subpart_{letter}_{i}_{j}"
168
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
181
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
169
182
 
170
183
  def refresh(self, *args, **kwargs):
171
184
  """Override refresh to set rows/cols for compatibility."""
@@ -286,7 +299,7 @@ class MatrixScalarMultiplication(MatrixMathQuestion):
286
299
  for i in range(rows):
287
300
  for j in range(cols):
288
301
  answer_key = f"answer_{i}_{j}"
289
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
302
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
290
303
  else:
291
304
  # For multipart questions, use subpart letter format
292
305
  letter = chr(ord('a') + subpart_index)
@@ -295,7 +308,7 @@ class MatrixScalarMultiplication(MatrixMathQuestion):
295
308
  for i in range(rows):
296
309
  for j in range(cols):
297
310
  answer_key = f"subpart_{letter}_{i}_{j}"
298
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
311
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
299
312
 
300
313
  def refresh(self, *args, **kwargs):
301
314
  """Override refresh to handle different scalars per subpart."""
@@ -488,27 +501,27 @@ class MatrixMultiplication(MatrixMathQuestion):
488
501
  # For single questions, use the old answer format
489
502
  # Dimension answers
490
503
  if result is not None:
491
- self.answers["result_rows"] = Answer.integer("result_rows", self.result_rows)
492
- self.answers["result_cols"] = Answer.integer("result_cols", self.result_cols)
504
+ self.answers["result_rows"] = AnswerTypes.Int(self.result_rows, label="Number of rows in result")
505
+ self.answers["result_cols"] = AnswerTypes.Int(self.result_cols, label="Number of columns in result")
493
506
 
494
507
  # Matrix element answers
495
508
  for i in range(self.max_dim):
496
509
  for j in range(self.max_dim):
497
510
  answer_key = f"answer_{i}_{j}"
498
511
  if i < self.result_rows and j < self.result_cols:
499
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
512
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
500
513
  else:
501
- self.answers[answer_key] = Answer.string(answer_key, "-")
514
+ self.answers[answer_key] = AnswerTypes.String("-")
502
515
  else:
503
516
  # Multiplication not possible
504
- self.answers["result_rows"] = Answer.string("result_rows", "-")
505
- self.answers["result_cols"] = Answer.string("result_cols", "-")
517
+ self.answers["result_rows"] = AnswerTypes.String("-", label="Number of rows in result")
518
+ self.answers["result_cols"] = AnswerTypes.String("-", label="Number of columns in result")
506
519
 
507
520
  # All matrix elements are "-"
508
521
  for i in range(self.max_dim):
509
522
  for j in range(self.max_dim):
510
523
  answer_key = f"answer_{i}_{j}"
511
- self.answers[answer_key] = Answer.string(answer_key, "-")
524
+ self.answers[answer_key] = AnswerTypes.String("-")
512
525
  else:
513
526
  # For multipart questions, use subpart letter format
514
527
  letter = chr(ord('a') + subpart_index)
@@ -520,35 +533,39 @@ class MatrixMultiplication(MatrixMathQuestion):
520
533
  for i in range(rows):
521
534
  for j in range(cols):
522
535
  answer_key = f"subpart_{letter}_{i}_{j}"
523
- self.answers[answer_key] = Answer.integer(answer_key, result[i][j])
536
+ self.answers[answer_key] = AnswerTypes.Int(result[i][j])
524
537
 
525
538
  def _add_single_question_answers(self, body):
526
- """Add Canvas-only answer fields for MatrixMultiplication with dash instruction."""
539
+ """Add Canvas-only answer fields for MatrixMultiplication with dash instruction.
540
+
541
+ Returns:
542
+ List of Answer objects that were added to the body.
543
+ """
544
+ answers = []
545
+
527
546
  # Dimension answers for matrix multiplication
528
547
  if hasattr(self, 'answers') and "result_rows" in self.answers:
548
+ rows_ans = self.answers["result_rows"]
549
+ cols_ans = self.answers["result_cols"]
550
+ answers.extend([rows_ans, cols_ans])
529
551
  body.add_element(
530
552
  ContentAST.OnlyHtml([
531
- ContentAST.AnswerBlock([
532
- ContentAST.Answer(
533
- answer=self.answers["result_rows"],
534
- label="Number of rows in result"
535
- ),
536
- ContentAST.Answer(
537
- answer=self.answers["result_cols"],
538
- label="Number of columns in result"
539
- )
540
- ])
553
+ ContentAST.AnswerBlock([rows_ans, cols_ans])
541
554
  ])
542
555
  )
543
556
 
544
557
  # Matrix result table with dash instruction
558
+ table, table_answers = self._create_answer_table(self.max_dim, self.max_dim, self.answers)
559
+ answers.extend(table_answers)
545
560
  body.add_element(
546
561
  ContentAST.OnlyHtml([
547
562
  ContentAST.Paragraph(["Result matrix (use '-' if cell doesn't exist):"]),
548
- self._create_answer_table(self.max_dim, self.max_dim, self.answers)
563
+ table
549
564
  ])
550
565
  )
551
566
 
567
+ return answers
568
+
552
569
  def refresh(self, *args, **kwargs):
553
570
  """Override refresh to handle matrix attributes."""
554
571
  super().refresh(*args, **kwargs)