add alternative algorithm with grouped questions and feedback items per question group

This commit is contained in:
Helmut Merz 2013-02-24 11:10:44 +01:00
parent 4d9844391e
commit 6164b311a6
3 changed files with 80 additions and 15 deletions

View file

@ -11,16 +11,20 @@ Let's first set up a questionaire.
>>> qu02 = Question(quest)
>>> qu03 = Question(quest)
Question-related Feedback Items
===============================
We now assign result elements with the questions of this questionnaire.
>>> from cybertools.knowledge.survey.questionnaire import FeedbackItem
>>> re01 = FeedbackItem('re01')
>>> re02 = FeedbackItem('re02')
>>> re03 = FeedbackItem('re03')
>>> fi01 = FeedbackItem('fi01')
>>> fi02 = FeedbackItem('fi02')
>>> fi03 = FeedbackItem('fi03')
>>> qu01.feedbackItems = {re01: 0.8, re03: 0.2}
>>> qu02.feedbackItems = {re01: 0.3, re02: 0.7, re03: 0.1}
>>> qu03.feedbackItems = {re01: 0.2, re03: 0.9}
>>> qu01.feedbackItems = {fi01: 0.8, fi03: 0.2}
>>> qu02.feedbackItems = {fi01: 0.3, fi02: 0.7, fi03: 0.1}
>>> qu03.feedbackItems = {fi01: 0.2, fi03: 0.9}
Responses
@ -34,8 +38,23 @@ Responses
Now let's calculate the result for resp01.
>>> res = resp01.getResult()
>>> for re, score in res:
... print re.text, score
re03 4.1
re01 2.7
re02 0.7
>>> for fi, score in res:
... print fi.text, score
fi03 4.1
fi01 2.7
fi02 0.7
Grouped Feedback Items
======================
>>> from cybertools.knowledge.survey.questionnaire import QuestionGroup
>>> qugroup = QuestionGroup(quest)
>>> quest.questionGroups.append(qugroup)
>>> qugroup.questions = [qu01, qu02, qu03]
>>> qugroup.feedbackItems = [fi01, fi02, fi03]
>>> res = resp01.getGroupedResult()
>>> for fi, score in res:
... print fi.text, round(score, 2)
fi02 1.17

View file

@ -32,12 +32,25 @@ class IQuestionnaire(Interface):
"""
questions = Attribute('An ordered collection of questions.')
questionGroups = Attribute('An ordered collection of question groups (optional).')
responses = Attribute('A set of responses.')
defaultAnswerOptions = Attribute('A sequence of answer options to select from. '
'Default value used for questions that do not '
'explicitly provide the values attribute.')
class IQuestionGroup(Interface):
""" A group of questions within a questionnaire.
This may be used just for the presentation of questions or for
grouped feedback items.
"""
questionnaire = Attribute('The questionnaire this question belongs to.')
questions = Attribute('An ordered collection of questions.')
feedbackItems = Attribute('An ordered collection of feedback items.')
class IQuestion(Interface):
""" A single question within a questionnaire.
"""
@ -46,7 +59,9 @@ class IQuestion(Interface):
questionnaire = Attribute('The questionnaire this question belongs to.')
answerOptions = Attribute('A sequence of answer options to select from.')
feedbackItems = Attribute('A mapping with feedback items as keys and '
'corresponding relevance factors as values.')
'corresponding relevance factors as values.')
revertAnswerOptions = Attribute('Revert the sequence of answer '
'options internally so that a high selection gets a low score.')
class IFeedbackItem(Interface):
@ -71,3 +86,6 @@ class IResponse(Interface):
""" Calculate the result for this response.
"""
def getGroupedResult():
""" Calculate the result for a questionnaire with grouped feedback items.
"""

View file

@ -21,7 +21,8 @@ Questionnaires, questions and other stuff needed for surveys.
"""
from zope.interface import implements
from cybertools.knowledge.survey.interfaces import IQuestionnaire, IQuestion
from cybertools.knowledge.survey.interfaces import IQuestionnaire
from cybertools.knowledge.survey.interfaces import IQuestionGroup, IQuestion
from cybertools.knowledge.survey.interfaces import IFeedbackItem, IResponse
@ -30,16 +31,29 @@ class Questionnaire(object):
implements(IQuestionnaire)
def __init__(self):
self.questionGroups = []
self.questions = []
self.responses = []
self.defaultAnswerOptions = range(5)
class QuestionGroup(object):
implements(IQuestionGroup)
def __init__(self, questionnaire):
self.questionnaire = questionnaire
self.questions = []
self.feedbackItems = []
class Question(object):
implements(IQuestion)
_answerOptions = None
revertAnswerOptions = False
def __init__(self, questionnaire, text=u''):
self.questionnaire = questionnaire
@ -47,7 +61,10 @@ class Question(object):
self.text = text
def getAnswerOptions(self):
return self._answerOptions or self.questionnaire.defaultAnswerOptions
result = self._answerOptions or self.questionnaire.defaultAnswerOptions
if self.revertAnswerOptions:
result.reverse()
return result
def setAnswerOptions(self, value):
self._answerOptions = value
answerOptions = property(getAnswerOptions, setAnswerOptions)
@ -75,5 +92,16 @@ class Response(object):
for question, value in self.values.items():
for fi, rf in question.feedbackItems.items():
result[fi] = result.get(fi, 0.0) + rf * value
#print re.text, rf, value
return sorted(result.items(), key=lambda x: -x[1])
def getGroupedResult(self):
result = []
for qugroup in self.questionnaire.questionGroups:
score = scoreMax = 0.0
for qu in qugroup.questions:
score += self.values.get(qu, 0.0)
scoreMax += max(qu.answerOptions)
relScore = score / scoreMax
wScore = relScore * (len(qugroup.feedbackItems) - 1)
result.append((qugroup.feedbackItems[int(wScore)], wScore))
return result