1from decimal import localcontext, Decimal, ROUND_HALF_DOWN
2from functools import reduce
3from copy import deepcopy
4
5class Effect:
6
7 @staticmethod
8 def get_molecule_mass(name):
9 return reduce(lambda a, b: a + ord(b), name, 0)
10
11 def __init__(self, name, effect):
12 self. is_depleted = False
13 self.intensity = 1
14 self.effect = effect
15 self.molecule_mass = Effect.get_molecule_mass(name)
16
17 def __call__(self, target):
18 if self.is_depleted:
19 raise TypeError("Effect is depleted.")
20
21 for _ in range(self.intensity):
22 self.effect(target)
23 self.is_depleted = True
24
25 def reapply(self, target):
26 for _ in range(self.intensity):
27 self.effect(target)
28
29
30class Potion:
31
32 def __init__(self, effects, duration):
33 self.is_something_bigger = False
34 self.is_depleted = False
35 self.effects = {name: Effect(name, effect) for name, effect in effects.items()}
36 self.duration = duration
37
38 def __getattr__(self, name):
39 if name in self.effects:
40 if self.is_something_bigger:
41 raise TypeError(
42 "Potion is now part of something bigger than itself.")
43
44 if self.is_depleted:
45 raise TypeError("Potion is depleted.")
46
47 return self.effects[name]
48
49 raise AttributeError(f"No such effect: {name}")
50
51 def get_check_for_deep_meaning_decorator(is_target):
52 def check_for_deep_meaning_decorator(fun):
53 def check_for_deep_meaning(self, target):
54 if self.is_something_bigger or (is_target and target.is_something_bigger):
55 raise TypeError("Potion is now part of something bigger than itself.")
56
57 if self.is_depleted or (is_target and target.is_depleted):
58 raise TypeError("Potion is depleted.")
59
60 return fun(self, target)
61 return check_for_deep_meaning
62 return check_for_deep_meaning_decorator
63
64 def get_is_something_bigger_decorator(is_target):
65 def is_something_bigger_decorator(fun):
66 def is_something_bigger(self, target):
67 self.is_something_bigger = True
68 if is_target:
69 target.is_something_bigger = True
70 return fun(self, target)
71 return is_something_bigger
72 return is_something_bigger_decorator
73
74 @get_check_for_deep_meaning_decorator(True)
75 @get_is_something_bigger_decorator(True)
76 def __add__(self, other):
77 new_duration = max(self.duration, other.duration)
78 not_used_effects_potion_1 = filter(
79 lambda item: not item[1].is_depleted, self.effects.items())
80 not_used_effects_potion_2 = filter(
81 lambda item: not item[1].is_depleted, other.effects.items())
82 new_effects = dict(not_used_effects_potion_1)
83
84 for key, effect in not_used_effects_potion_2:
85 if key in new_effects:
86 new_effects[key].intensity += effect.intensity
87 else:
88 new_effects[key] = effect
89
90 new_potion = Potion({}, new_duration)
91 new_potion.effects = new_effects
92
93 return new_potion
94
95 @staticmethod
96 def round_half_down(num):
97 with localcontext() as ctx:
98 ctx.rounding = ROUND_HALF_DOWN
99 return int(Decimal(num).to_integral_value())
100
101 @get_check_for_deep_meaning_decorator(False)
102 @get_is_something_bigger_decorator(False)
103 def __mul__(self, number):
104 new_effects = {}
105
106 for key, effect in self.effects.items():
107 if effect.is_depleted:
108 continue
109
110 new_effects[key] = Effect(key, effect.effect)
111 new_effects[key].intensity = Potion.round_half_down(effect.intensity * number)
112
113 new_potion = Potion({}, self.duration)
114 new_potion.effects = new_effects
115
116 return new_potion
117
118 @get_check_for_deep_meaning_decorator(True)
119 @get_is_something_bigger_decorator(True)
120 def __sub__(self, target):
121 new_effects = {}
122
123 for key, effect in target.effects.items():
124 if key not in self.effects:
125 raise TypeError("Throwing Beans")
126
127 if effect.is_depleted or self.effects[key].is_depleted:
128 continue
129
130 new_effect = Effect(key, effect.effect)
131 new_effect.intensity = self.effects[key].intensity - effect.intensity
132 if new_effect.intensity <= 0:
133 continue
134 new_effects[key] = new_effect
135
136 for key, effect in self.effects.items():
137 if key not in target.effects or (target.effects[key].is_depleted and not effect.is_depleted):
138 new_effects[key] = effect
139
140 new_potion = Potion({}, self.duration)
141 new_potion.effects = new_effects
142 return new_potion
143
144 @get_check_for_deep_meaning_decorator(False)
145 @get_is_something_bigger_decorator(False)
146 def __truediv__(self, number):
147 new_effects = {}
148
149 for key, effect in self.effects.items():
150 if effect.is_depleted:
151 continue
152
153 new_effects[key] = effect
154 new_effects[key].intensity = Potion.round_half_down(effect.intensity / number)
155
156 def create_new_potion():
157 new_potion = Potion({}, self.duration)
158 copy_new_effects = {}
159
160 for name, effect in new_effects.items():
161 copy_new_effects[name] = Effect(name, effect.effect)
162 copy_new_effects[name].intensity = effect.intensity
163
164 new_potion.effects = copy_new_effects
165 return new_potion
166 return (create_new_potion() for _ in range(number))
167
168 @get_check_for_deep_meaning_decorator(True)
169 def __eq__(self, other):
170 if(self.effects.keys() != other.effects.keys()):
171 return False
172
173 for key, effect in self.effects.items():
174 if effect.is_depleted:
175 effect.intensity = 0
176
177 if other.effects[key].is_depleted:
178 other.effects[key].intensity = 0
179
180 if effect.intensity != other.effects[key].intensity:
181 return False
182
183 return True
184
185 @get_check_for_deep_meaning_decorator(True)
186 def __lt__(self, other):
187 left_part = sum(effect.intensity if not effect.is_depleted else 0 for effect in self.effects.values())
188 right_part = sum(effect.intensity if not effect.is_depleted else 0 for effect in other.effects.values())
189 return left_part < right_part
190
191
192 @property
193 def effects_for_potions(self):
194 not_used_effects = filter(lambda effect: not effect.is_depleted, self.effects.values())
195 sorted_not_used_effects = sorted(not_used_effects, key=lambda effect: effect.molecule_mass, reverse=True)
196 return list(sorted_not_used_effects)
197
198
199 @get_check_for_deep_meaning_decorator(False)
200 def apply(self, target):
201 self.is_depleted = True
202 effects = self.effects_for_potions
203
204 for effect in effects:
205 effect(target)
206
207 return effects
208
209
210
211class EnchantedTarget:
212
213 def __init__(self, target):
214 self.target = target
215 self.target_dict = deepcopy(target.__dict__)
216 self.active_potions = []
217
218 def add_potion(self, potion, active_to):
219 self.active_potions.append((potion.apply(self.target), active_to))
220
221 def tick(self, time):
222 still_active_potions = list(filter(lambda potion: potion[1] > time, self.active_potions))
223
224 self.target.__dict__ = deepcopy(self.target_dict)
225 for potion in still_active_potions:
226 for effect in potion[0]:
227 effect.reapply(self.target)
228
229 self.active_potions = still_active_potions
230
231
232
233class ГоспожатаПоХимия:
234
235 def __init__(self):
236 self.timer = 0
237 self.narcos = {}
238
239 def apply(self, target, potion):
240 if potion.duration <= 0:
241 return
242
243 target_id = id(target)
244 if target_id not in self.narcos:
245 self.narcos[target_id] = EnchantedTarget(target)
246
247 self.narcos[target_id].add_potion(potion, self.timer + potion.duration)
248
249 def tick(self):
250 self.timer += 1
251
252 for enchanted_target in self.narcos.values():
253 enchanted_target.tick(self.timer)
....................
----------------------------------------------------------------------
Ran 20 tests in 0.002s
OK
Георги Кунчев
05.12.2023 16:51Е, да. Всеки път ще е, но това не мисля, че е голяма драма.
|
Михаил Цанков
05.12.2023 16:31```
Методът можеш да достъпиш и с self. Просто споделям, не казвам, че е по-добре.
Аз бих направил този метод като @property, или пък направо като __lt__, за да сравнявам обекти с него.
```
Ако е пропърти няма ли да се изчислява всеки път като се извика. #cutting-edge-speed
|
Михаил Цанков
05.12.2023 13:26Pep8 e най трудното предизвикателство в курса. Може би може да направите догодина по-подробна лекция за клийн код, защото си е едно от най-важните неща, което може да се научи от курса според мен.
|
Михаил Цанков
05.12.2023 13:24Ще кача нова версия със подобрения, но ще е малко преди крайния срок.
Не знаех че трябва да пишем по малко нови редове, аз определено слагам доста. Също за атрибутите на класа - трябва да си настроя мозъка, че не трябва да ги пиша там също определено е грешка... ще го избягвам за в бъдеще
|
Георги Кунчев
05.12.2023 10:28Бях на кантар дали да ти дам бонус точка, защото оставих доста коментари за стила. Да, някои от тях са субективни, но има и общоприети неща, за които се "оплаках". Поради няколкото интересни имплементации на парчета код, както и качеството на кода като функционалност, давам една бонус точка.
|
f | 1 | from decimal import localcontext, Decimal, ROUND_HALF_DOWN | f | 1 | from decimal import localcontext, Decimal, ROUND_HALF_DOWN |
2 | from functools import reduce | 2 | from functools import reduce | ||
3 | from copy import deepcopy | 3 | from copy import deepcopy | ||
4 | 4 | ||||
5 | class Effect: | 5 | class Effect: | ||
n | 6 | is_depleted = False | n | 6 | |
7 | intensity = 1 | ||||
8 | molecule_mass = 0 | ||||
9 | effect = None | ||||
10 | |||||
11 | @staticmethod | 7 | @staticmethod | ||
12 | def get_molecule_mass(name): | 8 | def get_molecule_mass(name): | ||
13 | return reduce(lambda a, b: a + ord(b), name, 0) | 9 | return reduce(lambda a, b: a + ord(b), name, 0) | ||
14 | 10 | ||||
15 | def __init__(self, name, effect): | 11 | def __init__(self, name, effect): | ||
n | n | 12 | self. is_depleted = False | ||
13 | self.intensity = 1 | ||||
16 | self.effect = effect | 14 | self.effect = effect | ||
17 | self.molecule_mass = Effect.get_molecule_mass(name) | 15 | self.molecule_mass = Effect.get_molecule_mass(name) | ||
18 | 16 | ||||
19 | def __call__(self, target): | 17 | def __call__(self, target): | ||
20 | if self.is_depleted: | 18 | if self.is_depleted: | ||
21 | raise TypeError("Effect is depleted.") | 19 | raise TypeError("Effect is depleted.") | ||
22 | 20 | ||||
23 | for _ in range(self.intensity): | 21 | for _ in range(self.intensity): | ||
24 | self.effect(target) | 22 | self.effect(target) | ||
25 | self.is_depleted = True | 23 | self.is_depleted = True | ||
26 | 24 | ||||
27 | def reapply(self, target): | 25 | def reapply(self, target): | ||
28 | for _ in range(self.intensity): | 26 | for _ in range(self.intensity): | ||
29 | self.effect(target) | 27 | self.effect(target) | ||
30 | 28 | ||||
31 | 29 | ||||
32 | class Potion: | 30 | class Potion: | ||
n | 33 | duration = 0 | n | 31 | |
34 | is_something_bigger = False | ||||
35 | is_depleted = False | ||||
36 | |||||
37 | def __init__(self, effects, duration): | 32 | def __init__(self, effects, duration): | ||
n | 38 | self.effects = {name: Effect(name, effect) | n | 33 | self.is_something_bigger = False |
39 | for name, effect in effects.items()} | 34 | self.is_depleted = False | ||
35 | self.effects = {name: Effect(name, effect) for name, effect in effects.items()} | ||||
40 | self.duration = duration | 36 | self.duration = duration | ||
41 | 37 | ||||
42 | def __getattr__(self, name): | 38 | def __getattr__(self, name): | ||
43 | if name in self.effects: | 39 | if name in self.effects: | ||
44 | if self.is_something_bigger: | 40 | if self.is_something_bigger: | ||
45 | raise TypeError( | 41 | raise TypeError( | ||
46 | "Potion is now part of something bigger than itself.") | 42 | "Potion is now part of something bigger than itself.") | ||
n | 47 | n | 43 | ||
48 | if self.is_depleted: | 44 | if self.is_depleted: | ||
n | 49 | raise TypeError( | n | ||
50 | "Potion is depleted.") | 45 | raise TypeError("Potion is depleted.") | ||
51 | 46 | ||||
52 | return self.effects[name] | 47 | return self.effects[name] | ||
53 | 48 | ||||
n | 54 | raise AttributeError("No such effect: " + name) | n | 49 | raise AttributeError(f"No such effect: {name}") |
55 | 50 | ||||
56 | def get_check_for_deep_meaning_decorator(is_target): | 51 | def get_check_for_deep_meaning_decorator(is_target): | ||
57 | def check_for_deep_meaning_decorator(fun): | 52 | def check_for_deep_meaning_decorator(fun): | ||
58 | def check_for_deep_meaning(self, target): | 53 | def check_for_deep_meaning(self, target): | ||
59 | if self.is_something_bigger or (is_target and target.is_something_bigger): | 54 | if self.is_something_bigger or (is_target and target.is_something_bigger): | ||
n | 60 | raise TypeError( | n | ||
61 | "Potion is now part of something bigger than itself.") | 55 | raise TypeError("Potion is now part of something bigger than itself.") | ||
56 | |||||
57 | if self.is_depleted or (is_target and target.is_depleted): | ||||
58 | raise TypeError("Potion is depleted.") | ||||
62 | 59 | ||||
n | 63 | if self.is_depleted or (is_target and target.is_depleted): | n | ||
64 | raise TypeError( | ||||
65 | "Potion is depleted.") | ||||
66 | |||||
67 | return fun(self, target) | 60 | return fun(self, target) | ||
n | 68 | n | |||
69 | return check_for_deep_meaning | 61 | return check_for_deep_meaning | ||
n | 70 | n | |||
71 | return check_for_deep_meaning_decorator | 62 | return check_for_deep_meaning_decorator | ||
72 | 63 | ||||
73 | def get_is_something_bigger_decorator(is_target): | 64 | def get_is_something_bigger_decorator(is_target): | ||
74 | def is_something_bigger_decorator(fun): | 65 | def is_something_bigger_decorator(fun): | ||
75 | def is_something_bigger(self, target): | 66 | def is_something_bigger(self, target): | ||
76 | self.is_something_bigger = True | 67 | self.is_something_bigger = True | ||
n | 77 | if (is_target): | n | 68 | if is_target: |
78 | target.is_something_bigger = True | 69 | target.is_something_bigger = True | ||
n | 79 | n | |||
80 | return fun(self, target) | 70 | return fun(self, target) | ||
n | 81 | n | |||
82 | return is_something_bigger | 71 | return is_something_bigger | ||
n | 83 | n | |||
84 | return is_something_bigger_decorator | 72 | return is_something_bigger_decorator | ||
85 | 73 | ||||
86 | @get_check_for_deep_meaning_decorator(True) | 74 | @get_check_for_deep_meaning_decorator(True) | ||
87 | @get_is_something_bigger_decorator(True) | 75 | @get_is_something_bigger_decorator(True) | ||
88 | def __add__(self, other): | 76 | def __add__(self, other): | ||
89 | new_duration = max(self.duration, other.duration) | 77 | new_duration = max(self.duration, other.duration) | ||
n | 90 | n | |||
91 | not_used_effects_potion_1 = filter( | 78 | not_used_effects_potion_1 = filter( | ||
92 | lambda item: not item[1].is_depleted, self.effects.items()) | 79 | lambda item: not item[1].is_depleted, self.effects.items()) | ||
93 | not_used_effects_potion_2 = filter( | 80 | not_used_effects_potion_2 = filter( | ||
94 | lambda item: not item[1].is_depleted, other.effects.items()) | 81 | lambda item: not item[1].is_depleted, other.effects.items()) | ||
n | 95 | n | |||
96 | new_effects = dict(not_used_effects_potion_1) | 82 | new_effects = dict(not_used_effects_potion_1) | ||
97 | 83 | ||||
98 | for key, effect in not_used_effects_potion_2: | 84 | for key, effect in not_used_effects_potion_2: | ||
99 | if key in new_effects: | 85 | if key in new_effects: | ||
100 | new_effects[key].intensity += effect.intensity | 86 | new_effects[key].intensity += effect.intensity | ||
101 | else: | 87 | else: | ||
102 | new_effects[key] = effect | 88 | new_effects[key] = effect | ||
103 | 89 | ||||
104 | new_potion = Potion({}, new_duration) | 90 | new_potion = Potion({}, new_duration) | ||
105 | new_potion.effects = new_effects | 91 | new_potion.effects = new_effects | ||
106 | 92 | ||||
107 | return new_potion | 93 | return new_potion | ||
108 | 94 | ||||
109 | @staticmethod | 95 | @staticmethod | ||
110 | def round_half_down(num): | 96 | def round_half_down(num): | ||
111 | with localcontext() as ctx: | 97 | with localcontext() as ctx: | ||
112 | ctx.rounding = ROUND_HALF_DOWN | 98 | ctx.rounding = ROUND_HALF_DOWN | ||
113 | return int(Decimal(num).to_integral_value()) | 99 | return int(Decimal(num).to_integral_value()) | ||
114 | 100 | ||||
115 | @get_check_for_deep_meaning_decorator(False) | 101 | @get_check_for_deep_meaning_decorator(False) | ||
116 | @get_is_something_bigger_decorator(False) | 102 | @get_is_something_bigger_decorator(False) | ||
117 | def __mul__(self, number): | 103 | def __mul__(self, number): | ||
n | 118 | new_duration = self.duration | n | ||
119 | |||||
120 | new_effects = {} | 104 | new_effects = {} | ||
121 | 105 | ||||
122 | for key, effect in self.effects.items(): | 106 | for key, effect in self.effects.items(): | ||
123 | if effect.is_depleted: | 107 | if effect.is_depleted: | ||
124 | continue | 108 | continue | ||
125 | 109 | ||||
126 | new_effects[key] = Effect(key, effect.effect) | 110 | new_effects[key] = Effect(key, effect.effect) | ||
n | 127 | new_effects[key].intensity = Potion.round_half_down( | n | 111 | new_effects[key].intensity = Potion.round_half_down(effect.intensity * number) |
128 | effect.intensity * number) | ||||
129 | 112 | ||||
n | 130 | new_potion = Potion({}, new_duration) | n | 113 | new_potion = Potion({}, self.duration) |
131 | new_potion.effects = new_effects | 114 | new_potion.effects = new_effects | ||
132 | 115 | ||||
133 | return new_potion | 116 | return new_potion | ||
134 | 117 | ||||
135 | @get_check_for_deep_meaning_decorator(True) | 118 | @get_check_for_deep_meaning_decorator(True) | ||
136 | @get_is_something_bigger_decorator(True) | 119 | @get_is_something_bigger_decorator(True) | ||
137 | def __sub__(self, target): | 120 | def __sub__(self, target): | ||
n | 138 | n | |||
139 | new_effects = {} | 121 | new_effects = {} | ||
140 | 122 | ||||
141 | for key, effect in target.effects.items(): | 123 | for key, effect in target.effects.items(): | ||
142 | if key not in self.effects: | 124 | if key not in self.effects: | ||
143 | raise TypeError("Throwing Beans") | 125 | raise TypeError("Throwing Beans") | ||
144 | 126 | ||||
n | 145 | n | |||
146 | if effect.is_depleted or self.effects[key].is_depleted: | 127 | if effect.is_depleted or self.effects[key].is_depleted: | ||
147 | continue | 128 | continue | ||
148 | 129 | ||||
149 | new_effect = Effect(key, effect.effect) | 130 | new_effect = Effect(key, effect.effect) | ||
150 | new_effect.intensity = self.effects[key].intensity - effect.intensity | 131 | new_effect.intensity = self.effects[key].intensity - effect.intensity | ||
n | 151 | n | |||
152 | if new_effect.intensity <= 0: | 132 | if new_effect.intensity <= 0: | ||
153 | continue | 133 | continue | ||
n | 154 | n | |||
155 | new_effects[key] = new_effect | 134 | new_effects[key] = new_effect | ||
156 | 135 | ||||
157 | for key, effect in self.effects.items(): | 136 | for key, effect in self.effects.items(): | ||
158 | if key not in target.effects or (target.effects[key].is_depleted and not effect.is_depleted): | 137 | if key not in target.effects or (target.effects[key].is_depleted and not effect.is_depleted): | ||
159 | new_effects[key] = effect | 138 | new_effects[key] = effect | ||
n | 160 | n | 139 | ||
161 | new_potion = Potion({}, self.duration) | 140 | new_potion = Potion({}, self.duration) | ||
162 | new_potion.effects = new_effects | 141 | new_potion.effects = new_effects | ||
n | 163 | n | |||
164 | return new_potion | 142 | return new_potion | ||
165 | 143 | ||||
166 | @get_check_for_deep_meaning_decorator(False) | 144 | @get_check_for_deep_meaning_decorator(False) | ||
167 | @get_is_something_bigger_decorator(False) | 145 | @get_is_something_bigger_decorator(False) | ||
168 | def __truediv__(self, number): | 146 | def __truediv__(self, number): | ||
n | 169 | n | |||
170 | new_effects = {} | 147 | new_effects = {} | ||
171 | 148 | ||||
172 | for key, effect in self.effects.items(): | 149 | for key, effect in self.effects.items(): | ||
173 | if effect.is_depleted: | 150 | if effect.is_depleted: | ||
174 | continue | 151 | continue | ||
175 | 152 | ||||
176 | new_effects[key] = effect | 153 | new_effects[key] = effect | ||
n | 177 | new_effects[key].intensity = Potion.round_half_down( | n | 154 | new_effects[key].intensity = Potion.round_half_down(effect.intensity / number) |
178 | effect.intensity / number) | ||||
179 | 155 | ||||
180 | def create_new_potion(): | 156 | def create_new_potion(): | ||
181 | new_potion = Potion({}, self.duration) | 157 | new_potion = Potion({}, self.duration) | ||
n | 182 | n | |||
183 | copy_new_effects = {} | 158 | copy_new_effects = {} | ||
n | n | 159 | |||
184 | for name, effect in new_effects.items(): | 160 | for name, effect in new_effects.items(): | ||
185 | copy_new_effects[name] = Effect(name, effect.effect) | 161 | copy_new_effects[name] = Effect(name, effect.effect) | ||
186 | copy_new_effects[name].intensity = effect.intensity | 162 | copy_new_effects[name].intensity = effect.intensity | ||
187 | 163 | ||||
188 | new_potion.effects = copy_new_effects | 164 | new_potion.effects = copy_new_effects | ||
n | 189 | n | |||
190 | return new_potion | 165 | return new_potion | ||
n | 191 | n | |||
192 | return (create_new_potion() for _ in range(number)) | 166 | return (create_new_potion() for _ in range(number)) | ||
193 | 167 | ||||
194 | @get_check_for_deep_meaning_decorator(True) | 168 | @get_check_for_deep_meaning_decorator(True) | ||
195 | def __eq__(self, other): | 169 | def __eq__(self, other): | ||
196 | if(self.effects.keys() != other.effects.keys()): | 170 | if(self.effects.keys() != other.effects.keys()): | ||
197 | return False | 171 | return False | ||
198 | 172 | ||||
199 | for key, effect in self.effects.items(): | 173 | for key, effect in self.effects.items(): | ||
200 | if effect.is_depleted: | 174 | if effect.is_depleted: | ||
201 | effect.intensity = 0 | 175 | effect.intensity = 0 | ||
n | 202 | n | 176 | ||
203 | if other.effects[key].is_depleted: | 177 | if other.effects[key].is_depleted: | ||
204 | other.effects[key].intensity = 0 | 178 | other.effects[key].intensity = 0 | ||
n | 205 | n | 179 | ||
206 | if effect.intensity != other.effects[key].intensity: | 180 | if effect.intensity != other.effects[key].intensity: | ||
207 | return False | 181 | return False | ||
208 | 182 | ||||
209 | return True | 183 | return True | ||
210 | 184 | ||||
211 | @get_check_for_deep_meaning_decorator(True) | 185 | @get_check_for_deep_meaning_decorator(True) | ||
212 | def __lt__(self, other): | 186 | def __lt__(self, other): | ||
n | 213 | return sum(effect.intensity if not effect.is_depleted | n | 187 | left_part = sum(effect.intensity if not effect.is_depleted else 0 for effect in self.effects.values()) |
214 | else 0 for effect in self.effects.values()) < sum(effect.intensity if not effect.is_depleted | 188 | right_part = sum(effect.intensity if not effect.is_depleted else 0 for effect in other.effects.values()) | ||
215 | else 0 for effect in other.effects.values()) | 189 | return left_part < right_part | ||
216 | 190 | ||||
n | n | 191 | |||
192 | @property | ||||
193 | def effects_for_potions(self): | ||||
194 | not_used_effects = filter(lambda effect: not effect.is_depleted, self.effects.values()) | ||||
195 | sorted_not_used_effects = sorted(not_used_effects, key=lambda effect: effect.molecule_mass, reverse=True) | ||||
196 | return list(sorted_not_used_effects) | ||||
197 | |||||
198 | |||||
217 | @get_check_for_deep_meaning_decorator(False) | 199 | @get_check_for_deep_meaning_decorator(False) | ||
218 | def apply(self, target): | 200 | def apply(self, target): | ||
219 | self.is_depleted = True | 201 | self.is_depleted = True | ||
t | 220 | t | 202 | effects = self.effects_for_potions | |
221 | effects = list(sorted(filter(lambda effect: not effect.is_depleted, self.effects.values()) , key=lambda effect: effect.molecule_mass, reverse=True)) | ||||
222 | 203 | ||||
223 | for effect in effects: | 204 | for effect in effects: | ||
224 | effect(target) | 205 | effect(target) | ||
225 | 206 | ||||
226 | return effects | 207 | return effects | ||
227 | 208 | ||||
228 | 209 | ||||
229 | 210 | ||||
230 | class EnchantedTarget: | 211 | class EnchantedTarget: | ||
231 | 212 | ||||
232 | def __init__(self, target): | 213 | def __init__(self, target): | ||
233 | self.target = target | 214 | self.target = target | ||
234 | self.target_dict = deepcopy(target.__dict__) | 215 | self.target_dict = deepcopy(target.__dict__) | ||
235 | self.active_potions = [] | 216 | self.active_potions = [] | ||
236 | 217 | ||||
237 | def add_potion(self, potion, active_to): | 218 | def add_potion(self, potion, active_to): | ||
238 | self.active_potions.append((potion.apply(self.target), active_to)) | 219 | self.active_potions.append((potion.apply(self.target), active_to)) | ||
239 | 220 | ||||
240 | def tick(self, time): | 221 | def tick(self, time): | ||
241 | still_active_potions = list(filter(lambda potion: potion[1] > time, self.active_potions)) | 222 | still_active_potions = list(filter(lambda potion: potion[1] > time, self.active_potions)) | ||
242 | 223 | ||||
243 | self.target.__dict__ = deepcopy(self.target_dict) | 224 | self.target.__dict__ = deepcopy(self.target_dict) | ||
244 | for potion in still_active_potions: | 225 | for potion in still_active_potions: | ||
245 | for effect in potion[0]: | 226 | for effect in potion[0]: | ||
246 | effect.reapply(self.target) | 227 | effect.reapply(self.target) | ||
247 | 228 | ||||
248 | self.active_potions = still_active_potions | 229 | self.active_potions = still_active_potions | ||
249 | 230 | ||||
250 | 231 | ||||
251 | 232 | ||||
252 | class ГоспожатаПоХимия: | 233 | class ГоспожатаПоХимия: | ||
253 | 234 | ||||
254 | def __init__(self): | 235 | def __init__(self): | ||
255 | self.timer = 0 | 236 | self.timer = 0 | ||
256 | self.narcos = {} | 237 | self.narcos = {} | ||
257 | 238 | ||||
258 | def apply(self, target, potion): | 239 | def apply(self, target, potion): | ||
259 | if potion.duration <= 0: | 240 | if potion.duration <= 0: | ||
260 | return | 241 | return | ||
261 | 242 | ||||
262 | target_id = id(target) | 243 | target_id = id(target) | ||
263 | if target_id not in self.narcos: | 244 | if target_id not in self.narcos: | ||
264 | self.narcos[target_id] = EnchantedTarget(target) | 245 | self.narcos[target_id] = EnchantedTarget(target) | ||
265 | 246 | ||||
266 | self.narcos[target_id].add_potion(potion, self.timer + potion.duration) | 247 | self.narcos[target_id].add_potion(potion, self.timer + potion.duration) | ||
267 | 248 | ||||
268 | def tick(self): | 249 | def tick(self): | ||
269 | self.timer += 1 | 250 | self.timer += 1 | ||
270 | 251 | ||||
271 | for enchanted_target in self.narcos.values(): | 252 | for enchanted_target in self.narcos.values(): | ||
272 | enchanted_target.tick(self.timer) | 253 | enchanted_target.tick(self.timer) | ||
273 | 254 | ||||
274 | 255 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|