1import math
2
3class Potion:
4 def __init__(self, effects, duration):
5 self.duration = duration
6 self.effects = effects
7 for effect in effects:
8 setattr(self, effect, effects[effect])
9 self.intensity = {effect : 1 for effect in effects}
10 self.used_effects = []
11 self.used = False
12
13 def __intensify(self, effect):
14 def effect_with_intensity(target):
15 if self.used:
16 raise TypeError('Potion is now part of something bigger than itself.')
17 if effect in self.used_effects:
18 raise TypeError('Effect is depleted.')
19 self.used_effects.append(effect)
20 for _ in range(self.intensity[effect]):
21 self.effects[effect](target)
22 return effect_with_intensity
23
24 def __getattribute__(self, name):
25 if name in object.__getattribute__(self, 'effects'):
26 return self.__intensify(name)
27 return object.__getattribute__(self, name)
28
29 def __add__(self, other):
30 self.used = True
31 other.used = True
32 combined_potion_effects = dict(self.effects)
33 combined_potion_intensity = dict(self.intensity)
34 for effect in other.effects:
35 if effect not in combined_potion_effects:
36 combined_potion_effects[effect] = other.effects[effect]
37 combined_potion_intensity[effect] = other.intensity[effect]
38 else:
39 combined_potion_intensity[effect] += other.intensity[effect]
40 combined_potion_duration = max(self.duration, other.duration)
41 combined_potion = Potion(combined_potion_effects, combined_potion_duration)
42 combined_potion.intensity = combined_potion_intensity
43 return combined_potion
44
45 def __mul__(self, other):
46 self.used = True
47 potentiated_potion = Potion(dict(self.effects), self.duration)
48 potentiated_potion.intensity = dict(self.intensity)
49 for effect in potentiated_potion.effects:
50 effect_intensity = potentiated_potion.intensity[effect]
51 effect_intensity *= other
52 potentiated_potion.intensity[effect] = math.floor(effect_intensity) if effect_intensity - int(effect_intensity) <= 0.5 else math.ceil(effect_intensity)
53 return potentiated_potion
54
55 def __sub__(self, other):
56 self.used = True
57 other.used = True
58 purified_potion = Potion(dict(self.effects), self.duration)
59 purified_potion.intensity = dict(self.intensity)
60 for effect in other.effects:
61 if effect not in purified_potion.effects:
62 raise TypeError('(╯°□°)╯︵ ┻━┻')
63 if purified_potion.intensity[effect] > other.intensity[effect]:
64 purified_potion.intensity[effect] -= other.intensity[effect]
65 else:
66 delattr(purified_potion, effect)
67 del purified_potion.effects[effect]
68 del purified_potion.intensity[effect]
69 return purified_potion
70
71 def __truediv__(self, other):
72 self.used = True
73 return tuple(self * (1 / other) for _ in range(other))
74
75 def __eq__(self, other):
76 return self.effects == other.effects and self.intensity == other.intensity
77
78 def __lt__(self, other):
79 return sum(self.intensity.values()) < sum(other.intensity.values())
80
81 def __gt__(self, other):
82 return other < self and self != other
83
84class ГоспожатаПоХимия:
85 def __init__(self):
86 self.applied_potions = []
87 self.applied_potions_to_targets = {}
88 self.targets_initial_state = {}
89
90 def apply(self, target, potion):
91 if potion in self.applied_potions or potion.used:
92 raise TypeError('Potion is depleted.') # TODO
93 self.applied_potions.append(potion)
94 if target in self.applied_potions_to_targets:
95 self.applied_potions_to_targets[target].append([potion, 0])
96 else :
97 self.applied_potions_to_targets[target] = [[potion, 0]]
98 self.targets_initial_state[target] = dict(target.__dict__)
99 effects_to_apply = []
100 for effect in potion.effects:
101 if effect not in potion.used_effects:
102 effects_to_apply.append(effect)
103 effects_to_apply.sort(key = lambda name : sum(ord(ch) for ch in name))
104 for effect in effects_to_apply:
105 potion.effects[effect](target)
106 potion.used = True # idk
107
108 def tick(self):
109 effect_wore_off = False
110 for target in self.applied_potions_to_targets:
111 for potions in self.applied_potions_to_targets[target]:
112 potions[1] += 1
113 if(potions[1] >= potions[0].duration):
114 self.applied_potions_to_targets[target].remove(potions)
115 effect_wore_off = True
116 if effect_wore_off:
117 for target in self.applied_potions_to_targets:
118 target.__dict__ = dict(self.targets_initial_state[target])
119 for potions in self.applied_potions_to_targets[target]:
120 potion = potions[0]
121 potion.used = False
122 self.applied_potions.remove(potion)
123 self.apply(target, potion)
............F.F.FEFF
======================================================================
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/test.py", line 455, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion2)
File "/tmp/solution.py", line 92, in apply
raise TypeError('Potion is depleted.') # TODO
TypeError: Potion is depleted.
======================================================================
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_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: 50 != 500
======================================================================
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 487, in test_ticking_multiple_targets
self.assertEqual(target1.int_attr, 500)
AssertionError: 50 != 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 446, in test_ticking_mutable
self.assertEqual(self._target.list_attr, [1, 2, 3])
AssertionError: Lists differ: [1, 2, 3, 4] != [1, 2, 3]
First list contains 1 additional elements.
First extra element 3:
4
- [1, 2, 3, 4]
? ---
+ [1, 2, 3]
----------------------------------------------------------------------
Ran 20 tests in 0.003s
FAILED (failures=5, errors=1)
Виктор Бечев
08.12.2023 14:27Честно казано стилистично нямам какво да коментирам (сигурно бих могъл ако задълбая, но на този етап ще е излишно).
П.П. На места ми е тромав и тежък за четене, което обаче вероятно е по-скоро функция на логиката, отколкото на стила.
|
06.12.2023 09:45