Skip to content
This repository was archived by the owner on Feb 5, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/flindt/integrations/providers/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
60 changes: 39 additions & 21 deletions backend/flindt/round/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -26,7 +27,6 @@ class NoSolutionFound(Exception):
class NoSolutionPossible(Exception):
pass


class UserInformationNotComplete(Exception):
def __init__(self, data):
super(Exception, self).__init__()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not needed here. If you run into an error, please put it on the more appropiate place. This function simply returns all users without a slack id, but it does not connect to Slack in any way. So DRY_RUN should only be used on places where actual Slack communication is used.

return []
receivers = self.round.participants_receivers.all()
senders = self.round.participants_senders.all()

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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()):
Expand Down Expand Up @@ -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] = []
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use set() for this.


senders = self._get_senders_for_user(feedback.recipient)

users_done = self.users_have_given_feedback_on_individual.copy()
Expand All @@ -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:
Expand All @@ -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 recipient {} to sender {}".format(feedback.recipient, feedback.sender))