1import random
2import re
3import threading
4import time
5from collections import defaultdict, Counter, OrderedDict
6from datetime import datetime
7
8
9class CSI:
10 """Central Santa Intelligence."""
11
12 _instance = None
13 _naughty_list = defaultdict(OrderedDict)
14 _individuals_under_observation = {}
15
16 def __new__(cls, *args, **kwargs):
17 """There can be only one CSI."""
18 if cls._instance is None:
19 cls._instance = super().__new__(cls, *args, **kwargs)
20 return cls._instance
21
22 @classmethod
23 def notify_about_new_baby(cls, individual):
24 """Here's your package of earthworms. How are Kevin and the kids?"""
25 cls._individuals_under_observation[id(individual)] = individual
26
27 def notify_about_transgression(method):
28 """CSI sees EVERYTHING."""
29 def decorated(*args, **kwargs):
30 try:
31 result = method(individual, *args, **kwargs)
32 except Exception as err:
33 time_of_naughtiness = datetime.now()
34 print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.")
35 CSI._naughty_list[individual][time_of_naughtiness] = err
36 raise
37 return result
38 return decorated
39
40 for attr_name, obj in type(individual).__dict__.items():
41 if callable(obj) and not attr_name.startswith('_'):
42 setattr(individual, attr_name, notify_about_transgression(obj))
43
44 @property
45 def all_individuals(self):
46 return self._individuals_under_observation.values()
47
48 def identify_sender(self, text):
49 """Santa leaves espionage to the CSI."""
50 sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None)
51 return self._individuals_under_observation[sender_id]
52
53 def is_naughty(self, individual):
54 """Assess if the individual has erred this year."""
55 return individual in self._naughty_list
56
57 def prepare_for_next_christmass(self):
58 """Update the ages of people and give everyone another chance for the new year."""
59 self._naughty_list = defaultdict(OrderedDict)
60
61
62class Santa:
63 """Saint Nicholas... Or however he's called in your culture."""
64
65 _csi = CSI()
66 _wishes = OrderedDict()
67 _instance = None
68 _santas_private_list = {}
69
70 def __new__(cls, *args, **kwargs):
71 """There can be only one Santa!"""
72 if cls._instance is None:
73 cls._instance = super().__new__(cls, *args, **kwargs)
74 return cls._instance
75
76 def __call__(self, kid, request):
77 """Call santa with a gift request."""
78 self._wishes[kid] = self._extract_gift(request)
79
80 def __matmul__(self, letter):
81 """Write a letter to Santa."""
82 kid = self._csi.identify_sender(letter)
83 self._wishes[kid] = self._extract_gift(letter)
84
85 def __iter__(self):
86 """Santa is iterable, if you didn't know."""
87 return iter(self._wishes.values())
88
89 def _extract_gift(self, text):
90 """Santa takes notes of all gifts."""
91 return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None
92
93 def xmas(self):
94 """Deliver gifts."""
95 most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None
96 # Make sure to give presents to the ones who called or sent letters first
97 kids_with_wishes = list(self._wishes.keys())
98 kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes))
99 for kid in kids_with_wishes + kids_without_wishes:
100 if kid.age >= 18 and self._csi.is_naughty(kid):
101 self._santas_private_list.add(kid)
102 continue
103 # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad
104 if kids_with_wishes and kid.age < 5:
105 if self._csi.is_naughty(kid):
106 present = 'coal'
107 else:
108 present = self._wishes.get(kid, most_wanted)
109 kid(present)
110 else:
111 kid(None) # A Christmas is a Christmas even without the presents
112 self._prepare_for_next_christmass()
113
114 def _prepare_for_next_christmass(self):
115 """Prepare for next Christmas by giving everyone the benefit of the doubt."""
116 self._csi.prepare_for_next_christmass()
117 self._wishes = OrderedDict()
118
119
120class Kid(type):
121
122 @staticmethod
123 def _better_init(original_init):
124 """Because sometimes people need a push in the right direction."""
125 def decorated(self, *args, **kwargs):
126 original_init(self, *args, **kwargs)
127 Person.__init__(self)
128 return decorated
129
130 @staticmethod
131 def _better_new(*genetic_information):
132 """Because this is how babies are made, canonically speaking."""
133 return Stork.deliver_baby(genetic_information)
134
135 @staticmethod
136 def _better_call(original_call): # Saul
137 """Add an increase of age to the original call."""
138 def decorated(self, *args, **kwargs):
139 result = original_call(self, *args, **kwargs)
140 self.age += 1
141 return result
142 return decorated
143
144 def __new__(cls, name, bases, attr_dict):
145 """Create a type of kid."""
146 if '__call__' not in attr_dict:
147 raise NotImplementedError
148 attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None))
149 attr_dict['__new__'] = cls._better_new
150 attr_dict['__call__'] = cls._better_call(attr_dict['__call__'])
151 return super().__new__(cls, name, bases + (Person,), attr_dict)
152
153
154class Person:
155 """What is a person?"""
156
157 def __init__(self):
158 """Initialize age for each person."""
159 self.age = 0
160
161 def __hash__(self):
162 """Can you hash a person?"""
163 return hash(id(self))
164
165
166class Stork:
167 """A main worker in the baby-delivery service."""
168
169 _available_storks = []
170
171 def __init__(self):
172 """Initialize carrying space for babies for the current stork."""
173 self.baby = []
174
175 def _procure_a_baby(self, genetic_information):
176 """Where from? No idea."""
177 # Part of an old implementation, left here only for the joke
178 # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he
179 self.baby = [object.__new__(*genetic_information)]
180 self._____notify_CSI()
181
182 def _____notify_CSI(self):
183 """Nothing to see here, move along."""
184 CSI.notify_about_new_baby(self.baby[0])
185
186 def _deliver_baby(self):
187 """Hehe, *pop*."""
188 return self.baby.pop()
189
190 @classmethod
191 def deliver_baby(cls, genetic_information):
192 """Deliver a baby to the happy parents."""
193 threading.Thread(target=cls._request_storks).start()
194 while not cls._available_storks:
195 print("There are no storks available, please wait as your call is important to us!")
196 time.sleep(0.03)
197 return cls._dispatch_stork(genetic_information)
198
199 @classmethod
200 def _request_storks(cls):
201 """Request for adding storks to the stork pool."""
202 time.sleep(0.09)
203 storks = [cls() for _ in range(random.randint(1, 10))]
204 cls._available_storks.extend(storks)
205 print("Thank you for your patience. Storks are ready for dispatch!")
206
207 @classmethod
208 def _dispatch_stork(cls, genetic_information):
209 """Dispatch an available stork in the area."""
210 stork_index = random.randint(0, len(cls._available_storks) - 1)
211 stork = cls._available_storks.pop(stork_index)
212 stork._procure_a_baby(genetic_information)
213 print("Stork dispatched, please wait for your delivery.")
214 return stork._deliver_baby()
Timed out.
Георги Кунчев
19.12.2024 15:46I've got you, bro!
Here - take these 10 bonus points.
|
Виктор Бечев
19.12.2024 14:32Лол, това заслужавам, таймаут. :rofl:
|
f | 1 | import random | f | 1 | import random |
2 | import re | 2 | import re | ||
3 | import threading | 3 | import threading | ||
4 | import time | 4 | import time | ||
5 | from collections import defaultdict, Counter, OrderedDict | 5 | from collections import defaultdict, Counter, OrderedDict | ||
6 | from datetime import datetime | 6 | from datetime import datetime | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class CSI: | 9 | class CSI: | ||
10 | """Central Santa Intelligence.""" | 10 | """Central Santa Intelligence.""" | ||
11 | 11 | ||||
12 | _instance = None | 12 | _instance = None | ||
13 | _naughty_list = defaultdict(OrderedDict) | 13 | _naughty_list = defaultdict(OrderedDict) | ||
14 | _individuals_under_observation = {} | 14 | _individuals_under_observation = {} | ||
15 | 15 | ||||
16 | def __new__(cls, *args, **kwargs): | 16 | def __new__(cls, *args, **kwargs): | ||
17 | """There can be only one CSI.""" | 17 | """There can be only one CSI.""" | ||
18 | if cls._instance is None: | 18 | if cls._instance is None: | ||
19 | cls._instance = super().__new__(cls, *args, **kwargs) | 19 | cls._instance = super().__new__(cls, *args, **kwargs) | ||
20 | return cls._instance | 20 | return cls._instance | ||
21 | 21 | ||||
22 | @classmethod | 22 | @classmethod | ||
23 | def notify_about_new_baby(cls, individual): | 23 | def notify_about_new_baby(cls, individual): | ||
24 | """Here's your package of earthworms. How are Kevin and the kids?""" | 24 | """Here's your package of earthworms. How are Kevin and the kids?""" | ||
25 | cls._individuals_under_observation[id(individual)] = individual | 25 | cls._individuals_under_observation[id(individual)] = individual | ||
26 | 26 | ||||
27 | def notify_about_transgression(method): | 27 | def notify_about_transgression(method): | ||
28 | """CSI sees EVERYTHING.""" | 28 | """CSI sees EVERYTHING.""" | ||
29 | def decorated(*args, **kwargs): | 29 | def decorated(*args, **kwargs): | ||
30 | try: | 30 | try: | ||
31 | result = method(individual, *args, **kwargs) | 31 | result = method(individual, *args, **kwargs) | ||
32 | except Exception as err: | 32 | except Exception as err: | ||
33 | time_of_naughtiness = datetime.now() | 33 | time_of_naughtiness = datetime.now() | ||
34 | print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.") | 34 | print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.") | ||
35 | CSI._naughty_list[individual][time_of_naughtiness] = err | 35 | CSI._naughty_list[individual][time_of_naughtiness] = err | ||
36 | raise | 36 | raise | ||
37 | return result | 37 | return result | ||
38 | return decorated | 38 | return decorated | ||
39 | 39 | ||||
40 | for attr_name, obj in type(individual).__dict__.items(): | 40 | for attr_name, obj in type(individual).__dict__.items(): | ||
41 | if callable(obj) and not attr_name.startswith('_'): | 41 | if callable(obj) and not attr_name.startswith('_'): | ||
42 | setattr(individual, attr_name, notify_about_transgression(obj)) | 42 | setattr(individual, attr_name, notify_about_transgression(obj)) | ||
43 | 43 | ||||
44 | @property | 44 | @property | ||
45 | def all_individuals(self): | 45 | def all_individuals(self): | ||
46 | return self._individuals_under_observation.values() | 46 | return self._individuals_under_observation.values() | ||
47 | 47 | ||||
48 | def identify_sender(self, text): | 48 | def identify_sender(self, text): | ||
49 | """Santa leaves espionage to the CSI.""" | 49 | """Santa leaves espionage to the CSI.""" | ||
50 | sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None) | 50 | sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None) | ||
51 | return self._individuals_under_observation[sender_id] | 51 | return self._individuals_under_observation[sender_id] | ||
52 | 52 | ||||
53 | def is_naughty(self, individual): | 53 | def is_naughty(self, individual): | ||
54 | """Assess if the individual has erred this year.""" | 54 | """Assess if the individual has erred this year.""" | ||
55 | return individual in self._naughty_list | 55 | return individual in self._naughty_list | ||
56 | 56 | ||||
57 | def prepare_for_next_christmass(self): | 57 | def prepare_for_next_christmass(self): | ||
58 | """Update the ages of people and give everyone another chance for the new year.""" | 58 | """Update the ages of people and give everyone another chance for the new year.""" | ||
59 | self._naughty_list = defaultdict(OrderedDict) | 59 | self._naughty_list = defaultdict(OrderedDict) | ||
60 | 60 | ||||
61 | 61 | ||||
62 | class Santa: | 62 | class Santa: | ||
63 | """Saint Nicholas... Or however he's called in your culture.""" | 63 | """Saint Nicholas... Or however he's called in your culture.""" | ||
64 | 64 | ||||
65 | _csi = CSI() | 65 | _csi = CSI() | ||
66 | _wishes = OrderedDict() | 66 | _wishes = OrderedDict() | ||
67 | _instance = None | 67 | _instance = None | ||
68 | _santas_private_list = {} | 68 | _santas_private_list = {} | ||
69 | 69 | ||||
70 | def __new__(cls, *args, **kwargs): | 70 | def __new__(cls, *args, **kwargs): | ||
71 | """There can be only one Santa!""" | 71 | """There can be only one Santa!""" | ||
72 | if cls._instance is None: | 72 | if cls._instance is None: | ||
73 | cls._instance = super().__new__(cls, *args, **kwargs) | 73 | cls._instance = super().__new__(cls, *args, **kwargs) | ||
74 | return cls._instance | 74 | return cls._instance | ||
75 | 75 | ||||
76 | def __call__(self, kid, request): | 76 | def __call__(self, kid, request): | ||
77 | """Call santa with a gift request.""" | 77 | """Call santa with a gift request.""" | ||
78 | self._wishes[kid] = self._extract_gift(request) | 78 | self._wishes[kid] = self._extract_gift(request) | ||
79 | 79 | ||||
80 | def __matmul__(self, letter): | 80 | def __matmul__(self, letter): | ||
81 | """Write a letter to Santa.""" | 81 | """Write a letter to Santa.""" | ||
82 | kid = self._csi.identify_sender(letter) | 82 | kid = self._csi.identify_sender(letter) | ||
83 | self._wishes[kid] = self._extract_gift(letter) | 83 | self._wishes[kid] = self._extract_gift(letter) | ||
84 | 84 | ||||
85 | def __iter__(self): | 85 | def __iter__(self): | ||
86 | """Santa is iterable, if you didn't know.""" | 86 | """Santa is iterable, if you didn't know.""" | ||
87 | return iter(self._wishes.values()) | 87 | return iter(self._wishes.values()) | ||
88 | 88 | ||||
89 | def _extract_gift(self, text): | 89 | def _extract_gift(self, text): | ||
90 | """Santa takes notes of all gifts.""" | 90 | """Santa takes notes of all gifts.""" | ||
91 | return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None | 91 | return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None | ||
92 | 92 | ||||
93 | def xmas(self): | 93 | def xmas(self): | ||
94 | """Deliver gifts.""" | 94 | """Deliver gifts.""" | ||
95 | most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None | 95 | most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None | ||
96 | # Make sure to give presents to the ones who called or sent letters first | 96 | # Make sure to give presents to the ones who called or sent letters first | ||
97 | kids_with_wishes = list(self._wishes.keys()) | 97 | kids_with_wishes = list(self._wishes.keys()) | ||
98 | kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes)) | 98 | kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes)) | ||
99 | for kid in kids_with_wishes + kids_without_wishes: | 99 | for kid in kids_with_wishes + kids_without_wishes: | ||
100 | if kid.age >= 18 and self._csi.is_naughty(kid): | 100 | if kid.age >= 18 and self._csi.is_naughty(kid): | ||
101 | self._santas_private_list.add(kid) | 101 | self._santas_private_list.add(kid) | ||
102 | continue | 102 | continue | ||
103 | # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad | 103 | # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad | ||
104 | if kids_with_wishes and kid.age < 5: | 104 | if kids_with_wishes and kid.age < 5: | ||
105 | if self._csi.is_naughty(kid): | 105 | if self._csi.is_naughty(kid): | ||
106 | present = 'coal' | 106 | present = 'coal' | ||
107 | else: | 107 | else: | ||
108 | present = self._wishes.get(kid, most_wanted) | 108 | present = self._wishes.get(kid, most_wanted) | ||
109 | kid(present) | 109 | kid(present) | ||
110 | else: | 110 | else: | ||
111 | kid(None) # A Christmas is a Christmas even without the presents | 111 | kid(None) # A Christmas is a Christmas even without the presents | ||
112 | self._prepare_for_next_christmass() | 112 | self._prepare_for_next_christmass() | ||
113 | 113 | ||||
114 | def _prepare_for_next_christmass(self): | 114 | def _prepare_for_next_christmass(self): | ||
115 | """Prepare for next Christmas by giving everyone the benefit of the doubt.""" | 115 | """Prepare for next Christmas by giving everyone the benefit of the doubt.""" | ||
116 | self._csi.prepare_for_next_christmass() | 116 | self._csi.prepare_for_next_christmass() | ||
117 | self._wishes = OrderedDict() | 117 | self._wishes = OrderedDict() | ||
118 | 118 | ||||
119 | 119 | ||||
120 | class Kid(type): | 120 | class Kid(type): | ||
121 | 121 | ||||
122 | @staticmethod | 122 | @staticmethod | ||
123 | def _better_init(original_init): | 123 | def _better_init(original_init): | ||
124 | """Because sometimes people need a push in the right direction.""" | 124 | """Because sometimes people need a push in the right direction.""" | ||
125 | def decorated(self, *args, **kwargs): | 125 | def decorated(self, *args, **kwargs): | ||
126 | original_init(self, *args, **kwargs) | 126 | original_init(self, *args, **kwargs) | ||
127 | Person.__init__(self) | 127 | Person.__init__(self) | ||
128 | return decorated | 128 | return decorated | ||
129 | 129 | ||||
130 | @staticmethod | 130 | @staticmethod | ||
131 | def _better_new(*genetic_information): | 131 | def _better_new(*genetic_information): | ||
132 | """Because this is how babies are made, canonically speaking.""" | 132 | """Because this is how babies are made, canonically speaking.""" | ||
133 | return Stork.deliver_baby(genetic_information) | 133 | return Stork.deliver_baby(genetic_information) | ||
134 | 134 | ||||
135 | @staticmethod | 135 | @staticmethod | ||
136 | def _better_call(original_call): # Saul | 136 | def _better_call(original_call): # Saul | ||
137 | """Add an increase of age to the original call.""" | 137 | """Add an increase of age to the original call.""" | ||
138 | def decorated(self, *args, **kwargs): | 138 | def decorated(self, *args, **kwargs): | ||
139 | result = original_call(self, *args, **kwargs) | 139 | result = original_call(self, *args, **kwargs) | ||
140 | self.age += 1 | 140 | self.age += 1 | ||
141 | return result | 141 | return result | ||
142 | return decorated | 142 | return decorated | ||
143 | 143 | ||||
144 | def __new__(cls, name, bases, attr_dict): | 144 | def __new__(cls, name, bases, attr_dict): | ||
145 | """Create a type of kid.""" | 145 | """Create a type of kid.""" | ||
146 | if '__call__' not in attr_dict: | 146 | if '__call__' not in attr_dict: | ||
147 | raise NotImplementedError | 147 | raise NotImplementedError | ||
148 | attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None)) | 148 | attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None)) | ||
149 | attr_dict['__new__'] = cls._better_new | 149 | attr_dict['__new__'] = cls._better_new | ||
150 | attr_dict['__call__'] = cls._better_call(attr_dict['__call__']) | 150 | attr_dict['__call__'] = cls._better_call(attr_dict['__call__']) | ||
151 | return super().__new__(cls, name, bases + (Person,), attr_dict) | 151 | return super().__new__(cls, name, bases + (Person,), attr_dict) | ||
152 | 152 | ||||
153 | 153 | ||||
154 | class Person: | 154 | class Person: | ||
155 | """What is a person?""" | 155 | """What is a person?""" | ||
156 | 156 | ||||
157 | def __init__(self): | 157 | def __init__(self): | ||
158 | """Initialize age for each person.""" | 158 | """Initialize age for each person.""" | ||
159 | self.age = 0 | 159 | self.age = 0 | ||
160 | 160 | ||||
161 | def __hash__(self): | 161 | def __hash__(self): | ||
162 | """Can you hash a person?""" | 162 | """Can you hash a person?""" | ||
163 | return hash(id(self)) | 163 | return hash(id(self)) | ||
164 | 164 | ||||
165 | 165 | ||||
166 | class Stork: | 166 | class Stork: | ||
167 | """A main worker in the baby-delivery service.""" | 167 | """A main worker in the baby-delivery service.""" | ||
168 | 168 | ||||
169 | _available_storks = [] | 169 | _available_storks = [] | ||
170 | 170 | ||||
171 | def __init__(self): | 171 | def __init__(self): | ||
172 | """Initialize carrying space for babies for the current stork.""" | 172 | """Initialize carrying space for babies for the current stork.""" | ||
173 | self.baby = [] | 173 | self.baby = [] | ||
174 | 174 | ||||
175 | def _procure_a_baby(self, genetic_information): | 175 | def _procure_a_baby(self, genetic_information): | ||
176 | """Where from? No idea.""" | 176 | """Where from? No idea.""" | ||
177 | # Part of an old implementation, left here only for the joke | 177 | # Part of an old implementation, left here only for the joke | ||
178 | # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he | 178 | # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he | ||
179 | self.baby = [object.__new__(*genetic_information)] | 179 | self.baby = [object.__new__(*genetic_information)] | ||
180 | self._____notify_CSI() | 180 | self._____notify_CSI() | ||
181 | 181 | ||||
182 | def _____notify_CSI(self): | 182 | def _____notify_CSI(self): | ||
t | 183 | """Nothing to see here, move along,""" | t | 183 | """Nothing to see here, move along.""" |
184 | CSI.notify_about_new_baby(self.baby[0]) | 184 | CSI.notify_about_new_baby(self.baby[0]) | ||
185 | 185 | ||||
186 | def _deliver_baby(self): | 186 | def _deliver_baby(self): | ||
187 | """Hehe, *pop*.""" | 187 | """Hehe, *pop*.""" | ||
188 | return self.baby.pop() | 188 | return self.baby.pop() | ||
189 | 189 | ||||
190 | @classmethod | 190 | @classmethod | ||
191 | def deliver_baby(cls, genetic_information): | 191 | def deliver_baby(cls, genetic_information): | ||
192 | """Deliver a baby to the happy parents.""" | 192 | """Deliver a baby to the happy parents.""" | ||
193 | threading.Thread(target=cls._request_storks).start() | 193 | threading.Thread(target=cls._request_storks).start() | ||
194 | while not cls._available_storks: | 194 | while not cls._available_storks: | ||
195 | print("There are no storks available, please wait as your call is important to us!") | 195 | print("There are no storks available, please wait as your call is important to us!") | ||
196 | time.sleep(0.03) | 196 | time.sleep(0.03) | ||
197 | return cls._dispatch_stork(genetic_information) | 197 | return cls._dispatch_stork(genetic_information) | ||
198 | 198 | ||||
199 | @classmethod | 199 | @classmethod | ||
200 | def _request_storks(cls): | 200 | def _request_storks(cls): | ||
201 | """Request for adding storks to the stork pool.""" | 201 | """Request for adding storks to the stork pool.""" | ||
202 | time.sleep(0.09) | 202 | time.sleep(0.09) | ||
203 | storks = [cls() for _ in range(random.randint(1, 10))] | 203 | storks = [cls() for _ in range(random.randint(1, 10))] | ||
204 | cls._available_storks.extend(storks) | 204 | cls._available_storks.extend(storks) | ||
205 | print("Thank you for your patience. Storks are ready for dispatch!") | 205 | print("Thank you for your patience. Storks are ready for dispatch!") | ||
206 | 206 | ||||
207 | @classmethod | 207 | @classmethod | ||
208 | def _dispatch_stork(cls, genetic_information): | 208 | def _dispatch_stork(cls, genetic_information): | ||
209 | """Dispatch an available stork in the area.""" | 209 | """Dispatch an available stork in the area.""" | ||
210 | stork_index = random.randint(0, len(cls._available_storks) - 1) | 210 | stork_index = random.randint(0, len(cls._available_storks) - 1) | ||
211 | stork = cls._available_storks.pop(stork_index) | 211 | stork = cls._available_storks.pop(stork_index) | ||
212 | stork._procure_a_baby(genetic_information) | 212 | stork._procure_a_baby(genetic_information) | ||
213 | print("Stork dispatched, please wait for your delivery.") | 213 | print("Stork dispatched, please wait for your delivery.") | ||
214 | return stork._deliver_baby() | 214 | return stork._deliver_baby() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | import random | f | 1 | import random |
2 | import re | 2 | import re | ||
3 | import threading | 3 | import threading | ||
4 | import time | 4 | import time | ||
5 | from collections import defaultdict, Counter, OrderedDict | 5 | from collections import defaultdict, Counter, OrderedDict | ||
6 | from datetime import datetime | 6 | from datetime import datetime | ||
7 | 7 | ||||
8 | 8 | ||||
9 | class CSI: | 9 | class CSI: | ||
10 | """Central Santa Intelligence.""" | 10 | """Central Santa Intelligence.""" | ||
11 | 11 | ||||
12 | _instance = None | 12 | _instance = None | ||
13 | _naughty_list = defaultdict(OrderedDict) | 13 | _naughty_list = defaultdict(OrderedDict) | ||
14 | _individuals_under_observation = {} | 14 | _individuals_under_observation = {} | ||
15 | 15 | ||||
16 | def __new__(cls, *args, **kwargs): | 16 | def __new__(cls, *args, **kwargs): | ||
17 | """There can be only one CSI.""" | 17 | """There can be only one CSI.""" | ||
18 | if cls._instance is None: | 18 | if cls._instance is None: | ||
19 | cls._instance = super().__new__(cls, *args, **kwargs) | 19 | cls._instance = super().__new__(cls, *args, **kwargs) | ||
20 | return cls._instance | 20 | return cls._instance | ||
21 | 21 | ||||
22 | @classmethod | 22 | @classmethod | ||
23 | def notify_about_new_baby(cls, individual): | 23 | def notify_about_new_baby(cls, individual): | ||
24 | """Here's your package of earthworms. How are Kevin and the kids?""" | 24 | """Here's your package of earthworms. How are Kevin and the kids?""" | ||
25 | cls._individuals_under_observation[id(individual)] = individual | 25 | cls._individuals_under_observation[id(individual)] = individual | ||
26 | 26 | ||||
27 | def notify_about_transgression(method): | 27 | def notify_about_transgression(method): | ||
28 | """CSI sees EVERYTHING.""" | 28 | """CSI sees EVERYTHING.""" | ||
29 | def decorated(*args, **kwargs): | 29 | def decorated(*args, **kwargs): | ||
30 | try: | 30 | try: | ||
31 | result = method(individual, *args, **kwargs) | 31 | result = method(individual, *args, **kwargs) | ||
32 | except Exception as err: | 32 | except Exception as err: | ||
33 | time_of_naughtiness = datetime.now() | 33 | time_of_naughtiness = datetime.now() | ||
34 | print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.") | 34 | print(f"Individual {individual} has caused a problem at {time_of_naughtiness} - {err}.") | ||
35 | CSI._naughty_list[individual][time_of_naughtiness] = err | 35 | CSI._naughty_list[individual][time_of_naughtiness] = err | ||
36 | raise | 36 | raise | ||
37 | return result | 37 | return result | ||
38 | return decorated | 38 | return decorated | ||
39 | 39 | ||||
40 | for attr_name, obj in type(individual).__dict__.items(): | 40 | for attr_name, obj in type(individual).__dict__.items(): | ||
41 | if callable(obj) and not attr_name.startswith('_'): | 41 | if callable(obj) and not attr_name.startswith('_'): | ||
42 | setattr(individual, attr_name, notify_about_transgression(obj)) | 42 | setattr(individual, attr_name, notify_about_transgression(obj)) | ||
43 | 43 | ||||
44 | @property | 44 | @property | ||
45 | def all_individuals(self): | 45 | def all_individuals(self): | ||
46 | return self._individuals_under_observation.values() | 46 | return self._individuals_under_observation.values() | ||
47 | 47 | ||||
48 | def identify_sender(self, text): | 48 | def identify_sender(self, text): | ||
49 | """Santa leaves espionage to the CSI.""" | 49 | """Santa leaves espionage to the CSI.""" | ||
50 | sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None) | 50 | sender_id = int(match.group().strip() if (match := re.search(r'^\s*\d+\s*$', text, re.M)) else None) | ||
51 | return self._individuals_under_observation[sender_id] | 51 | return self._individuals_under_observation[sender_id] | ||
52 | 52 | ||||
53 | def is_naughty(self, individual): | 53 | def is_naughty(self, individual): | ||
54 | """Assess if the individual has erred this year.""" | 54 | """Assess if the individual has erred this year.""" | ||
55 | return individual in self._naughty_list | 55 | return individual in self._naughty_list | ||
56 | 56 | ||||
57 | def prepare_for_next_christmass(self): | 57 | def prepare_for_next_christmass(self): | ||
58 | """Update the ages of people and give everyone another chance for the new year.""" | 58 | """Update the ages of people and give everyone another chance for the new year.""" | ||
59 | self._naughty_list = defaultdict(OrderedDict) | 59 | self._naughty_list = defaultdict(OrderedDict) | ||
60 | 60 | ||||
61 | 61 | ||||
62 | class Santa: | 62 | class Santa: | ||
63 | """Saint Nicholas... Or however he's called in your culture.""" | 63 | """Saint Nicholas... Or however he's called in your culture.""" | ||
64 | 64 | ||||
65 | _csi = CSI() | 65 | _csi = CSI() | ||
66 | _wishes = OrderedDict() | 66 | _wishes = OrderedDict() | ||
67 | _instance = None | 67 | _instance = None | ||
68 | _santas_private_list = {} | 68 | _santas_private_list = {} | ||
69 | 69 | ||||
70 | def __new__(cls, *args, **kwargs): | 70 | def __new__(cls, *args, **kwargs): | ||
71 | """There can be only one Santa!""" | 71 | """There can be only one Santa!""" | ||
72 | if cls._instance is None: | 72 | if cls._instance is None: | ||
73 | cls._instance = super().__new__(cls, *args, **kwargs) | 73 | cls._instance = super().__new__(cls, *args, **kwargs) | ||
74 | return cls._instance | 74 | return cls._instance | ||
75 | 75 | ||||
76 | def __call__(self, kid, request): | 76 | def __call__(self, kid, request): | ||
77 | """Call santa with a gift request.""" | 77 | """Call santa with a gift request.""" | ||
78 | self._wishes[kid] = self._extract_gift(request) | 78 | self._wishes[kid] = self._extract_gift(request) | ||
79 | 79 | ||||
80 | def __matmul__(self, letter): | 80 | def __matmul__(self, letter): | ||
81 | """Write a letter to Santa.""" | 81 | """Write a letter to Santa.""" | ||
82 | kid = self._csi.identify_sender(letter) | 82 | kid = self._csi.identify_sender(letter) | ||
83 | self._wishes[kid] = self._extract_gift(letter) | 83 | self._wishes[kid] = self._extract_gift(letter) | ||
84 | 84 | ||||
85 | def __iter__(self): | 85 | def __iter__(self): | ||
n | 86 | """Santa """ | n | 86 | """Santa is iterable, if you didn't know.""" |
87 | return iter(self._wishes.values()) | 87 | return iter(self._wishes.values()) | ||
88 | 88 | ||||
89 | def _extract_gift(self, text): | 89 | def _extract_gift(self, text): | ||
90 | """Santa takes notes of all gifts.""" | 90 | """Santa takes notes of all gifts.""" | ||
91 | return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None | 91 | return match.group() if (match := re.search(r'(?<=[\'"])[a-zA-Z\d\s]+?(?=[\'"])', text)) else None | ||
92 | 92 | ||||
93 | def xmas(self): | 93 | def xmas(self): | ||
94 | """Deliver gifts.""" | 94 | """Deliver gifts.""" | ||
95 | most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None | 95 | most_wanted = common[0][0] if (common := Counter(self._wishes.values()).most_common()) else None | ||
96 | # Make sure to give presents to the ones who called or sent letters first | 96 | # Make sure to give presents to the ones who called or sent letters first | ||
97 | kids_with_wishes = list(self._wishes.keys()) | 97 | kids_with_wishes = list(self._wishes.keys()) | ||
98 | kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes)) | 98 | kids_without_wishes = list(set(self._csi.all_individuals) - set(kids_with_wishes)) | ||
99 | for kid in kids_with_wishes + kids_without_wishes: | 99 | for kid in kids_with_wishes + kids_without_wishes: | ||
100 | if kid.age >= 18 and self._csi.is_naughty(kid): | 100 | if kid.age >= 18 and self._csi.is_naughty(kid): | ||
101 | self._santas_private_list.add(kid) | 101 | self._santas_private_list.add(kid) | ||
102 | continue | 102 | continue | ||
103 | # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad | 103 | # If there weren't any wishes, Santa doesn't care anymore and he's a bit sad | ||
104 | if kids_with_wishes and kid.age < 5: | 104 | if kids_with_wishes and kid.age < 5: | ||
105 | if self._csi.is_naughty(kid): | 105 | if self._csi.is_naughty(kid): | ||
106 | present = 'coal' | 106 | present = 'coal' | ||
107 | else: | 107 | else: | ||
108 | present = self._wishes.get(kid, most_wanted) | 108 | present = self._wishes.get(kid, most_wanted) | ||
109 | kid(present) | 109 | kid(present) | ||
110 | else: | 110 | else: | ||
111 | kid(None) # A Christmas is a Christmas even without the presents | 111 | kid(None) # A Christmas is a Christmas even without the presents | ||
112 | self._prepare_for_next_christmass() | 112 | self._prepare_for_next_christmass() | ||
113 | 113 | ||||
114 | def _prepare_for_next_christmass(self): | 114 | def _prepare_for_next_christmass(self): | ||
115 | """Prepare for next Christmas by giving everyone the benefit of the doubt.""" | 115 | """Prepare for next Christmas by giving everyone the benefit of the doubt.""" | ||
116 | self._csi.prepare_for_next_christmass() | 116 | self._csi.prepare_for_next_christmass() | ||
117 | self._wishes = OrderedDict() | 117 | self._wishes = OrderedDict() | ||
118 | 118 | ||||
119 | 119 | ||||
120 | class Kid(type): | 120 | class Kid(type): | ||
121 | 121 | ||||
122 | @staticmethod | 122 | @staticmethod | ||
123 | def _better_init(original_init): | 123 | def _better_init(original_init): | ||
124 | """Because sometimes people need a push in the right direction.""" | 124 | """Because sometimes people need a push in the right direction.""" | ||
125 | def decorated(self, *args, **kwargs): | 125 | def decorated(self, *args, **kwargs): | ||
126 | original_init(self, *args, **kwargs) | 126 | original_init(self, *args, **kwargs) | ||
127 | Person.__init__(self) | 127 | Person.__init__(self) | ||
128 | return decorated | 128 | return decorated | ||
129 | 129 | ||||
130 | @staticmethod | 130 | @staticmethod | ||
131 | def _better_new(*genetic_information): | 131 | def _better_new(*genetic_information): | ||
132 | """Because this is how babies are made, canonically speaking.""" | 132 | """Because this is how babies are made, canonically speaking.""" | ||
133 | return Stork.deliver_baby(genetic_information) | 133 | return Stork.deliver_baby(genetic_information) | ||
134 | 134 | ||||
135 | @staticmethod | 135 | @staticmethod | ||
136 | def _better_call(original_call): # Saul | 136 | def _better_call(original_call): # Saul | ||
137 | """Add an increase of age to the original call.""" | 137 | """Add an increase of age to the original call.""" | ||
138 | def decorated(self, *args, **kwargs): | 138 | def decorated(self, *args, **kwargs): | ||
139 | result = original_call(self, *args, **kwargs) | 139 | result = original_call(self, *args, **kwargs) | ||
140 | self.age += 1 | 140 | self.age += 1 | ||
141 | return result | 141 | return result | ||
142 | return decorated | 142 | return decorated | ||
143 | 143 | ||||
144 | def __new__(cls, name, bases, attr_dict): | 144 | def __new__(cls, name, bases, attr_dict): | ||
145 | """Create a type of kid.""" | 145 | """Create a type of kid.""" | ||
146 | if '__call__' not in attr_dict: | 146 | if '__call__' not in attr_dict: | ||
147 | raise NotImplementedError | 147 | raise NotImplementedError | ||
148 | attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None)) | 148 | attr_dict['__init__'] = cls._better_init(attr_dict.get('__init__', lambda _: None)) | ||
149 | attr_dict['__new__'] = cls._better_new | 149 | attr_dict['__new__'] = cls._better_new | ||
150 | attr_dict['__call__'] = cls._better_call(attr_dict['__call__']) | 150 | attr_dict['__call__'] = cls._better_call(attr_dict['__call__']) | ||
151 | return super().__new__(cls, name, bases + (Person,), attr_dict) | 151 | return super().__new__(cls, name, bases + (Person,), attr_dict) | ||
152 | 152 | ||||
153 | 153 | ||||
154 | class Person: | 154 | class Person: | ||
155 | """What is a person?""" | 155 | """What is a person?""" | ||
156 | 156 | ||||
157 | def __init__(self): | 157 | def __init__(self): | ||
n | 158 | """Initialize default attributes for each person. | n | 158 | """Initialize age for each person.""" |
159 | |||||
160 | Although don't we all start life in love and then slowly | ||||
161 | fall out of love? | ||||
162 | """ | ||||
163 | self.age = 0 | 159 | self.age = 0 | ||
t | 164 | self.in_love = False | t | ||
165 | 160 | ||||
166 | def __hash__(self): | 161 | def __hash__(self): | ||
167 | """Can you hash a person?""" | 162 | """Can you hash a person?""" | ||
168 | return hash(id(self)) | 163 | return hash(id(self)) | ||
169 | 164 | ||||
170 | 165 | ||||
171 | class Stork: | 166 | class Stork: | ||
172 | """A main worker in the baby-delivery service.""" | 167 | """A main worker in the baby-delivery service.""" | ||
173 | 168 | ||||
174 | _available_storks = [] | 169 | _available_storks = [] | ||
175 | 170 | ||||
176 | def __init__(self): | 171 | def __init__(self): | ||
177 | """Initialize carrying space for babies for the current stork.""" | 172 | """Initialize carrying space for babies for the current stork.""" | ||
178 | self.baby = [] | 173 | self.baby = [] | ||
179 | 174 | ||||
180 | def _procure_a_baby(self, genetic_information): | 175 | def _procure_a_baby(self, genetic_information): | ||
181 | """Where from? No idea.""" | 176 | """Where from? No idea.""" | ||
182 | # Part of an old implementation, left here only for the joke | 177 | # Part of an old implementation, left here only for the joke | ||
183 | # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he | 178 | # self.baby = [Baby('Baby', tuple(type(parent) for parent in parents), ({}))] # He-he | ||
184 | self.baby = [object.__new__(*genetic_information)] | 179 | self.baby = [object.__new__(*genetic_information)] | ||
185 | self._____notify_CSI() | 180 | self._____notify_CSI() | ||
186 | 181 | ||||
187 | def _____notify_CSI(self): | 182 | def _____notify_CSI(self): | ||
188 | """Nothing to see here, move along,""" | 183 | """Nothing to see here, move along,""" | ||
189 | CSI.notify_about_new_baby(self.baby[0]) | 184 | CSI.notify_about_new_baby(self.baby[0]) | ||
190 | 185 | ||||
191 | def _deliver_baby(self): | 186 | def _deliver_baby(self): | ||
192 | """Hehe, *pop*.""" | 187 | """Hehe, *pop*.""" | ||
193 | return self.baby.pop() | 188 | return self.baby.pop() | ||
194 | 189 | ||||
195 | @classmethod | 190 | @classmethod | ||
196 | def deliver_baby(cls, genetic_information): | 191 | def deliver_baby(cls, genetic_information): | ||
197 | """Deliver a baby to the happy parents.""" | 192 | """Deliver a baby to the happy parents.""" | ||
198 | threading.Thread(target=cls._request_storks).start() | 193 | threading.Thread(target=cls._request_storks).start() | ||
199 | while not cls._available_storks: | 194 | while not cls._available_storks: | ||
200 | print("There are no storks available, please wait as your call is important to us!") | 195 | print("There are no storks available, please wait as your call is important to us!") | ||
201 | time.sleep(0.03) | 196 | time.sleep(0.03) | ||
202 | return cls._dispatch_stork(genetic_information) | 197 | return cls._dispatch_stork(genetic_information) | ||
203 | 198 | ||||
204 | @classmethod | 199 | @classmethod | ||
205 | def _request_storks(cls): | 200 | def _request_storks(cls): | ||
206 | """Request for adding storks to the stork pool.""" | 201 | """Request for adding storks to the stork pool.""" | ||
207 | time.sleep(0.09) | 202 | time.sleep(0.09) | ||
208 | storks = [cls() for _ in range(random.randint(1, 10))] | 203 | storks = [cls() for _ in range(random.randint(1, 10))] | ||
209 | cls._available_storks.extend(storks) | 204 | cls._available_storks.extend(storks) | ||
210 | print("Thank you for your patience. Storks are ready for dispatch!") | 205 | print("Thank you for your patience. Storks are ready for dispatch!") | ||
211 | 206 | ||||
212 | @classmethod | 207 | @classmethod | ||
213 | def _dispatch_stork(cls, genetic_information): | 208 | def _dispatch_stork(cls, genetic_information): | ||
214 | """Dispatch an available stork in the area.""" | 209 | """Dispatch an available stork in the area.""" | ||
215 | stork_index = random.randint(0, len(cls._available_storks) - 1) | 210 | stork_index = random.randint(0, len(cls._available_storks) - 1) | ||
216 | stork = cls._available_storks.pop(stork_index) | 211 | stork = cls._available_storks.pop(stork_index) | ||
217 | stork._procure_a_baby(genetic_information) | 212 | stork._procure_a_baby(genetic_information) | ||
218 | print("Stork dispatched, please wait for your delivery.") | 213 | print("Stork dispatched, please wait for your delivery.") | ||
219 | return stork._deliver_baby() | 214 | return stork._deliver_baby() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
19.12.2024 14:40