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) >>> qu02 = Question(quest)
>>> qu03 = Question(quest) >>> qu03 = Question(quest)
Question-related Feedback Items
===============================
We now assign result elements with the questions of this questionnaire. We now assign result elements with the questions of this questionnaire.
>>> from cybertools.knowledge.survey.questionnaire import FeedbackItem >>> from cybertools.knowledge.survey.questionnaire import FeedbackItem
>>> re01 = FeedbackItem('re01') >>> fi01 = FeedbackItem('fi01')
>>> re02 = FeedbackItem('re02') >>> fi02 = FeedbackItem('fi02')
>>> re03 = FeedbackItem('re03') >>> fi03 = FeedbackItem('fi03')
>>> qu01.feedbackItems = {re01: 0.8, re03: 0.2} >>> qu01.feedbackItems = {fi01: 0.8, fi03: 0.2}
>>> qu02.feedbackItems = {re01: 0.3, re02: 0.7, re03: 0.1} >>> qu02.feedbackItems = {fi01: 0.3, fi02: 0.7, fi03: 0.1}
>>> qu03.feedbackItems = {re01: 0.2, re03: 0.9} >>> qu03.feedbackItems = {fi01: 0.2, fi03: 0.9}
Responses Responses
@ -34,8 +38,23 @@ Responses
Now let's calculate the result for resp01. Now let's calculate the result for resp01.
>>> res = resp01.getResult() >>> res = resp01.getResult()
>>> for re, score in res: >>> for fi, score in res:
... print re.text, score ... print fi.text, score
re03 4.1 fi03 4.1
re01 2.7 fi01 2.7
re02 0.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.') questions = Attribute('An ordered collection of questions.')
questionGroups = Attribute('An ordered collection of question groups (optional).')
responses = Attribute('A set of responses.') responses = Attribute('A set of responses.')
defaultAnswerOptions = Attribute('A sequence of answer options to select from. ' defaultAnswerOptions = Attribute('A sequence of answer options to select from. '
'Default value used for questions that do not ' 'Default value used for questions that do not '
'explicitly provide the values attribute.') '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): class IQuestion(Interface):
""" A single question within a questionnaire. """ A single question within a questionnaire.
""" """
@ -47,6 +60,8 @@ class IQuestion(Interface):
answerOptions = Attribute('A sequence of answer options to select from.') answerOptions = Attribute('A sequence of answer options to select from.')
feedbackItems = Attribute('A mapping with feedback items as keys and ' 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): class IFeedbackItem(Interface):
@ -71,3 +86,6 @@ class IResponse(Interface):
""" Calculate the result for this response. """ 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 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 from cybertools.knowledge.survey.interfaces import IFeedbackItem, IResponse
@ -30,24 +31,40 @@ class Questionnaire(object):
implements(IQuestionnaire) implements(IQuestionnaire)
def __init__(self): def __init__(self):
self.questionGroups = []
self.questions = [] self.questions = []
self.responses = [] self.responses = []
self.defaultAnswerOptions = range(5) self.defaultAnswerOptions = range(5)
class QuestionGroup(object):
implements(IQuestionGroup)
def __init__(self, questionnaire):
self.questionnaire = questionnaire
self.questions = []
self.feedbackItems = []
class Question(object): class Question(object):
implements(IQuestion) implements(IQuestion)
_answerOptions = None _answerOptions = None
revertAnswerOptions = False
def __init__(self, questionnaire, text=u''): def __init__(self, questionnaire, text=u''):
self.questionnaire = questionnaire self.questionnaire = questionnaire
self.feedbackItems = {} self.feedbackItems = {}
self.text = text self.text = text
def getAnswerOptions(self): 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): def setAnswerOptions(self, value):
self._answerOptions = value self._answerOptions = value
answerOptions = property(getAnswerOptions, setAnswerOptions) answerOptions = property(getAnswerOptions, setAnswerOptions)
@ -75,5 +92,16 @@ class Response(object):
for question, value in self.values.items(): for question, value in self.values.items():
for fi, rf in question.feedbackItems.items(): for fi, rf in question.feedbackItems.items():
result[fi] = result.get(fi, 0.0) + rf * value result[fi] = result.get(fi, 0.0) + rf * value
#print re.text, rf, value
return sorted(result.items(), key=lambda x: -x[1]) 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