def test_no_re_matches(minimal_database): pref_1 = SubscriptionDateTime( datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]).put() user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime) meeting_spec.put() users = [] num_users = 20 for i in range(0, num_users): user = User(email='{}@yelp.com'.format(i), metadata={'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref]) user.put() MeetingRequest(user=user.key, meeting_spec=meeting_spec.key).put() users.append(user) previous_meetings = { pair for pair in itertools.combinations([user.key.id() for user in users], 2) } previous_meetings = previous_meetings - { (users[0].key.id(), users[1].key.id()) } matches, unmatched = generate_meetings(users, meeting_spec, previous_meetings) assert len(unmatched) == num_users - 2 assert [(match[0].key.id(), match[1].key.id()) for match in matches] == [(users[0].key.id(), users[1].key.id())]
def test_generate_save_meetings(minimal_database, subscription): pref_1 = SubscriptionDateTime( datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]).put() user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() user1 = User(email='*****@*****.**', metadata={ 'department': 'dept' }, subscription_preferences=[user_pref]).put() user2 = User(email='*****@*****.**', metadata={ 'department': 'dept2' }, subscription_preferences=[user_pref]).put() meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime) meeting_spec.put() MeetingRequest(user=user1, meeting_spec=meeting_spec.key).put() MeetingRequest(user=user2, meeting_spec=meeting_spec.key).put() matches, unmatched = generate_meetings( [user1.get(), user2.get()], meeting_spec) save_meetings(matches, meeting_spec) assert unmatched == [] participants = [ participant.user for participant in MeetingParticipant.query().fetch() ] assert participants == [user1, user2]
def test_generate_group_meetings(): pref_1 = SubscriptionDateTime( datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]).put() user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() user1 = User(email='*****@*****.**', metadata={ 'department': 'dept' }, subscription_preferences=[user_pref]).put() user2 = User(email='*****@*****.**', metadata={ 'department': 'dept2' }, subscription_preferences=[user_pref]).put() user3 = User(email='*****@*****.**', metadata={ 'department': 'dept3' }, subscription_preferences=[user_pref]).put() meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime).put() meeting = Meeting(meeting_spec=meeting_spec, cancelled=False).put() MeetingParticipant(meeting=meeting, user=user3).put() MeetingParticipant(meeting=meeting, user=user2).put() MeetingParticipant(meeting=meeting, user=user1).put() matched, unmatched = generate_group_meetings( [user1.get(), user2.get(), user3.get()], meeting_spec.get(), 3, 10, 5) assert {user.key for user in matched[0]} == {user1, user2, user3} assert unmatched == []
def test_generate_meeting_specs(database): # delete current specs keys = [key for key in MeetingSpec.query().iter(keys_only=True)] ndb.delete_multi(keys) meeting_specs = MeetingSpec.query().fetch() assert len(meeting_specs) == 0 # ensure we create new specs generate_meeting_specs() meeting_specs = MeetingSpec.query().fetch() assert len(meeting_specs) == 2
def test_generate_group_meetings(session): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]) user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) user1 = User(email='*****@*****.**', meta_data={'department': 'dept'}, subscription_preferences=[user_pref]) user2 = User(email='*****@*****.**', meta_data={'department': 'dept2'}, subscription_preferences=[user_pref]) user3 = User(email='*****@*****.**', meta_data={'department': 'dept3'}, subscription_preferences=[user_pref]) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) meeting = Meeting(meeting_spec=meeting_spec, cancelled=False) mp1 = MeetingParticipant(meeting=meeting, user=user3) mp2 = MeetingParticipant(meeting=meeting, user=user2) mp3 = MeetingParticipant(meeting=meeting, user=user1) session.add(pref_1) session.add(subscription) session.add(user_pref) session.add(user1) session.add(user2) session.add(user3) session.add(meeting_spec) session.add(meeting) session.add(mp1) session.add(mp2) session.add(mp3) session.commit() matched, unmatched = generate_group_meetings([user1, user2, user3], meeting_spec, 3, 10, 5) assert {user for user in matched[0]} == {user1, user2, user3} assert unmatched == []
def test_get_previous_meetings(session): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]) user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) user1 = User(email='*****@*****.**', meta_data={'department': 'dept'}, subscription_preferences=[user_pref]) user2 = User(email='*****@*****.**', meta_data={'department': 'dept2'}, subscription_preferences=[user_pref]) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) meeting = Meeting(meeting_spec=meeting_spec, cancelled=False) mp1 = MeetingParticipant(meeting=meeting, user=user2) mp2 = MeetingParticipant(meeting=meeting, user=user1) session.add(pref_1) session.add(subscription) session.add(user_pref) session.add(user1) session.add(user2) session.add(meeting_spec) session.add(meeting) session.add(mp1) session.add(mp2) session.commit() assert get_previous_meetings(subscription) == set([(user1.id, user2.id)])
def test_get_previous_meetings(minimal_database): pref_1 = SubscriptionDateTime( datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]).put() user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() user1 = User(email='*****@*****.**', metadata={ 'department': 'dept' }, subscription_preferences=[user_pref]).put() user2 = User(email='*****@*****.**', metadata={ 'department': 'dept2' }, subscription_preferences=[user_pref]).put() meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime).put() meeting = Meeting(meeting_spec=meeting_spec, cancelled=False).put() MeetingParticipant(meeting=meeting, user=user2).put() MeetingParticipant(meeting=meeting, user=user1).put() assert get_previous_meetings() == set([(user1.id(), user2.id())])
def get_specs_from_subscription(subscription): specs = [] for subscription_datetime in subscription.datetime: subscription_tz = timezone(subscription.timezone) week_start = datetime.now(subscription_tz) - timedelta( days=datetime.now(subscription_tz).weekday()) week_start = week_start.replace(hour=0, minute=0, second=0, microsecond=0) subscription_dt = subscription_datetime.datetime.replace( tzinfo=utc).astimezone(subscription_tz) week_iter = week_start while week_iter.weekday() != subscription_dt.weekday(): week_iter += timedelta(days=1) meeting_datetime = week_iter.replace( hour=subscription_dt.hour, minute=subscription_dt.minute).astimezone(utc) specs.append( MeetingSpec(meeting_subscription=subscription, datetime=meeting_datetime)) return week_start, specs
def test_no_re_matches(session): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]) user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) session.add(pref_1) session.add(subscription) session.add(user_pref) session.add(meeting_spec) users = [] num_users = 20 for i in range(0, num_users): user = User(email='{}@yelp.com'.format(i), meta_data={ 'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref]) session.add(user) mr = MeetingRequest(user=user, meeting_spec=meeting_spec) session.add(mr) users.append(user) session.commit() previous_meetings = {pair for pair in itertools.combinations([user.id for user in users], 2)} previous_meetings = previous_meetings - {(users[0].id, users[1].id)} matches, unmatched = generate_meetings(users, meeting_spec, previous_meetings) assert len(unmatched) == num_users - 2 assert [(match[0].id, match[1].id) for match in matches] == [(users[0].id, users[1].id)]
def test_generate_group_meeting(session): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]) user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) session.add(pref_1) session.add(subscription) session.add(user_pref) session.add(meeting_spec) users = [] num_users = 21 for i in range(0, num_users): user = User(email='{}@yelp.com'.format(i), meta_data={ 'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref]) session.add(user) mr = MeetingRequest(user=user, meeting_spec=meeting_spec) session.add(mr) users.append(user) session.commit() matches, unmatched = generate_meetings(users, meeting_spec, prev_meeting_tuples=None, group_size=3) assert(len(matches) == 7) assert (len(unmatched) == 0) matches, unmatched = generate_meetings(users, meeting_spec, prev_meeting_tuples=None, group_size=5) assert(len(matches) == 4) assert (len(unmatched) == 1)
def test_user_preference(minimal_database, subscription): preference = subscription.datetime[0] user_pref = UserSubscriptionPreferences( preference=preference, subscription=subscription.key, ).put() user = User(email='*****@*****.**', metadata={'department': 'dept'}, subscription_preferences=[user_pref]) user.put() meeting_spec = MeetingSpec( meeting_subscription=subscription.key, datetime=subscription.datetime[0].get().datetime) meeting_spec.put() assert user_pref == user_preference(user, meeting_spec)
def get_previous_meetings(cooldown=MEETING_COOLDOWN_WEEKS): meetings = defaultdict(list) # get all meeting specs from x weeks ago til now time_threshold_for_meetings = datetime.now() - timedelta(weeks=cooldown) meeting_spec_keys = [ spec.key for spec in MeetingSpec.query( MeetingSpec.datetime > time_threshold_for_meetings).fetch() ] logging.info('Previous Meeting History: ') logging.info([ meeting.get().datetime.strftime("%Y-%m-%d %H:%M") for meeting in meeting_spec_keys ]) if meeting_spec_keys == []: return set([]) # get all meetings from meeting specs meeting_keys = [ meeting.key for meeting in Meeting.query().filter( Meeting.meeting_spec.IN(meeting_spec_keys)).fetch() ] if meeting_keys == []: return set([]) # get all participants from meetings participants = MeetingParticipant.query().filter( MeetingParticipant.meeting.IN(meeting_keys)).fetch() if participants == []: return set([]) # group by meeting Id for participant in participants: meetings[participant.meeting.id()].append(participant.user) # ids are sorted, all matches should be in increasing order by id for the matching algorithm to work disallowed_meetings = set([ tuple(sorted(meeting, key=lambda Key: Key.id())) for meeting in meetings.values() ]) logging.info('Past Meetings') logging.info([ tuple([meeting.get().get_username() for meeting in meeting]) for meeting in disallowed_meetings ]) disallowed_meetings = { tuple([meeting.id() for meeting in meeting]) for meeting in disallowed_meetings } return disallowed_meetings
def test_generate_group_meeting_invalid_number_of_users(minimal_database): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]).put() user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime) meeting_spec.put() users = [] for i in range(0, 2): user = User(email='{}@yelp.com'.format(i), metadata={ 'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref]) user.put() MeetingRequest(user=user.key, meeting_spec=meeting_spec.key).put() users.append(user) matches, unmatched = generate_meetings(users, meeting_spec, prev_meeting_tuples=None, group_size=3) assert(len(matches) == 0) assert (len(unmatched) == 2)
def store_specs_from_subscription(subscription_key, week_start, specs): """ Idempotent function to store meeting specs for this week. """ try: current_specs = MeetingSpec.query( MeetingSpec.meeting_subscription == subscription_key, MeetingSpec.datetime > week_start).fetch() except NeedIndexError: current_specs = [] if current_specs: return ndb.put_multi(specs) return specs
def test_user_preference(session, subscription): preference = subscription.datetime[0] user_pref = UserSubscriptionPreferences( preference=preference, subscription=subscription, ) session.add(user_pref) user = User(email='*****@*****.**', meta_data={'department': 'dept'}, subscription_preferences=[user_pref]) session.add(user) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=subscription.datetime[0].datetime) session.add(meeting_spec) session.commit() assert user_pref == user_preference(user, meeting_spec)
def get_specs_from_subscription(subscription): specs = [] for subscription_datetime in subscription.datetime: week_start = datetime.now() - timedelta(days=datetime.now().weekday()) week_start = week_start.replace(hour=0, minute=0, second=0, microsecond=0) subscription_dt = subscription_datetime.get().datetime week_iter = week_start while week_iter.weekday() != subscription_dt.weekday(): week_iter += timedelta(days=1) specs.append( MeetingSpec(meeting_subscription=subscription.key, datetime=week_iter.replace( hour=subscription_dt.hour, minute=subscription_dt.minute))) return week_start, specs
def test_generate_save_meetings(session, subscription): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1]) user_pref = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) user1 = User(email='*****@*****.**', meta_data={'department': 'dept'}, subscription_preferences=[user_pref]) user2 = User(email='*****@*****.**', meta_data={'department': 'dept2'}, subscription_preferences=[user_pref]) meeting_spec = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) mr1 = MeetingRequest(user=user1, meeting_spec=meeting_spec) mr2 = MeetingRequest(user=user2, meeting_spec=meeting_spec) session.add(pref_1) session.add(subscription) session.add(user_pref) session.add(user1) session.add(user2) session.add(meeting_spec) session.add(mr1) session.add(mr2) session.commit() matches, unmatched = generate_meetings([user1, user2], meeting_spec) save_meetings(matches, meeting_spec) assert unmatched == [] participants = [ participant.user for participant in MeetingParticipant.query.all() ] assert participants == [user1, user2]
def test_previous_meeting_penalty(session): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)) pref_2 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 2)) pref_3 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 3)) subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1, pref_2, pref_3]) user_pref1 = UserSubscriptionPreferences(preference=pref_1, subscription=subscription) user_pref2 = UserSubscriptionPreferences(preference=pref_2, subscription=subscription) user_pref3 = UserSubscriptionPreferences(preference=pref_3, subscription=subscription) meeting_spec1 = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.datetime) meeting_spec2 = MeetingSpec(meeting_subscription=subscription, datetime=pref_2.datetime) meeting_spec3 = MeetingSpec(meeting_subscription=subscription, datetime=pref_3.datetime) session.add(pref_1) session.add(pref_2) session.add(pref_3) session.add(subscription) session.add(user_pref1) session.add(user_pref2) session.add(user_pref3) session.add(meeting_spec1) session.add(meeting_spec2) session.add(meeting_spec3) users = [] num_users = 20 for i in range(0, num_users): user = User(email='{}@yelp.com'.format(i), meta_data={ 'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref1, user_pref2, user_pref3]) session.add(user) mr1 = MeetingRequest(user=user, meeting_spec=meeting_spec1) mr2 = MeetingRequest(user=user, meeting_spec=meeting_spec2) mr3 = MeetingRequest(user=user, meeting_spec=meeting_spec3) session.add(mr1) session.add(mr2) session.add(mr3) users.append(user) meeting1 = Meeting(meeting_spec=meeting_spec1, cancelled=False) mp1 = MeetingParticipant(meeting=meeting1, user=users[1]) mp2 = MeetingParticipant(meeting=meeting1, user=users[0]) session.add(meeting1) session.add(mp1) session.add(mp2) meeting2 = Meeting(meeting_spec=meeting_spec2, cancelled=False) mp1 = MeetingParticipant(meeting=meeting2, user=users[1]) mp2 = MeetingParticipant(meeting=meeting2, user=users[0]) session.add(meeting2) session.add(mp1) session.add(mp2) meeting3 = Meeting(meeting_spec=meeting_spec3, cancelled=False) mp1 = MeetingParticipant(meeting=meeting3, user=users[1]) mp2 = MeetingParticipant(meeting=meeting3, user=users[0]) session.add(meeting3) session.add(mp1) session.add(mp2) session.commit() for run in range(10): matches, unmatched = generate_meetings(users, meeting_spec1, prev_meeting_tuples=None, group_size=3) assert(len(matches) == 6) assert (len(unmatched) == 2) for matched_group in matches: assert(not (users[0] in matched_group and users[1] in matched_group))
def test_store_specs_from_subscription(database): week_start, specs = get_specs_from_subscription(database.sub) store_specs_from_subscription(database.sub.key, week_start, specs) assert len(MeetingSpec.query().fetch()) == 2
def test_generate_meeting_specs_idempotent(database): # ensure we don't create more specs generate_meeting_specs() meeting_specs = MeetingSpec.query().fetch() assert len(meeting_specs) == 2
def get_specs_for_current_week(): week_start = datetime.now() - timedelta(days=datetime.now().weekday()) week_start.replace(hour=0, minute=0, second=0, microsecond=0) return MeetingSpec.query(MeetingSpec.datetime > week_start).fetch()
def test_previous_meeting_penalty(minimal_database): pref_1 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 1)).put() pref_2 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 2)).put() pref_3 = SubscriptionDateTime(datetime=datetime.now() - timedelta(weeks=MEETING_COOLDOWN_WEEKS - 3)).put() subscription = MeetingSubscription(title='all engineering weekly', datetime=[pref_1, pref_2, pref_3]).put() user_pref1 = UserSubscriptionPreferences(preference=pref_1, subscription=subscription).put() user_pref2 = UserSubscriptionPreferences(preference=pref_2, subscription=subscription).put() user_pref3 = UserSubscriptionPreferences(preference=pref_3, subscription=subscription).put() meeting_spec1 = MeetingSpec(meeting_subscription=subscription, datetime=pref_1.get().datetime) meeting_spec1.put() meeting_spec2 = MeetingSpec(meeting_subscription=subscription, datetime=pref_2.get().datetime) meeting_spec2.put() meeting_spec3 = MeetingSpec(meeting_subscription=subscription, datetime=pref_3.get().datetime) meeting_spec3.put() users = [] num_users = 20 for i in range(0, num_users): user = User(email='{}@yelp.com'.format(i), metadata={ 'department': 'dept{}'.format(i)}, subscription_preferences=[user_pref1, user_pref2, user_pref3]) user.put() MeetingRequest(user=user.key, meeting_spec=meeting_spec1.key).put() MeetingRequest(user=user.key, meeting_spec=meeting_spec2.key).put() MeetingRequest(user=user.key, meeting_spec=meeting_spec3.key).put() users.append(user) meeting1 = Meeting(meeting_spec=meeting_spec1.key, cancelled=False).put() MeetingParticipant(meeting=meeting1, user=users[1].key).put() MeetingParticipant(meeting=meeting1, user=users[0].key).put() meeting2 = Meeting(meeting_spec=meeting_spec2.key, cancelled=False).put() MeetingParticipant(meeting=meeting2, user=users[1].key).put() MeetingParticipant(meeting=meeting2, user=users[0].key).put() meeting3 = Meeting(meeting_spec=meeting_spec3.key, cancelled=False).put() MeetingParticipant(meeting=meeting3, user=users[1].key).put() MeetingParticipant(meeting=meeting3, user=users[0].key).put() for run in range(10): matches, unmatched = generate_meetings(users, meeting_spec1, prev_meeting_tuples=None, group_size=3) assert(len(matches) == 6) assert (len(unmatched) == 2) for matched_group in matches: assert(not (users[0] in matched_group and users[1] in matched_group))