1import weakref
2
3class Potion():
4 instances = []
5
6 def __init__(self,effects, duration):
7 self.effects = effects
8 self.duration = duration
9 self.is_depleted = False
10 self.is_used_in_reaction = False
11 self.__class__.instances.append(weakref.proxy(self))
12
13 for key, value in effects.items():
14 setattr(self, "intensity_" + key, 1)
15 setattr(self, "is_depleted_" + key, False)
16 setattr(self, key, Potion.call_intensity_times(self, key, value))
17
18 @staticmethod
19 def call_intensity_times(self, key, value):
20 def decorator(target):
21 deplete_attr = "is_depleted_" + key
22 i = 0
23 if not getattr(self,deplete_attr):
24 while i < getattr(self,deplete_attr):
25 value(target)
26 i += 1
27 setattr(self, "is_depleted_" + key, True)
28 else:
29 raise TypeError("Effect is depleted.")
30
31 return decorator
32
33 def __add__(self, other_potion):
34 Potion.is_depleted_or_used(self, other_potion)
35
36 new_duration = max(self.duration, other_potion.duration)
37 self.effects.update(other_potion.effects)
38 new_potion = Potion(self.effects, new_duration)
39
40 for key in self.effects.keys():
41 intensity_name = "intensity_" + key
42 if hasattr(other_potion, intensity_name) and hasattr(self, intensity_name):
43 setattr(new_potion, intensity_name, getattr(self,intensity_name) + getattr(other_potion,intensity_name))
44 elif hasattr(other_potion, intensity_name):
45 setattr(new_potion, intensity_name, getattr(other_potion,intensity_name))
46 else:
47 setattr(new_potion, intensity_name,getattr(self, intensity_name))
48
49 Potion.add_attr_used_in_reaction(self,other_potion)
50
51 return new_potion
52
53 def __mul__(self,number):
54 Potion.is_depleted_or_used(self)
55
56 for key in self.effects.keys():
57 intensity_name = "intensity_" + key
58 if 0 < number < 1:
59 setattr(self,intensity_name, round( getattr(self,intensity_name)* number))
60
61 elif hasattr(self, intensity_name):
62 setattr(self,intensity_name, getattr(self,intensity_name)* number)
63
64 Potion.add_attr_used_in_reaction(self)
65
66 return self
67
68 def __sub__(self, other_potion):
69 Potion.is_depleted_or_used(other_potion)
70
71 new_duration = self.duration
72 new_potion = Potion(self.effects, new_duration)
73
74 for key in self.effects.keys():
75 intensity_name = "intensity_" + key
76 if hasattr(other_potion, intensity_name) and hasattr(new_potion, intensity_name):
77 if getattr(new_potion,intensity_name) - getattr(other_potion,intensity_name) < 0:
78 delattr(new_potion, intensity_name)
79 else:
80 setattr(new_potion, intensity_name, getattr(self,intensity_name) - getattr(other_potion,intensity_name))
81 else:
82 raise TypeError("No such attribute!")
83
84 Potion.add_attr_used_in_reaction(self,other_potion)
85
86 return new_potion
87
88 def __truediv__(self,number):
89 Potion.is_depleted_or_used(self)
90 new_potion = Potion(self.effects, self.duration)
91 if number == 1:
92 return self
93
94 for key in self.effects.keys():
95 intensity_name = "intensity_" + key
96 setattr(new_potion,intensity_name, round( getattr(self,intensity_name) / number))
97
98 potions = ( new_potion for _ in range(number))
99
100 Potion.add_attr_used_in_reaction(self)
101
102 return potions
103
104 def __eq__(self,other_potion):
105 for key in self.effects.keys():
106 intensity_name = "intensity_" + key
107 if not hasattr(other_potion,intensity_name):
108 return False
109 if getattr(self,intensity_name) != getattr(other_potion,intensity_name):
110 return False
111
112 return self.effects == other_potion.effects
113
114 def __gt__(self, other_potion):
115 return Potion.get_sum(self) > Potion.get_sum(other_potion)
116
117 @staticmethod
118 def get_sum(obj):
119 sum = 0
120 for key in obj.effects.keys():
121 intensity_name = "intensity_" + key
122 sum += getattr(obj,intensity_name)
123 return sum
124
125 @staticmethod
126 def is_depleted_or_used(*potions):
127 for poiton in potions:
128 if poiton.is_depleted:
129 raise TypeError("Potion is depleted.")
130 if poiton.is_used_in_reaction:
131 raise TypeError("Potion is now part of something bigger than itself.")
132
133 @staticmethod
134 def add_attr_used_in_reaction(*potions):
135 for potion in potions:
136 setattr(potion, "is_used_in_reaction", True)
137
138class ГоспожатаПоХимия():
139 def tick():
140 all_instances_of_potions = Potion.instances
141 for instance in all_instances_of_potions:
142 instance.duration = instance.duration - 1
143
144 def apply(self, target, potion):
145 Potion.is_depleted_or_used(potion)
146 sorted_effects = sorted(potion.effects, reverse = True)
147 is_all_depleted = True
148
149 for effect in sorted_effects:
150 deplete_attr = "is_depleted_" + effect
151 if not getattr(potion,deplete_attr):
152 is_all_depleted = False
153 getattr(potion, effect)(target)
154 if is_all_depleted:
155 raise TypeError("Potion is depleted.")
156
157 potion.is_depleted = True
FF...FFFFFEE.FFFFFEF
======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 165, in test_purification
potion = potion1 - potion2
File "/tmp/solution.py", line 82, in __sub__
raise TypeError("No such attribute!")
TypeError: No such attribute!
======================================================================
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
File "/tmp/solution.py", line 89, in __truediv__
Potion.is_depleted_or_used(self)
File "/tmp/solution.py", line 131, in is_depleted_or_used
raise TypeError("Potion is now part of something bigger than itself.")
TypeError: Potion is now part of something bigger than itself.
======================================================================
ERROR: 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 485, in test_ticking_multiple_targets
self._dimitrichka.apply(target1, potion1)
File "/tmp/solution.py", line 145, in apply
Potion.is_depleted_or_used(potion)
File "/tmp/solution.py", line 131, in is_depleted_or_used
raise TypeError("Potion is now part of something bigger than itself.")
TypeError: Potion is now part of something bigger than itself.
======================================================================
FAIL: test_applying (test.TestBasicPotion)
Test applying a potion to a target.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 64, in test_applying
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
======================================================================
FAIL: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 77, in test_depletion
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
======================================================================
FAIL: test_combination_no_overlap (test.TestPotionOperations)
Test combining potions with no overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 96, in test_combination_no_overlap
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
======================================================================
FAIL: test_combination_with_overlap (test.TestPotionOperations)
Test combining potions with overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 105, in test_combination_with_overlap
self.assertEqual(self._target.int_attr, 500)
AssertionError: 5 != 500
======================================================================
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_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 127, in test_dilution
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
======================================================================
FAIL: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 112, in test_potentiation
self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
AssertionError: 5 != 5000
======================================================================
FAIL: test_applying_normal_case (test.TestГоспожатаПоХимия)
Test applying a normal potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 351, in test_applying_normal_case
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
======================================================================
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: 5 != 12
======================================================================
FAIL: test_applying_part_of_potion (test.TestГоспожатаПоХимия)
Test applying only a part of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 367, in test_applying_part_of_potion
self.assertAlmostEqual(self._target.float_attr, 4.14)
AssertionError: 3.14 != 4.14 within 7 places (0.9999999999999996 difference)
======================================================================
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 425, in test_ticking_immutable
self.assertEqual(self._target.int_attr, 500)
AssertionError: 5 != 500
======================================================================
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 456, in test_ticking_multiple_potions
self.assertEqual(self._target.int_attr, 500)
AssertionError: 5 != 500
======================================================================
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 439, in test_ticking_mutable
self.assertEqual(self._target.int_attr, 50)
AssertionError: 5 != 50
----------------------------------------------------------------------
Ran 20 tests in 0.002s
FAILED (failures=13, errors=3)
f | 1 | import weakref | f | 1 | import weakref |
2 | 2 | ||||
3 | class Potion(): | 3 | class Potion(): | ||
4 | instances = [] | 4 | instances = [] | ||
5 | 5 | ||||
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.is_depleted = False | 9 | self.is_depleted = False | ||
10 | self.is_used_in_reaction = False | 10 | self.is_used_in_reaction = False | ||
11 | self.__class__.instances.append(weakref.proxy(self)) | 11 | self.__class__.instances.append(weakref.proxy(self)) | ||
12 | 12 | ||||
13 | for key, value in effects.items(): | 13 | for key, value in effects.items(): | ||
14 | setattr(self, "intensity_" + key, 1) | 14 | setattr(self, "intensity_" + key, 1) | ||
15 | setattr(self, "is_depleted_" + key, False) | 15 | setattr(self, "is_depleted_" + key, False) | ||
16 | setattr(self, key, Potion.call_intensity_times(self, key, value)) | 16 | setattr(self, key, Potion.call_intensity_times(self, key, value)) | ||
17 | 17 | ||||
18 | @staticmethod | 18 | @staticmethod | ||
19 | def call_intensity_times(self, key, value): | 19 | def call_intensity_times(self, key, value): | ||
20 | def decorator(target): | 20 | def decorator(target): | ||
n | n | 21 | deplete_attr = "is_depleted_" + key | ||
21 | i = 0 | 22 | i = 0 | ||
n | 22 | if not self["is_depleted_" + key]: | n | 23 | if not getattr(self,deplete_attr): |
23 | while i < self["intensity_" + key]: | 24 | while i < getattr(self,deplete_attr): | ||
24 | value(target) | 25 | value(target) | ||
25 | i += 1 | 26 | i += 1 | ||
26 | setattr(self, "is_depleted_" + key, True) | 27 | setattr(self, "is_depleted_" + key, True) | ||
27 | else: | 28 | else: | ||
28 | raise TypeError("Effect is depleted.") | 29 | raise TypeError("Effect is depleted.") | ||
29 | 30 | ||||
30 | return decorator | 31 | return decorator | ||
31 | 32 | ||||
32 | def __add__(self, other_potion): | 33 | def __add__(self, other_potion): | ||
33 | Potion.is_depleted_or_used(self, other_potion) | 34 | Potion.is_depleted_or_used(self, other_potion) | ||
34 | 35 | ||||
35 | new_duration = max(self.duration, other_potion.duration) | 36 | new_duration = max(self.duration, other_potion.duration) | ||
36 | self.effects.update(other_potion.effects) | 37 | self.effects.update(other_potion.effects) | ||
37 | new_potion = Potion(self.effects, new_duration) | 38 | new_potion = Potion(self.effects, new_duration) | ||
38 | 39 | ||||
39 | for key in self.effects.keys(): | 40 | for key in self.effects.keys(): | ||
40 | intensity_name = "intensity_" + key | 41 | intensity_name = "intensity_" + key | ||
41 | if hasattr(other_potion, intensity_name) and hasattr(self, intensity_name): | 42 | if hasattr(other_potion, intensity_name) and hasattr(self, intensity_name): | ||
42 | setattr(new_potion, intensity_name, getattr(self,intensity_name) + getattr(other_potion,intensity_name)) | 43 | setattr(new_potion, intensity_name, getattr(self,intensity_name) + getattr(other_potion,intensity_name)) | ||
43 | elif hasattr(other_potion, intensity_name): | 44 | elif hasattr(other_potion, intensity_name): | ||
44 | setattr(new_potion, intensity_name, getattr(other_potion,intensity_name)) | 45 | setattr(new_potion, intensity_name, getattr(other_potion,intensity_name)) | ||
45 | else: | 46 | else: | ||
46 | setattr(new_potion, intensity_name,getattr(self, intensity_name)) | 47 | setattr(new_potion, intensity_name,getattr(self, intensity_name)) | ||
47 | 48 | ||||
48 | Potion.add_attr_used_in_reaction(self,other_potion) | 49 | Potion.add_attr_used_in_reaction(self,other_potion) | ||
49 | 50 | ||||
50 | return new_potion | 51 | return new_potion | ||
51 | 52 | ||||
52 | def __mul__(self,number): | 53 | def __mul__(self,number): | ||
53 | Potion.is_depleted_or_used(self) | 54 | Potion.is_depleted_or_used(self) | ||
54 | 55 | ||||
55 | for key in self.effects.keys(): | 56 | for key in self.effects.keys(): | ||
56 | intensity_name = "intensity_" + key | 57 | intensity_name = "intensity_" + key | ||
57 | if 0 < number < 1: | 58 | if 0 < number < 1: | ||
58 | setattr(self,intensity_name, round( getattr(self,intensity_name)* number)) | 59 | setattr(self,intensity_name, round( getattr(self,intensity_name)* number)) | ||
59 | 60 | ||||
60 | elif hasattr(self, intensity_name): | 61 | elif hasattr(self, intensity_name): | ||
61 | setattr(self,intensity_name, getattr(self,intensity_name)* number) | 62 | setattr(self,intensity_name, getattr(self,intensity_name)* number) | ||
62 | 63 | ||||
63 | Potion.add_attr_used_in_reaction(self) | 64 | Potion.add_attr_used_in_reaction(self) | ||
64 | 65 | ||||
65 | return self | 66 | return self | ||
66 | 67 | ||||
67 | def __sub__(self, other_potion): | 68 | def __sub__(self, other_potion): | ||
68 | Potion.is_depleted_or_used(other_potion) | 69 | Potion.is_depleted_or_used(other_potion) | ||
69 | 70 | ||||
70 | new_duration = self.duration | 71 | new_duration = self.duration | ||
71 | new_potion = Potion(self.effects, new_duration) | 72 | new_potion = Potion(self.effects, new_duration) | ||
72 | 73 | ||||
73 | for key in self.effects.keys(): | 74 | for key in self.effects.keys(): | ||
74 | intensity_name = "intensity_" + key | 75 | intensity_name = "intensity_" + key | ||
75 | if hasattr(other_potion, intensity_name) and hasattr(new_potion, intensity_name): | 76 | if hasattr(other_potion, intensity_name) and hasattr(new_potion, intensity_name): | ||
76 | if getattr(new_potion,intensity_name) - getattr(other_potion,intensity_name) < 0: | 77 | if getattr(new_potion,intensity_name) - getattr(other_potion,intensity_name) < 0: | ||
77 | delattr(new_potion, intensity_name) | 78 | delattr(new_potion, intensity_name) | ||
78 | else: | 79 | else: | ||
79 | setattr(new_potion, intensity_name, getattr(self,intensity_name) - getattr(other_potion,intensity_name)) | 80 | setattr(new_potion, intensity_name, getattr(self,intensity_name) - getattr(other_potion,intensity_name)) | ||
80 | else: | 81 | else: | ||
81 | raise TypeError("No such attribute!") | 82 | raise TypeError("No such attribute!") | ||
82 | 83 | ||||
83 | Potion.add_attr_used_in_reaction(self,other_potion) | 84 | Potion.add_attr_used_in_reaction(self,other_potion) | ||
84 | 85 | ||||
85 | return new_potion | 86 | return new_potion | ||
86 | 87 | ||||
87 | def __truediv__(self,number): | 88 | def __truediv__(self,number): | ||
88 | Potion.is_depleted_or_used(self) | 89 | Potion.is_depleted_or_used(self) | ||
89 | new_potion = Potion(self.effects, self.duration) | 90 | new_potion = Potion(self.effects, self.duration) | ||
90 | if number == 1: | 91 | if number == 1: | ||
91 | return self | 92 | return self | ||
92 | 93 | ||||
93 | for key in self.effects.keys(): | 94 | for key in self.effects.keys(): | ||
94 | intensity_name = "intensity_" + key | 95 | intensity_name = "intensity_" + key | ||
95 | setattr(new_potion,intensity_name, round( getattr(self,intensity_name) / number)) | 96 | setattr(new_potion,intensity_name, round( getattr(self,intensity_name) / number)) | ||
96 | 97 | ||||
97 | potions = ( new_potion for _ in range(number)) | 98 | potions = ( new_potion for _ in range(number)) | ||
98 | 99 | ||||
99 | Potion.add_attr_used_in_reaction(self) | 100 | Potion.add_attr_used_in_reaction(self) | ||
100 | 101 | ||||
101 | return potions | 102 | return potions | ||
102 | 103 | ||||
103 | def __eq__(self,other_potion): | 104 | def __eq__(self,other_potion): | ||
104 | for key in self.effects.keys(): | 105 | for key in self.effects.keys(): | ||
105 | intensity_name = "intensity_" + key | 106 | intensity_name = "intensity_" + key | ||
106 | if not hasattr(other_potion,intensity_name): | 107 | if not hasattr(other_potion,intensity_name): | ||
107 | return False | 108 | return False | ||
108 | if getattr(self,intensity_name) != getattr(other_potion,intensity_name): | 109 | if getattr(self,intensity_name) != getattr(other_potion,intensity_name): | ||
109 | return False | 110 | return False | ||
110 | 111 | ||||
111 | return self.effects == other_potion.effects | 112 | return self.effects == other_potion.effects | ||
112 | 113 | ||||
113 | def __gt__(self, other_potion): | 114 | def __gt__(self, other_potion): | ||
114 | return Potion.get_sum(self) > Potion.get_sum(other_potion) | 115 | return Potion.get_sum(self) > Potion.get_sum(other_potion) | ||
115 | 116 | ||||
116 | @staticmethod | 117 | @staticmethod | ||
117 | def get_sum(obj): | 118 | def get_sum(obj): | ||
118 | sum = 0 | 119 | sum = 0 | ||
119 | for key in obj.effects.keys(): | 120 | for key in obj.effects.keys(): | ||
120 | intensity_name = "intensity_" + key | 121 | intensity_name = "intensity_" + key | ||
121 | sum += getattr(obj,intensity_name) | 122 | sum += getattr(obj,intensity_name) | ||
122 | return sum | 123 | return sum | ||
123 | 124 | ||||
124 | @staticmethod | 125 | @staticmethod | ||
125 | def is_depleted_or_used(*potions): | 126 | def is_depleted_or_used(*potions): | ||
126 | for poiton in potions: | 127 | for poiton in potions: | ||
127 | if poiton.is_depleted: | 128 | if poiton.is_depleted: | ||
128 | raise TypeError("Potion is depleted.") | 129 | raise TypeError("Potion is depleted.") | ||
129 | if poiton.is_used_in_reaction: | 130 | if poiton.is_used_in_reaction: | ||
130 | raise TypeError("Potion is now part of something bigger than itself.") | 131 | raise TypeError("Potion is now part of something bigger than itself.") | ||
131 | 132 | ||||
132 | @staticmethod | 133 | @staticmethod | ||
133 | def add_attr_used_in_reaction(*potions): | 134 | def add_attr_used_in_reaction(*potions): | ||
134 | for potion in potions: | 135 | for potion in potions: | ||
135 | setattr(potion, "is_used_in_reaction", True) | 136 | setattr(potion, "is_used_in_reaction", True) | ||
136 | 137 | ||||
137 | class ГоспожатаПоХимия(): | 138 | class ГоспожатаПоХимия(): | ||
138 | def tick(): | 139 | def tick(): | ||
139 | all_instances_of_potions = Potion.instances | 140 | all_instances_of_potions = Potion.instances | ||
140 | for instance in all_instances_of_potions: | 141 | for instance in all_instances_of_potions: | ||
141 | instance.duration = instance.duration - 1 | 142 | instance.duration = instance.duration - 1 | ||
142 | 143 | ||||
143 | def apply(self, target, potion): | 144 | def apply(self, target, potion): | ||
144 | Potion.is_depleted_or_used(potion) | 145 | Potion.is_depleted_or_used(potion) | ||
145 | sorted_effects = sorted(potion.effects, reverse = True) | 146 | sorted_effects = sorted(potion.effects, reverse = True) | ||
146 | is_all_depleted = True | 147 | is_all_depleted = True | ||
147 | 148 | ||||
148 | for effect in sorted_effects: | 149 | for effect in sorted_effects: | ||
t | 149 | if not potion["is_depleted_" + effect]: | t | 150 | deplete_attr = "is_depleted_" + effect |
151 | if not getattr(potion,deplete_attr): | ||||
150 | is_all_depleted = False | 152 | is_all_depleted = False | ||
151 | getattr(potion, effect)(target) | 153 | getattr(potion, effect)(target) | ||
152 | if is_all_depleted: | 154 | if is_all_depleted: | ||
153 | raise TypeError("Potion is depleted.") | 155 | raise TypeError("Potion is depleted.") | ||
154 | 156 | ||||
155 | potion.is_depleted = True | 157 | potion.is_depleted = True |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | import weakref | f | 1 | import weakref |
2 | 2 | ||||
3 | class Potion(): | 3 | class Potion(): | ||
4 | instances = [] | 4 | instances = [] | ||
5 | 5 | ||||
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.is_depleted = False | 9 | self.is_depleted = False | ||
10 | self.is_used_in_reaction = False | 10 | self.is_used_in_reaction = False | ||
11 | self.__class__.instances.append(weakref.proxy(self)) | 11 | self.__class__.instances.append(weakref.proxy(self)) | ||
12 | 12 | ||||
13 | for key, value in effects.items(): | 13 | for key, value in effects.items(): | ||
14 | setattr(self, "intensity_" + key, 1) | 14 | setattr(self, "intensity_" + key, 1) | ||
15 | setattr(self, "is_depleted_" + key, False) | 15 | setattr(self, "is_depleted_" + key, False) | ||
16 | setattr(self, key, Potion.call_intensity_times(self, key, value)) | 16 | setattr(self, key, Potion.call_intensity_times(self, key, value)) | ||
17 | 17 | ||||
18 | @staticmethod | 18 | @staticmethod | ||
19 | def call_intensity_times(self, key, value): | 19 | def call_intensity_times(self, key, value): | ||
20 | def decorator(target): | 20 | def decorator(target): | ||
21 | i = 0 | 21 | i = 0 | ||
22 | if not self["is_depleted_" + key]: | 22 | if not self["is_depleted_" + key]: | ||
23 | while i < self["intensity_" + key]: | 23 | while i < self["intensity_" + key]: | ||
24 | value(target) | 24 | value(target) | ||
25 | i += 1 | 25 | i += 1 | ||
26 | setattr(self, "is_depleted_" + key, True) | 26 | setattr(self, "is_depleted_" + key, True) | ||
27 | else: | 27 | else: | ||
28 | raise TypeError("Effect is depleted.") | 28 | raise TypeError("Effect is depleted.") | ||
29 | 29 | ||||
30 | return decorator | 30 | return decorator | ||
31 | 31 | ||||
32 | def __add__(self, other_potion): | 32 | def __add__(self, other_potion): | ||
33 | Potion.is_depleted_or_used(self, other_potion) | 33 | Potion.is_depleted_or_used(self, other_potion) | ||
34 | 34 | ||||
35 | new_duration = max(self.duration, other_potion.duration) | 35 | new_duration = max(self.duration, other_potion.duration) | ||
36 | self.effects.update(other_potion.effects) | 36 | self.effects.update(other_potion.effects) | ||
37 | new_potion = Potion(self.effects, new_duration) | 37 | new_potion = Potion(self.effects, new_duration) | ||
38 | 38 | ||||
39 | for key in self.effects.keys(): | 39 | for key in self.effects.keys(): | ||
40 | intensity_name = "intensity_" + key | 40 | intensity_name = "intensity_" + key | ||
41 | if hasattr(other_potion, intensity_name) and hasattr(self, intensity_name): | 41 | if hasattr(other_potion, intensity_name) and hasattr(self, intensity_name): | ||
42 | setattr(new_potion, intensity_name, getattr(self,intensity_name) + getattr(other_potion,intensity_name)) | 42 | setattr(new_potion, intensity_name, getattr(self,intensity_name) + getattr(other_potion,intensity_name)) | ||
43 | elif hasattr(other_potion, intensity_name): | 43 | elif hasattr(other_potion, intensity_name): | ||
44 | setattr(new_potion, intensity_name, getattr(other_potion,intensity_name)) | 44 | setattr(new_potion, intensity_name, getattr(other_potion,intensity_name)) | ||
45 | else: | 45 | else: | ||
46 | setattr(new_potion, intensity_name,getattr(self, intensity_name)) | 46 | setattr(new_potion, intensity_name,getattr(self, intensity_name)) | ||
47 | 47 | ||||
48 | Potion.add_attr_used_in_reaction(self,other_potion) | 48 | Potion.add_attr_used_in_reaction(self,other_potion) | ||
49 | 49 | ||||
50 | return new_potion | 50 | return new_potion | ||
51 | 51 | ||||
52 | def __mul__(self,number): | 52 | def __mul__(self,number): | ||
53 | Potion.is_depleted_or_used(self) | 53 | Potion.is_depleted_or_used(self) | ||
54 | 54 | ||||
55 | for key in self.effects.keys(): | 55 | for key in self.effects.keys(): | ||
56 | intensity_name = "intensity_" + key | 56 | intensity_name = "intensity_" + key | ||
57 | if 0 < number < 1: | 57 | if 0 < number < 1: | ||
58 | setattr(self,intensity_name, round( getattr(self,intensity_name)* number)) | 58 | setattr(self,intensity_name, round( getattr(self,intensity_name)* number)) | ||
59 | 59 | ||||
60 | elif hasattr(self, intensity_name): | 60 | elif hasattr(self, intensity_name): | ||
61 | setattr(self,intensity_name, getattr(self,intensity_name)* number) | 61 | setattr(self,intensity_name, getattr(self,intensity_name)* number) | ||
62 | 62 | ||||
63 | Potion.add_attr_used_in_reaction(self) | 63 | Potion.add_attr_used_in_reaction(self) | ||
64 | 64 | ||||
65 | return self | 65 | return self | ||
66 | 66 | ||||
67 | def __sub__(self, other_potion): | 67 | def __sub__(self, other_potion): | ||
68 | Potion.is_depleted_or_used(other_potion) | 68 | Potion.is_depleted_or_used(other_potion) | ||
69 | 69 | ||||
70 | new_duration = self.duration | 70 | new_duration = self.duration | ||
71 | new_potion = Potion(self.effects, new_duration) | 71 | new_potion = Potion(self.effects, new_duration) | ||
72 | 72 | ||||
73 | for key in self.effects.keys(): | 73 | for key in self.effects.keys(): | ||
74 | intensity_name = "intensity_" + key | 74 | intensity_name = "intensity_" + key | ||
75 | if hasattr(other_potion, intensity_name) and hasattr(new_potion, intensity_name): | 75 | if hasattr(other_potion, intensity_name) and hasattr(new_potion, intensity_name): | ||
76 | if getattr(new_potion,intensity_name) - getattr(other_potion,intensity_name) < 0: | 76 | if getattr(new_potion,intensity_name) - getattr(other_potion,intensity_name) < 0: | ||
77 | delattr(new_potion, intensity_name) | 77 | delattr(new_potion, intensity_name) | ||
78 | else: | 78 | else: | ||
79 | setattr(new_potion, intensity_name, getattr(self,intensity_name) - getattr(other_potion,intensity_name)) | 79 | setattr(new_potion, intensity_name, getattr(self,intensity_name) - getattr(other_potion,intensity_name)) | ||
80 | else: | 80 | else: | ||
81 | raise TypeError("No such attribute!") | 81 | raise TypeError("No such attribute!") | ||
82 | 82 | ||||
83 | Potion.add_attr_used_in_reaction(self,other_potion) | 83 | Potion.add_attr_used_in_reaction(self,other_potion) | ||
84 | 84 | ||||
85 | return new_potion | 85 | return new_potion | ||
86 | 86 | ||||
87 | def __truediv__(self,number): | 87 | def __truediv__(self,number): | ||
88 | Potion.is_depleted_or_used(self) | 88 | Potion.is_depleted_or_used(self) | ||
89 | new_potion = Potion(self.effects, self.duration) | 89 | new_potion = Potion(self.effects, self.duration) | ||
90 | if number == 1: | 90 | if number == 1: | ||
91 | return self | 91 | return self | ||
92 | 92 | ||||
93 | for key in self.effects.keys(): | 93 | for key in self.effects.keys(): | ||
94 | intensity_name = "intensity_" + key | 94 | intensity_name = "intensity_" + key | ||
95 | setattr(new_potion,intensity_name, round( getattr(self,intensity_name) / number)) | 95 | setattr(new_potion,intensity_name, round( getattr(self,intensity_name) / number)) | ||
96 | 96 | ||||
97 | potions = ( new_potion for _ in range(number)) | 97 | potions = ( new_potion for _ in range(number)) | ||
98 | 98 | ||||
99 | Potion.add_attr_used_in_reaction(self) | 99 | Potion.add_attr_used_in_reaction(self) | ||
100 | 100 | ||||
101 | return potions | 101 | return potions | ||
102 | 102 | ||||
103 | def __eq__(self,other_potion): | 103 | def __eq__(self,other_potion): | ||
104 | for key in self.effects.keys(): | 104 | for key in self.effects.keys(): | ||
105 | intensity_name = "intensity_" + key | 105 | intensity_name = "intensity_" + key | ||
106 | if not hasattr(other_potion,intensity_name): | 106 | if not hasattr(other_potion,intensity_name): | ||
107 | return False | 107 | return False | ||
108 | if getattr(self,intensity_name) != getattr(other_potion,intensity_name): | 108 | if getattr(self,intensity_name) != getattr(other_potion,intensity_name): | ||
109 | return False | 109 | return False | ||
110 | 110 | ||||
111 | return self.effects == other_potion.effects | 111 | return self.effects == other_potion.effects | ||
112 | 112 | ||||
113 | def __gt__(self, other_potion): | 113 | def __gt__(self, other_potion): | ||
114 | return Potion.get_sum(self) > Potion.get_sum(other_potion) | 114 | return Potion.get_sum(self) > Potion.get_sum(other_potion) | ||
115 | 115 | ||||
116 | @staticmethod | 116 | @staticmethod | ||
117 | def get_sum(obj): | 117 | def get_sum(obj): | ||
118 | sum = 0 | 118 | sum = 0 | ||
119 | for key in obj.effects.keys(): | 119 | for key in obj.effects.keys(): | ||
120 | intensity_name = "intensity_" + key | 120 | intensity_name = "intensity_" + key | ||
121 | sum += getattr(obj,intensity_name) | 121 | sum += getattr(obj,intensity_name) | ||
122 | return sum | 122 | return sum | ||
123 | 123 | ||||
124 | @staticmethod | 124 | @staticmethod | ||
125 | def is_depleted_or_used(*potions): | 125 | def is_depleted_or_used(*potions): | ||
126 | for poiton in potions: | 126 | for poiton in potions: | ||
127 | if poiton.is_depleted: | 127 | if poiton.is_depleted: | ||
128 | raise TypeError("Potion is depleted.") | 128 | raise TypeError("Potion is depleted.") | ||
129 | if poiton.is_used_in_reaction: | 129 | if poiton.is_used_in_reaction: | ||
130 | raise TypeError("Potion is now part of something bigger than itself.") | 130 | raise TypeError("Potion is now part of something bigger than itself.") | ||
131 | 131 | ||||
132 | @staticmethod | 132 | @staticmethod | ||
133 | def add_attr_used_in_reaction(*potions): | 133 | def add_attr_used_in_reaction(*potions): | ||
134 | for potion in potions: | 134 | for potion in potions: | ||
135 | setattr(potion, "is_used_in_reaction", True) | 135 | setattr(potion, "is_used_in_reaction", True) | ||
136 | 136 | ||||
137 | class ГоспожатаПоХимия(): | 137 | class ГоспожатаПоХимия(): | ||
138 | def tick(): | 138 | def tick(): | ||
139 | all_instances_of_potions = Potion.instances | 139 | all_instances_of_potions = Potion.instances | ||
140 | for instance in all_instances_of_potions: | 140 | for instance in all_instances_of_potions: | ||
141 | instance.duration = instance.duration - 1 | 141 | instance.duration = instance.duration - 1 | ||
142 | 142 | ||||
143 | def apply(self, target, potion): | 143 | def apply(self, target, potion): | ||
144 | Potion.is_depleted_or_used(potion) | 144 | Potion.is_depleted_or_used(potion) | ||
145 | sorted_effects = sorted(potion.effects, reverse = True) | 145 | sorted_effects = sorted(potion.effects, reverse = True) | ||
146 | is_all_depleted = True | 146 | is_all_depleted = True | ||
147 | 147 | ||||
n | 148 | for key in sorted_effects.keys(): | n | 148 | for effect in sorted_effects: |
149 | if not potion["is_depleted_" + key]: | 149 | if not potion["is_depleted_" + effect]: | ||
150 | is_all_depleted = False | 150 | is_all_depleted = False | ||
t | 151 | getattr(potion, key)(target) | t | 151 | getattr(potion, effect)(target) |
152 | if is_all_depleted: | 152 | if is_all_depleted: | ||
153 | raise TypeError("Potion is depleted.") | 153 | raise TypeError("Potion is depleted.") | ||
154 | 154 | ||||
155 | potion.is_depleted = True | 155 | potion.is_depleted = True |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
08.12.2023 13:45
08.12.2023 13:46
08.12.2023 13:41
08.12.2023 13:42
08.12.2023 13:44