- Add rudimentary classes for reading MoxQuizz questions. - Add a very simple ask command. No scores or quiz game-play yet. - Refactor SQL models out into a separate file. - Make the code more Python 3 friendly. - PEP8 and pyflakes.
181 lines
5.5 KiB
Python
181 lines
5.5 KiB
Python
#!/usr/bin/env python
|
|
## -*- coding: utf-8 -*-
|
|
from __future__ import unicode_literals, print_function
|
|
from io import open
|
|
|
|
|
|
class Question:
|
|
"""
|
|
Represents one MoxQuizz question.
|
|
"""
|
|
|
|
category = None
|
|
question = None
|
|
answer = None
|
|
regexp = None
|
|
author = None
|
|
level = None
|
|
comment = None
|
|
score = 0
|
|
tip = list()
|
|
tipcycle = 0
|
|
|
|
TRIVIAL = 1
|
|
EASY = 2
|
|
NORMAL = 3
|
|
HARD = 4
|
|
EXTREME = 5
|
|
|
|
LEVELS = (TRIVIAL, EASY, NORMAL, HARD, EXTREME)
|
|
|
|
def __init__(self, attributes_dict):
|
|
self.parse(attributes_dict)
|
|
|
|
def parse(self, attributes_dict):
|
|
"""
|
|
Populate fields from a dictionary of attributes (from a question bank).
|
|
"""
|
|
|
|
## Valid keys:
|
|
# ----------
|
|
# Category? (should always be on top!)
|
|
# Question (should always stand after Category)
|
|
# Answer (will be matched if no regexp is provided)
|
|
# Regexp? (use UNIX-style expressions)
|
|
# Author? (the brain behind this question)
|
|
# Level? [baby|easy|normal|hard|extreme] (difficulty)
|
|
# Comment? (comment line)
|
|
# Score? [#] (credits for answering this question)
|
|
# Tip* (provide one or more hints)
|
|
# TipCycle? [#] (Specify number of generated tips)
|
|
|
|
if 'Question' in attributes_dict.keys():
|
|
self.question = attributes_dict['Question']
|
|
else:
|
|
raise Exception("Cannot instantiate Question: 'Question' attribute required.")
|
|
|
|
if 'Category' in attributes_dict.keys():
|
|
self.category = attributes_dict['Category']
|
|
|
|
if 'Answer' in attributes_dict.keys():
|
|
self.answer = attributes_dict['Answer']
|
|
else:
|
|
raise Exception("Cannot instantiate Question: 'Answer' attribute required.")
|
|
|
|
if 'Regexp' in attributes_dict.keys():
|
|
self.regexp = attributes_dict['Regexp']
|
|
|
|
if 'Author' in attributes_dict.keys():
|
|
self.category = attributes_dict['Author']
|
|
|
|
if 'Level' in attributes_dict.keys() and attributes_dict['Level'] in self.LEVELS:
|
|
self.level = attributes_dict['level']
|
|
|
|
if 'Comment' in attributes_dict.keys():
|
|
self.comment = attributes_dict['Comment']
|
|
|
|
if 'Score' in attributes_dict.keys():
|
|
self.score = attributes_dict['Score']
|
|
|
|
if 'Tip' in attributes_dict.keys():
|
|
self.tip = attributes_dict['Tip']
|
|
|
|
if 'Tipcycle' in attributes_dict.keys():
|
|
self.tipcycle = attributes_dict['Tipcycle']
|
|
|
|
|
|
class QuestionBank:
|
|
"""
|
|
Represents a MoxQuizz question bank.
|
|
"""
|
|
|
|
filename = ''
|
|
questions = list()
|
|
|
|
# Case sensitive, to remain backwards-compatible with MoxQuizz.
|
|
KEYS = ('Answer',
|
|
'Author',
|
|
'Category',
|
|
'Comment',
|
|
'Level',
|
|
'Question',
|
|
'Regexp',
|
|
'Score',
|
|
'Tip',
|
|
'Tipcycle',
|
|
)
|
|
|
|
def __init__(self, filename):
|
|
"""
|
|
Construct a question bank from a file.
|
|
"""
|
|
self.filename = filename
|
|
self.questions = self.parse(filename)
|
|
|
|
def parse(self, filename):
|
|
"""
|
|
Read a Moxquizz question bank file into a list.
|
|
"""
|
|
questions = list()
|
|
|
|
with open(filename) as f:
|
|
key = ''
|
|
i = 0
|
|
|
|
# new question
|
|
q = dict()
|
|
q['Tip'] = list()
|
|
|
|
for line in f:
|
|
line = line.strip()
|
|
i += 1
|
|
|
|
# Ignore comments.
|
|
if line.startswith('#'):
|
|
continue
|
|
|
|
# A blank line starts a new question.
|
|
if line == '':
|
|
# Store the previous question, if valid.
|
|
if 'Question' in q.keys() and 'Answer' in q.keys():
|
|
question = Question(q)
|
|
questions.append(question)
|
|
|
|
# Start a new question.
|
|
q = dict()
|
|
q['Tip'] = list()
|
|
continue
|
|
|
|
# Fetch the next parameter.
|
|
try:
|
|
(key, value) = line.split(':', 1)
|
|
except ValueError:
|
|
print("Unexpected weirdness in MoxQuizz questionbank '%s', line %s." % (self.filename, i))
|
|
continue
|
|
# break # TODO: is it appropriate to bail on broken bank files?
|
|
|
|
# Ignore bad parameters.
|
|
if key not in self.KEYS:
|
|
print("Unexpected key '%s' in MoxQuizz questionbank '%s', line %s." % (key, self.filename, i))
|
|
continue
|
|
|
|
# Enumerate the Tips.
|
|
if key == 'Tip':
|
|
q['Tip'].append(value.strip())
|
|
else:
|
|
q[key] = value.strip()
|
|
|
|
return questions
|
|
|
|
|
|
# A crappy test.
|
|
if __name__ == '__main__':
|
|
qb = QuestionBank('questions.doctorlard.en')
|
|
for q in qb.questions:
|
|
print(q.question)
|
|
a = unicode(raw_input('A: '), 'utf8')
|
|
#a = input('A: ') # Python 3
|
|
if a.lower() == q.answer.lower():
|
|
print("Correct!")
|
|
else:
|
|
print("Incorrect - the answer is '%s'" % q.answer)
|