diff --git a/knowledge/survey/README.txt b/knowledge/survey/README.txt index 317411f..9c4e0a9 100644 --- a/knowledge/survey/README.txt +++ b/knowledge/survey/README.txt @@ -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 diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py index ed7da20..08337b3 100644 --- a/knowledge/survey/interfaces.py +++ b/knowledge/survey/interfaces.py @@ -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. + """ diff --git a/knowledge/survey/questionnaire.py b/knowledge/survey/questionnaire.py index b30c780..b7d9417 100644 --- a/knowledge/survey/questionnaire.py +++ b/knowledge/survey/questionnaire.py @@ -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