1import functools
2from copy import deepcopy
3
4
5class Potion:
6
7 def __init__(self, effects, duration):
8 self.effects = effects
9 self.duration = duration
10 #self.__dict__.update(effects)
11 self.effects_intensity = {}
12 for effect in effects:
13 self.effects_intensity[effect] = 1
14 for effect_name, effect_func in self.effects.items():
15 self.__dict__[effect_name] = self.__effects_decorator(effect_name, effect_func)
16 self.is_used = False
17
18 def __effects_decorator(self, effect_name, effect_func):
19 def composed_effect(target):
20 if self.effects_intensity[effect_name] == 0:
21 raise TypeError ("Effect is depleted.")
22 while self.effects_intensity[effect_name] != 0:
23 self.effects_intensity[effect_name] -= 1
24 effect_func(target)
25 return composed_effect
26
27 @staticmethod
28 def __potion_result(effects, effects_intensity, duration):
29 result = Potion(effects, duration)
30 result.effects_intensity = effects_intensity
31 return result
32
33 def __add__(self, other):
34 if self.is_used:
35 raise TypeError("Potion is now part of something bigger than itself.")
36 resultring_effects = dict(self.effects)
37 resultring_effects_intensity = dict(self.effects_intensity)
38 for effect in other.effects_intensity:
39 if effect in resultring_effects_intensity:
40 resultring_effects_intensity[effect] += other.effects_intensity[effect]
41 else:
42 resultring_effects[effect] = other.effects[effect]
43 resultring_effects_intensity[effect] = 1
44 self.is_used = True
45 return Potion.__potion_result(resultring_effects, resultring_effects_intensity, max(self.duration, other.duration))
46
47 def __mul__(self, value):
48 if self.is_used:
49 raise TypeError("Potion is now part of something bigger than itself.")
50 resulting_effects_intensity = dict(self.effects_intensity)
51 for effect in resulting_effects_intensity:
52 resulting_effects_intensity[effect] = int(resulting_effects_intensity[effect] * value)
53 self.is_used = True
54 return Potion.__potion_result(dict(self.effects), resulting_effects_intensity, self.duration)
55
56 def __sub__(self, other):
57 if self.is_used:
58 raise TypeError("Potion is now part of something bigger than itself.")
59 if not all(map(lambda x : x in self.effects , other.effects)):
60 raise TypeError
61 resulting_effects = dict(self.effects)
62 resulting_effects_intensity = dict(self.effects_intensity)
63 for effect in other.effects:
64 if resulting_effects_intensity[effect] > other.effects_intensity[effect]:
65 resulting_effects_intensity[effect] -= other.effects_intensity[effect]
66 else:
67 resulting_effects.pop(effect)
68 resulting_effects_intensity.pop(effect)
69 self.is_used = True
70 return Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration)
71
72 def __truediv__(self, value):
73 if self.is_used:
74 raise TypeError("Potion is now part of something bigger than itself.")
75 resulting_effects = dict(self.effects)
76 resulting_effects_intensity = dict(self.effects_intensity)
77 for effect in resulting_effects_intensity:
78 resulting_effects_intensity[effect] //= value
79 result = ()
80 for _ in range(value):
81 result += (Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration), )
82 self.is_used = True
83 return result
84
85 def __eq__(self, other):
86 return self.effects_intensity == other.effects_intensity
87
88 def __lt__(self, other):
89 res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0)
90 res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0)
91 print(res_self)
92 print(res_other)
93 return res_self < res_other
94
95 def __gt__(self, other):
96 res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0)
97 res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0)
98 print(self.effects_intensity)
99 print(other.effects_intensity)
100 print(res_self)
101 print(res_other)
102 return res_self > res_other
103
104 def apply(self, target):
105 if not self.is_used:
106 for effect in self.effects:
107 self.is_used = True
108 self.__dict__[effect](target)
109 else:
110 raise TypeError("Potion is now part of something bigger than itself.")
111
112 def apply_for_consistancy(self, target):
113 if not self.is_used:
114 for effect in self.effects:
115 self.__dict__[effect](target)
116 else:
117 raise TypeError("Potion is now part of something bigger than itself.")
118
119
120class ГоспожатаПоХимия:
121
122 def __init__(self):
123 self.time = 0
124 self.reverser = []
125
126 def apply(self, target, potion):
127 try:
128 self.reverser.append([potion.duration + self.time, target, deepcopy(target)])
129 for change in self.reverser:
130 if change[1] == target and change[0] < potion.duration + self.time:
131 potion.apply_for_consistancy(change[2])
132 potion.apply(target)
133 except TypeError:
134 raise TypeError("Potion is depleted.")
135
136 def tick(self):
137 self.time += 1
138 for change in self.reverser:
139 if self.time == change[0]:
140 change[1] = change[2]
.......FE..EF.FEFEFF
======================================================================
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 21, in composed_effect
raise TypeError ("Effect is depleted.")
TypeError: Effect is depleted.
======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 218, in test_separation
potion2.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in composed_effect
raise TypeError ("Effect is depleted.")
TypeError: Effect is depleted.
======================================================================
ERROR: test_applying_part_of_potion (test.TestГоспожатаПоХимия)
Test applying only a part of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/solution.py", line 132, in apply
potion.apply(target)
File "/tmp/solution.py", line 108, in apply
self.__dict__[effect](target)
File "/tmp/solution.py", line 21, in composed_effect
raise TypeError ("Effect is depleted.")
TypeError: Effect is depleted.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/tmp/test.py", line 365, in test_applying_part_of_potion
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 134, in apply
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.
======================================================================
ERROR: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/solution.py", line 132, in apply
potion.apply(target)
File "/tmp/solution.py", line 108, in apply
self.__dict__[effect](target)
File "/tmp/solution.py", line 21, in composed_effect
raise TypeError ("Effect is depleted.")
TypeError: Effect is depleted.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/tmp/test.py", line 455, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion2)
File "/tmp/solution.py", line 134, in apply
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.
======================================================================
FAIL: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 257, 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.
----------------------------------------------------------------------
TypeError: Potion is now part of something bigger than itself.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/tmp/test.py", line 382, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: "Potion is depleted\." does not match "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
======================================================================
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_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=6, errors=4)
| f | 1 | import functools | f | 1 | import functools |
| 2 | from copy import deepcopy | 2 | from copy import deepcopy | ||
| 3 | 3 | ||||
| 4 | 4 | ||||
| 5 | class Potion: | 5 | class Potion: | ||
| 6 | 6 | ||||
| 7 | def __init__(self, effects, duration): | 7 | def __init__(self, effects, duration): | ||
| 8 | self.effects = effects | 8 | self.effects = effects | ||
| 9 | self.duration = duration | 9 | self.duration = duration | ||
| 10 | #self.__dict__.update(effects) | 10 | #self.__dict__.update(effects) | ||
| 11 | self.effects_intensity = {} | 11 | self.effects_intensity = {} | ||
| 12 | for effect in effects: | 12 | for effect in effects: | ||
| 13 | self.effects_intensity[effect] = 1 | 13 | self.effects_intensity[effect] = 1 | ||
| 14 | for effect_name, effect_func in self.effects.items(): | 14 | for effect_name, effect_func in self.effects.items(): | ||
| 15 | self.__dict__[effect_name] = self.__effects_decorator(effect_name, effect_func) | 15 | self.__dict__[effect_name] = self.__effects_decorator(effect_name, effect_func) | ||
| 16 | self.is_used = False | 16 | self.is_used = False | ||
| 17 | 17 | ||||
| 18 | def __effects_decorator(self, effect_name, effect_func): | 18 | def __effects_decorator(self, effect_name, effect_func): | ||
| 19 | def composed_effect(target): | 19 | def composed_effect(target): | ||
| 20 | if self.effects_intensity[effect_name] == 0: | 20 | if self.effects_intensity[effect_name] == 0: | ||
| 21 | raise TypeError ("Effect is depleted.") | 21 | raise TypeError ("Effect is depleted.") | ||
| 22 | while self.effects_intensity[effect_name] != 0: | 22 | while self.effects_intensity[effect_name] != 0: | ||
| 23 | self.effects_intensity[effect_name] -= 1 | 23 | self.effects_intensity[effect_name] -= 1 | ||
| 24 | effect_func(target) | 24 | effect_func(target) | ||
| 25 | return composed_effect | 25 | return composed_effect | ||
| 26 | 26 | ||||
| 27 | @staticmethod | 27 | @staticmethod | ||
| 28 | def __potion_result(effects, effects_intensity, duration): | 28 | def __potion_result(effects, effects_intensity, duration): | ||
| 29 | result = Potion(effects, duration) | 29 | result = Potion(effects, duration) | ||
| 30 | result.effects_intensity = effects_intensity | 30 | result.effects_intensity = effects_intensity | ||
| 31 | return result | 31 | return result | ||
| 32 | 32 | ||||
| 33 | def __add__(self, other): | 33 | def __add__(self, other): | ||
| 34 | if self.is_used: | 34 | if self.is_used: | ||
| 35 | raise TypeError("Potion is now part of something bigger than itself.") | 35 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 36 | resultring_effects = dict(self.effects) | 36 | resultring_effects = dict(self.effects) | ||
| 37 | resultring_effects_intensity = dict(self.effects_intensity) | 37 | resultring_effects_intensity = dict(self.effects_intensity) | ||
| 38 | for effect in other.effects_intensity: | 38 | for effect in other.effects_intensity: | ||
| 39 | if effect in resultring_effects_intensity: | 39 | if effect in resultring_effects_intensity: | ||
| 40 | resultring_effects_intensity[effect] += other.effects_intensity[effect] | 40 | resultring_effects_intensity[effect] += other.effects_intensity[effect] | ||
| 41 | else: | 41 | else: | ||
| 42 | resultring_effects[effect] = other.effects[effect] | 42 | resultring_effects[effect] = other.effects[effect] | ||
| 43 | resultring_effects_intensity[effect] = 1 | 43 | resultring_effects_intensity[effect] = 1 | ||
| 44 | self.is_used = True | 44 | self.is_used = True | ||
| 45 | return Potion.__potion_result(resultring_effects, resultring_effects_intensity, max(self.duration, other.duration)) | 45 | return Potion.__potion_result(resultring_effects, resultring_effects_intensity, max(self.duration, other.duration)) | ||
| 46 | 46 | ||||
| 47 | def __mul__(self, value): | 47 | def __mul__(self, value): | ||
| 48 | if self.is_used: | 48 | if self.is_used: | ||
| 49 | raise TypeError("Potion is now part of something bigger than itself.") | 49 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 50 | resulting_effects_intensity = dict(self.effects_intensity) | 50 | resulting_effects_intensity = dict(self.effects_intensity) | ||
| 51 | for effect in resulting_effects_intensity: | 51 | for effect in resulting_effects_intensity: | ||
| n | 52 | resulting_effects_intensity[effect] =int(resulting_effects_intensity[effect] * value) | n | 52 | resulting_effects_intensity[effect] = int(resulting_effects_intensity[effect] * value) |
| 53 | self.is_used = True | 53 | self.is_used = True | ||
| 54 | return Potion.__potion_result(dict(self.effects), resulting_effects_intensity, self.duration) | 54 | return Potion.__potion_result(dict(self.effects), resulting_effects_intensity, self.duration) | ||
| 55 | 55 | ||||
| 56 | def __sub__(self, other): | 56 | def __sub__(self, other): | ||
| 57 | if self.is_used: | 57 | if self.is_used: | ||
| 58 | raise TypeError("Potion is now part of something bigger than itself.") | 58 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 59 | if not all(map(lambda x : x in self.effects , other.effects)): | 59 | if not all(map(lambda x : x in self.effects , other.effects)): | ||
| 60 | raise TypeError | 60 | raise TypeError | ||
| 61 | resulting_effects = dict(self.effects) | 61 | resulting_effects = dict(self.effects) | ||
| 62 | resulting_effects_intensity = dict(self.effects_intensity) | 62 | resulting_effects_intensity = dict(self.effects_intensity) | ||
| 63 | for effect in other.effects: | 63 | for effect in other.effects: | ||
| 64 | if resulting_effects_intensity[effect] > other.effects_intensity[effect]: | 64 | if resulting_effects_intensity[effect] > other.effects_intensity[effect]: | ||
| 65 | resulting_effects_intensity[effect] -= other.effects_intensity[effect] | 65 | resulting_effects_intensity[effect] -= other.effects_intensity[effect] | ||
| 66 | else: | 66 | else: | ||
| 67 | resulting_effects.pop(effect) | 67 | resulting_effects.pop(effect) | ||
| 68 | resulting_effects_intensity.pop(effect) | 68 | resulting_effects_intensity.pop(effect) | ||
| 69 | self.is_used = True | 69 | self.is_used = True | ||
| 70 | return Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration) | 70 | return Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration) | ||
| 71 | 71 | ||||
| 72 | def __truediv__(self, value): | 72 | def __truediv__(self, value): | ||
| 73 | if self.is_used: | 73 | if self.is_used: | ||
| 74 | raise TypeError("Potion is now part of something bigger than itself.") | 74 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 75 | resulting_effects = dict(self.effects) | 75 | resulting_effects = dict(self.effects) | ||
| 76 | resulting_effects_intensity = dict(self.effects_intensity) | 76 | resulting_effects_intensity = dict(self.effects_intensity) | ||
| 77 | for effect in resulting_effects_intensity: | 77 | for effect in resulting_effects_intensity: | ||
| 78 | resulting_effects_intensity[effect] //= value | 78 | resulting_effects_intensity[effect] //= value | ||
| 79 | result = () | 79 | result = () | ||
| 80 | for _ in range(value): | 80 | for _ in range(value): | ||
| 81 | result += (Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration), ) | 81 | result += (Potion.__potion_result(resulting_effects, resulting_effects_intensity, self.duration), ) | ||
| 82 | self.is_used = True | 82 | self.is_used = True | ||
| 83 | return result | 83 | return result | ||
| 84 | 84 | ||||
| 85 | def __eq__(self, other): | 85 | def __eq__(self, other): | ||
| 86 | return self.effects_intensity == other.effects_intensity | 86 | return self.effects_intensity == other.effects_intensity | ||
| 87 | 87 | ||||
| 88 | def __lt__(self, other): | 88 | def __lt__(self, other): | ||
| 89 | res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0) | 89 | res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0) | ||
| 90 | res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0) | 90 | res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0) | ||
| 91 | print(res_self) | 91 | print(res_self) | ||
| 92 | print(res_other) | 92 | print(res_other) | ||
| 93 | return res_self < res_other | 93 | return res_self < res_other | ||
| 94 | 94 | ||||
| 95 | def __gt__(self, other): | 95 | def __gt__(self, other): | ||
| 96 | res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0) | 96 | res_self = functools.reduce(lambda a, b : a + self.effects_intensity[b], self.effects_intensity, 0) | ||
| 97 | res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0) | 97 | res_other = functools.reduce(lambda a, b : a + other.effects_intensity[b], other.effects_intensity, 0) | ||
| 98 | print(self.effects_intensity) | 98 | print(self.effects_intensity) | ||
| 99 | print(other.effects_intensity) | 99 | print(other.effects_intensity) | ||
| 100 | print(res_self) | 100 | print(res_self) | ||
| 101 | print(res_other) | 101 | print(res_other) | ||
| 102 | return res_self > res_other | 102 | return res_self > res_other | ||
| 103 | 103 | ||||
| 104 | def apply(self, target): | 104 | def apply(self, target): | ||
| 105 | if not self.is_used: | 105 | if not self.is_used: | ||
| 106 | for effect in self.effects: | 106 | for effect in self.effects: | ||
| 107 | self.is_used = True | 107 | self.is_used = True | ||
| 108 | self.__dict__[effect](target) | 108 | self.__dict__[effect](target) | ||
| 109 | else: | 109 | else: | ||
| 110 | raise TypeError("Potion is now part of something bigger than itself.") | 110 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 111 | 111 | ||||
| 112 | def apply_for_consistancy(self, target): | 112 | def apply_for_consistancy(self, target): | ||
| 113 | if not self.is_used: | 113 | if not self.is_used: | ||
| 114 | for effect in self.effects: | 114 | for effect in self.effects: | ||
| 115 | self.__dict__[effect](target) | 115 | self.__dict__[effect](target) | ||
| 116 | else: | 116 | else: | ||
| 117 | raise TypeError("Potion is now part of something bigger than itself.") | 117 | raise TypeError("Potion is now part of something bigger than itself.") | ||
| 118 | 118 | ||||
| 119 | 119 | ||||
| 120 | class ГоспожатаПоХимия: | 120 | class ГоспожатаПоХимия: | ||
| 121 | 121 | ||||
| t | 122 | def __init__(self) -> None: | t | 122 | def __init__(self): |
| 123 | self.time=0 | 123 | self.time = 0 | ||
| 124 | self.reverser = [] | 124 | self.reverser = [] | ||
| 125 | 125 | ||||
| 126 | def apply(self, target, potion): | 126 | def apply(self, target, potion): | ||
| 127 | try: | 127 | try: | ||
| 128 | self.reverser.append([potion.duration + self.time, target, deepcopy(target)]) | 128 | self.reverser.append([potion.duration + self.time, target, deepcopy(target)]) | ||
| 129 | for change in self.reverser: | 129 | for change in self.reverser: | ||
| 130 | if change[1] == target and change[0] < potion.duration + self.time: | 130 | if change[1] == target and change[0] < potion.duration + self.time: | ||
| 131 | potion.apply_for_consistancy(change[2]) | 131 | potion.apply_for_consistancy(change[2]) | ||
| 132 | potion.apply(target) | 132 | potion.apply(target) | ||
| 133 | except TypeError: | 133 | except TypeError: | ||
| 134 | raise TypeError("Potion is depleted.") | 134 | raise TypeError("Potion is depleted.") | ||
| 135 | 135 | ||||
| 136 | def tick(self): | 136 | def tick(self): | ||
| 137 | self.time += 1 | 137 | self.time += 1 | ||
| 138 | for change in self.reverser: | 138 | for change in self.reverser: | ||
| 139 | if self.time == change[0]: | 139 | if self.time == change[0]: | ||
| 140 | change[1] = change[2] | 140 | change[1] = change[2] |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||