-
Notifications
You must be signed in to change notification settings - Fork 3
/
create_level_revision_quizzes.py
169 lines (140 loc) · 6.76 KB
/
create_level_revision_quizzes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import kolibri # noqa F401
import django
import uuid
import random
from colors import *
from helpers import (
get_facility_or_default,
get_or_create_classroom,
get_or_create_learnergroup,
get_channels_in_module,
get_channels_in_level,
get_admins_for_facility,
)
django.setup()
from kolibri.core.auth.models import Facility, FacilityUser # noqa E402
from kolibri.core.exams.models import Exam, ExamAssignment # noqa E402
from kolibri.core.content.models import ContentNode, ChannelMetadata # noqa E402
from le_utils.constants import content_kinds # noqa E402
def create_revision_quizzes(
classroomname,
facilityname=None,
levels=["Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6"],
):
"""Function that creates 1 quiz for each topic in each channel having the module passed in
each quiz contains 10 questions
e.g create_quizzes('numeracy','a1') will create 1 quiz for each topic in each numeracy channel
Args:
modulename (string): Name of the module
classroomname (string): Name of the classroom to create the quizzes in
facilityname (string): Name of the facility to create the quizzes for(default facility if not specified)
Returns:
None
"""
# get a reference to the facility to create the lessons in
facility_for_quizzes = get_facility_or_default(facilityname)
# set the seed that will be used to generate the sequence of exam_ids
seed = random.randint(1, 100)
# get or create the class to create the quizzes for
# store a reference to the classroom object if it is created
class_for_quizzes = get_or_create_classroom(classroomname, facilityname)
# get a list of the admin and coach accounts on the device
admin_for_quizzes = get_admins_for_facility(facility_for_quizzes)[0]
for level in levels:
# get all channels with the level passed in
channels = get_channels_in_level(level)
# get a list of all the channel ids for the channels in the level
channel_ids = [channel.id for channel in channels]
# Get the exercise content nodes for all the channels within a level
level_exercise_content = (
ContentNode.objects.filter(
channel_id__in=channel_ids, kind=content_kinds.EXERCISE
)
.exclude(parent_id__isnull=True)
.order_by("sort_order")
)
# Number of revision quizzes to create
num_revision_quizzes = 3
# Loop to generate number of quizzes above
for quiz_num in range(1, num_revision_quizzes + 1):
# Set the quiz name
quiz_title = level + " - " + "Revision Quiz " + str(quiz_num)
# Set the quiz length (number of questions)
quiz_length = 30
# Placeholder var for the number of items in a quiz
n_content_items = 0
# initialize empty array to hold the content
quiz_content = []
# Loop until we have number of items in a quiz = quiz length
while n_content_items < quiz_length:
# If there is only 1 exercise, break the loop and don't create the quiz
if len(level_exercise_content) < 2:
break
else:
# Randomly select an exercise content node in the topic to add to the quiz
random_node = random.choice(level_exercise_content)
# grab this exercise node's assessment ids
# assessment_item_ids = random_node.assessmentmetadata.first().assessment_item_ids
assessment_item_ids = (
random_node.assessmentmetadata.first().assessment_item_ids
)
# select a random assessment item from the assessment items of the exercise
# create a json object with information about the exerise node and the random assessment id chosen
content = {
"exercise_id": random_node.id,
"question_id": random.choice(assessment_item_ids),
"title": random_node.title,
}
# append the content json object to the quiz_content array
# quiz_content.append(content)
quiz_content.append(content)
# increment number of items by 1
n_content_items += 1
# If there werent enough items to make a quiz, inform the user
if len(quiz_content) == 0:
print_colored(
"Could not cerate quiz {}. Not enough content".format(
str(quiz_title)
),
colors.fg.red,
)
else:
# create a new quiz object with the content items gathered above
# use uuid1 with a set seed to make pseudo-random uuids
new_quiz = Exam.objects.create(
id=uuid.uuid1(node=None, clock_seq=seed),
title=quiz_title,
question_count=n_content_items,
question_sources=quiz_content,
active=True,
collection=class_for_quizzes,
creator=admin_for_quizzes,
data_model_version=1,
)
# Inform the user that the new quiz has been generated in the class
# Print('Quiz {} created in class {}'.format(str(new_quiz.title), str(class_for_quizzes.name)))
print_colored(
"Quiz {} created in class {} with {} content items".format(
str(new_quiz.title),
str(class_for_quizzes.name),
str(n_content_items),
),
colors.fg.lightblue,
)
# get or create a group to assign the quiz to based on the channel name
group_for_quiz = get_or_create_learnergroup(
level, classroomname, facilityname
)
# create an ExamAssignment object to assign the quiz to a group
ExamAssignment.objects.create(
exam=new_quiz,
collection=group_for_quiz,
assigned_by=admin_for_quizzes,
)
# inform the user that the quiz has been assigned successfully
print_colored(
"Quiz {} assigned to group {}".format(
str(new_quiz.title), str(group_for_quiz.name)
),
colors.fg.lightblue,
)