diff --git a/knowledge/survey/README.txt b/knowledge/survey/README.txt new file mode 100644 index 0000000..25a6c47 --- /dev/null +++ b/knowledge/survey/README.txt @@ -0,0 +1,41 @@ +========================== +Surveys and Questionnaires +========================== + +Let's first set up a questionaire. + + >>> from cybertools.knowledge.survey.questionnaire import Questionnaire, Question + >>> quest = Questionnaire() + + >>> qu01 = Question(quest) + >>> qu02 = Question(quest) + >>> qu03 = Question(quest) + +We now assign result elements with the questions of this questionnaire. + + >>> from cybertools.knowledge.survey.questionnaire import ResultElement + >>> re01 = ResultElement('re01') + >>> re02 = ResultElement('re02') + >>> re03 = ResultElement('re03') + + >>> qu01.resultElements = {re01: 0.8, re03: 0.2} + >>> qu02.resultElements = {re01: 0.3, re02: 0.7, re03: 0.1} + >>> qu03.resultElements = {re01: 0.2, re03: 0.9} + + +Responses +--------- + + >>> from cybertools.knowledge.survey.questionnaire import Response + >>> resp01 = Response(quest, 'john') + + >>> resp01.values = {qu01: 2, qu02: 1, qu03: 4} + +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 diff --git a/knowledge/survey/__init__.py b/knowledge/survey/__init__.py new file mode 100644 index 0000000..7432a20 --- /dev/null +++ b/knowledge/survey/__init__.py @@ -0,0 +1 @@ +"package cybertools.composer.survey" diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py new file mode 100644 index 0000000..10abfd3 --- /dev/null +++ b/knowledge/survey/interfaces.py @@ -0,0 +1,73 @@ +# +# Copyright (c) 2013 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Interfaces for surveys. +""" + +from zope.interface import Interface, Attribute +from zope import schema +from zope.i18nmessageid import MessageFactory + +_ = MessageFactory('cybertools.knowledge') + + +class IQuestionnaire(Interface): + """ A collection of questions for setting up a survey. + """ + + questions = Attribute('An ordered collection of questions.') + responses = Attribute('A set of responses.') + defaultOptions = Attribute('A sequence of answer options to select from. ' + 'Default value used for questions that do not ' + 'explicitly provide the values attribute.') + + +class IQuestion(Interface): + """ A single question within a questionnaire. + """ + + text = Attribute('The question asked.') + questionnaire = Attribute('The questionnaire this question belongs to.') + options = Attribute('A sequence of answer options to select from.') + resultElements = Attribute('A mapping with result elements as keys and ' + 'corresponding relevance factors as values.') + + +class IResultElement(Interface): + """ Some text (e.g. a recommendation) or some other kind of information + that may be deduced from the res)ponses to a questionnaire. + """ + + text = Attribute('A text representing this result element.') + + +class IResponse(Interface): + """ A set of response values given to the questions of a questionnaire + by a single person or party. + """ + + questionnaire = Attribute('The questionnaire this response belongs to.') + party = Attribute('Some identification of the party that responded ' + 'to this questionnaire.') + values = Attribute('A mapping associating response values with questions.') + + def getResult(): + """ Calculate the result for this response. + """ + diff --git a/knowledge/survey/questionnaire.py b/knowledge/survey/questionnaire.py new file mode 100644 index 0000000..e54624f --- /dev/null +++ b/knowledge/survey/questionnaire.py @@ -0,0 +1,79 @@ +# +# Copyright (c) 2013 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +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 IResultElement, IResponse + + +class Questionnaire(object): + + implements(IQuestionnaire) + + def __init__(self): + self.questions = [] + self.responses = [] + self.defaultOptions = range(5) + + +class Question(object): + + implements(IQuestion) + + _options = None + + def __init__(self, questionnaire, text=u''): + self.questionnaire = questionnaire + self.resultElements = {} + self.text = text + + def getOptions(self): + return self._options or self.questionnaire.defaultOptions + def setOptions(self, value): + self._options = value + options = property(getOptions, setOptions) + + +class ResultElement(object): + + implements(IResultElement) + + def __init__(self, text=u''): + self.text = text + + +class Response(object): + + implements(IResponse) + + def __init__(self, questionnaire, party): + self.questionnaire = questionnaire + self.party = party + self.values = {} + + def getResult(self): + result = {} + for question, value in self.values.items(): + for re, rf in question.resultElements.items(): + result[re] = result.get(re, 0.0) + rf * value + #print re.text, rf, value + return sorted(result.items(), key=lambda x: -x[1]) diff --git a/knowledge/survey/tests.py b/knowledge/survey/tests.py new file mode 100644 index 0000000..5cf6d0d --- /dev/null +++ b/knowledge/survey/tests.py @@ -0,0 +1,27 @@ +#! /usr/bin/python + +""" +Tests for the 'cybertools.knowledge.survey' package. +""" + +import unittest, doctest +from zope.testing.doctestunit import DocFileSuite +from cybertools.knowledge.knowing import Knowing + + +class TestSurvey(unittest.TestCase): + "Basic tests for the survey package." + + def testBasicStuff(self): + p = Knowing() + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + return unittest.TestSuite(( + unittest.makeSuite(TestSurvey), + DocFileSuite('README.txt', optionflags=flags), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite')