-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_ranking.py
More file actions
167 lines (133 loc) · 5.38 KB
/
Copy pathtest_ranking.py
File metadata and controls
167 lines (133 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
"""Unit tests for restaurant ranking logic.
Verifies rule: Current food prompt BEATS favorite restaurant.
"""
from hungrycall.models import Mode, OpeningHours, Restaurant, UserRequest
from hungrycall.ranking import (
filter_and_rank_restaurants,
filter_candidate,
)
def build_sample_candidates():
open_hours = OpeningHours(
days=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
open_time="10:00",
close_time="23:00"
)
burger_house = Restaurant(
id="rest_burger",
name="Dorf Burger Joint",
phone="+491701111111",
cuisines=["Burger", "American"],
opening_hours=open_hours,
is_favorite=False
)
favorite_italian = Restaurant(
id="rest_italian",
name="Mama Mia Pizza",
phone="+491702222222",
cuisines=["Italian", "Pizza"],
opening_hours=open_hours,
is_favorite=True
)
closed_restaurant = Restaurant(
id="rest_closed",
name="Closed Diner",
phone="+491703333333",
cuisines=["Burger"],
opening_hours=OpeningHours(days=["Mon"], open_time="10:00", close_time="12:00"),
is_favorite=False
)
return [burger_house, favorite_italian, closed_restaurant]
def test_food_prompt_beats_favorite():
candidates = build_sample_candidates()
# User requests "Burger". Favorite restaurant is Italian.
request = UserRequest(
mode=Mode.DELIVERY,
customer_name="Lukas",
food_prompt="Burger",
max_budget_eur=35.0,
delivery_address="Hauptstraße 1",
day_of_week="Fri",
time_of_request="19:00"
)
ranked = filter_and_rank_restaurants(candidates, request)
# Closed restaurant excluded
assert len(ranked) == 2
# Burger House MUST be ranked #1 above Favorite Italian because food prompt beats favorite
top_restaurant, top_score = ranked[0]
second_restaurant, second_score = ranked[1]
assert top_restaurant.id == "rest_burger"
assert second_restaurant.id == "rest_italian"
assert top_score > second_score
def test_favorite_wins_when_cuisine_matches():
candidates = build_sample_candidates()
# User requests "Pizza". Favorite Italian serves Pizza.
request = UserRequest(
mode=Mode.DELIVERY,
customer_name="Lukas",
food_prompt="Pizza",
max_budget_eur=35.0,
delivery_address="Hauptstraße 1",
day_of_week="Fri",
time_of_request="19:00"
)
ranked = filter_and_rank_restaurants(candidates, request)
top_restaurant, _top_score = ranked[0]
# Favorite Italian wins when food prompt matches cuisine
assert top_restaurant.id == "rest_italian"
def test_distance_weighs_differently_per_mode():
"""The mode switch has to reach the ranking, or it is only a label.
Same two places, same food: a nearby plain restaurant against a favourite
four kilometres away. Delivered, the favourite wins — the driver covers the
distance. Collected, the near one wins, because now the user drives.
"""
hours = OpeningHours(days=["Fri"], open_time="10:00", close_time="23:00")
near = Restaurant(
id="near", name="Ecke", phone="+491701111111", cuisines=["Pizza"],
opening_hours=hours, lat=52.5200, lon=13.4050, distance_km=0.2,
)
far_favorite = Restaurant(
id="far", name="Mama Mia", phone="+491702222222", cuisines=["Pizza"],
opening_hours=hours, is_favorite=True,
lat=52.5560, lon=13.4050, distance_km=4.0,
)
candidates = [near, far_favorite]
def order_for(mode, **extra):
request = UserRequest(
mode=mode, customer_name="Lukas", food_prompt="Pizza",
max_budget_eur=35.0, delivery_address="Hauptstraße 1",
day_of_week="Fri", time_of_request="19:00", **extra,
)
return [r.id for r, _ in filter_and_rank_restaurants(candidates, request)]
assert order_for(Mode.DELIVERY)[0] == "far"
assert order_for(Mode.PICKUP, pickup_time="19:00")[0] == "near"
def test_distance_limit_removes_candidates_before_any_call():
hours = OpeningHours(days=["Fri"], open_time="10:00", close_time="23:00")
far = Restaurant(
id="far", name="Weit weg", phone="+491702222222", cuisines=["Pizza"],
opening_hours=hours, distance_km=9.0,
)
request = UserRequest(
mode=Mode.PICKUP, customer_name="Lukas", food_prompt="Pizza",
max_budget_eur=35.0, pickup_time="19:00", max_distance_km=5.0,
day_of_week="Fri", time_of_request="19:00",
)
assert filter_and_rank_restaurants([far], request) == []
assert "beyond the 5.0 km limit" in filter_candidate(far, request)
def test_place_open_past_midnight_counts_as_open():
"""22:00–04:00 used to read as closed all night, which is backwards."""
night = OpeningHours(days=["Fri"], open_time="22:00", close_time="04:00")
assert night.is_open("Fri", "23:30") is True
assert night.is_open("Fri", "02:00") is True
assert night.is_open("Fri", "18:00") is False
def test_closed_restaurant_filtered_out():
candidates = build_sample_candidates()
request = UserRequest(
mode=Mode.DELIVERY,
customer_name="Lukas",
food_prompt="Burger",
day_of_week="Sun",
time_of_request="20:00"
)
ranked = filter_and_rank_restaurants(candidates, request)
candidate_ids = [r[0].id for r in ranked]
assert "rest_closed" not in candidate_ids