Initial commit, questionhandling
This commit is contained in:
commit
9d176a206d
|
@ -0,0 +1,6 @@
|
||||||
|
.*.swp
|
||||||
|
.*.swo
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*~
|
||||||
|
*.o
|
|
@ -0,0 +1,96 @@
|
||||||
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
class QuestionException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Questions(object):
|
||||||
|
QUESTION_TYPES = ["Text", "Image", "Music"]
|
||||||
|
QUESTION_KEYS = ["Name", "Question", "Answer", "Type", "Double-Jeopardy"]
|
||||||
|
def __init__(self, qfile):
|
||||||
|
self.qfile = qfile
|
||||||
|
self._questions = None
|
||||||
|
self._read_questions()
|
||||||
|
|
||||||
|
def get_sections(self):
|
||||||
|
return [s["Section"] for s in self._questions]
|
||||||
|
|
||||||
|
def get_questions(self, section):
|
||||||
|
sec = filter(lambda s: s["Section"] == section, self._questions)
|
||||||
|
if len(sec) < 1:
|
||||||
|
raise ValueError("Section %s does not exist" % (section,))
|
||||||
|
return sec[0]["Questions"]
|
||||||
|
|
||||||
|
def get_question(self, section, question):
|
||||||
|
if type(question) != int or question < 1 or question > 5:
|
||||||
|
raise ValueError("question parameter needs to be an integer between 1 and 5")
|
||||||
|
return self.get_questions(section)[question-1]
|
||||||
|
|
||||||
|
def _read_questions(self):
|
||||||
|
f = None
|
||||||
|
|
||||||
|
# open file
|
||||||
|
try:
|
||||||
|
f = open(self.qfile)
|
||||||
|
except OSError as e:
|
||||||
|
raise QuestionException("Could not read question file: %s" % e)
|
||||||
|
|
||||||
|
# load yaml
|
||||||
|
ysrc = None
|
||||||
|
try:
|
||||||
|
ysrc = yaml.load(f.read())
|
||||||
|
except Exception as e:
|
||||||
|
raise QuestionException("Error parsing question file %s: %s" % (self.qfile, e))
|
||||||
|
|
||||||
|
# now to check the integrity of the question file
|
||||||
|
if type(ysrc) is not list:
|
||||||
|
raise QuestionException("The questionfile has to be a list of question")
|
||||||
|
|
||||||
|
for i, sec in enumerate(ysrc, 1):
|
||||||
|
if not "Section" in sec.keys() or not "Questions" in sec.keys():
|
||||||
|
raise QuestionException("Section %d needs to have the keys 'Section' and 'Question' (case-sensitive)" % i)
|
||||||
|
|
||||||
|
for j, q in enumerate(sec["Questions"], 1):
|
||||||
|
# check for keys we need in each question
|
||||||
|
if any([x not in q.keys() for x in ["Question", "Answer", "Type"]]):
|
||||||
|
raise QuestionException("Question %d from section %d (%s) is missing one of the keywords Question, Answer or Type" % (j, i, sec["Section"]))
|
||||||
|
|
||||||
|
# check for keys we do not know
|
||||||
|
for key in q.keys():
|
||||||
|
if key not in self.QUESTION_KEYS:
|
||||||
|
raise QuestionException("Qestion %d from section %d (%s) has invalid keyword '%s'" % (j, i, sec["Section"], key))
|
||||||
|
|
||||||
|
# check Double-Jeopardy is a bool and is set to false it non-existant
|
||||||
|
if "Double-Jeopardy" not in q.keys():
|
||||||
|
q["Double-Jeopardy"] = False
|
||||||
|
elif type(q["Double-Jeopardy"]) != bool:
|
||||||
|
raise QuestionException("The Double-Jeopardy key from question %d from section %d (%s) must be either true or false" % (j, i, sec["Section"]))
|
||||||
|
|
||||||
|
# check for broken question types
|
||||||
|
if q["Type"] not in self.QUESTION_TYPES:
|
||||||
|
raise QuestionException("Question %d from Section %d (%s) has an invalid type '%s' (valid types are %s)" % (j, i, sec["Section"], q["Type"], ", ".join(self.VALID_TYPES)))
|
||||||
|
|
||||||
|
# check if file for music/image questions exist
|
||||||
|
if q["Type"] in ("Music", "Image"):
|
||||||
|
if not os.path.isfile(q["Question"]):
|
||||||
|
raise QuestionException("File for question %d, section %d (%s) not found" % (j, i, sec["Section"]))
|
||||||
|
|
||||||
|
# check if this section has enough questions
|
||||||
|
if j != 5:
|
||||||
|
raise QuestionException("Section %d (%s) needs to have exactly %d questions (has %d)" % (i, sec["Section"], 5, j))
|
||||||
|
|
||||||
|
# check for only having unique section names
|
||||||
|
sections = [s["Section"] for s in self._questions]
|
||||||
|
if len(sections) != len(set(sections)):
|
||||||
|
raise QuestionException("All section names must be unique")
|
||||||
|
|
||||||
|
# done, save yaml src to _questions
|
||||||
|
self._questions = ysrc
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
q = Questions("questions/template.q")
|
||||||
|
print(q.get_sections())
|
||||||
|
print(q.get_questions("A"))
|
||||||
|
print(q.get_question("A", 1))
|
|
@ -0,0 +1,110 @@
|
||||||
|
- Section: A
|
||||||
|
Questions:
|
||||||
|
- Name: Question 1
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 2
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 3
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 4
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
Double-Jeopardy: true
|
||||||
|
|
||||||
|
- Name: Question 5
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Section: B
|
||||||
|
Questions:
|
||||||
|
- Name: Question 1
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 2
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 3
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 4
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 5
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
Double-Jeopardy: true
|
||||||
|
|
||||||
|
- Section: C
|
||||||
|
Questions:
|
||||||
|
- Name: Question 1
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 2
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 3
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 4
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 5
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Section: D
|
||||||
|
Questions:
|
||||||
|
- Name: Question 1
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 2
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 3
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 4
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
||||||
|
- Name: Question 5
|
||||||
|
Question: Foo.
|
||||||
|
Answer: Bar?
|
||||||
|
Type: Text
|
||||||
|
|
Loading…
Reference in New Issue