示例#1
0
def execute_the_todo_list(study=None, user=None):
    """Create list of Observations due and do() them"""
    from signalbox.models.observation_timing_functions import observations_due_in_window

    todo = observations_due_in_window()

    if study:
        todo = [x for x in todo if supergetattr(x, 'dyad.study', None) == study]

    if user:
        todo = [x for x in todo if supergetattr(x, 'dyad.user', None) == user]

    return [(i, i.do()) for i in todo]
示例#2
0
def execute_the_todo_list(study=None, user=None):
    """Create list of Observations due and do() them"""
    from signalbox.models.observation_timing_functions import observations_due_in_window

    todo = observations_due_in_window()

    if study:
        todo = [
            x for x in todo if supergetattr(x, 'dyad.study', None) == study
        ]

    if user:
        todo = [x for x in todo if supergetattr(x, 'dyad.user', None) == user]

    return [(i, i.do()) for i in todo]
示例#3
0
    def display_text(self, reply=None, request=None):
        """
        :type reply: is_reply|None
        :type request: c|None

        :return: The html formatted string displaying the question
        :rtype: string
        """

        templ_header = r"""{% load humanize %}"""  # include these templatetags in render context
        templ = Template(templ_header + self.text)
        context = {
            'reply': reply,
            'user': supergetattr(reply, 'observation.dyad.user', default=None),
            'page': self.page,
            'scores': {},
            'answers': {},
            'answers_label': {}
        }

        fc = self.field_class()
        if reply and reply.asker and fc.compute_scores:
            context['scores'] = self.page.summary_scores(reply)
            # put actual values into main namespace too
            context.update({k: v.get('score', None) for k, v in context['scores'].items()})

        if fc.allow_showing_answers and reply:
            context['answers'] = {i.variable_name(): int_or_string(i.answer) for i in reply.answer_set.all()}

        for i in self.questionasset_set.all():
            context[i.slug] = unicode(i)

        return markdown.markdown(templ.render(Context(context)))
示例#4
0
    def clean(self):
        super(ShowIf, self).clean()

        if self.values and supergetattr(self, 'previous_question.choices',
                                        None):
            possibles = set(
                self.previous_question.choiceset.allowed_responses())
            vals = set(
                filter(bool, list(map(valid.is_int, self.values.split(",")))))
            if not vals.issubset(possibles):
                raise ValidationError(
                    """Valid choices for the selected question are: %s""" %
                    ("; ".join(map(str, possibles)), ))

        if self.previous_question and self.summary_score:
            raise ValidationError(
                """You can hide/show this item based on a previous question value
            or a summary score, but not both.""")

        if self.values and (self.less_than or self.more_than):
            raise ValidationError(
                """You can either specify a range using the more_than and
            less_than fields, or exact values, but not both.""")

        if not self.values and not (self.less_than or self.more_than):
            raise ValidationError(
                """Please specify a list of values to match, or a range.""")
示例#5
0
 def dict_for_yaml(self):
     d = {
         "text": self.text,
         "q_type": self.q_type,
         "choiceset": supergetattr(self, "choiceset.name", None),
         "required": self.required,
     }
     return {self.variable_name: {k: v for k, v in list(d.items()) if v}}
示例#6
0
 def dict_for_yaml(self):
     d = {
         "text": self.text,
         "q_type": self.q_type,
         "choiceset": supergetattr(self, "choiceset.name", None),
         "required": self.required,
     }
     return {self.variable_name: {k: v for k, v in d.items() if v}}
示例#7
0
    def get_value_for_export(self):
        """Pre-process the answer in preparation for exporting as csv etc.

        The processing which occurs will depend on the field type and the methods
        described in ask.fields.
        """
        class_name = fields.class_name(supergetattr(self, 'question.q_type', ""))
        processor = getattr(getattr(fields, class_name), 'export_processor')
        return processor(self.answer)
示例#8
0
    def display_text(self, reply=None, request=None):
        """
        :type reply: is_reply|None
        :type request: c|None

        :return: The html formatted string displaying the question
        :rtype: string
        """

        templ_header = r"""{% load humanize %}{% load mathfilters %}"""  # include these templatetags
        # in render context
        templ = Template(templ_header + self.text)
        context = {
            'reply': reply,
            'condition': supergetattr(reply, "observation.dyad.condition"),
            'user': supergetattr(reply, 'observation.dyad.user', default=None),
            'page': self.page,
            'scores': {},
            'answers': defaultdict(None),
            'answers_label': {}
        }

        fc = self.field_class()
        if reply and reply.asker and fc.compute_scores:
            context['scores'] = self.page.summary_scores(reply)
            # put actual values into main namespace too
            context.update({
                k: v.get('score', None)
                for k, v in list(context['scores'].items())
            })

        if fc.allow_showing_answers and reply:
            context['answers'] = {
                i.variable_name(): int_or_string(i.answer)
                for i in reply.answer_set.all()
            }

        for i in self.questionasset_set.all():
            context[i.slug] = str(i)
        from django.template.base import VariableDoesNotExist
        try:
            return markdown.markdown(templ.render(Context(context)))
        except VariableDoesNotExist:
            return markdown.markdown(self.text)
示例#9
0
    def get_value_for_export(self):
        """Pre-process the answer in preparation for exporting as csv etc.

        The processing which occurs will depend on the field type and the methods
        described in ask.fields.
        """
        class_name = fields.class_name(
            supergetattr(self, 'question.q_type', ""))
        processor = getattr(getattr(fields, class_name), 'export_processor')
        return processor(self.answer)
示例#10
0
    def finish(self, request):
        """Questionnaire is complete, so finish up."""

        mess = supergetattr(self, "asker.success_message", None)
        mess and messages.add_message(request, messages.SUCCESS, mess)

        if self.observation:
            self.observation.status = 1
            self.observation.save()

        self.complete = True
        self.save()
示例#11
0
    def mapping_of_answers_and_scores(self):
        """
        Create a mapping of all answers and summary scores in this Reply
        :rtype: dict
        """

        mapping = {
            supergetattr(i, 'question.variable_name', i.other_variable_name): i.answer
            for i in self.answer_set.all()
        }
        mapping.update({k: v.get('score', None) for k, v in self.asker.summary_scores(self).items()})
        return mapping
示例#12
0
    def finish(self, request):
        """Questionnaire is complete, so finish up."""

        mess = supergetattr(self, "asker.success_message", None)
        mess and messages.add_message(request, messages.SUCCESS, mess)

        if self.observation:
            self.observation.status = 1
            self.observation.save()

        self.complete = True
        self.save()
        sbox_anonymous_reply_complete.send(sender=self.__class__,
                                           reply=self,
                                           request=request,
                                           dispatch_uid="reply_finished")
示例#13
0
    def mapping_of_answers_and_scores(self):
        """
        Create a mapping of all answers and summary scores in this Reply
        :rtype: dict
        """

        mapping = {
            supergetattr(i, 'question.variable_name', i.other_variable_name):
            i.answer
            for i in self.answer_set.all()
        }
        mapping.update({
            k: v.get('score', None)
            for k, v in list(self.asker.summary_scores(self).items())
        })
        return mapping
示例#14
0
    def json_export(self):
        """Export Asker and related objects as json.

        Export everything needed to recreate this questionnaire on
        another signalbox instance (or 3rd party system) with the
        exception of question assets."""

        _asdict = lambda object, fields: {
            i: str(supergetattr(object, i))
            for i in fields
        }

        pages = self.askpage_set.all()
        questionlists = [i.get_questions() for i in pages]
        questions = list(itertools.chain(*questionlists))

        choicesets = set([i.choiceset for i in questions if i.choiceset])
        choices = Choice.objects.filter(choiceset__in=choicesets)

        QUESTION_FIELDS = ('natural_key', 'variable_name', 'order', 'required',
                           'help_text', 'text', 'choiceset.pk', 'q_type',
                           'showif')
        CHOICESET_FIELDS = ('natural_key', 'name')
        CHOICE_FIELDS = ('choiceset.natural_key', 'is_default_value', 'order',
                         'label', 'score')

        qdicts = [_asdict(i, QUESTION_FIELDS) for i in questions]
        # give a consistent ordering to everything
        [d.update({'order': i}) for i, d in enumerate(qdicts)]

        output = {
            'meta': {
                'name': self.slug,
                'show_progress': self.show_progress,
                'generated': str(datetime.now()),
            },
            'questions': qdicts,
            'choicesets': [_asdict(i, CHOICESET_FIELDS) for i in choicesets],
            'choices': [_asdict(i, CHOICE_FIELDS) for i in choices],
            'scoresheets':
            [i.as_simplified_dict() for i in self.scoresheets()]
        }

        jsonstring = json.dumps(output, indent=4)

        return "{}".format(jsonstring)
示例#15
0
    def finish(self, request):
        """Questionnaire is complete, so finish up."""

        mess = supergetattr(self, "asker.success_message", None)
        mess and messages.add_message(request, messages.SUCCESS, mess)

        if self.observation:
            self.observation.status = 1
            self.observation.save()

        self.complete = True
        self.save()
        sbox_anonymous_reply_complete.send(
            sender=self.__class__, 
            reply=self,  
            request=request,
            dispatch_uid="reply_finished")
示例#16
0
    def clean(self):
        if self.asker and self.external_asker_url:
            raise ValidationError("""You can't use both an internal
                                    Questionnaire and one hosted on an external site.""")

        if self.asker and supergetattr(self, "script_type.require_study_ivr_number", False):
            last_q = self.asker.questions()[-1]
            if last_q.q_type != "hangup":
                raise ValidationError("The last question of a telephone call needs to be a 'hangup' type (currently {})".format(last_q.q_type))


        try:
            if len(self.script_body) > 160 and self.script_type.name == "TwilioSMS":
                raise ValidationError(
                    "Messages must be < 160 characters long.")
        except AttributeError:
            raise
示例#17
0
    def clean(self):
        super(ShowIf, self).clean()

        if self.values and supergetattr(self, 'previous_question.choices', None):
            possibles = set(self.previous_question.choiceset.allowed_responses())
            vals = set(filter(bool, map(valid.is_int, self.values.split(","))))
            if not vals.issubset(possibles):
                raise ValidationError("""Valid choices for the selected question are: %s""" % (
                    "; ".join(map(str, possibles)), ))

        if self.previous_question and self.summary_score:
            raise ValidationError("""You can hide/show this item based on a previous question value
            or a summary score, but not both.""")

        if self.values and (self.less_than or self.more_than):
            raise ValidationError("""You can either specify a range using the more_than and
            less_than fields, or exact values, but not both.""")

        if not self.values and not (self.less_than or self.more_than):
            raise ValidationError(
                """Please specify a list of values to match, or a range.""")
示例#18
0
    def clean(self):
        if self.asker and self.external_asker_url:
            raise ValidationError("""You can't use both an internal
                                    Questionnaire and one hosted on an external site."""
                                  )

        if self.asker and supergetattr(
                self, "script_type.require_study_ivr_number", False):
            last_q = self.asker.questions()[-1]
            if last_q.q_type != "hangup":
                raise ValidationError(
                    "The last question of a telephone call needs to be a 'hangup' type (currently {})"
                    .format(last_q.q_type))

        try:
            if len(self.script_body
                   ) > 160 and self.script_type.name == "TwilioSMS":
                raise ValidationError(
                    "Messages must be < 160 characters long.")
        except AttributeError:
            raise
示例#19
0
    def json_export(self):
        """Export Asker and related objects as json.

        Export everything needed to recreate this questionnaire on
        another signalbox instance (or 3rd party system) with the
        exception of question assets."""

        _asdict = lambda object, fields: {i: str(supergetattr(object, i)) for i in fields}

        pages = self.askpage_set.all()
        questionlists = [i.get_questions() for i in pages]
        questions = list(itertools.chain(*questionlists))

        choicesets = set([i.choiceset for i in questions if i.choiceset])
        choices = Choice.objects.filter(choiceset__in=choicesets)

        QUESTION_FIELDS = ('natural_key', 'variable_name', 'order', 'required',
                           'help_text', 'text', 'choiceset.pk', 'q_type', 'showif')
        CHOICESET_FIELDS = ('natural_key', 'name')
        CHOICE_FIELDS = ('choiceset.natural_key', 'is_default_value', 'order',
                         'label', 'score')

        qdicts = [_asdict(i, QUESTION_FIELDS) for i in questions]
        # give a consistent ordering to everything
        [d.update({'order': i}) for i, d in enumerate(qdicts)]

        output = {
            'meta': {'name': self.slug,
                     'show_progress': self.show_progress,
                     'generated': str(datetime.now()),
                     },
            'questions': qdicts,
            'choicesets': [_asdict(i, CHOICESET_FIELDS) for i in choicesets],
            'choices': [_asdict(i, CHOICE_FIELDS) for i in choices],
            'scoresheets': [i.as_simplified_dict() for i in self.scoresheets()]
        }

        jsonstring = json.dumps(output, indent=4)

        return "{}".format(jsonstring)
示例#20
0
 def __unicode__(self):
     return smart_text("{} (page {}): {}".format(
         self.variable_name(),
         supergetattr(self, "page.id", None),
         smart_text(self.answer)[:80])
     )
示例#21
0
 def __unicode__(self):
     return smart_text("{} (page {}): {}".format(
         self.variable_name(), supergetattr(self, "page.id", None),
         smart_text(self.answer)[:80]))
示例#22
0
 def mapped_score(self):
     """Return mapped score; leave answer unchanged if no map found."""
     possiblechoices = supergetattr(self, 'question.choiceset.get_choices',
                                    ())
     score_maptos = {i.score: i.mapped_score for i in possiblechoices}
     return score_maptos.get(self.answer, self.answer)
示例#23
0
 def redirect_url(self):
     return self.redirect_to or \
         supergetattr(self, "created_by_script.asker.redirect_url", None) or reverse('user_homepage')
示例#24
0
 def participant(self):
     """Return the user to whom the answer relates (maybe not the user who entered it)."""
     return supergetattr(self, "reply.observation.dyad.user", None)
示例#25
0
    def study(self):
        """Return the study this Answer was made in response to."""

        return supergetattr(self, "reply.observation.dyad.study", None)
示例#26
0
 def redirect_url(self):
     return self.redirect_to or \
         supergetattr(self, "created_by_script.asker.redirect_url", None) or reverse('user_homepage')
示例#27
0
    def study(self):
        """Return the study this Answer was made in response to."""

        return supergetattr(self, "reply.observation.dyad.study", None)
示例#28
0
 def participant(self):
     """Return the user to whom the answer relates (maybe not the user who entered it)."""
     return supergetattr(self, "reply.observation.dyad.user", None)
示例#29
0
 def mapped_score(self):
     """Return mapped score; leave answer unchanged if no map found."""
     possiblechoices = supergetattr(self, 'question.choiceset.get_choices', ())
     score_maptos = {i.score: i.mapped_score for i in possiblechoices}
     return score_maptos.get(self.answer, self.answer)