1def asciiSort(list_of_names):
2 return sum(map(ord, list_of_names))
3
4
5class Potion():
6 def __init__(self, effects, duration):
7 self.effects = effects
8 self.duration = duration
9 self._effects_names = {}
10 self._set_attributes()
11 self._used_effects_list = []
12 self.changed = False
13 self.depleted = False
14
15 def _set_attributes(self):
16 for name, effect in self.effects.items():
17 if name not in self._effects_names:
18 self._effects_names[name] = 1
19 else:
20 self._effects_names[name] = self._effects_names[name] + 1
21 setattr(self, name, lambda argument,
22 effect=effect, name=name: self._call_filter(name, argument, effect))
23
24 def _call_filter(self, name, argument, effect):
25 if name in self._used_effects_list:
26 raise TypeError("Effect is depleted.")
27
28 if self.changed:
29 raise TypeError(
30 "Potion is now part of something bigger than itself.")
31
32 self._used_effects_list.append(name)
33
34 for i in range(self._effects_names[name]):
35 effect(argument)
36
37 if len(self._used_effects_list) == len(self._effects_names):
38 self.depleted = True
39
40 def __add__(self, other):
41 if self.depleted:
42 raise TypeError("Potion is depleted.")
43 self.changed = True
44 combined_effects = self.effects | other.effects
45 max_duration = max(self.duration, other.duration)
46
47 combined_potion = Potion(combined_effects, max_duration)
48
49 for name, intensity in self._effects_names.items():
50 if name in other._effects_names:
51 combined_potion._effects_names[name] = intensity + \
52 other._effects_names[name]
53
54 return combined_potion
55
56 def __sub__(self, other):
57 if self.depleted:
58 raise TypeError("Potion is depleted.")
59 self.changed = True
60
61 # check if other has different effects from self
62 for name, intensity in other._effects_names.items():
63 if name not in self._effects_names:
64 raise TypeError("Invalid subtraction")
65
66 new_effects = {}
67 new_effects_names = {}
68 for name, action in self.effects.items():
69 if name in other._effects_names:
70 new_intensity = self._effects_names[name] - \
71 other._effects_names[name]
72 if new_intensity >= 1:
73 new_effects[name] = action
74 new_effects_names[name] = new_intensity
75 else:
76 new_effects[name] = action
77 new_effects_names[name] = self._effects_names[name]
78
79 new_potion = Potion(new_effects, self.duration)
80 new_potion._effects_names = new_effects_names
81
82 return new_potion
83
84 def __mul__(self, multiply_num):
85 if self.depleted:
86 raise TypeError("Potion is depleted.")
87 self.changed = True
88
89 if not isinstance(multiply_num, int):
90 raise TypeError("Multiplier must be an integer")
91
92 multiplied_poition = Potion(self.effects, self.duration)
93
94 if multiply_num != 0:
95 for name, intensity in self._effects_names.items():
96 # if new intensity is zero, set it to one
97 new_intensity = max(round(intensity * multiply_num), 1)
98 multiplied_poition._effects_names[name] = new_intensity
99
100 return multiplied_poition
101
102 def __truediv__(self, devide_num):
103 if self.depleted:
104 raise TypeError("Potion is depleted.")
105 self.changed = True
106
107 if not isinstance(devide_num, int):
108 raise TypeError("Divider must be an integer")
109
110 if devide_num <= 0:
111 raise ValueError("Divider must be a positive integer")
112
113 def __eq__(self, other):
114 return self._effects_names == other._effects_names and self.effects == other.effects
115
116 def __lt__(self, other):
117 self_intensity = 0
118 other_intensity = 0
119
120 for name, intensity in self._effects_names.items():
121 self_intensity = self_intensity + intensity
122
123 for name, intensity in other._effects_names.items():
124 other_intensity = other_intensity + intensity
125
126 return self_intensity < other_intensity
127
128 def __gt__(self, other):
129 self_intensity = 0
130 other_intensity = 0
131
132 for name, intensity in self._effects_names.items():
133 self_intensity = self_intensity + intensity
134
135 for name, intensity in other._effects_names.items():
136 other_intensity = other_intensity + intensity
137
138 return self_intensity > other_intensity
139
140
141class ГоспожатаПоХимия():
142 def __init__(self):
143 self.potion = None
144 self.ticks = None
145
146 def apply(self, target, potion):
147 if potion.depleted:
148 raise TypeError("Potion is depleted.")
149
150 self.potion = potion
151 self.ticks = potion.duration
152
153 # sort by molecular mass
154 list_to_execute = list(potion.effects.keys())
155 list_to_execute = sorted(list_to_execute, key=asciiSort)
156 print(list_to_execute)
157
158 for name in list_to_execute:
159 try:
160 for i in range(potion._effects_names[name]):
161 effect = getattr(potion, name)
162 effect(target)
163 except TypeError as error:
164 if "Effect is depleted." in str(error):
165 pass
166 else:
167 print(error)
168
169 def tick(self):
170 self.ticks = self.ticks-1
.......FE.EEF
Stdout:
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
.F
Stdout:
['z_name', 'aa_name']
.F
Stdout:
['int_attr_fun']
F
Stdout:
['int_attr_fun']
['int_attr_fun']
F
Stdout:
['int_attr_fun']
['int_attr_fun']
F
Stdout:
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
======================================================================
ERROR: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 118, in test_dilution
half_potion = base_potion * 0.5
File "/tmp/solution.py", line 90, in __mul__
raise TypeError("Multiplier must be an integer")
TypeError: Multiplier must be an integer
======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 190, in test_purification
potion.int_attr_fun(self._target)
AttributeError: 'Potion' object has no attribute 'int_attr_fun'
======================================================================
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 NoneType object
======================================================================
FAIL: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 259, in test_deprecation
with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
AssertionError: TypeError 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 391, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
AssertionError: TypeError not raised
Stdout:
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
Potion is now part of something bigger than itself.
======================================================================
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
Stdout:
['z_name', 'aa_name']
======================================================================
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
Stdout:
['int_attr_fun']
======================================================================
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
Stdout:
['int_attr_fun']
['int_attr_fun']
======================================================================
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
Stdout:
['int_attr_fun']
['int_attr_fun']
======================================================================
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
Stdout:
['int_attr_fun', 'dict_attr_fun', 'list_attr_fun', 'float_attr_fun']
----------------------------------------------------------------------
Ran 20 tests in 0.002s
FAILED (failures=7, errors=3)
f | 1 | def asciiSort(list_of_names): | f | 1 | def asciiSort(list_of_names): |
2 | return sum(map(ord, list_of_names)) | 2 | return sum(map(ord, list_of_names)) | ||
3 | 3 | ||||
4 | 4 | ||||
5 | class Potion(): | 5 | class Potion(): | ||
6 | def __init__(self, effects, duration): | 6 | def __init__(self, effects, duration): | ||
7 | self.effects = effects | 7 | self.effects = effects | ||
8 | self.duration = duration | 8 | self.duration = duration | ||
9 | self._effects_names = {} | 9 | self._effects_names = {} | ||
10 | self._set_attributes() | 10 | self._set_attributes() | ||
11 | self._used_effects_list = [] | 11 | self._used_effects_list = [] | ||
12 | self.changed = False | 12 | self.changed = False | ||
13 | self.depleted = False | 13 | self.depleted = False | ||
14 | 14 | ||||
15 | def _set_attributes(self): | 15 | def _set_attributes(self): | ||
16 | for name, effect in self.effects.items(): | 16 | for name, effect in self.effects.items(): | ||
17 | if name not in self._effects_names: | 17 | if name not in self._effects_names: | ||
18 | self._effects_names[name] = 1 | 18 | self._effects_names[name] = 1 | ||
19 | else: | 19 | else: | ||
20 | self._effects_names[name] = self._effects_names[name] + 1 | 20 | self._effects_names[name] = self._effects_names[name] + 1 | ||
21 | setattr(self, name, lambda argument, | 21 | setattr(self, name, lambda argument, | ||
22 | effect=effect, name=name: self._call_filter(name, argument, effect)) | 22 | effect=effect, name=name: self._call_filter(name, argument, effect)) | ||
23 | 23 | ||||
24 | def _call_filter(self, name, argument, effect): | 24 | def _call_filter(self, name, argument, effect): | ||
25 | if name in self._used_effects_list: | 25 | if name in self._used_effects_list: | ||
26 | raise TypeError("Effect is depleted.") | 26 | raise TypeError("Effect is depleted.") | ||
27 | 27 | ||||
28 | if self.changed: | 28 | if self.changed: | ||
29 | raise TypeError( | 29 | raise TypeError( | ||
30 | "Potion is now part of something bigger than itself.") | 30 | "Potion is now part of something bigger than itself.") | ||
31 | 31 | ||||
32 | self._used_effects_list.append(name) | 32 | self._used_effects_list.append(name) | ||
33 | 33 | ||||
34 | for i in range(self._effects_names[name]): | 34 | for i in range(self._effects_names[name]): | ||
n | 35 | print("call") | n | ||
36 | print(name) | ||||
37 | effect(argument) | 35 | effect(argument) | ||
38 | 36 | ||||
39 | if len(self._used_effects_list) == len(self._effects_names): | 37 | if len(self._used_effects_list) == len(self._effects_names): | ||
40 | self.depleted = True | 38 | self.depleted = True | ||
t | 41 | t | |||
42 | def print(self): | ||||
43 | print(self._effects_names) | ||||
44 | print(self.duration) | ||||
45 | 39 | ||||
46 | def __add__(self, other): | 40 | def __add__(self, other): | ||
47 | if self.depleted: | 41 | if self.depleted: | ||
48 | raise TypeError("Potion is depleted.") | 42 | raise TypeError("Potion is depleted.") | ||
49 | self.changed = True | 43 | self.changed = True | ||
50 | combined_effects = self.effects | other.effects | 44 | combined_effects = self.effects | other.effects | ||
51 | max_duration = max(self.duration, other.duration) | 45 | max_duration = max(self.duration, other.duration) | ||
52 | 46 | ||||
53 | combined_potion = Potion(combined_effects, max_duration) | 47 | combined_potion = Potion(combined_effects, max_duration) | ||
54 | 48 | ||||
55 | for name, intensity in self._effects_names.items(): | 49 | for name, intensity in self._effects_names.items(): | ||
56 | if name in other._effects_names: | 50 | if name in other._effects_names: | ||
57 | combined_potion._effects_names[name] = intensity + \ | 51 | combined_potion._effects_names[name] = intensity + \ | ||
58 | other._effects_names[name] | 52 | other._effects_names[name] | ||
59 | 53 | ||||
60 | return combined_potion | 54 | return combined_potion | ||
61 | 55 | ||||
62 | def __sub__(self, other): | 56 | def __sub__(self, other): | ||
63 | if self.depleted: | 57 | if self.depleted: | ||
64 | raise TypeError("Potion is depleted.") | 58 | raise TypeError("Potion is depleted.") | ||
65 | self.changed = True | 59 | self.changed = True | ||
66 | 60 | ||||
67 | # check if other has different effects from self | 61 | # check if other has different effects from self | ||
68 | for name, intensity in other._effects_names.items(): | 62 | for name, intensity in other._effects_names.items(): | ||
69 | if name not in self._effects_names: | 63 | if name not in self._effects_names: | ||
70 | raise TypeError("Invalid subtraction") | 64 | raise TypeError("Invalid subtraction") | ||
71 | 65 | ||||
72 | new_effects = {} | 66 | new_effects = {} | ||
73 | new_effects_names = {} | 67 | new_effects_names = {} | ||
74 | for name, action in self.effects.items(): | 68 | for name, action in self.effects.items(): | ||
75 | if name in other._effects_names: | 69 | if name in other._effects_names: | ||
76 | new_intensity = self._effects_names[name] - \ | 70 | new_intensity = self._effects_names[name] - \ | ||
77 | other._effects_names[name] | 71 | other._effects_names[name] | ||
78 | if new_intensity >= 1: | 72 | if new_intensity >= 1: | ||
79 | new_effects[name] = action | 73 | new_effects[name] = action | ||
80 | new_effects_names[name] = new_intensity | 74 | new_effects_names[name] = new_intensity | ||
81 | else: | 75 | else: | ||
82 | new_effects[name] = action | 76 | new_effects[name] = action | ||
83 | new_effects_names[name] = self._effects_names[name] | 77 | new_effects_names[name] = self._effects_names[name] | ||
84 | 78 | ||||
85 | new_potion = Potion(new_effects, self.duration) | 79 | new_potion = Potion(new_effects, self.duration) | ||
86 | new_potion._effects_names = new_effects_names | 80 | new_potion._effects_names = new_effects_names | ||
87 | 81 | ||||
88 | return new_potion | 82 | return new_potion | ||
89 | 83 | ||||
90 | def __mul__(self, multiply_num): | 84 | def __mul__(self, multiply_num): | ||
91 | if self.depleted: | 85 | if self.depleted: | ||
92 | raise TypeError("Potion is depleted.") | 86 | raise TypeError("Potion is depleted.") | ||
93 | self.changed = True | 87 | self.changed = True | ||
94 | 88 | ||||
95 | if not isinstance(multiply_num, int): | 89 | if not isinstance(multiply_num, int): | ||
96 | raise TypeError("Multiplier must be an integer") | 90 | raise TypeError("Multiplier must be an integer") | ||
97 | 91 | ||||
98 | multiplied_poition = Potion(self.effects, self.duration) | 92 | multiplied_poition = Potion(self.effects, self.duration) | ||
99 | 93 | ||||
100 | if multiply_num != 0: | 94 | if multiply_num != 0: | ||
101 | for name, intensity in self._effects_names.items(): | 95 | for name, intensity in self._effects_names.items(): | ||
102 | # if new intensity is zero, set it to one | 96 | # if new intensity is zero, set it to one | ||
103 | new_intensity = max(round(intensity * multiply_num), 1) | 97 | new_intensity = max(round(intensity * multiply_num), 1) | ||
104 | multiplied_poition._effects_names[name] = new_intensity | 98 | multiplied_poition._effects_names[name] = new_intensity | ||
105 | 99 | ||||
106 | return multiplied_poition | 100 | return multiplied_poition | ||
107 | 101 | ||||
108 | def __truediv__(self, devide_num): | 102 | def __truediv__(self, devide_num): | ||
109 | if self.depleted: | 103 | if self.depleted: | ||
110 | raise TypeError("Potion is depleted.") | 104 | raise TypeError("Potion is depleted.") | ||
111 | self.changed = True | 105 | self.changed = True | ||
112 | 106 | ||||
113 | if not isinstance(devide_num, int): | 107 | if not isinstance(devide_num, int): | ||
114 | raise TypeError("Divider must be an integer") | 108 | raise TypeError("Divider must be an integer") | ||
115 | 109 | ||||
116 | if devide_num <= 0: | 110 | if devide_num <= 0: | ||
117 | raise ValueError("Divider must be a positive integer") | 111 | raise ValueError("Divider must be a positive integer") | ||
118 | 112 | ||||
119 | def __eq__(self, other): | 113 | def __eq__(self, other): | ||
120 | return self._effects_names == other._effects_names and self.effects == other.effects | 114 | return self._effects_names == other._effects_names and self.effects == other.effects | ||
121 | 115 | ||||
122 | def __lt__(self, other): | 116 | def __lt__(self, other): | ||
123 | self_intensity = 0 | 117 | self_intensity = 0 | ||
124 | other_intensity = 0 | 118 | other_intensity = 0 | ||
125 | 119 | ||||
126 | for name, intensity in self._effects_names.items(): | 120 | for name, intensity in self._effects_names.items(): | ||
127 | self_intensity = self_intensity + intensity | 121 | self_intensity = self_intensity + intensity | ||
128 | 122 | ||||
129 | for name, intensity in other._effects_names.items(): | 123 | for name, intensity in other._effects_names.items(): | ||
130 | other_intensity = other_intensity + intensity | 124 | other_intensity = other_intensity + intensity | ||
131 | 125 | ||||
132 | return self_intensity < other_intensity | 126 | return self_intensity < other_intensity | ||
133 | 127 | ||||
134 | def __gt__(self, other): | 128 | def __gt__(self, other): | ||
135 | self_intensity = 0 | 129 | self_intensity = 0 | ||
136 | other_intensity = 0 | 130 | other_intensity = 0 | ||
137 | 131 | ||||
138 | for name, intensity in self._effects_names.items(): | 132 | for name, intensity in self._effects_names.items(): | ||
139 | self_intensity = self_intensity + intensity | 133 | self_intensity = self_intensity + intensity | ||
140 | 134 | ||||
141 | for name, intensity in other._effects_names.items(): | 135 | for name, intensity in other._effects_names.items(): | ||
142 | other_intensity = other_intensity + intensity | 136 | other_intensity = other_intensity + intensity | ||
143 | 137 | ||||
144 | return self_intensity > other_intensity | 138 | return self_intensity > other_intensity | ||
145 | 139 | ||||
146 | 140 | ||||
147 | class ГоспожатаПоХимия(): | 141 | class ГоспожатаПоХимия(): | ||
148 | def __init__(self): | 142 | def __init__(self): | ||
149 | self.potion = None | 143 | self.potion = None | ||
150 | self.ticks = None | 144 | self.ticks = None | ||
151 | 145 | ||||
152 | def apply(self, target, potion): | 146 | def apply(self, target, potion): | ||
153 | if potion.depleted: | 147 | if potion.depleted: | ||
154 | raise TypeError("Potion is depleted.") | 148 | raise TypeError("Potion is depleted.") | ||
155 | 149 | ||||
156 | self.potion = potion | 150 | self.potion = potion | ||
157 | self.ticks = potion.duration | 151 | self.ticks = potion.duration | ||
158 | 152 | ||||
159 | # sort by molecular mass | 153 | # sort by molecular mass | ||
160 | list_to_execute = list(potion.effects.keys()) | 154 | list_to_execute = list(potion.effects.keys()) | ||
161 | list_to_execute = sorted(list_to_execute, key=asciiSort) | 155 | list_to_execute = sorted(list_to_execute, key=asciiSort) | ||
162 | print(list_to_execute) | 156 | print(list_to_execute) | ||
163 | 157 | ||||
164 | for name in list_to_execute: | 158 | for name in list_to_execute: | ||
165 | try: | 159 | try: | ||
166 | for i in range(potion._effects_names[name]): | 160 | for i in range(potion._effects_names[name]): | ||
167 | effect = getattr(potion, name) | 161 | effect = getattr(potion, name) | ||
168 | effect(target) | 162 | effect(target) | ||
169 | except TypeError as error: | 163 | except TypeError as error: | ||
170 | if "Effect is depleted." in str(error): | 164 | if "Effect is depleted." in str(error): | ||
171 | pass | 165 | pass | ||
172 | else: | 166 | else: | ||
173 | print(error) | 167 | print(error) | ||
174 | 168 | ||||
175 | def tick(self): | 169 | def tick(self): | ||
176 | self.ticks = self.ticks-1 | 170 | self.ticks = self.ticks-1 |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
05.12.2023 16:21
05.12.2023 16:22
05.12.2023 16:25
05.12.2023 16:27
05.12.2023 16:30
05.12.2023 16:36
05.12.2023 16:38