QuizGenerator 0.4.4__py3-none-any.whl → 0.5.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 +952 -82
  2. QuizGenerator/generate.py +45 -9
  3. QuizGenerator/misc.py +4 -554
  4. QuizGenerator/mixins.py +47 -25
  5. QuizGenerator/premade_questions/cst334/languages.py +139 -125
  6. QuizGenerator/premade_questions/cst334/math_questions.py +78 -66
  7. QuizGenerator/premade_questions/cst334/memory_questions.py +258 -144
  8. QuizGenerator/premade_questions/cst334/persistence_questions.py +71 -33
  9. QuizGenerator/premade_questions/cst334/process.py +554 -64
  10. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +32 -6
  11. QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +59 -34
  12. QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +27 -8
  13. QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +53 -32
  14. QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +228 -88
  15. QuizGenerator/premade_questions/cst463/models/attention.py +26 -10
  16. QuizGenerator/premade_questions/cst463/models/cnns.py +32 -19
  17. QuizGenerator/premade_questions/cst463/models/rnns.py +25 -12
  18. QuizGenerator/premade_questions/cst463/models/text.py +26 -11
  19. QuizGenerator/premade_questions/cst463/models/weight_counting.py +36 -22
  20. QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +89 -109
  21. QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +117 -51
  22. QuizGenerator/question.py +110 -15
  23. QuizGenerator/quiz.py +81 -24
  24. QuizGenerator/regenerate.py +98 -29
  25. {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/METADATA +1 -1
  26. {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/RECORD +29 -31
  27. QuizGenerator/README.md +0 -5
  28. QuizGenerator/logging.yaml +0 -55
  29. {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/WHEEL +0 -0
  30. {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/entry_points.txt +0 -0
  31. {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/licenses/LICENSE +0 -0
QuizGenerator/quiz.py CHANGED
@@ -11,6 +11,7 @@ import subprocess
11
11
  import tempfile
12
12
  from datetime import datetime
13
13
  from typing import List, Dict, Optional
14
+ import re
14
15
 
15
16
  import yaml
16
17
 
@@ -87,6 +88,11 @@ class Quiz:
87
88
 
88
89
  # Get general quiz information from the dictionary
89
90
  name = exam_dict.get("name", f"Unnamed Exam ({datetime.now().strftime('%a %b %d %I:%M %p')})")
91
+ if isinstance(name, str):
92
+ def replace_time(match: re.Match) -> str:
93
+ fmt = match.group(1) or "%b %d %I:%M%p"
94
+ return datetime.now().strftime(fmt)
95
+ name = re.sub(r"\$TIME(?:\{([^}]+)\})?", replace_time, name)
90
96
  practice = exam_dict.get("practice", False)
91
97
  description = exam_dict.get("description", None)
92
98
  sort_order = list(map(lambda t: Question.Topic.from_string(t), exam_dict.get("sort order", [])))
@@ -275,10 +281,29 @@ class Quiz:
275
281
 
276
282
  # For each point group, estimate heights and apply bin-packing optimization
277
283
  optimized_questions = []
278
- is_first_page = True # Track if we're packing the first page
284
+ is_first_bin_overall = True # Track if we're packing the very first bin of the entire exam
279
285
 
280
286
  log.debug("Optimizing question order for PDF layout...")
281
287
 
288
+ def get_spacing_priority(question):
289
+ """
290
+ Get placement priority based on spacing. Lower values = higher priority.
291
+ Order: LONG (9), MEDIUM (6), SHORT (4), NONE (0), then PAGE (99), EXTRA_PAGE (199)
292
+ """
293
+ spacing = question.spacing
294
+ if spacing >= 199: # EXTRA_PAGE
295
+ return 5
296
+ elif spacing >= 99: # PAGE
297
+ return 4
298
+ elif spacing >= 9: # LONG
299
+ return 0
300
+ elif spacing >= 6: # MEDIUM
301
+ return 1
302
+ elif spacing >= 4: # SHORT
303
+ return 2
304
+ else: # NONE or custom small values
305
+ return 3
306
+
282
307
  for points in sorted(point_groups.keys(), reverse=True):
283
308
  group = point_groups[points]
284
309
 
@@ -288,27 +313,30 @@ class Quiz:
288
313
  group.sort(key=lambda q: self.question_sort_order.index(q.topic))
289
314
  optimized_questions.extend(group)
290
315
  log.debug(f" {points}pt questions: {len(group)} questions (order preserved by config)")
291
- # After adding preserved-order questions, we're likely past the first page
292
- is_first_page = False
316
+ # After adding preserved-order questions, we're no longer on the first bin
317
+ is_first_bin_overall = False
293
318
  continue
294
319
 
295
320
  # If only 1-2 questions, no optimization needed
296
321
  if len(group) <= 2:
297
- # Still sort by topic for consistency
298
- group.sort(key=lambda q: self.question_sort_order.index(q.topic))
322
+ # Sort by spacing priority first, then topic
323
+ group.sort(key=lambda q: (get_spacing_priority(q), self.question_sort_order.index(q.topic)))
299
324
  optimized_questions.extend(group)
300
325
  log.debug(f" {points}pt questions: {len(group)} questions (no optimization needed)")
301
- is_first_page = False
326
+ is_first_bin_overall = False
302
327
  continue
303
328
 
304
- # Estimate height for each question
305
- question_heights = [(q, self._estimate_question_height(q, **kwargs)) for q in group]
329
+ # Estimate height for each question, preserving original index for stable sorting
330
+ question_heights = [(i, q, self._estimate_question_height(q, **kwargs)) for i, q in enumerate(group)]
306
331
 
307
- # Sort by height descending to identify large and small questions
308
- question_heights.sort(key=lambda x: x[1], reverse=True)
332
+ # Sort by:
333
+ # 1. Spacing priority (LONG, MEDIUM, SHORT, NONE, then PAGE, EXTRA_PAGE)
334
+ # 2. Height descending (within same spacing category)
335
+ # 3. Original index (for deterministic ordering)
336
+ question_heights.sort(key=lambda x: (get_spacing_priority(x[1]), -x[2], x[0]))
309
337
 
310
338
  log.debug(f" Question heights for {points}pt questions:")
311
- for q, h in question_heights:
339
+ for idx, q, h in question_heights:
312
340
  log.debug(f" {q.name}: {h:.1f}cm (spacing={q.spacing}cm)")
313
341
 
314
342
  # Calculate page capacity in centimeters
@@ -317,7 +345,7 @@ class Quiz:
317
345
  base_page_capacity = 22.0 # cm
318
346
 
319
347
  # First page has header (title + name line) which takes ~3cm
320
- first_page_capacity = base_page_capacity - 3.0 if is_first_page else base_page_capacity
348
+ first_page_capacity = base_page_capacity - 3.0 # cm
321
349
 
322
350
  # Better bin-packing strategy: interleave large and small questions
323
351
  # Strategy: Start each page with the largest unplaced question, then fill with smaller ones
@@ -326,21 +354,48 @@ class Quiz:
326
354
 
327
355
  while not all(placed):
328
356
  # Determine capacity for this page
329
- page_capacity = first_page_capacity if len(bins) == 0 and is_first_page else base_page_capacity
357
+ # Use first_page_capacity only for the very first bin of the entire exam
358
+ page_capacity = first_page_capacity if (len(bins) == 0 and is_first_bin_overall) else base_page_capacity
330
359
 
331
360
  # Find the largest unplaced question to start a new page
332
361
  new_page = []
333
362
  page_height = 0
334
363
 
335
- for i, (question, height) in enumerate(question_heights):
336
- if not placed[i]:
337
- new_page.append(question)
338
- page_height = height
339
- placed[i] = True
340
- break
364
+ # Special handling for first bin of entire exam: avoid questions with PAGE spacing (99+cm)
365
+ # to prevent them from pushing content to page 2
366
+ if len(bins) == 0 and is_first_bin_overall:
367
+ # Try to find a question without PAGE/EXTRA_PAGE spacing for the first page
368
+ # PAGE=99cm, EXTRA_PAGE=199cm - these need full pages
369
+ found_non_page_question = False
370
+ for i, (idx, question, height) in enumerate(question_heights):
371
+ if not placed[i] and question.spacing < 99:
372
+ new_page.append(question)
373
+ page_height = height
374
+ placed[i] = True
375
+ found_non_page_question = True
376
+ log.debug(f" First bin (page 1): Selected {question.name} with spacing={question.spacing}cm")
377
+ break
378
+
379
+ # If all questions have PAGE spacing, fall back to normal behavior (use largest question)
380
+ if not found_non_page_question:
381
+ for i, (idx, question, height) in enumerate(question_heights):
382
+ if not placed[i]:
383
+ new_page.append(question)
384
+ page_height = height
385
+ placed[i] = True
386
+ log.debug(f" First bin (page 1): All questions have PAGE spacing, using {question.name} (spacing={question.spacing}cm)")
387
+ break
388
+ else:
389
+ # Normal behavior for non-first pages
390
+ for i, (idx, question, height) in enumerate(question_heights):
391
+ if not placed[i]:
392
+ new_page.append(question)
393
+ page_height = height
394
+ placed[i] = True
395
+ break
341
396
 
342
397
  # Now try to fill the remaining space with smaller questions
343
- for i, (question, height) in enumerate(question_heights):
398
+ for i, (idx, question, height) in enumerate(question_heights):
344
399
  if not placed[i] and page_height + height <= page_capacity:
345
400
  new_page.append(question)
346
401
  page_height += height
@@ -348,6 +403,11 @@ class Quiz:
348
403
 
349
404
  bins.append((new_page, page_height))
350
405
 
406
+ # After creating the first bin, we're no longer on the first page
407
+ if len(bins) == 1 and is_first_bin_overall:
408
+ is_first_bin_overall = False
409
+ log.debug(f" First bin created, subsequent bins will use normal page capacity")
410
+
351
411
  log.debug(f" {points}pt questions: {len(group)} questions packed into {len(bins)} pages")
352
412
  for i, (page_questions, height) in enumerate(bins):
353
413
  log.debug(f" Page {i+1}: {height:.1f}cm with {len(page_questions)} questions: {[q.name for q in page_questions]}")
@@ -356,9 +416,6 @@ class Quiz:
356
416
  for bin_contents, _ in bins:
357
417
  optimized_questions.extend(bin_contents)
358
418
 
359
- # After packing questions, we're no longer on the first page
360
- is_first_page = False
361
-
362
419
  return optimized_questions
363
420
 
364
421
  def get_quiz(self, **kwargs) -> ContentAST.Document:
@@ -464,4 +521,4 @@ def main():
464
521
 
465
522
  if __name__ == "__main__":
466
523
  main()
467
-
524
+
@@ -13,6 +13,12 @@ CLI Usage:
13
13
  # Scan QR codes from a scanned exam page
14
14
  python grade_from_qr.py --image exam_page.jpg --all
15
15
 
16
+ # Decode an encrypted string directly
17
+ python -m QuizGenerator.regenerate --encrypted_str "EzE6JF86CDlf..."
18
+
19
+ # Decode with custom point value
20
+ python -m QuizGenerator.regenerate --encrypted_str "EzE6JF86CDlf..." --points 5.0
21
+
16
22
  API Usage (recommended for web UIs):
17
23
  from grade_from_qr import regenerate_from_encrypted
18
24
 
@@ -36,9 +42,22 @@ import argparse
36
42
  import json
37
43
  import sys
38
44
  import logging
45
+ import os
39
46
  from pathlib import Path
40
47
  from typing import Dict, Any, Optional, List
41
48
 
49
+ # Load environment variables from .env file
50
+ try:
51
+ from dotenv import load_dotenv
52
+ # Try loading from current directory first, then home directory
53
+ if os.path.exists('.env'):
54
+ load_dotenv('.env')
55
+ else:
56
+ load_dotenv(os.path.join(os.path.expanduser("~"), ".env"))
57
+ except ImportError:
58
+ # dotenv not available, will use system environment variables only
59
+ pass
60
+
42
61
  # Quiz generator imports (always available)
43
62
  from QuizGenerator.qrcode_generator import QuestionQRCode
44
63
  from QuizGenerator.question import QuestionRegistry
@@ -400,6 +419,17 @@ def main():
400
419
  type=str,
401
420
  help='Path to image file containing QR code(s)'
402
421
  )
422
+ parser.add_argument(
423
+ '--encrypted_str',
424
+ type=str,
425
+ help='Encrypted string from QR code to decode directly'
426
+ )
427
+ parser.add_argument(
428
+ '--points',
429
+ type=float,
430
+ default=1.0,
431
+ help='Point value for the question (default: 1.0, only used with --encrypted_str)'
432
+ )
403
433
  parser.add_argument(
404
434
  '--all',
405
435
  action='store_true',
@@ -415,44 +445,83 @@ def main():
415
445
  action='store_true',
416
446
  help='Enable verbose debug logging'
417
447
  )
418
-
448
+
419
449
  args = parser.parse_args()
420
-
450
+
421
451
  if args.verbose:
422
452
  logging.getLogger().setLevel(logging.DEBUG)
423
-
424
- if not args.image:
453
+
454
+ # Check for required arguments
455
+ if not args.image and not args.encrypted_str:
425
456
  parser.print_help()
426
- print("\nERROR: --image is required")
457
+ print("\nERROR: Either --image or --encrypted_str is required")
427
458
  sys.exit(1)
428
-
429
- # Scan QR codes from image
430
- qr_codes = scan_qr_from_image(args.image)
431
-
432
- if not qr_codes:
433
- print("No QR codes found in image")
459
+
460
+ if args.image and args.encrypted_str:
461
+ print("ERROR: Cannot use both --image and --encrypted_str at the same time")
434
462
  sys.exit(1)
435
-
436
- # Process QR codes
437
- if not args.all:
438
- qr_codes = qr_codes[:1]
439
- log.info("Processing only the first QR code (use --all to process all)")
440
-
463
+
441
464
  results = []
442
-
443
- for qr_string in qr_codes:
444
- # Parse QR data
445
- qr_data = parse_qr_data(qr_string)
446
-
447
- if not qr_data:
448
- continue
449
-
450
- # Regenerate question and answer
451
- question_data = regenerate_question_answer(qr_data)
452
-
453
- if question_data:
465
+
466
+ # Handle direct encrypted string input
467
+ if args.encrypted_str:
468
+ try:
469
+ log.info(f"Decoding encrypted string (points={args.points})")
470
+ result = regenerate_from_encrypted(args.encrypted_str, args.points)
471
+
472
+ # Format result similar to regenerate_question_answer output
473
+ question_data = {
474
+ "question_number": "N/A",
475
+ "points": args.points,
476
+ "question_type": result["question_type"],
477
+ "seed": result["seed"],
478
+ "version": result["version"],
479
+ "answers": result["answers"],
480
+ "answer_objects": result["answer_objects"],
481
+ "answer_key_html": result["answer_key_html"],
482
+ "explanation_markdown": result.get("explanation_markdown")
483
+ }
484
+
485
+ if "kwargs" in result:
486
+ question_data["config"] = result["kwargs"]
487
+
454
488
  results.append(question_data)
455
489
  display_answer_summary(question_data)
490
+
491
+ except Exception as e:
492
+ log.error(f"Failed to decode encrypted string: {e}")
493
+ import traceback
494
+ if args.verbose:
495
+ log.debug(traceback.format_exc())
496
+ sys.exit(1)
497
+
498
+ # Handle image scanning
499
+ else:
500
+ # Scan QR codes from image
501
+ qr_codes = scan_qr_from_image(args.image)
502
+
503
+ if not qr_codes:
504
+ print("No QR codes found in image")
505
+ sys.exit(1)
506
+
507
+ # Process QR codes
508
+ if not args.all:
509
+ qr_codes = qr_codes[:1]
510
+ log.info("Processing only the first QR code (use --all to process all)")
511
+
512
+ for qr_string in qr_codes:
513
+ # Parse QR data
514
+ qr_data = parse_qr_data(qr_string)
515
+
516
+ if not qr_data:
517
+ continue
518
+
519
+ # Regenerate question and answer
520
+ question_data = regenerate_question_answer(qr_data)
521
+
522
+ if question_data:
523
+ results.append(question_data)
524
+ display_answer_summary(question_data)
456
525
 
457
526
  # Save to file if requested
458
527
  if args.output:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuizGenerator
3
- Version: 0.4.4
3
+ Version: 0.5.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
@@ -1,17 +1,15 @@
1
- QuizGenerator/README.md,sha256=4n16gKyhIAKRBX4VKlpfcK0pyUYJ6Ht08MUsnwgxrZo,145
2
1
  QuizGenerator/__init__.py,sha256=8EV-k90A3PNC8Cm2-ZquwNyVyvnwW1gs6u-nGictyhs,840
3
2
  QuizGenerator/__main__.py,sha256=Dd9w4R0Unm3RiXztvR4Y_g9-lkWp6FHg-4VN50JbKxU,151
4
3
  QuizGenerator/constants.py,sha256=AO-UWwsWPLb1k2JW6KP8rl9fxTcdT0rW-6XC6zfnDOs,4386
5
- QuizGenerator/contentast.py,sha256=nx0-y3LTyInzX9QheweHhA90zNsdtXie7X-ckYu1_rM,68318
6
- QuizGenerator/generate.py,sha256=o2XezoSE0u-qjxYu1_Ofm9Lpkza7M2Tg47C-ClMcPsE,7197
7
- QuizGenerator/logging.yaml,sha256=VJCdh26D8e_PNUs4McvvP1ojz9EVjQNifJzfhEk1Mbo,1114
8
- QuizGenerator/misc.py,sha256=2vEztj-Kt_0Q2OnynJKC4gL_w7l1MqWsBhhIDOuVD1s,18710
9
- QuizGenerator/mixins.py,sha256=zUKTkswq7aoDZ_nGPUdRuvnza8iH8ZCi6IH2Uw-kCvs,18492
4
+ QuizGenerator/contentast.py,sha256=k38x8ukpLxCk2saun_O3K_n8NJL1leLhj-5iog0MkNg,100124
5
+ QuizGenerator/generate.py,sha256=FNHkHsxysQrsMOfLqborr5FYIKc0zd4qI97TJwAMtFs,8581
6
+ QuizGenerator/misc.py,sha256=JpHdZZI-dCa15KQYXlJrrMFrnsMMkhXpEvyGC2R7wiE,666
7
+ QuizGenerator/mixins.py,sha256=3o8tkTTtfqxUKCQrBtQc152owjXuWAVYqzi-HP4Rx2s,19172
10
8
  QuizGenerator/performance.py,sha256=CM3zLarJXN5Hfrl4-6JRBqD03j4BU1B2QW699HAr1Ds,7002
11
9
  QuizGenerator/qrcode_generator.py,sha256=S3mzZDk2UiHiw6ipSCpWPMhbKvSRR1P5ordZJUTo6ug,10776
12
- QuizGenerator/question.py,sha256=pyDQJzqqyEwhnqCl0PqdTNvM7bTPy7m31qdzGfYC0j4,28269
13
- QuizGenerator/quiz.py,sha256=toPodXea2UYGgAf4jyor3Gz-gtXYN1YUJFJFQ5u70v4,18718
14
- QuizGenerator/regenerate.py,sha256=EvtFhDUXYaWEBCGJ4RW-zN65qj3cMxWa_Y_Rn44WU6c,14282
10
+ QuizGenerator/question.py,sha256=S-DC6pWSgP5NDjSqj6kmiVxqzMrL9sGucZFMhr9H7yw,31633
11
+ QuizGenerator/quiz.py,sha256=f2HLrawUlu3ULkNDzcihBWAt-e-49AIPz_l1edMAEQ0,21503
12
+ QuizGenerator/regenerate.py,sha256=Uh4B9aKQvL3zD7PT-uH-GvrcSuUygV1BimvPVuErc-g,16525
15
13
  QuizGenerator/typst_utils.py,sha256=XtMEO1e4_Tg0G1zR9D1fmrYKlUfHenBPdGoCKR0DhZg,3154
16
14
  QuizGenerator/canvas/__init__.py,sha256=TwFP_zgxPIlWtkvIqQ6mcvBNTL9swIH_rJl7DGKcvkQ,286
17
15
  QuizGenerator/canvas/canvas_interface.py,sha256=wsEWh2lonUMgmbtXF-Zj59CAM_0NInoaERqsujlYMfc,24501
@@ -19,34 +17,34 @@ QuizGenerator/canvas/classes.py,sha256=v_tQ8t_JJplU9sv2p4YctX45Fwed1nQ2HC1oC9BnD
19
17
  QuizGenerator/premade_questions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
18
  QuizGenerator/premade_questions/basic.py,sha256=wAvVZED6a7VToIvSCdAx6SrExmR0xVRo5dL40kycdXI,3402
21
19
  QuizGenerator/premade_questions/cst334/__init__.py,sha256=BTz-Os1XbwIRKqAilf2UIva2NlY0DbA_XbSIggO2Tdk,36
22
- QuizGenerator/premade_questions/cst334/languages.py,sha256=MTqprY8VUWgNlP0zRRpZXOAP2dd6ocx_XWVqcNlxYg8,14390
23
- QuizGenerator/premade_questions/cst334/math_questions.py,sha256=za8lNqhM0RB8qefmPP-Ww0WB_SQn0iRcBKOrZgyHCQQ,9290
24
- QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=B4hpnMliJY-x65hNbjwbf22m-jiTi3WEXmauKv_YA84,51598
20
+ QuizGenerator/premade_questions/cst334/languages.py,sha256=EFkS22mw4-jWOemU1qP58-_nymuZHm4UClaDj2ehpks,14966
21
+ QuizGenerator/premade_questions/cst334/math_questions.py,sha256=yqQsNeXJH8ySPrzYyyJg4sGerKH_xo1gw-kw54f4lmU,10281
22
+ QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=ImjUSFE5soDb_79uzai6aVvHtnMQ0DVdCZ6QGRf1Fao,55279
25
23
  QuizGenerator/premade_questions/cst334/ostep13_vsfs.py,sha256=d9jjrynEw44vupAH_wKl57UoHooCNEJXaC5DoNYualk,16163
26
- QuizGenerator/premade_questions/cst334/persistence_questions.py,sha256=hIOi-_K-0B_owWtV_YnXXW8Bb51uQF_lpVcXQkAlbXc,16520
27
- QuizGenerator/premade_questions/cst334/process.py,sha256=EB0iuT9Q8FfOnmlQoXL7gkfsPyVJP55cRFOe2mWfamc,23647
24
+ QuizGenerator/premade_questions/cst334/persistence_questions.py,sha256=2P79FHZBVmtfov56PokmNhp9QXMWQtuljiIFwpDJ9jA,17825
25
+ QuizGenerator/premade_questions/cst334/process.py,sha256=Wk-XatiL5YdIKEr1CenPJNUUtlOssUaP5dzY_BO_QjI,40108
28
26
  QuizGenerator/premade_questions/cst463/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
27
  QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py,sha256=sH2CUV6zK9FT3jWTn453ys6_JTrUKRtZnU8hK6RmImU,240
30
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=ssj6Xkpw6vDiL4qwVOiHUhly3TX50oX4KJtouj7qN6g,12809
31
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=VjmNDpV3YgeYKqyYp4wQXZIViZVvC1GcnjVUl7valhU,9724
32
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=TnhcD9OBsYgVDdSY5qPrSovnYB6r90wiGcg934czIrY,21500
28
+ QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=WUCI_KlgGN5lgF50USEoMdj-hDgkmu0JBTBQlcEiUYU,13928
29
+ QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=xauxxY-fYiod8kcd9FB1RAVb1ImBH7_qDNSCJMacqJY,10890
30
+ QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=aOGrhN3PyDX7ESCMFeWQ1gzbh2cdbbLG4J34-Ac716A,22259
33
31
  QuizGenerator/premade_questions/cst463/gradient_descent/misc.py,sha256=iB3obG6-uXr_yrLVT7L_9j1H54f7oe5Rk9w45yW-lnw,2654
34
32
  QuizGenerator/premade_questions/cst463/math_and_data/__init__.py,sha256=EbIaUrx7_aK9j3Gd8Mk08h9GocTq_0OoNu2trfNwaU8,202
35
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=sq27xv7X9aa0axFxomusZRwM-ICj9grbhD_Bv3n3gJg,28947
36
- QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=tNxfR6J1cZHsHG9GfwVyl6lxxN_TEnhKDmMq4aVLwow,20793
33
+ QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=9D-DrWAB2j_FXY4HBoEiBp_i7V5dsc7Ac6rb44T9oW0,29470
34
+ QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=BOpv22yr3UfEAFI2Z3dxRSMSSEEvtZWtV4m7YOvBgOc,24730
37
35
  QuizGenerator/premade_questions/cst463/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- QuizGenerator/premade_questions/cst463/models/attention.py,sha256=i8h6DihzJTc_QFrdm1eaYhnuhlXKRUv_vIDg3jk_LZ8,5502
39
- QuizGenerator/premade_questions/cst463/models/cnns.py,sha256=M0_9wlPhQICje1UdwIbDoBA4qzjmJtmP9VVVneYM5Mc,5766
36
+ QuizGenerator/premade_questions/cst463/models/attention.py,sha256=6X5CzeFQVnthqo76OfG1dbuAtXCdDrkT6_P56iu0qPc,6115
37
+ QuizGenerator/premade_questions/cst463/models/cnns.py,sha256=kQAiTloKvrWYtDMBNQs9-_cnzNUXK_p7L8ubFPos6wU,6352
40
38
  QuizGenerator/premade_questions/cst463/models/matrices.py,sha256=H61_8cF1DGCt4Z4Ssoi4SMClf6tD5wHkOqY5bMdsSt4,699
41
- QuizGenerator/premade_questions/cst463/models/rnns.py,sha256=-tXeGgqPkctBBUy4RvEPqhv2kfPqoyO2wk-lNJLNWmY,6697
42
- QuizGenerator/premade_questions/cst463/models/text.py,sha256=bUiDIzOBEzilUKQjm2yO9ufcvJGY6Gt3qfeNP9UZOrc,6400
43
- QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=k_FVS3JYP8MUmghHzpSR5DKJ973TGRa43MRMs3GzSTo,6768
39
+ QuizGenerator/premade_questions/cst463/models/rnns.py,sha256=jee-IyGxZUHrit-9mTnWuOJ9TRyaNfULI7E-iENxoHo,7271
40
+ QuizGenerator/premade_questions/cst463/models/text.py,sha256=Sk_KI98rKgaoKS_yjdazNWqQN41j27xUAMsmlRfwglE,7025
41
+ QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=0SVDCz43_LCfrxTtcDbFYnKpKd4FggrvkvU04gj3Ufw,7287
44
42
  QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py,sha256=pmyCezO-20AFEQC6MR7KnAsaU9TcgZYsGQOMVkRZ-U8,149
45
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=gd5zI-6gmXUiK8GaCOCq0IlOwDg4YS0NlOdoN9v_flo,44810
43
+ QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=DMK9jYk_yn7XevFRG06UL8yi7UMT64P8KOzb3ikhq0g,46129
46
44
  QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py,sha256=G1gEHtG4KakYgi8ZXSYYhX6bQRtnm2tZVGx36d63Nmo,173
47
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=z2eMjDFQnyjoKglJ4cuZKWFmN9n3Dt7UTwuMLhriWLM,30244
48
- quizgenerator-0.4.4.dist-info/METADATA,sha256=sxm0mKRsHvLNX99ZFRBcjpZnQ6puZ4WZf-e8JgjmafE,7212
49
- quizgenerator-0.4.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
50
- quizgenerator-0.4.4.dist-info/entry_points.txt,sha256=aOIdRdw26xY8HkxOoKHBnUPe2mwGv5Ti3U1zojb6zxQ,98
51
- quizgenerator-0.4.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
52
- quizgenerator-0.4.4.dist-info/RECORD,,
45
+ QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=vCJHq6SNf-U2BIgNKt33gAEfeSgMbKDuLaWj9zdx9cw,33616
46
+ quizgenerator-0.5.1.dist-info/METADATA,sha256=kT5tAexb_kDMZmJ-zQbCPorvY98xaCA0tutt_IWhHUw,7212
47
+ quizgenerator-0.5.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
+ quizgenerator-0.5.1.dist-info/entry_points.txt,sha256=aOIdRdw26xY8HkxOoKHBnUPe2mwGv5Ti3U1zojb6zxQ,98
49
+ quizgenerator-0.5.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
50
+ quizgenerator-0.5.1.dist-info/RECORD,,
QuizGenerator/README.md DELETED
@@ -1,5 +0,0 @@
1
-
2
-
3
- ## Installation
4
-
5
- Note, you will need to install `pandoc` prior to running since it is used to convert to HTML (for canvas) and Latex (for PDF)`
@@ -1,55 +0,0 @@
1
- version: 1
2
- disable_existing_loggers: false
3
-
4
- formatters:
5
- standard:
6
- format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
7
- datefmt: '%Y-%m-%d %H:%M:%S'
8
-
9
- detailed:
10
- format: '%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(funcName)s:%(lineno)d - %(message)s'
11
- datefmt: '%Y-%m-%d %H:%M:%S'
12
-
13
- simple:
14
- format: '%(levelname)s - %(message)s'
15
-
16
- handlers:
17
- console:
18
- class: logging.StreamHandler
19
- level: INFO
20
- formatter: standard
21
- stream: ext://sys.stdout
22
-
23
- file:
24
- class: logging.FileHandler
25
- level: INFO
26
- formatter: detailed
27
- filename: ${LOG_FILE:-teachingtools.log}
28
- mode: a
29
-
30
- error_file:
31
- class: logging.FileHandler
32
- level: ERROR
33
- formatter: detailed
34
- filename: ${ERROR_LOG_FILE:-teachingtools_errors.log}
35
- mode: a
36
-
37
- loggers:
38
- QuizGenerator:
39
- level: INFO
40
- handlers: [console, file]
41
- propagate: false
42
-
43
- lms_interface:
44
- level: INFO
45
- handlers: [console, file]
46
- propagate: false
47
-
48
- canvasapi:
49
- level: WARNING
50
- handlers: [console]
51
- propagate: false
52
-
53
- root:
54
- level: INFO
55
- handlers: [console, file, error_file]