Домашни > Работилница за отвари! > Решения > Решението на Михаил Цанков

Резултати
10 точки от тестове
1 точки от учител

11 точки общо

20 успешни теста
0 неуспешни теста
Код (v2 hope it still works 🤞)

  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:26

Pep8 e най трудното предизвикателство в курса. Може би може да направите догодина по-подробна лекция за клийн код, защото си е едно от най-важните неща, което може да се научи от курса според мен.
Михаил Цанков
05.12.2023 13:24

Ще кача нова версия със подобрения, но ще е малко преди крайния срок. Не знаех че трябва да пишем по малко нови редове, аз определено слагам доста. Също за атрибутите на класа - трябва да си настроя мозъка, че не трябва да ги пиша там също определено е грешка... ще го избягвам за в бъдеще
Георги Кунчев
05.12.2023 10:28

Бях на кантар дали да ти дам бонус точка, защото оставих доста коментари за стила. Да, някои от тях са субективни, но има и общоприети неща, за които се "оплаках". Поради няколкото интересни имплементации на парчета код, както и качеството на кода като функционалност, давам една бонус точка.
История

f1from decimal import localcontext, Decimal, ROUND_HALF_DOWNf1from decimal import localcontext, Decimal, ROUND_HALF_DOWN
2from functools import reduce2from functools import reduce
3from copy import deepcopy3from copy import deepcopy
44
5class Effect:5class Effect:
n6    is_depleted = Falsen6   
7    intensity = 1
8    molecule_mass = 0
9    effect = None
10 
11    @staticmethod7    @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)
1410
15    def __init__(self, name, effect):11    def __init__(self, name, effect):
nn12        self. is_depleted = False
13        self.intensity = 1
16        self.effect = effect14        self.effect = effect
17        self.molecule_mass = Effect.get_molecule_mass(name)15        self.molecule_mass = Effect.get_molecule_mass(name)
1816
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.")
2220
23        for _ in range(self.intensity):21        for _ in range(self.intensity):
24            self.effect(target)22            self.effect(target)
25        self.is_depleted = True23        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)
3028
3129
32class Potion:30class Potion:
n33    duration = 0n31    
34    is_something_bigger = False
35    is_depleted = False
36 
37    def __init__(self, effects, duration):32    def __init__(self, effects, duration):
n38        self.effects = {name: Effect(name, effect)n33        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 = duration36        self.duration = duration
4137
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.")
n47            n43 
48            if self.is_depleted:44            if self.is_depleted:
n49                    raise TypeError(n
50                        "Potion is depleted.")45                    raise TypeError("Potion is depleted.")
5146
52            return self.effects[name]47            return self.effects[name]
5348
n54        raise AttributeError("No such effect: " + name)n49        raise AttributeError(f"No such effect: {name}")
5550
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):
n60                    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                
n63                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)
n68 n
69            return check_for_deep_meaning61            return check_for_deep_meaning
n70 n
71        return check_for_deep_meaning_decorator62        return check_for_deep_meaning_decorator
7263
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 = True67                self.is_something_bigger = True
n77                if (is_target):n68                if is_target:
78                    target.is_something_bigger = True69                    target.is_something_bigger = True
n79 n
80                return fun(self, target)70                return fun(self, target)
n81 n
82            return is_something_bigger71            return is_something_bigger
n83 n
84        return is_something_bigger_decorator72        return is_something_bigger_decorator
8573
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)
n90 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())
n95 n
96        new_effects = dict(not_used_effects_potion_1)82        new_effects = dict(not_used_effects_potion_1)
9783
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.intensity86                new_effects[key].intensity += effect.intensity
101            else:87            else:
102                new_effects[key] = effect88                new_effects[key] = effect
10389
104        new_potion = Potion({}, new_duration)90        new_potion = Potion({}, new_duration)
105        new_potion.effects = new_effects91        new_potion.effects = new_effects
10692
107        return new_potion93        return new_potion
10894
109    @staticmethod95    @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_DOWN98            ctx.rounding = ROUND_HALF_DOWN
113            return int(Decimal(num).to_integral_value())99            return int(Decimal(num).to_integral_value())
114100
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):
n118        new_duration = self.durationn
119 
120        new_effects = {}104        new_effects = {}
121105
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                continue108                continue
125109
126            new_effects[key] = Effect(key, effect.effect)110            new_effects[key] = Effect(key, effect.effect)
n127            new_effects[key].intensity = Potion.round_half_down(n111            new_effects[key].intensity = Potion.round_half_down(effect.intensity * number)
128                effect.intensity * number)
129112
n130        new_potion = Potion({}, new_duration)n113        new_potion = Potion({}, self.duration)
131        new_potion.effects = new_effects114        new_potion.effects = new_effects
132115
133        return new_potion116        return new_potion
134117
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):
n138 n
139        new_effects = {}121        new_effects = {}
140122
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")
144126
n145 n
146            if effect.is_depleted or self.effects[key].is_depleted:127            if effect.is_depleted or self.effects[key].is_depleted:
147                continue128                continue
148129
149            new_effect = Effect(key, effect.effect)130            new_effect = Effect(key, effect.effect)
150            new_effect.intensity = self.effects[key].intensity - effect.intensity131            new_effect.intensity = self.effects[key].intensity - effect.intensity
n151 n
152            if new_effect.intensity <= 0:132            if new_effect.intensity <= 0:
153                continue133                continue
n154 n
155            new_effects[key] = new_effect134            new_effects[key] = new_effect
156135
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] = effect138                new_effects[key] = effect
n160 n139        
161        new_potion = Potion({}, self.duration)140        new_potion = Potion({}, self.duration)
162        new_potion.effects = new_effects141        new_potion.effects = new_effects
n163 n
164        return new_potion142        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):
n169 n
170        new_effects = {}147        new_effects = {}
171148
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                continue151                continue
175152
176            new_effects[key] = effect153            new_effects[key] = effect
n177            new_effects[key].intensity = Potion.round_half_down(n154            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)
n182 n
183            copy_new_effects = {}158            copy_new_effects = {}
nn159 
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.intensity162                copy_new_effects[name].intensity = effect.intensity
187            163            
188            new_potion.effects = copy_new_effects164            new_potion.effects = copy_new_effects
n189 n
190            return new_potion165            return new_potion
n191 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 False171            return False
198172
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 = 0175                effect.intensity = 0
n202            n176 
203            if other.effects[key].is_depleted:177            if other.effects[key].is_depleted:
204                other.effects[key].intensity = 0178                other.effects[key].intensity = 0
n205            n179 
206            if effect.intensity != other.effects[key].intensity:180            if effect.intensity != other.effects[key].intensity:
207                return False181                return False
208        182        
209        return True183        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):
n213        return sum(effect.intensity if not effect.is_depleted n187        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            
nn191    
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 = True201        self.is_depleted = True
t220        t202        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))
222203
223        for effect in effects:204        for effect in effects:
224            effect(target)205            effect(target)
225206
226        return effects207        return effects
227    208    
228209
229210
230class EnchantedTarget:211class EnchantedTarget:
231    212    
232    def __init__(self, target):213    def __init__(self, target):
233        self.target = target214        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 = []
236217
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))
239220
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_potions229        self.active_potions = still_active_potions
249    230    
250231
251232
252class ГоспожатаПоХимия:233class ГоспожатаПоХимия:
253234
254    def __init__(self):235    def __init__(self):
255        self.timer = 0236        self.timer = 0
256        self.narcos = {}237        self.narcos = {}
257238
258    def apply(self, target, potion):239    def apply(self, target, potion):
259        if potion.duration <= 0:240        if potion.duration <= 0:
260            return241            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)
265246
266        self.narcos[target_id].add_potion(potion, self.timer + potion.duration)247        self.narcos[target_id].add_potion(potion, self.timer + potion.duration)
267248
268    def tick(self):249    def tick(self):
269        self.timer += 1250        self.timer += 1
270251
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)
273254
274255
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op