1from types import MethodType
2
3class Potion:
4
5 def __init__(self, effects, duration):
6 self.effects = effects
7 self.duration = duration
8 self.applied_buffs = set()
9 self.used_for_the_greater_good = False
10 self.ticks = duration
11 self.effect_intensity = {effect: 1 for effect in effects}
12 for effect_name, effect_func in effects.items():
13 method = MethodType(self.create_method(effect_name, effect_func), self)
14 setattr(self, effect_name, method)
15
16 #помощна фунция за създаване на методи
17 def create_method(self, effect_name, effect_func):
18 def effect_method(self, target):
19 if effect_name in self.applied_buffs:
20 raise TypeError('Effect is depleted.')
21 if self.used_for_the_greater_good:
22 raise TypeError('Potion is now part of something bigger than itself.')
23
24 if self.effect_intensity[effect_name]:
25 for _ in range(self.effect_intensity[effect_name]):
26 effect_func(target)
27 self.applied_buffs.add(effect_name)
28
29 return effect_method
30
31 #правя го hashable за да мога да го пъхна в списъка на Димитричка :)
32 def __hash__(self):
33 return hash(id(self))
34
35 #комбиниране на коктейли (коктейл-fication)
36 def __add__(self, other):
37 combo_effects = {**self.effects}
38 combo_intensity = self.effect_intensity
39
40 for effect_name in other.effects.keys():
41 if effect_name in self.effects.keys():
42 self.effect_intensity[effect_name] += 1
43 else:
44 self.effect_intensity.update({effect_name : 1})
45
46 combo_duration = max(self.duration, other.duration)
47 combo_potion = Potion(combo_effects, combo_duration)
48 combo_potion.effect_intensity = combo_intensity
49
50 self.used_for_the_greater_good = True
51 other.used_for_the_greater_good = True
52
53 return combo_potion
54
55 #Като си сложиш екстра шот в коктейла (или като го разредиш idk)
56 def __mul__(self, other):
57 if other >= 1:
58 potent_potion = self
59 for _ in range(other - 1):
60 potent_potion += self
61 return potent_potion
62 elif 0 < other < 1:
63 diluted_intensity = {effect_name : round(self.effect_intensity[effect_name] * other) for effect_name in self.effect_intensity}
64 diluted_potion = self
65 diluted_potion.effect_intensity = diluted_intensity
66
67 self.used_for_the_greater_good = True
68
69 return diluted_potion
70
71 #тук waterbend-ваме и премахваме съставки от коктейла
72 def __sub__(self, other):
73 if not all(effect in self.effects for effect in other.effects):
74 raise TypeError('Cannot purify what does not exist.')
75
76 purified_effects = self.effects
77 purified_intensity = {effect: self.effect_intensity[effect] - other.effect_intensity.get(effect, 0) for effect in self.effect_intensity}
78 for effect_name, effect_intensity in purified_intensity.items():
79 if effect_intensity < 0:
80 self.applied_buffs.add(effect_name)
81
82 purified_potion = Potion(purified_effects, self.duration)
83 purified_potion.effect_intensity = purified_intensity
84
85 self.used_for_the_greater_good = True
86 other.used_for_the_greater_good = True
87
88 return purified_potion
89
90 #споделяме с приятели
91 #абсолютно същото като __mul__, но с '/'
92 def __truediv__(self, other):
93 split_intensity = {effect_name : round(self.effect_intensity[effect_name] / other) for effect_name in self.effect_intensity}
94
95 split_potion = self
96 split_potion.effect_intensity = split_intensity
97
98 self.used_for_the_greater_good = True
99
100 return split_potion
101
102 #мерим си... коктейлите
103 def __lt__(self, other):
104 return sum(self.effect_intensity.values()) < sum(other.effect_intensity.values())
105
106 def __gt__(self, other):
107 return sum(self.effect_intensity.values()) > sum(other.effect_intensity.values())
108
109 def __eq__(self, other):
110 return self.effect_intensity == other.effect_intensity
111
112 def tick(self):
113 self.ticks = max(0, self.ticks - 1)
114
115
116class ГоспожатаПоХимия:
117
118 def __init__(self):
119 self.applied_potions = set()
120
121 def apply(self, target, potion):
122 if potion in self.applied_potions:
123 raise TypeError('Potion is depleted.')
124
125 sorted_effects = sorted(potion.effects, key=lambda effect_name: sum(ord(letter) for letter in effect_name))
126
127 for effect_name in sorted_effects:
128 effect_method = getattr(potion, effect_name)
129 try:
130 effect_method(target)
131 except TypeError:
132 continue
133
134 self.applied_potions.add(potion)
135
136 def tick(self):
137 for potion in self.applied_potions.copy():
138 potion.tick()
139 if potion.ticks == 0:
140 self.applied_potions.remove(potion)
.....E..E.FEF.F.FFFF
======================================================================
ERROR: test_combination_no_overlap (test.TestPotionOperations)
Test combining potions with no overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 95, in test_combination_no_overlap
potion.float_attr_fun(self._target)
AttributeError: 'Potion' object has no attribute 'float_attr_fun'
======================================================================
ERROR: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 119, in test_dilution
half_potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 22, in effect_method
raise TypeError('Potion is now part of something bigger than itself.')
TypeError: Potion is now part of something bigger than itself.
======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 213, in test_separation
potion1, potion2, potion3 = potion / 3
TypeError: cannot unpack non-iterable Potion object
======================================================================
FAIL: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 168, in test_purification
with self.assertRaises(AttributeError):
AssertionError: AttributeError not raised
======================================================================
FAIL: test_applying_depleted_potion (test.TestГоспожатаПоХимия)
Test applying a depleted potion or a potion that was used in a reaction.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 382, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: TypeError not raised
======================================================================
FAIL: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 405, in test_applying_order
self.assertEqual(self._target.int_attr, 12)
AssertionError: 14 != 12
======================================================================
FAIL: test_ticking_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 429, in test_ticking_immutable
self.assertEqual(self._target.int_attr, 5)
AssertionError: 500 != 5
======================================================================
FAIL: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 458, in test_ticking_multiple_potions
self.assertEqual(self._target.int_attr, 50)
AssertionError: 500 != 50
======================================================================
FAIL: test_ticking_multiple_targets (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 490, in test_ticking_multiple_targets
self.assertEqual(target1.int_attr, 5)
AssertionError: 500 != 5
======================================================================
FAIL: test_ticking_mutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 444, in test_ticking_mutable
self.assertEqual(self._target.int_attr, 5)
AssertionError: 50 != 5
----------------------------------------------------------------------
Ran 20 tests in 0.002s
FAILED (failures=7, errors=3)
Георги Кунчев
01.12.2023 10:10Нямам големи коментари по кода. Прилично написан е. Довърши си това, за което спомена, изтествай добре срещу изискванията и си готов.
|
Константин Кирязов
30.11.2023 21:11Остава само да напиша как се премахват ефектите на отварата след като й изтече времето, но за сега толкоз. Уикенда ще има ъпдейт. ;)
|
f | 1 | from types import MethodType | f | 1 | from types import MethodType |
2 | 2 | ||||
3 | class Potion: | 3 | class Potion: | ||
4 | 4 | ||||
5 | def __init__(self, effects, duration): | 5 | def __init__(self, effects, duration): | ||
6 | self.effects = effects | 6 | self.effects = effects | ||
7 | self.duration = duration | 7 | self.duration = duration | ||
8 | self.applied_buffs = set() | 8 | self.applied_buffs = set() | ||
9 | self.used_for_the_greater_good = False | 9 | self.used_for_the_greater_good = False | ||
10 | self.ticks = duration | 10 | self.ticks = duration | ||
11 | self.effect_intensity = {effect: 1 for effect in effects} | 11 | self.effect_intensity = {effect: 1 for effect in effects} | ||
12 | for effect_name, effect_func in effects.items(): | 12 | for effect_name, effect_func in effects.items(): | ||
13 | method = MethodType(self.create_method(effect_name, effect_func), self) | 13 | method = MethodType(self.create_method(effect_name, effect_func), self) | ||
14 | setattr(self, effect_name, method) | 14 | setattr(self, effect_name, method) | ||
15 | 15 | ||||
16 | #помощна фунция за създаване на методи | 16 | #помощна фунция за създаване на методи | ||
17 | def create_method(self, effect_name, effect_func): | 17 | def create_method(self, effect_name, effect_func): | ||
18 | def effect_method(self, target): | 18 | def effect_method(self, target): | ||
19 | if effect_name in self.applied_buffs: | 19 | if effect_name in self.applied_buffs: | ||
20 | raise TypeError('Effect is depleted.') | 20 | raise TypeError('Effect is depleted.') | ||
21 | if self.used_for_the_greater_good: | 21 | if self.used_for_the_greater_good: | ||
22 | raise TypeError('Potion is now part of something bigger than itself.') | 22 | raise TypeError('Potion is now part of something bigger than itself.') | ||
23 | 23 | ||||
24 | if self.effect_intensity[effect_name]: | 24 | if self.effect_intensity[effect_name]: | ||
25 | for _ in range(self.effect_intensity[effect_name]): | 25 | for _ in range(self.effect_intensity[effect_name]): | ||
26 | effect_func(target) | 26 | effect_func(target) | ||
27 | self.applied_buffs.add(effect_name) | 27 | self.applied_buffs.add(effect_name) | ||
28 | 28 | ||||
29 | return effect_method | 29 | return effect_method | ||
30 | 30 | ||||
31 | #правя го hashable за да мога да го пъхна в списъка на Димитричка :) | 31 | #правя го hashable за да мога да го пъхна в списъка на Димитричка :) | ||
32 | def __hash__(self): | 32 | def __hash__(self): | ||
33 | return hash(id(self)) | 33 | return hash(id(self)) | ||
34 | 34 | ||||
35 | #комбиниране на коктейли (коктейл-fication) | 35 | #комбиниране на коктейли (коктейл-fication) | ||
36 | def __add__(self, other): | 36 | def __add__(self, other): | ||
37 | combo_effects = {**self.effects} | 37 | combo_effects = {**self.effects} | ||
38 | combo_intensity = self.effect_intensity | 38 | combo_intensity = self.effect_intensity | ||
39 | 39 | ||||
40 | for effect_name in other.effects.keys(): | 40 | for effect_name in other.effects.keys(): | ||
41 | if effect_name in self.effects.keys(): | 41 | if effect_name in self.effects.keys(): | ||
42 | self.effect_intensity[effect_name] += 1 | 42 | self.effect_intensity[effect_name] += 1 | ||
43 | else: | 43 | else: | ||
44 | self.effect_intensity.update({effect_name : 1}) | 44 | self.effect_intensity.update({effect_name : 1}) | ||
45 | 45 | ||||
46 | combo_duration = max(self.duration, other.duration) | 46 | combo_duration = max(self.duration, other.duration) | ||
47 | combo_potion = Potion(combo_effects, combo_duration) | 47 | combo_potion = Potion(combo_effects, combo_duration) | ||
48 | combo_potion.effect_intensity = combo_intensity | 48 | combo_potion.effect_intensity = combo_intensity | ||
49 | 49 | ||||
50 | self.used_for_the_greater_good = True | 50 | self.used_for_the_greater_good = True | ||
51 | other.used_for_the_greater_good = True | 51 | other.used_for_the_greater_good = True | ||
52 | 52 | ||||
53 | return combo_potion | 53 | return combo_potion | ||
54 | 54 | ||||
55 | #Като си сложиш екстра шот в коктейла (или като го разредиш idk) | 55 | #Като си сложиш екстра шот в коктейла (или като го разредиш idk) | ||
56 | def __mul__(self, other): | 56 | def __mul__(self, other): | ||
57 | if other >= 1: | 57 | if other >= 1: | ||
58 | potent_potion = self | 58 | potent_potion = self | ||
59 | for _ in range(other - 1): | 59 | for _ in range(other - 1): | ||
60 | potent_potion += self | 60 | potent_potion += self | ||
61 | return potent_potion | 61 | return potent_potion | ||
62 | elif 0 < other < 1: | 62 | elif 0 < other < 1: | ||
63 | diluted_intensity = {effect_name : round(self.effect_intensity[effect_name] * other) for effect_name in self.effect_intensity} | 63 | diluted_intensity = {effect_name : round(self.effect_intensity[effect_name] * other) for effect_name in self.effect_intensity} | ||
64 | diluted_potion = self | 64 | diluted_potion = self | ||
65 | diluted_potion.effect_intensity = diluted_intensity | 65 | diluted_potion.effect_intensity = diluted_intensity | ||
66 | 66 | ||||
67 | self.used_for_the_greater_good = True | 67 | self.used_for_the_greater_good = True | ||
68 | 68 | ||||
69 | return diluted_potion | 69 | return diluted_potion | ||
70 | 70 | ||||
71 | #тук waterbend-ваме и премахваме съставки от коктейла | 71 | #тук waterbend-ваме и премахваме съставки от коктейла | ||
72 | def __sub__(self, other): | 72 | def __sub__(self, other): | ||
73 | if not all(effect in self.effects for effect in other.effects): | 73 | if not all(effect in self.effects for effect in other.effects): | ||
74 | raise TypeError('Cannot purify what does not exist.') | 74 | raise TypeError('Cannot purify what does not exist.') | ||
75 | 75 | ||||
76 | purified_effects = self.effects | 76 | purified_effects = self.effects | ||
77 | purified_intensity = {effect: self.effect_intensity[effect] - other.effect_intensity.get(effect, 0) for effect in self.effect_intensity} | 77 | purified_intensity = {effect: self.effect_intensity[effect] - other.effect_intensity.get(effect, 0) for effect in self.effect_intensity} | ||
78 | for effect_name, effect_intensity in purified_intensity.items(): | 78 | for effect_name, effect_intensity in purified_intensity.items(): | ||
79 | if effect_intensity < 0: | 79 | if effect_intensity < 0: | ||
80 | self.applied_buffs.add(effect_name) | 80 | self.applied_buffs.add(effect_name) | ||
81 | 81 | ||||
82 | purified_potion = Potion(purified_effects, self.duration) | 82 | purified_potion = Potion(purified_effects, self.duration) | ||
83 | purified_potion.effect_intensity = purified_intensity | 83 | purified_potion.effect_intensity = purified_intensity | ||
84 | 84 | ||||
85 | self.used_for_the_greater_good = True | 85 | self.used_for_the_greater_good = True | ||
86 | other.used_for_the_greater_good = True | 86 | other.used_for_the_greater_good = True | ||
87 | 87 | ||||
88 | return purified_potion | 88 | return purified_potion | ||
89 | 89 | ||||
90 | #споделяме с приятели | 90 | #споделяме с приятели | ||
91 | #абсолютно същото като __mul__, но с '/' | 91 | #абсолютно същото като __mul__, но с '/' | ||
92 | def __truediv__(self, other): | 92 | def __truediv__(self, other): | ||
93 | split_intensity = {effect_name : round(self.effect_intensity[effect_name] / other) for effect_name in self.effect_intensity} | 93 | split_intensity = {effect_name : round(self.effect_intensity[effect_name] / other) for effect_name in self.effect_intensity} | ||
94 | 94 | ||||
95 | split_potion = self | 95 | split_potion = self | ||
96 | split_potion.effect_intensity = split_intensity | 96 | split_potion.effect_intensity = split_intensity | ||
97 | 97 | ||||
98 | self.used_for_the_greater_good = True | 98 | self.used_for_the_greater_good = True | ||
99 | 99 | ||||
100 | return split_potion | 100 | return split_potion | ||
101 | 101 | ||||
102 | #мерим си... коктейлите | 102 | #мерим си... коктейлите | ||
103 | def __lt__(self, other): | 103 | def __lt__(self, other): | ||
104 | return sum(self.effect_intensity.values()) < sum(other.effect_intensity.values()) | 104 | return sum(self.effect_intensity.values()) < sum(other.effect_intensity.values()) | ||
105 | 105 | ||||
106 | def __gt__(self, other): | 106 | def __gt__(self, other): | ||
107 | return sum(self.effect_intensity.values()) > sum(other.effect_intensity.values()) | 107 | return sum(self.effect_intensity.values()) > sum(other.effect_intensity.values()) | ||
108 | 108 | ||||
109 | def __eq__(self, other): | 109 | def __eq__(self, other): | ||
110 | return self.effect_intensity == other.effect_intensity | 110 | return self.effect_intensity == other.effect_intensity | ||
111 | 111 | ||||
112 | def tick(self): | 112 | def tick(self): | ||
113 | self.ticks = max(0, self.ticks - 1) | 113 | self.ticks = max(0, self.ticks - 1) | ||
t | 114 | print(self.ticks) | t | ||
115 | 114 | ||||
116 | 115 | ||||
117 | class ГоспожатаПоХимия: | 116 | class ГоспожатаПоХимия: | ||
118 | 117 | ||||
119 | def __init__(self): | 118 | def __init__(self): | ||
120 | self.applied_potions = set() | 119 | self.applied_potions = set() | ||
121 | 120 | ||||
122 | def apply(self, target, potion): | 121 | def apply(self, target, potion): | ||
123 | if potion in self.applied_potions: | 122 | if potion in self.applied_potions: | ||
124 | raise TypeError('Potion is depleted.') | 123 | raise TypeError('Potion is depleted.') | ||
125 | 124 | ||||
126 | sorted_effects = sorted(potion.effects, key=lambda effect_name: sum(ord(letter) for letter in effect_name)) | 125 | sorted_effects = sorted(potion.effects, key=lambda effect_name: sum(ord(letter) for letter in effect_name)) | ||
127 | 126 | ||||
128 | for effect_name in sorted_effects: | 127 | for effect_name in sorted_effects: | ||
129 | effect_method = getattr(potion, effect_name) | 128 | effect_method = getattr(potion, effect_name) | ||
130 | try: | 129 | try: | ||
131 | effect_method(target) | 130 | effect_method(target) | ||
132 | except TypeError: | 131 | except TypeError: | ||
133 | continue | 132 | continue | ||
134 | 133 | ||||
135 | self.applied_potions.add(potion) | 134 | self.applied_potions.add(potion) | ||
136 | 135 | ||||
137 | def tick(self): | 136 | def tick(self): | ||
138 | for potion in self.applied_potions.copy(): | 137 | for potion in self.applied_potions.copy(): | ||
139 | potion.tick() | 138 | potion.tick() | ||
140 | if potion.ticks == 0: | 139 | if potion.ticks == 0: | ||
141 | self.applied_potions.remove(potion) | 140 | self.applied_potions.remove(potion) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
01.12.2023 10:08
01.12.2023 10:03