from canvasapi import Canvas
import itertools
import random
API_URL = "https://canvas.instructure.com"
API_KEY = <your api key here>
canvas = Canvas(API_URL, API_KEY)
# create a calculated_question
# example of a potential divider
#
# U2 = U0 * R2 / ( R1 + R2 )
#
E3 = [1, 2, 5]
E6 = [1.0, 1.5, 2.2, 3.3, 4.7, 6.8]
E12 = [1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]
coursename = 'test'
quizname = 'test'
# define the input variable names
# each variable has its own range, format and scale
#
variables = \
[
{
'name': 'U0',
'unit': 'V',
'format': '{:.1f}',
'scale': '1',
'range': [1.2, 1.5, 4.5, 9, 12, 24, 48, 110, 220]
},
{
'name': 'R1',
'unit': 'ohm',
'format': '{:.1f}',
'scale': '1',
'range': [ i*j for i, j in itertools.product([10, 100, 1000], E12)]
},
{
'name': 'R2',
'unit': 'ohm',
'format': '{:.1f}',
'scale': '1',
'range': [ i*j for i, j in itertools.product([10, 100, 1000], E12)]
},
]
# how many sets of answers
rows = 30
# create an empty list of lists (array) for the values
values = [ [ i for i in range(len(variables))] for _ in range(rows)]
# create an empty list for the calculated results
results = [i for i in range(rows)]
# fill the array of input values with random choices from the given ranges
for i in range(rows):
for j in range(len(variables)):
values[i][j] = random.choice(variables[j].get('range'))
# and calculate the result value
results[i] = values[i][0] * values[i][2] / (values[i][1]+values[i][2])
# format the text field for the question
# an HTML table is created which presents the variables and their values
question_text = '<p><table border="1"><tr><th></th><th>value</th><th>unit</th></tr>';
for j in range(len(variables)):
question_text += '<tr>'
question_text += '<td style="text-align:center;">' + variables[j].get('name') + '</td>'
question_text += '<td style="text-align:right;">[' + variables[j].get('name') + ']</td>'
question_text += '<td style="text-align:center;">' + variables[j].get('unit') + '</td>'
question_text += '</tr>'
question_text += '</table></p>'
# format the central block of values and results
answers = []
for i in range(rows):
answers.append(\
{
'weight': '100',
'variables':
[
{
'name': variables[j].get('name'),
'value': variables[j].get('format').format(values[i][j])
} for j in range(len(variables))
],
'answer_text': '{:.5g}'.format(results[i])
})
# format the block of variables,
# 'min' and 'max' do not matter since the values are created inside the script
# 'scale' determines the decimal places during output
variables_block = []
for j in range(len(variables)):
variables_block.append(\
{
'name': variables[j].get('name'),
'min': '1.0',
'max': '10.0',
'scale': variables[j].get('scale')
})
# put together the structure of the question
new_question = \
{
'question_name': 'Question 6',
'question_type': 'calculated_question',
'question_text': question_text,
'points_possible': '1.0',
'correct_comments': '',
'incorrect_comments': '',
'neutral_comments': '',
'correct_comments_html': '',
'incorrect_comments_html': '',
'neutral_comments_html': '',
'answers': answers,
'variables': variables_block,
'formulas': ['automated by python'],
'answer_tolerance': '5%',
'formula_decimal_places': '1',
'matches': None,
'matching_answer_incorrect_matches': None,
}
courses = canvas.get_courses()
for course in courses:
if course.name.lower() == coursename.lower():
print('found course')
quizzes = course.get_quizzes()
for quiz in quizzes:
if quiz.title.lower() == quizname.lower():
print('found quiz')
question = quiz.create_question(question = new_question)