Esempio n. 1
0
    def create_update(self, user, indicator, action_date, value, is_skip, answer=None): 
        'Creates and returns a new Answer with the given parameters, or updates the given one'
        
        is_new_answer = False

        if not answer:
            try:
                answer = self.get(
                              user = user, 
                              indicator_id = indicator.id,
                              indicator_content_type = ContentType.objects.get_for_model(indicator),
                              action_date = action_date
                              )
                
            except Answer.DoesNotExist:
                answer = Answer(user = user, 
                                action_date = action_date,
                                is_skip = is_skip)
                answer.indicator = indicator
                is_new_answer = True
        
        if is_skip:
            answer.answer_num = None
        else:
            answer.answer_num = int( value )
        
        answer.is_skip = is_skip
        answer.save()
        
        if is_new_answer:
            user.add_participation_points()
        
        try:
            Indicator.objects.next(user, indicator.campaign)
            is_last_indicator = False
        except Indicator.DoesNotExist:
            is_last_indicator = True

        if not is_skip:
            if is_last_indicator:
                # Worker won't have time before results screen comes up
                answer.update_averages()
            else:
                # Usual case, do out-of-band for performance
                messaging.send(messaging.SUBJECT_AVG, answer.id)

        return answer
Esempio n. 2
0
    def answers_with_average(self, from_user_or_group, to_user_or_group):
        """ Data for graphing.
        Tuple of four values, each one is a list of [date, value]:
        - from_data: From User or Group's answers to this indicator.
        - to_data: The To Users or Group's answers to this indicator.
        - from_avgs: Time average of from User or Group's answers
        - to_avgs: Time average of to User or Group's answers.
        """

        def userize(user_or_group):
            """Takes a Profile or Group and returns a Profile.
            If given a Group, returns the system user that owns that groups averages"""

            if isinstance(user_or_group, Profile):
                return user_or_group

            elif isinstance(user_or_group, Group):
                return user_or_group.avg_user

            else:
                return None

        from_user = userize(from_user_or_group)
        to_user = userize(to_user_or_group)

        my_answers_iter = Answer.objects.by_indicator(from_user, self)
        my_answers = answer_map_by_date(my_answers_iter)
                
        average_answers_iter = Answer.objects.by_indicator(to_user, self)
        average_answers = answer_map_by_date(average_answers_iter) 

        my_avgs = self._aggregate_averages(my_answers_iter)
        average_avgs = self._aggregate_averages(average_answers_iter)

        for action_date in my_answers.keys():
            # This can happen if the back-end worker fell over or is slow
            if not action_date in average_answers:
                my_ans = Answer.objects.get(
                        action_date=action_date, 
                        user=from_user, 
                        indicator_id=self.id)
                messaging.send(messaging.SUBJECT_AVG, my_ans.id)
                # No value for avg yet, so pretend avg has same value as user
                average_answers[action_date] = my_ans.num_value
                average_avgs[action_date] = my_ans.num_value

        answers = []
        for action_date, average_value in average_answers.items():
            me_value = my_answers[action_date] if action_date in my_answers else None
            my_avg = my_avgs[action_date] if action_date in my_avgs else None 
                
            answers.append(
                    (action_date, 
                    me_value, 
                    average_value, 
                    my_avg, 
                    average_avgs[action_date]
                    )
                )
         
        answers.sort(key = lambda x: x[0])    # Sort by action_date        

        me_data, average_data, me_avgs, average_avgs = [], [], [], []
        for action_date, me_value, average_value, me_avg, average_avg in answers:
            
            if me_value or me_value == 0:
                me_data.append( [action_date, me_value] )
            if average_value or average_value == 0:
                average_data.append( [action_date, average_value] )
            
            if me_avg or me_avg == 0:
                me_avgs.append( [action_date, me_avg] )
            if average_avg or average_avg == 0:
                average_avgs.append( [action_date, average_avg] )

        return (me_data, average_data, me_avgs, average_avgs)