Last active
December 23, 2015 15:59
-
-
Save zeimusu/6659089 to your computer and use it in GitHub Desktop.
Simple python framework for multiple choice quizzes. It has interfaces for running the quiz on the console or as a cgi script.
The cgi interface can be used with jqmath.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
## Example of using the jqmath library. | |
import cgi | |
from multipletest import Quiz | |
mathsq= Quiz("Trig quiz") | |
mathsq.add_question("Solve $\sin(x) = 0.5$ in range $0<x<2π$.", | |
"$π/6$ and ${5π}/6$","$π/6$", | |
"$\π/6$, ${5π}/6$, ${7π}/6$, ${11π}/6$", | |
helptext=""" | |
There are two solutions. Since $\sin(x)$ is positive, they are found | |
in the first and second quadrants.""") | |
form = cgi.FieldStorage() | |
print("Content-type: text/html\n") | |
print(""" | |
<!DOCTYPE html> | |
<html lang="en" xmlns:m="http://www.w3.org/1998/Math/MathML"> | |
<head> | |
<meta charset="utf-8"> | |
<!-- | |
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=UnifrakturMaguntia"> | |
--> | |
<link rel="stylesheet" href="/mathscribe/jqmath-0.4.0.css"> | |
<script src="/mathscribe/jquery-1.4.3.min.js"></script> | |
<script src="/mathscribe/jqmath-etc-0.4.0.min.js"></script> | |
<title>{title}</title> | |
</head> | |
<body> | |
<h1>{title}</h1>""".format(title=mathsq.title)) | |
answered = form.getfirst("answered") | |
if answered: | |
mathsq.check_form(form) | |
else: | |
mathsq.show_html() | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
class Question(): | |
def __init__(self,qnum,q,answers,correct=0,helptext=None,shuffle=True): | |
self.qnum = qnum | |
self.question = q | |
self.answers = answers | |
self.correct = correct | |
self.helptext = helptext | |
self.shuffle = shuffle | |
def make_correction(self): | |
print("Sorry, the correct answers is:") | |
print(" ",self.answers[self.correct]) | |
if self.helptext: | |
print(self.helptext) | |
def ask_question_html(self): | |
frame = """ | |
<p class="question"> | |
<span class="qnumber">{qnumber}</span> | |
{question} | |
</p> | |
<p class="answers"> | |
{answerlist} | |
</p>""" | |
answerlist = "" | |
numquest=len(self.answers) | |
numbers = list(range(numquest)) | |
if self.shuffle : random.shuffle(numbers) | |
for i in range(numquest): | |
answerlist += """ | |
<label class="option"> | |
<input type="radio" | |
id="answer{qnum}.{ansnum}" name="question.{qnum}" | |
value="{ansnum}"/> {answer}</label><br />""".format( | |
qnum=self.qnum, | |
ansnum=numbers[i], | |
answer=self.answers[numbers[i]]) | |
print(frame.format(qnumber=self.qnum, | |
question=self.question, | |
answerlist=answerlist)) | |
def ask_question(self): | |
""" Asks a question on the console. Checks the answer and returns true | |
or false.""" | |
print(self.qnum,self.question) | |
numquest=len(self.answers) | |
numbers = list(range(numquest)) | |
if self.shuffle : random.shuffle(numbers) | |
for i in range(numquest): | |
print (i+1,":", self.answers[numbers[i]]) | |
while True: | |
try: | |
ans = int(input( | |
"Enter an answer from 1 to {}. ".format(numquest))) | |
except ValueError: | |
print("I don't understand that answer.") | |
continue | |
if ans < 1 or ans > numquest: | |
print("Must be in range 1 to {}.".format(numquest)) | |
continue | |
break | |
return numbers[ans - 1] == self.correct | |
class Quiz(): | |
def __init__(self,title): | |
self.quiz = [] | |
self.qcount = 0 | |
self.title=title | |
def add_question(self,q,*answers,correct=0,helptext=None,shuffle=True): | |
""" Add a question to the quiz. add_question would normally be called multiple | |
times at the start of the quiz. | |
the first argument is the question. Include a question mark. | |
after that there is a sequence of potential answers. | |
correct is the index of the correct answer | |
helptext is usually a longer string that explains the correct answer. | |
It is normally only seen after an incorrect answer has been given. | |
shuffle can be set to false to prevent the answers being listed in a | |
random order. It is useful for true/false quizzes.""" | |
self.qcount += 1 | |
question = Question( | |
"Q"+str(self.qcount)+".", | |
q, | |
answers, | |
correct, | |
helptext, | |
shuffle) | |
self.quiz.append(question) | |
def ask_q_number(self,n): | |
"""Ask and check a single question, given its index in the list""" | |
q=self.quiz[n] | |
result = self.ask_question(q) | |
if result: | |
print("That's right!") | |
else: | |
make_correction(q) | |
def run_quiz(self): | |
""" | |
Run a quiz in text mode. Each question is asked, an answer is sought, and feedback is given. | |
""" | |
import os | |
os.system('cls' if os.name=='nt' else 'clear') | |
score = 0 | |
for q in self.quiz: | |
result = q.ask_question() | |
if result: | |
print("That's right!") | |
score += 1 | |
else: | |
q.make_correction() | |
print("") | |
print("You scored {} out of {}.".format(score,len(self.quiz))) | |
def show_html(self): | |
"""Run a quiz in html mode. | |
All the questions are shown with radio buttons. | |
This can be incorperated into cgi type applications | |
""" | |
print('<form id="quiz">') | |
for q in self.quiz: | |
q.ask_question_html() | |
print('<input type="hidden" name="answered" value="True"/>') | |
print('<button type="submit">Check answers</button></form>') | |
def check_form(self,fieldstore): | |
""" | |
Check and give feedback on a quiz. Fieldstore is the list of key values that a cgi script returns. | |
fieldstore must include a getfirst method. | |
A summary of the questions, and correct answers is given, and helptexts are shown for | |
incorrect answers if available | |
""" | |
score = 0 | |
for q in self.quiz: | |
answerframe = """ | |
<p>I asked "{question}" <br> | |
You replied "{answer}".<br> | |
{assessment}</p> | |
{correction}""" | |
name = "question."+q.qnum | |
answernum = int(fieldstore.getfirst(name,"-1")) | |
answer = q.answers[answernum] | |
if q.correct == int(answernum): | |
assessment="That's correct!" | |
correction ="" | |
score +=1 | |
else: | |
assessment = "Sorry that's not correct." | |
correction = """ | |
<p>The correct answer is <strong>{correct}</strong></p>""".format( | |
correct = q.answers[q.correct]) | |
if q.helptext: | |
correction += "<p><em>{helptext}</em></p>".format( | |
helptext=q.helptext) | |
print(answerframe.format(question=q.question, | |
answer = answer, | |
assessment = assessment, | |
correction = correction)) | |
print("<p>You scored {} out of {} ({}%)<p>".format(score,self.qcount, | |
100*score//self.qcount)) | |
def main(): | |
"""Silly sample quiz""" | |
bod= Quiz("test quiz") | |
bod.add_question("What is your name?", "Arthur", "Kevin", "Robin", | |
helptext="I only speak to kings") | |
bod.add_question("What is your quest?", "To resuce the princess", | |
"To seek the holy grail",correct=1) | |
bod.add_question("What is your favourite colour?", | |
"red", "blue", "purple", "green",correct=1) | |
bod.add_question("It is an african swallow.", "True", "False", shuffle=False) | |
bod.run_quiz() | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
## Text mode quiz. | |
## The questions are set one by one and immediate feedback given. | |
from multipletest import Quiz | |
scienceq= Quiz("Micro-organisms") | |
scienceq.add_question("Which one is a micro-organism?", | |
"Bacteria","Ant","Computer","Crab","Atom", | |
helptext=""" | |
Micro-organisms are creatures which are smaller than mini-beasts. | |
They are too small to see without a powerful microscope. Examples include | |
bacteria, viruses and some fungi.""") | |
scienceq.add_question("All micro-organisms are bad", | |
"True","False",correct=1,shuffle=False) | |
scienceq.add_question("Which type of food do micro-organisms NOT make", | |
"Chocolate","Yogurt","Cheese","Wine","Bread") | |
scienceq.add_question("What do antibiotics do?", | |
"Kill bacteria","Cure a fever","Help viruses to grow") | |
scienceq.run_quiz() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
## CGI mode. The | |
import cgi | |
from multipletest import Quiz | |
scienceq= Quiz("Micro-organisms") | |
scienceq.add_question("Which one is a micro-organism?", | |
"Bacteria","Ant","Computer","Crab","Atom", | |
helptext=""" | |
Micro-organisms are creatures which are smaller than mini-beasts. | |
They are too small to see without a powerful microscope. Examples include | |
bacteria, viruses and some fungi.""") | |
scienceq.add_question("All micro-organisms are bad", | |
"True","False",correct=1,shuffle=False) | |
scienceq.add_question("Which type of food do micro-organisms NOT make", | |
"Chocolate","Yogurt","Cheese","Wine","Bread") | |
scienceq.add_question("What do antibiotics do?", | |
"Kill bacteria","Cure a fever","Help viruses to grow") | |
form = cgi.FieldStorage() | |
print("Content-type: text/html\n") | |
print(""" | |
<html> | |
<head> | |
<title>{title}</title> | |
</head> | |
<body> | |
<h1>{title}</h1>""".format(title=scienceq.title)) | |
answered = form.getfirst("answered") | |
if answered: | |
scienceq.check_form(form) | |
else: | |
scienceq.show_html() | |
print("</body></html>") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment