From 2248551f9ff051734285ebb787b0bff497cfd037 Mon Sep 17 00:00:00 2001 From: Redmer Loen Date: Mon, 29 Oct 2018 13:33:45 +0100 Subject: [PATCH] FEED-206: Fixed that there are no duplicate individual feedback requests are made --- .../flindt/integrations/providers/slack.py | 2 +- backend/flindt/round/manager.py | 60 ++++++++++++------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/backend/flindt/integrations/providers/slack.py b/backend/flindt/integrations/providers/slack.py index da02a923..cd17aacf 100644 --- a/backend/flindt/integrations/providers/slack.py +++ b/backend/flindt/integrations/providers/slack.py @@ -27,7 +27,7 @@ def send_message(self, message): try: if not settings.SILENT_RUN: self.slacker.chat.post_message(self.user.slack_user_name, message, as_user='@flindt') - logger.info('Slack send to {}.'.format(self.user.slack_user_name)) + logger.info('Slack send to {} ({}).'.format(self.user.email, self.user.slack_user_name)) except Error as e: from flindt.round.manager import IntegrationError raise IntegrationError('Slack error "{}" for user "{}"'.format(e, self.user)) diff --git a/backend/flindt/round/manager.py b/backend/flindt/round/manager.py index 7a861610..fd414c82 100644 --- a/backend/flindt/round/manager.py +++ b/backend/flindt/round/manager.py @@ -5,6 +5,7 @@ from django.utils import timezone +from flindt import settings from flindt.feedback.models import (Feedback, FeedbackOnIndividual, FeedbackOnRole) from flindt.user.models import User @@ -26,7 +27,6 @@ class NoSolutionFound(Exception): class NoSolutionPossible(Exception): pass - class UserInformationNotComplete(Exception): def __init__(self, data): super(Exception, self).__init__() @@ -70,6 +70,8 @@ def __init__(self, _round): # Will increase if no solution can be found. self.max_reviews_per_user = 0 + self.already_received_individual_feedback_by_user = {} + def start_round(self): """ This will try to create feedback objects for every receiver and sender @@ -153,6 +155,8 @@ def do_all_users_have_a_role(self): return users_without_role def do_all_users_have_a_slack_id(self): + if settings.SILENT_RUN: + return [] receivers = self.round.participants_receivers.all() senders = self.round.participants_senders.all() @@ -226,6 +230,7 @@ def _create_individual_feedback_for_participants(self): for i in range(self.round.individuals_to_review): for participant in self.round.participants_receivers.all(): + logger.info('Creating individual feedback for user: {}'.format(participant)) question = self.round.question_for_individual_feedback individual = FeedbackOnIndividual(question=question) feedback = Feedback( @@ -339,6 +344,7 @@ def _match_role_feedback_to_senders(self, feedbacks): senders.remove(feedback.recipient.id) users_done = self.users_have_given_feedback_on_role.copy() + # From the list of users that have given feedback, remove the users # that have given the maximum number of reviews. for key, count in dropwhile(lambda user: user[1] >= self.max_reviews_per_user, users_done.most_common()): @@ -403,6 +409,9 @@ def _match_individual_feedback_to_senders(self, feedbacks): # Get first object from the list. feedback = feedbacks[0] + if feedback.recipient.id not in self.already_received_individual_feedback_by_user: + self.already_received_individual_feedback_by_user[feedback.recipient.id] = [] + senders = self._get_senders_for_user(feedback.recipient) users_done = self.users_have_given_feedback_on_individual.copy() @@ -419,27 +428,34 @@ def _match_individual_feedback_to_senders(self, feedbacks): for sender in senders: matched_sender = sender - self.users_have_given_feedback_on_individual[sender] += 1 - - try: - self.tries += 1 - self.counter += 1 - self.max_depth = max(self.counter, self.max_depth) - if self.tries % 10000 == 0: - logger.info( - '(tries: {}, max depth: {}) counter: {}{}'.format( - self.tries, self.max_depth, self.counter * '#', ' ' * 100 - ) - ) - # Use the feedbacks objects from 1 and higher to prevent using the same object - # over and over again. - self._match_individual_feedback_to_senders(feedbacks[1:]) - except MatchNotFoundError: - self.counter -= 1 - self.users_have_given_feedback_on_individual[sender] -= 1 - matched_sender = None + # Check if the matched_sender already is giving individual feedback + # to the user, to prevent duplicate individual feedback requests. + if matched_sender in self.already_received_individual_feedback_by_user[feedback.recipient.id]: + logger.info("Sender: {} already giving individual feedback to user. {}".format(matched_sender, feedback.recipient.id)) else: - break + logger.info("User {} matched to {} for individual feedback.".format(matched_sender, feedback.recipient.id)) + self.already_received_individual_feedback_by_user[feedback.recipient.id].append(matched_sender) + self.users_have_given_feedback_on_individual[sender] += 1 + + try: + self.tries += 1 + self.counter += 1 + self.max_depth = max(self.counter, self.max_depth) + if self.tries % 10000 == 0: + logger.info( + '(tries: {}, max depth: {}) counter: {}{}'.format( + self.tries, self.max_depth, self.counter * '#', ' ' * 100 + ) + ) + # Use the feedbacks objects from 1 and higher to prevent using the same object + # over and over again. + self._match_individual_feedback_to_senders(feedbacks[1:]) + except MatchNotFoundError: + self.counter -= 1 + self.users_have_given_feedback_on_individual[sender] -= 1 + matched_sender = None + else: + break if not matched_sender: if self.tries >= 10000: @@ -452,3 +468,5 @@ def _match_individual_feedback_to_senders(self, feedbacks): feedback.individual = feedback.individual feedback.sender_id = matched_sender feedback.save() + + logger.info("Matching recepient {} to sender {}".format(feedback.recipient, feedback.sender))