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