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.
- QuizGenerator/contentast.py +952 -82
- QuizGenerator/generate.py +45 -9
- QuizGenerator/misc.py +4 -554
- QuizGenerator/mixins.py +47 -25
- QuizGenerator/premade_questions/cst334/languages.py +139 -125
- QuizGenerator/premade_questions/cst334/math_questions.py +78 -66
- QuizGenerator/premade_questions/cst334/memory_questions.py +258 -144
- QuizGenerator/premade_questions/cst334/persistence_questions.py +71 -33
- QuizGenerator/premade_questions/cst334/process.py +554 -64
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +32 -6
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +59 -34
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +27 -8
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +53 -32
- QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +228 -88
- QuizGenerator/premade_questions/cst463/models/attention.py +26 -10
- QuizGenerator/premade_questions/cst463/models/cnns.py +32 -19
- QuizGenerator/premade_questions/cst463/models/rnns.py +25 -12
- QuizGenerator/premade_questions/cst463/models/text.py +26 -11
- QuizGenerator/premade_questions/cst463/models/weight_counting.py +36 -22
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +89 -109
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +117 -51
- QuizGenerator/question.py +110 -15
- QuizGenerator/quiz.py +81 -24
- QuizGenerator/regenerate.py +98 -29
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/METADATA +1 -1
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/RECORD +29 -31
- QuizGenerator/README.md +0 -5
- QuizGenerator/logging.yaml +0 -55
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/WHEEL +0 -0
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
|
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
|
|
292
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
|
308
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
+
|
QuizGenerator/regenerate.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
430
|
-
|
|
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
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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.
|
|
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=
|
|
6
|
-
QuizGenerator/generate.py,sha256=
|
|
7
|
-
QuizGenerator/
|
|
8
|
-
QuizGenerator/
|
|
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=
|
|
13
|
-
QuizGenerator/quiz.py,sha256=
|
|
14
|
-
QuizGenerator/regenerate.py,sha256=
|
|
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=
|
|
23
|
-
QuizGenerator/premade_questions/cst334/math_questions.py,sha256=
|
|
24
|
-
QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=
|
|
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=
|
|
27
|
-
QuizGenerator/premade_questions/cst334/process.py,sha256=
|
|
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=
|
|
31
|
-
QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=
|
|
32
|
-
QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=
|
|
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=
|
|
36
|
-
QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=
|
|
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=
|
|
39
|
-
QuizGenerator/premade_questions/cst463/models/cnns.py,sha256=
|
|
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
|
|
42
|
-
QuizGenerator/premade_questions/cst463/models/text.py,sha256=
|
|
43
|
-
QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=
|
|
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=
|
|
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=
|
|
48
|
-
quizgenerator-0.
|
|
49
|
-
quizgenerator-0.
|
|
50
|
-
quizgenerator-0.
|
|
51
|
-
quizgenerator-0.
|
|
52
|
-
quizgenerator-0.
|
|
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
QuizGenerator/logging.yaml
DELETED
|
@@ -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]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|