-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfood.py
More file actions
208 lines (160 loc) · 6.18 KB
/
food.py
File metadata and controls
208 lines (160 loc) · 6.18 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import re
import json
from person import Person, Vegetarian
class Food:
"""Base class for food items with shared eating behavior and state."""
is_edible = True
eaten = False
def __init__(self, name):
"""Create a food item with a name."""
self.name = name
self.eater = None
def eat(self, person):
"""Attempt to eat the food with a Person, enforcing rules."""
if not isinstance(person, Person):
print("Can only eat food with a Person.")
return
if not self.is_edible:
print(f"{self.name} is not edible.")
return
if self.eaten:
print(f"{self.name} has already been eaten by {self.eater}.")
return
if person.hands != Person.HANDS_CLEAN:
print(f"{person.name} cannot eat {self.name}. Hands are not clean.")
person.show_status()
return
if person.is_full:
print(f"{person.name} cannot eat {self.name}. They are already full.")
person.show_status()
return
allergy_match = None
for allergy in person.allergies:
if re.search(allergy, self.name, flags=re.IGNORECASE):
allergy_match = allergy
break
if allergy_match is not None:
print(f"{person.name} cannot eat {self.name}. Allergy match: {allergy_match}")
person.show_status()
return
self.eaten = True
self.eater = person.name
person.is_full = True
if isinstance(self, Fruit) and person.is_diabetic:
person.fruits_eaten += 1
print(f"{person.name} has eaten {self.name}.")
person.show_status()
def to_dict(self):
"""Return a dictionary snapshot of the food state."""
return {
"type": self.__class__.__name__,
"name": self.name,
"is_edible": self.is_edible,
"eaten": self.eaten,
"eater": self.eater,
}
def to_json(self):
"""Print and return a JSON snapshot of the food state."""
data = self.to_dict()
print(json.dumps(data))
return data
class Fruit(Food):
"""Food subclass that must be washed and ripe before it can be eaten."""
is_edible = False
def __init__(self, name):
"""Create a fruit with default unwashed and unripe state."""
super().__init__(name)
self.is_ripe = False
self.is_washed = False
def wash(self):
"""Wash the fruit so it can be eaten."""
self.is_washed = True
print(f"{self.name} has been washed.")
def ripen(self):
"""Ripen the fruit and mark it edible."""
self.is_ripe = True
self.is_edible = True
print(f"{self.name} is now ripe.")
def eat(self, person):
"""Require washing before delegating to base eating rules."""
if not self.is_washed:
print(f"{self.name} cannot be eaten until it is washed.")
if isinstance(person, Person):
person.show_status()
return
if isinstance(person, Person) and person.is_diabetic and person.fruits_eaten >= 1:
print(f"{person.name} cannot eat {self.name}. Diabetic fruit limit reached.")
person.show_status()
return
super().eat(person)
def to_dict(self):
"""Return a dictionary snapshot of the fruit state."""
data = super().to_dict()
data["is_ripe"] = self.is_ripe
data["is_washed"] = self.is_washed
return data
class Meat(Food):
"""Food subclass that requires cooking and blocks vegetarian eaters."""
is_edible = False
def cook(self):
"""Cook the meat to make it edible."""
self.is_edible = True
print(f"{self.name} has been cooked and is now edible.")
def eat(self, person):
"""Block vegetarians before delegating to base eating rules."""
if isinstance(person, Vegetarian):
print(f"{person.name} cannot eat {self.name}. They are vegetarian.")
person.show_status()
return
super().eat(person)
class Beverage(Food):
"""Food subclass representing a drinkable beverage."""
def __init__(self, name, contains_alcohol=False):
"""Create a beverage with an alcohol flag."""
super().__init__(name)
self.contains_alcohol = contains_alcohol
def drink(self, person):
"""Drink the beverage using base eating rules."""
if not isinstance(person, Person):
print("Can only drink beverages with a Person.")
return
if self.contains_alcohol and person.age < 21:
print(f"{person.name} cannot drink {self.name}. Must be 21+.")
person.show_status()
return
if not self.is_edible:
print(f"{self.name} is not edible.")
return
if self.eaten:
print(f"{self.name} has already been drunk by {self.eater}.")
return
if person.hands != Person.HANDS_CLEAN:
print(f"{person.name} cannot drink {self.name}. Hands are not clean.")
person.show_status()
return
if person.is_full:
print(f"{person.name} cannot drink {self.name}. They are already full.")
person.show_status()
return
allergy_match = None
for allergy in person.allergies:
if re.search(allergy, self.name, flags=re.IGNORECASE):
allergy_match = allergy
break
if allergy_match is not None:
print(f"{person.name} cannot drink {self.name}. Allergy match: {allergy_match}")
person.show_status()
return
self.eaten = True
self.eater = person.name
person.is_full = True
print(f"{person.name} has drunk {self.name}.")
person.show_status()
def eat(self, person):
"""Alias to drink for compatibility with Food interface."""
self.drink(person)
def to_dict(self):
"""Return a dictionary snapshot of the beverage state."""
data = super().to_dict()
data["contains_alcohol"] = self.contains_alcohol
return data