1class Potion:
2 def __init__(self, effects, duration):
3 self._effects = {name: (func, 1) for name, func in effects.items()}
4 self._duration = duration
5 self._is_used = False
6 self._is_depleted = False
7
8 def _call_effect(self, effect_name, target):
9 if self._is_used or self._is_depleted:
10 raise TypeError("Potion is now part of something bigger than itself.")
11 func, intensity = self._effects.get(effect_name, (None, 0))
12 if intensity == 0:
13 raise TypeError("Effect is depleted.")
14 for _ in range(intensity):
15 func(target)
16 self._effects[effect_name] = (func, 0)
17 self._is_depleted = all(intensity == 0 for _, intensity in self._effects.values())
18
19 def __getattr__(self, name):
20 if name in self._effects:
21 return lambda target: self._call_effect(name, target)
22 raise TypeError("Effect is depleted.")
23
24 def __add__(self, other):
25 if self._is_used or other._is_used:
26 raise TypeError("Potion is now part of something bigger than itself.")
27 new_effects = {}
28 for name, (func, intensity) in self._effects.items():
29 new_intensity = intensity + other._effects.get(name, (None, 0))[1]
30 new_effects[name] = (func, new_intensity)
31 for name, (func, intensity) in other._effects.items():
32 if name not in new_effects:
33 new_effects[name] = (func, intensity)
34 self._is_used = True
35 other._is_used = True
36 return Potion(new_effects, max(self._duration, other._duration))
37
38 def __mul__(self, num):
39 if self._is_used:
40 raise TypeError("Potion is now part of something bigger than itself.")
41 new_effects = {name: (func, max(0, round(intensity * num)))
42 for name, (func, intensity) in self._effects.items()}
43 self._is_used = True
44 return Potion(new_effects, self._duration)
45
46 def __sub__(self, other):
47 if self._is_used or other._is_used:
48 raise TypeError("Potion is now part of something bigger than itself.")
49 new_effects = {}
50 for name, (func, intensity) in self._effects.items():
51 new_intensity = max(0, intensity - other._effects.get(name, (None, 0))[1])
52 if new_intensity > 0:
53 new_effects[name] = (func, new_intensity)
54 self._is_used = True
55 other._is_used = True
56 return Potion(new_effects, self._duration)
57
58 def __truediv__(self, num):
59 if self._is_used:
60 raise TypeError("Potion is now part of something bigger than itself.")
61 new_effects = {name: (func, max(0, intensity / num))
62 for name, (func, intensity) in self._effects.items()}
63 self._is_used = True
64 return [Potion(new_effects, self._duration) for _ in range(num)]
65
66 def __eq__(self, other):
67 return self._effects == other._effects
68
69 def __gt__(self, other):
70 return sum(intensity for _, intensity in self._effects.values()) > \
71 sum(intensity for _, intensity in other._effects.values())
72
73 def __lt__(self, other):
74 return sum(intensity for _, intensity in self._effects.values()) < \
75 sum(intensity for _, intensity in other._effects.values())
76
77
78class ГоспожатаПоХимия:
79 def __init__(self):
80 self._time = 0
81 self._applied_potions = []
82
83 def apply(self, target, potion):
84 if potion._is_used or potion._is_depleted:
85 raise TypeError("Potion is depleted.")
86 sorted_effects = sorted(potion._effects.items(), key=lambda x: sum(ord(s) for s in x[0]))
87 for name, (func, intensity) in sorted_effects:
88 for _ in range(intensity):
89 func(target)
90 potion._is_depleted = True
91 self._applied_potions.append((potion, self._time + potion._duration))
92
93 def tick(self):
94 self._time += 1
95 for potion, end_time in self._applied_potions:
96 if self._time >= end_time:
97 potion._is_depleted = True
.F.FFEE.EEEEF.F.EFEF
======================================================================
ERROR: test_combination_no_overlap (test.TestPotionOperations)
Test combining potions with no overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 94, in test_combination_no_overlap
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
ERROR: test_combination_with_overlap (test.TestPotionOperations)
Test combining potions with overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 104, in test_combination_with_overlap
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
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 <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
ERROR: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 111, in test_potentiation
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 166, in test_purification
potion.float_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 214, in test_separation
potion1.int_attr_fun(self._target)
File "/tmp/solution.py", line 21, in <lambda>
return lambda target: self._call_effect(name, target)
File "/tmp/solution.py", line 15, in _call_effect
func(target)
TypeError: 'tuple' object is not callable
======================================================================
ERROR: test_ticking_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 424, in test_ticking_immutable
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 89, in apply
func(target)
TypeError: 'tuple' object is not callable
======================================================================
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 89, in apply
func(target)
TypeError: 'tuple' object is not callable
======================================================================
FAIL: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
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 78, in test_depletion
with self.assertRaisesRegex(TypeError, 'Effect is depleted\.'):
AssertionError: "Effect is depleted\." does not match "Potion is now part of something bigger than itself."
======================================================================
FAIL: test_equal (test.TestPotionComparison)
Test equality of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 292, in test_equal
self.assertEqual(potion1 + potion2, potion3)
AssertionError: <solution.Potion object at 0x7fa4085570a0> != <solution.Potion object at 0x7fa408557190>
======================================================================
FAIL: test_superbness (test.TestPotionComparison)
Test superbness of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 317, in test_superbness
self.assertLess(potion1, potion2)
AssertionError: <solution.Potion object at 0x7fa408557190> not less than <solution.Potion object at 0x7fa4085571c0>
======================================================================
FAIL: test_applying_depleted_potion (test.TestГоспожатаПоХимия)
Test applying a depleted potion or a potion that was used in a reaction.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 382, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: TypeError not raised
======================================================================
FAIL: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 405, in test_applying_order
self.assertEqual(self._target.int_attr, 12)
AssertionError: 14 != 12
======================================================================
FAIL: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 458, in test_ticking_multiple_potions
self.assertEqual(self._target.int_attr, 50)
AssertionError: 500 != 50
======================================================================
FAIL: test_ticking_mutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 444, in test_ticking_mutable
self.assertEqual(self._target.int_attr, 5)
AssertionError: 50 != 5
----------------------------------------------------------------------
Ran 20 tests in 0.002s
FAILED (failures=7, errors=8)
08.12.2023 13:39
08.12.2023 13:35