"""Tests for the core domain model: Participant and Group.""" import datetime as dt import numpy as np import pytest from tatami.classes import Group, Participant from conftest import make_participants, make_timedelta_matrix class TestParticipant: def test_uuid_is_unique(self): a = Participant( name="A", address="addr", phone="", kitchen_size=5, allergies="" ) b = Participant( name="A", address="addr", phone="", kitchen_size=5, allergies="" ) assert a.uuid != b.uuid @pytest.mark.parametrize( "kitchen_size,minutes", [(10, 0), (7, 9), (0, 30), (5, 15)], ) def test_penalty_scales_with_kitchen_size(self, kitchen_size, minutes): p = Participant( name="A", address="addr", phone="", kitchen_size=kitchen_size, allergies="" ) assert p.get_penalty() == dt.timedelta(minutes=minutes) def test_after_party_time_combines_penalty_and_travel(self): people = make_participants(2, kitchen_sizes=[7.0, 10.0]) # 600s travel between the two participants. matrix = make_timedelta_matrix(people, np.array([[0, 600], [600, 0]])) after_party = Group(members=[people[1]]) result = people[0].get_after_party_time(matrix, after_party) assert result == dt.timedelta(minutes=9) + dt.timedelta(seconds=600) def test_dict_roundtrip_fields(self): p = Participant( name="Alice", address="addr", phone="555", kitchen_size=8, allergies="peanuts", ) d = p.dict() assert d == { "uuid": p.uuid, "name": "Alice", "address": "addr", "phone": "555", "kitchen_size": 8, "allergies": "peanuts", } class TestGroup: def test_default_main_member_is_first(self): people = make_participants(3) group = Group(members=people) assert group.main_member is people[0] def test_explicit_main_member_index(self): people = make_participants(3) group = Group(members=people, main_member=2) assert group.main_member is people[2] def test_add_member_appends_without_changing_main(self): people = make_participants(2) group = Group(members=[people[0]]) group.add_member(people[1]) assert people[1] in group.members assert group.main_member is people[0] def test_add_member_can_promote_to_main(self): people = make_participants(2) group = Group(members=[people[0]]) group.add_member(people[1], main_member=True) assert group.main_member is people[1] def test_set_hosts_sorts_by_course(self): people = make_participants(3) groups = [Group(members=[p]) for p in people] groups[0].set_course("dessert") groups[1].set_course("starter") groups[2].set_course("main") host = Group(members=[make_participants(1)[0]]) host.set_hosts([groups[0], groups[1], groups[2]]) assert [g.course for g in host.hosts] == ["starter", "main", "dessert"] def test_get_total_time_sums_legs_and_penalties(self): # Three host groups (penalties 0) + after party; verify the summed route. people = make_participants(4, kitchen_sizes=[10, 10, 10, 10]) seconds = np.array( [ [0, 100, 0, 0, 50], [0, 0, 200, 0, 0], [0, 0, 0, 0, 300], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ] ) # build matrix including an after party participant after_party_p = make_participants(1)[0] all_people = people + [after_party_p] full = make_timedelta_matrix(all_people, seconds) starter = Group(members=[people[0]]) starter.set_course("starter") main = Group(members=[people[1]]) main.set_course("main") dessert = Group(members=[people[2]]) dessert.set_course("dessert") after_party = Group(members=[after_party_p]) visitor = Group(members=[people[3]]) visitor.set_hosts([starter, main, dessert]) total = visitor.get_total_time(full, after_party) # legs: starter->main (100) + main->dessert (200) + dessert->afterparty (300) assert total == dt.timedelta(seconds=600) def test_get_total_time_raises_without_hosts(self): group = Group(members=make_participants(1)) after_party = Group(members=make_participants(1)) with pytest.raises(ValueError): group.get_total_time(None, after_party) def test_get_guests_collects_visiting_members(self): people = make_participants(4) host = Group(members=[people[0]]) guest_a = Group(members=[people[1]]) guest_b = Group(members=[people[2], people[3]]) # get_guests returns early when the host has no hosts of its own, so give it # a (self-)host as it would have in a real plan. host.set_hosts([host]) guest_a.set_hosts([host]) guest_b.set_hosts([host]) guests = host.get_guests([guest_a, guest_b]) guest_uuids = {p.uuid for p in guests} assert guest_uuids == {people[1].uuid, people[2].uuid, people[3].uuid} def test_dict_serializes_uuids(self): people = make_participants(2) group = Group(members=people) host = Group(members=make_participants(1)) host.set_course("starter") group.set_hosts([host]) d = group.dict() assert d["main_member"] == people[0].uuid assert d["members"] == [p.uuid for p in people] assert d["hosts"] == [host.uuid]