QuizGenerator 0.6.3__py3-none-any.whl → 0.7.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.
Files changed (31) hide show
  1. QuizGenerator/contentast.py +2191 -2193
  2. QuizGenerator/misc.py +1 -1
  3. QuizGenerator/mixins.py +64 -64
  4. QuizGenerator/premade_questions/basic.py +16 -16
  5. QuizGenerator/premade_questions/cst334/languages.py +26 -26
  6. QuizGenerator/premade_questions/cst334/math_questions.py +42 -42
  7. QuizGenerator/premade_questions/cst334/memory_questions.py +124 -124
  8. QuizGenerator/premade_questions/cst334/persistence_questions.py +48 -48
  9. QuizGenerator/premade_questions/cst334/process.py +38 -38
  10. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +45 -45
  11. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +34 -34
  12. QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +53 -53
  13. QuizGenerator/premade_questions/cst463/gradient_descent/misc.py +2 -2
  14. QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +65 -65
  15. QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +39 -39
  16. QuizGenerator/premade_questions/cst463/models/attention.py +36 -36
  17. QuizGenerator/premade_questions/cst463/models/cnns.py +26 -26
  18. QuizGenerator/premade_questions/cst463/models/rnns.py +36 -36
  19. QuizGenerator/premade_questions/cst463/models/text.py +32 -32
  20. QuizGenerator/premade_questions/cst463/models/weight_counting.py +15 -15
  21. QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +124 -124
  22. QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +161 -161
  23. QuizGenerator/question.py +41 -41
  24. QuizGenerator/quiz.py +7 -7
  25. QuizGenerator/regenerate.py +114 -13
  26. QuizGenerator/typst_utils.py +2 -2
  27. {quizgenerator-0.6.3.dist-info → quizgenerator-0.7.1.dist-info}/METADATA +1 -1
  28. {quizgenerator-0.6.3.dist-info → quizgenerator-0.7.1.dist-info}/RECORD +31 -31
  29. {quizgenerator-0.6.3.dist-info → quizgenerator-0.7.1.dist-info}/WHEEL +0 -0
  30. {quizgenerator-0.6.3.dist-info → quizgenerator-0.7.1.dist-info}/entry_points.txt +0 -0
  31. {quizgenerator-0.6.3.dist-info → quizgenerator-0.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,7 @@ import difflib
6
6
  import logging
7
7
 
8
8
  from QuizGenerator.question import Question, QuestionRegistry
9
- from QuizGenerator.contentast import ContentAST, AnswerTypes
9
+ import QuizGenerator.contentast as ca
10
10
  from QuizGenerator.mixins import TableQuestionMixin, BodyTemplatesMixin
11
11
 
12
12
  log = logging.getLogger(__name__)
@@ -36,10 +36,10 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
36
36
  self.disk_access_delay = self.access_delay * self.number_of_reads + self.transfer_delay
37
37
 
38
38
  self.answers.update({
39
- "answer__rotational_delay" : AnswerTypes.Float(self.rotational_delay),
40
- "answer__access_delay" : AnswerTypes.Float(self.access_delay),
41
- "answer__transfer_delay" : AnswerTypes.Float(self.transfer_delay),
42
- "answer__disk_access_delay" : AnswerTypes.Float(self.disk_access_delay),
39
+ "answer__rotational_delay" : ca.AnswerTypes.Float(self.rotational_delay),
40
+ "answer__access_delay" : ca.AnswerTypes.Float(self.access_delay),
41
+ "answer__transfer_delay" : ca.AnswerTypes.Float(self.transfer_delay),
42
+ "answer__disk_access_delay" : ca.AnswerTypes.Float(self.disk_access_delay),
43
43
  })
44
44
 
45
45
  def _get_body(self, *args, **kwargs):
@@ -94,16 +94,16 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
94
94
 
95
95
  return body, answers
96
96
 
97
- def get_body(self, *args, **kwargs) -> ContentAST.Section:
97
+ def get_body(self, *args, **kwargs) -> ca.Section:
98
98
  """Build question body (backward compatible interface)."""
99
99
  body, _ = self._get_body(*args, **kwargs)
100
100
  return body
101
101
 
102
102
  def _get_explanation(self):
103
- explanation = ContentAST.Section()
103
+ explanation = ca.Section()
104
104
 
105
105
  explanation.add_element(
106
- ContentAST.Paragraph([
106
+ ca.Paragraph([
107
107
  "To calculate the total disk access time (or \"delay\"), "
108
108
  "we should first calculate each of the individual parts.",
109
109
  r"Since we know that $t_{total} = (\text{# of reads}) \cdot t_{access} + t_{transfer}$"
@@ -113,8 +113,8 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
113
113
  )
114
114
 
115
115
  explanation.add_elements([
116
- ContentAST.Paragraph(["Starting with the rotation delay, we calculate:"]),
117
- ContentAST.Equation(
116
+ ca.Paragraph(["Starting with the rotation delay, we calculate:"]),
117
+ ca.Equation(
118
118
  "t_{rotation} = "
119
119
  + f"\\frac{{1 minute}}{{{self.hard_drive_rotation_speed}revolutions}}"
120
120
  + r"\cdot \frac{60 seconds}{1 minute} \cdot \frac{1000 ms}{1 second} \cdot \frac{1 revolution}{2} = "
@@ -123,10 +123,10 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
123
123
  ])
124
124
 
125
125
  explanation.add_elements([
126
- ContentAST.Paragraph([
126
+ ca.Paragraph([
127
127
  "Now we can calculate:",
128
128
  ]),
129
- ContentAST.Equation(
129
+ ca.Equation(
130
130
  f"t_{{access}} "
131
131
  f"= t_{{rotation}} + t_{{seek}} "
132
132
  f"= {self.rotational_delay:0.2f}ms + {self.seek_delay:0.2f}ms = {self.access_delay:0.2f}ms"
@@ -134,8 +134,8 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
134
134
  ])
135
135
 
136
136
  explanation.add_elements([
137
- ContentAST.Paragraph([r"Next we need to calculate our transfer delay, $t_{transfer}$, which we do as:"]),
138
- ContentAST.Equation(
137
+ ca.Paragraph([r"Next we need to calculate our transfer delay, $t_{transfer}$, which we do as:"]),
138
+ ca.Equation(
139
139
  f"t_{{transfer}} "
140
140
  f"= \\frac{{{self.number_of_reads} \\cdot {self.size_of_reads}KB}}{{1}} \\cdot \\frac{{1MB}}{{1024KB}} "
141
141
  f"\\cdot \\frac{{1 second}}{{{self.transfer_rate}MB}} \\cdot \\frac{{1000ms}}{{1second}} "
@@ -144,8 +144,8 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
144
144
  ])
145
145
 
146
146
  explanation.add_elements([
147
- ContentAST.Paragraph(["Putting these together we get:"]),
148
- ContentAST.Equation(
147
+ ca.Paragraph(["Putting these together we get:"]),
148
+ ca.Equation(
149
149
  f"t_{{total}} "
150
150
  f"= \\text{{(# reads)}} \\cdot t_{{access}} + t_{{transfer}} "
151
151
  f"= {self.number_of_reads} \\cdot {self.access_delay:0.2f} + {self.transfer_delay:0.2f} "
@@ -153,7 +153,7 @@ class HardDriveAccessTime(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
153
153
  ])
154
154
  return explanation, []
155
155
 
156
- def get_explanation(self) -> ContentAST.Section:
156
+ def get_explanation(self) -> ca.Section:
157
157
  """Build question explanation (backward compatible interface)."""
158
158
  explanation, _ = self._get_explanation()
159
159
  return explanation
@@ -178,10 +178,10 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
178
178
  self.inode_index_in_block = int(self.inode_address_in_block / self.inode_size)
179
179
 
180
180
  self.answers.update({
181
- "answer__inode_address": AnswerTypes.Int(self.inode_address),
182
- "answer__inode_block": AnswerTypes.Int(self.inode_block),
183
- "answer__inode_address_in_block": AnswerTypes.Int(self.inode_address_in_block),
184
- "answer__inode_index_in_block": AnswerTypes.Int(self.inode_index_in_block),
181
+ "answer__inode_address": ca.AnswerTypes.Int(self.inode_address),
182
+ "answer__inode_block": ca.AnswerTypes.Int(self.inode_block),
183
+ "answer__inode_address_in_block": ca.AnswerTypes.Int(self.inode_address_in_block),
184
+ "answer__inode_index_in_block": ca.AnswerTypes.Int(self.inode_index_in_block),
185
185
  })
186
186
 
187
187
  def _get_body(self):
@@ -229,16 +229,16 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
229
229
 
230
230
  return body, answers
231
231
 
232
- def get_body(self) -> ContentAST.Section:
232
+ def get_body(self) -> ca.Section:
233
233
  """Build question body (backward compatible interface)."""
234
234
  body, _ = self._get_body()
235
235
  return body
236
236
 
237
237
  def _get_explanation(self):
238
- explanation = ContentAST.Section()
238
+ explanation = ca.Section()
239
239
 
240
240
  explanation.add_element(
241
- ContentAST.Paragraph([
241
+ ca.Paragraph([
242
242
  "If we are given an inode number, there are a few steps that we need to take to load the actual inode. "
243
243
  "These consist of determining the address of the inode, which block would contain it, "
244
244
  "and then its address within the block.",
@@ -247,7 +247,7 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
247
247
  )
248
248
 
249
249
  explanation.add_element(
250
- ContentAST.Equation.make_block_equation__multiline_equals(
250
+ ca.Equation.make_block_equation__multiline_equals(
251
251
  r"(\text{Inode address})",
252
252
  [
253
253
  r"(\text{Inode Start Location}) + (\text{inode #}) \cdot (\text{inode size})",
@@ -257,13 +257,13 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
257
257
  )
258
258
 
259
259
  explanation.add_element(
260
- ContentAST.Paragraph([
260
+ ca.Paragraph([
261
261
  "Next, we us this to figure out what block the inode is in. "
262
262
  "We do this directly so we know what block to load, "
263
263
  "thus minimizing the number of loads we have to make.",
264
264
  ])
265
265
  )
266
- explanation.add_element(ContentAST.Equation.make_block_equation__multiline_equals(
266
+ explanation.add_element(ca.Equation.make_block_equation__multiline_equals(
267
267
  r"\text{Block containing inode}",
268
268
  [
269
269
  r"(\text{Inode address}) \mathbin{//} (\text{block size})",
@@ -273,7 +273,7 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
273
273
  ))
274
274
 
275
275
  explanation.add_element(
276
- ContentAST.Paragraph([
276
+ ca.Paragraph([
277
277
  "When we load this block, we now have in our system memory "
278
278
  "(remember, blocks on the hard drive are effectively useless to us until they're in main memory!), "
279
279
  "the inode, so next we need to figure out where it is within that block."
@@ -283,7 +283,7 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
283
283
  ])
284
284
  )
285
285
 
286
- explanation.add_element(ContentAST.Equation.make_block_equation__multiline_equals(
286
+ explanation.add_element(ca.Equation.make_block_equation__multiline_equals(
287
287
  r"\text{offset within block}",
288
288
  [
289
289
  r"(\text{Inode address}) \bmod (\text{block size})",
@@ -293,12 +293,12 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
293
293
  ))
294
294
 
295
295
  explanation.add_element(
296
- ContentAST.Text("Remember that `mod` is the same as `%`, the modulo operation.")
296
+ ca.Text("Remember that `mod` is the same as `%`, the modulo operation.")
297
297
  )
298
298
 
299
- explanation.add_element(ContentAST.Paragraph(["and"]))
299
+ explanation.add_element(ca.Paragraph(["and"]))
300
300
 
301
- explanation.add_element(ContentAST.Equation.make_block_equation__multiline_equals(
301
+ explanation.add_element(ca.Equation.make_block_equation__multiline_equals(
302
302
  r"\text{index within block}",
303
303
  [
304
304
  r"\dfrac{\text{offset within block}}{\text{inode size}}",
@@ -309,7 +309,7 @@ class INodeAccesses(IOQuestion, TableQuestionMixin, BodyTemplatesMixin):
309
309
 
310
310
  return explanation, []
311
311
 
312
- def get_explanation(self) -> ContentAST.Section:
312
+ def get_explanation(self) -> ca.Section:
313
313
  """Build question explanation (backward compatible interface)."""
314
314
  explanation, _ = self._get_explanation()
315
315
  return explanation
@@ -322,7 +322,7 @@ class VSFS_states(IOQuestion):
322
322
 
323
323
  def __init__(self, *args, **kwargs):
324
324
  super().__init__(*args, **kwargs)
325
- self.answer_kind = ContentAST.Answer.CanvasAnswerKind.MULTIPLE_DROPDOWN
325
+ self.answer_kind = ca.Answer.CanvasAnswerKind.MULTIPLE_DROPDOWN
326
326
 
327
327
  self.num_steps = kwargs.get("num_steps", 10)
328
328
 
@@ -344,7 +344,7 @@ class VSFS_states(IOQuestion):
344
344
  ))
345
345
  self.rng.shuffle(wrong_answers)
346
346
 
347
- self.answers["answer__cmd"] = ContentAST.Answer.dropdown(
347
+ self.answers["answer__cmd"] = ca.Answer.dropdown(
348
348
  f"{operations[-1]['cmd']}",
349
349
  baffles=list(set([op['cmd'] for op in operations[:-1] if op != operations[-1]['cmd']])),
350
350
  label="Command"
@@ -354,21 +354,21 @@ class VSFS_states(IOQuestion):
354
354
  """Build question body and collect answers."""
355
355
  answers = [self.answers["answer__cmd"]]
356
356
 
357
- body = ContentAST.Section()
357
+ body = ca.Section()
358
358
 
359
- body.add_element(ContentAST.Paragraph(["What operation happens between these two states?"]))
359
+ body.add_element(ca.Paragraph(["What operation happens between these two states?"]))
360
360
 
361
361
  body.add_element(
362
- ContentAST.Code(
362
+ ca.Code(
363
363
  self.start_state,
364
364
  make_small=True
365
365
  )
366
366
  )
367
367
 
368
- body.add_element(ContentAST.AnswerBlock(self.answers["answer__cmd"]))
368
+ body.add_element(ca.AnswerBlock(self.answers["answer__cmd"]))
369
369
 
370
370
  body.add_element(
371
- ContentAST.Code(
371
+ ca.Code(
372
372
  self.end_state,
373
373
  make_small=True
374
374
  )
@@ -376,19 +376,19 @@ class VSFS_states(IOQuestion):
376
376
 
377
377
  return body, answers
378
378
 
379
- def get_body(self) -> ContentAST.Section:
379
+ def get_body(self) -> ca.Section:
380
380
  """Build question body (backward compatible interface)."""
381
381
  body, _ = self._get_body()
382
382
  return body
383
383
 
384
384
  def _get_explanation(self):
385
- explanation = ContentAST.Section()
385
+ explanation = ca.Section()
386
386
 
387
387
  log.debug(f"self.start_state: {self.start_state}")
388
388
  log.debug(f"self.end_state: {self.end_state}")
389
389
 
390
390
  explanation.add_elements([
391
- ContentAST.Paragraph([
391
+ ca.Paragraph([
392
392
  "The key thing to pay attention to when solving these problems is where there are differences between the start state and the end state.",
393
393
  "In this particular problem, we can see that these lines are different:"
394
394
  ])
@@ -405,7 +405,7 @@ class VSFS_states(IOQuestion):
405
405
  )
406
406
 
407
407
  explanation.add_element(
408
- ContentAST.Paragraph(chunk_to_add)
408
+ ca.Paragraph(chunk_to_add)
409
409
  )
410
410
 
411
411
  chunk_to_add = [
@@ -452,22 +452,22 @@ class VSFS_states(IOQuestion):
452
452
  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.")
453
453
 
454
454
  explanation.add_element(
455
- ContentAST.Paragraph(chunk_to_add)
455
+ ca.Paragraph(chunk_to_add)
456
456
  )
457
457
 
458
458
  explanation.add_elements([
459
- ContentAST.Paragraph(["The overall changes are highlighted with `*` symbols below"])
459
+ ca.Paragraph(["The overall changes are highlighted with `*` symbols below"])
460
460
  ])
461
461
 
462
462
  explanation.add_element(
463
- ContentAST.Code(
463
+ ca.Code(
464
464
  highlight_changes(self.start_state, self.end_state)
465
465
  )
466
466
  )
467
467
 
468
468
  return explanation, []
469
469
 
470
- def get_explanation(self) -> ContentAST.Section:
470
+ def get_explanation(self) -> ca.Section:
471
471
  """Build question explanation (backward compatible interface)."""
472
472
  explanation, _ = self._get_explanation()
473
473
  return explanation
@@ -13,7 +13,7 @@ from typing import List
13
13
 
14
14
  import matplotlib.pyplot as plt
15
15
 
16
- from QuizGenerator.contentast import ContentAST, AnswerTypes
16
+ import QuizGenerator.contentast as ca
17
17
  from QuizGenerator.question import Question, QuestionRegistry, RegenerableChoiceMixin
18
18
  from QuizGenerator.mixins import TableQuestionMixin, BodyTemplatesMixin
19
19
 
@@ -356,15 +356,15 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
356
356
 
357
357
  for job_id in sorted(self.job_stats.keys()):
358
358
  self.answers.update({
359
- f"answer__response_time_job{job_id}": AnswerTypes.Float(self.job_stats[job_id]["Response"]),
360
- f"answer__turnaround_time_job{job_id}": AnswerTypes.Float(self.job_stats[job_id]["TAT"]),
359
+ f"answer__response_time_job{job_id}": ca.AnswerTypes.Float(self.job_stats[job_id]["Response"]),
360
+ f"answer__turnaround_time_job{job_id}": ca.AnswerTypes.Float(self.job_stats[job_id]["TAT"]),
361
361
  })
362
362
  self.answers.update({
363
- "answer__average_response_time": AnswerTypes.Float(
363
+ "answer__average_response_time": ca.AnswerTypes.Float(
364
364
  sum([job.response_time for job in jobs]) / len(jobs),
365
365
  label="Overall average response time"
366
366
  ),
367
- "answer__average_turnaround_time": AnswerTypes.Float(
367
+ "answer__average_turnaround_time": ca.AnswerTypes.Float(
368
368
  sum([job.turnaround_time for job in jobs]) / len(jobs),
369
369
  label="Overall average TAT"
370
370
  )
@@ -380,7 +380,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
380
380
  Tuple of (body_ast, answers_list)
381
381
  """
382
382
  from typing import List
383
- answers: List[ContentAST.Answer] = []
383
+ answers: List[ca.Answer] = []
384
384
 
385
385
  # Create table data for scheduling results
386
386
  table_rows = []
@@ -410,7 +410,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
410
410
  answers.append(avg_tat_answer)
411
411
 
412
412
  # Create average answer block
413
- average_block = ContentAST.AnswerBlock([avg_response_answer, avg_tat_answer])
413
+ average_block = ca.AnswerBlock([avg_response_answer, avg_tat_answer])
414
414
 
415
415
  # Use mixin to create complete body
416
416
  intro_text = (
@@ -418,8 +418,8 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
418
418
  f"Break any ties using the job number."
419
419
  )
420
420
 
421
- instructions = ContentAST.OnlyHtml([ContentAST.Paragraph([
422
- f"Please format answer as fractions, mixed numbers, or numbers rounded to a maximum of {ContentAST.Answer.DEFAULT_ROUNDING_DIGITS} digits after the decimal. "
421
+ instructions = ca.OnlyHtml([ca.Paragraph([
422
+ f"Please format answer as fractions, mixed numbers, or numbers rounded to a maximum of {ca.Answer.DEFAULT_ROUNDING_DIGITS} digits after the decimal. "
423
423
  "Examples of appropriately formatted answers would be `0`, `3/2`, `1 1/3`, `1.6667`, and `1.25`. "
424
424
  "Note that answers that can be rounded to whole numbers should be, rather than being left in fractional form."
425
425
  ])])
@@ -428,7 +428,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
428
428
  body.add_element(average_block)
429
429
  return body, answers
430
430
 
431
- def get_body(self, *args, **kwargs) -> ContentAST.Section:
431
+ def get_body(self, *args, **kwargs) -> ca.Section:
432
432
  """Build question body (backward compatible interface)."""
433
433
  body, _ = self._get_body(*args, **kwargs)
434
434
  return body
@@ -439,32 +439,32 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
439
439
  Returns:
440
440
  Tuple of (explanation_ast, answers_list)
441
441
  """
442
- explanation = ContentAST.Section()
442
+ explanation = ca.Section()
443
443
 
444
444
  explanation.add_element(
445
- ContentAST.Paragraph([
445
+ ca.Paragraph([
446
446
  f"To calculate the overall Turnaround and Response times using {self.scheduler_algorithm} "
447
447
  f"we want to first start by calculating the respective target and response times of all of our individual jobs."
448
448
  ])
449
449
  )
450
450
 
451
451
  explanation.add_elements([
452
- ContentAST.Paragraph([
452
+ ca.Paragraph([
453
453
  "We do this by subtracting arrival time from either the completion time or the start time. That is:"
454
454
  ]),
455
- ContentAST.Equation("Job_{TAT} = Job_{completion} - Job_{arrival\_time}"),
456
- ContentAST.Equation("Job_{response} = Job_{start} - Job_{arrival\_time}"),
455
+ ca.Equation("Job_{TAT} = Job_{completion} - Job_{arrival\_time}"),
456
+ ca.Equation("Job_{response} = Job_{start} - Job_{arrival\_time}"),
457
457
  ])
458
458
 
459
459
  explanation.add_element(
460
- ContentAST.Paragraph([
460
+ ca.Paragraph([
461
461
  f"For each of our {len(self.job_stats.keys())} jobs, we can make these calculations.",
462
462
  ])
463
463
  )
464
464
 
465
465
  ## Add in TAT
466
466
  explanation.add_element(
467
- ContentAST.Paragraph([
467
+ ca.Paragraph([
468
468
  "For turnaround time (TAT) this would be:"
469
469
  ] + [
470
470
  f"Job{job_id}_TAT "
@@ -479,7 +479,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
479
479
  f"{self.job_stats[job_id]['TAT']:0.{self.ROUNDING_DIGITS}f}" for job_id in sorted(self.job_stats.keys())
480
480
  ])
481
481
  explanation.add_element(
482
- ContentAST.Paragraph([
482
+ ca.Paragraph([
483
483
  f"We then calculate the average of these to find the average TAT time",
484
484
  f"Avg(TAT) = ({summation_line}) / ({len(self.job_stats.keys())}) "
485
485
  f"= {self.overall_stats['TAT']:0.{self.ROUNDING_DIGITS}f}",
@@ -489,7 +489,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
489
489
 
490
490
  ## Add in Response
491
491
  explanation.add_element(
492
- ContentAST.Paragraph([
492
+ ca.Paragraph([
493
493
  "For response time this would be:"
494
494
  ] + [
495
495
  f"Job{job_id}_response "
@@ -504,7 +504,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
504
504
  f"{self.job_stats[job_id]['Response']:0.{self.ROUNDING_DIGITS}f}" for job_id in sorted(self.job_stats.keys())
505
505
  ])
506
506
  explanation.add_element(
507
- ContentAST.Paragraph([
507
+ ca.Paragraph([
508
508
  f"We then calculate the average of these to find the average Response time",
509
509
  f"Avg(Response) "
510
510
  f"= ({summation_line}) / ({len(self.job_stats.keys())}) "
@@ -514,7 +514,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
514
514
  )
515
515
 
516
516
  explanation.add_element(
517
- ContentAST.Table(
517
+ ca.Table(
518
518
  headers=["Time", "Events"],
519
519
  data=[
520
520
  [f"{t:02.{self.ROUNDING_DIGITS}f}s"] + ['\n'.join(self.timeline[t])]
@@ -524,7 +524,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
524
524
  )
525
525
 
526
526
  explanation.add_element(
527
- ContentAST.Picture(
527
+ ca.Picture(
528
528
  img_data=self.make_image(),
529
529
  caption="Process Scheduling Overview"
530
530
  )
@@ -532,7 +532,7 @@ class SchedulingQuestion(ProcessQuestion, RegenerableChoiceMixin, TableQuestionM
532
532
 
533
533
  return explanation, []
534
534
 
535
- def get_explanation(self, **kwargs) -> ContentAST.Section:
535
+ def get_explanation(self, **kwargs) -> ca.Section:
536
536
  """Build question explanation (backward compatible interface)."""
537
537
  explanation, _ = self._get_explanation(**kwargs)
538
538
  return explanation
@@ -907,13 +907,13 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
907
907
 
908
908
  for job_id in sorted(self.job_stats.keys()):
909
909
  self.answers.update({
910
- f"answer__turnaround_time_job{job_id}": AnswerTypes.Float(self.job_stats[job_id]["TAT"])
910
+ f"answer__turnaround_time_job{job_id}": ca.AnswerTypes.Float(self.job_stats[job_id]["TAT"])
911
911
  })
912
912
 
913
913
  return self.is_interesting()
914
914
 
915
915
  def _get_body(self, *args, **kwargs):
916
- answers: List[ContentAST.Answer] = []
916
+ answers: List[ca.Answer] = []
917
917
 
918
918
  queue_rows = []
919
919
  for i in reversed(range(self.num_queues)):
@@ -923,7 +923,7 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
923
923
  self.queue_quantums[i],
924
924
  "infinite" if allotment is None else allotment
925
925
  ])
926
- queue_table = ContentAST.Table(
926
+ queue_table = ca.Table(
927
927
  headers=["Queue", "Quantum", "Allotment"],
928
928
  data=queue_rows
929
929
  )
@@ -953,38 +953,38 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
953
953
 
954
954
  instructions = (
955
955
  f"Compute the turnaround time (TAT) for each job. "
956
- f"Round to at most {ContentAST.Answer.DEFAULT_ROUNDING_DIGITS} digits after the decimal."
956
+ f"Round to at most {ca.Answer.DEFAULT_ROUNDING_DIGITS} digits after the decimal."
957
957
  )
958
958
 
959
- body = ContentAST.Section()
960
- body.add_element(ContentAST.Paragraph([intro_text]))
959
+ body = ca.Section()
960
+ body.add_element(ca.Paragraph([intro_text]))
961
961
  body.add_element(queue_table)
962
962
  if self.boost_interval is not None:
963
- body.add_element(ContentAST.Paragraph([
963
+ body.add_element(ca.Paragraph([
964
964
  f"Every {self.boost_interval} time units, all jobs are boosted to "
965
965
  f"Q{self.num_queues - 1}. After a boost, scheduling restarts with the "
966
966
  "lowest job number in that queue."
967
967
  ]))
968
- body.add_element(ContentAST.Paragraph([instructions]))
968
+ body.add_element(ca.Paragraph([instructions]))
969
969
  body.add_element(scheduling_table)
970
970
  return body, answers
971
971
 
972
- def get_body(self, *args, **kwargs) -> ContentAST.Section:
972
+ def get_body(self, *args, **kwargs) -> ca.Section:
973
973
  body, _ = self._get_body(*args, **kwargs)
974
974
  return body
975
975
 
976
976
  def _get_explanation(self, **kwargs):
977
- explanation = ContentAST.Section()
977
+ explanation = ca.Section()
978
978
 
979
979
  explanation.add_element(
980
- ContentAST.Paragraph([
980
+ ca.Paragraph([
981
981
  "Turnaround time (TAT) is the completion time minus the arrival time.",
982
982
  "We calculate it for each job after simulating the schedule."
983
983
  ])
984
984
  )
985
985
 
986
986
  explanation.add_element(
987
- ContentAST.Paragraph([
987
+ ca.Paragraph([
988
988
  "For each job:"
989
989
  ] + [
990
990
  f"Job{job_id}_TAT = "
@@ -996,7 +996,7 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
996
996
  )
997
997
 
998
998
  explanation.add_element(
999
- ContentAST.Table(
999
+ ca.Table(
1000
1000
  headers=["Time", "Events"],
1001
1001
  data=[
1002
1002
  [f"{t:0.{self.ROUNDING_DIGITS}f}s"] + ['\n'.join(events)]
@@ -1017,7 +1017,7 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
1017
1017
  )
1018
1018
 
1019
1019
  explanation.add_element(
1020
- ContentAST.Picture(
1020
+ ca.Picture(
1021
1021
  img_data=self.make_image(),
1022
1022
  caption="MLFQ Scheduling Overview"
1023
1023
  )
@@ -1025,7 +1025,7 @@ class MLFQQuestion(ProcessQuestion, TableQuestionMixin, BodyTemplatesMixin):
1025
1025
 
1026
1026
  return explanation, []
1027
1027
 
1028
- def get_explanation(self, **kwargs) -> ContentAST.Section:
1028
+ def get_explanation(self, **kwargs) -> ca.Section:
1029
1029
  explanation, _ = self._get_explanation(**kwargs)
1030
1030
  return explanation
1031
1031