Домашни > Работилница за отвари! > Решения > Решението на Калоян Крайнин

Резултати
0 точки от тестове
0 точки от учител

0 точки общо

1 успешни теста
19 неуспешни теста
Код
Скрий всички коментари

  1import math
  2from typing import Any
  3
  4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
  5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
  6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
  7POTION_DEPLETED_MESSAGE = "Potion is depleted."
  8
  9
 10def invalidating(f):
 11    def with_invalidation(self, other):
 12        assert type(self) is Potion
 13        if self.__is_used or self.__is_depleted:
 14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
 15        if type(other) is Potion:
 16            if other.__is_used or other.__is_depleted:
 17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
 18            other.__is_used = True
 19        self.__is_used = True
 20        return f(self, other)
 21    return with_invalidation
 22
 23
 24class Potion:
 25    _applied_effects = set()
 26    __is_used = False
 27    __is_depleted = False
 28
 29    def __init__(self, effects: dict, duration: int) -> None:
 30        self._effects = effects
 31        self._duration = duration
 32        self._intencities = {}
 33        for name in effects.keys():
 34            self._intencities[name] = 1
 35
 36    def __getattr__(self, name: str):
 37        if self.__is_depleted:
 38            raise TypeError(POTION_DEPLETED_MESSAGE)
 39        if name in self._applied_effect:
 40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
 41        self._applied_effects.add(name)
 42        return self._effects[name]
 43
 44    @invalidating
 45    def __add__(self, other):
 46        if type(other) is Potion:
 47            new_effects = dict(self._effects)
 48            new_duration = max(self._duration, other._duration)
 49            new_intencities = self._intencities
 50            for name, effect in other._effects:
 51                if name in self._effects.keys():
 52                    new_intencities[name] += 1
 53                    continue
 54                new_effects[name] = effect
 55                new_intencities[name] = 1
 56            pot = Potion(new_effects, new_duration)
 57            pot._intencities = new_intencities
 58            return pot
 59        pass
 60
 61    def __calculate_intencity(intencity, multiplier):
 62        new_intencity = intencity * multiplier
 63        whole_part = new_intencity - int(new_intencity)
 64        if whole_part <= 0.5:
 65            return math.floor(new_intencity)
 66        return math.ceil(new_intencity)
 67
 68    @invalidating
 69    def __mul__(self, other):
 70        if type(other) in (int, float):
 71            new_potion = Potion(self.get_effects, self._duration)
 72            for name, _ in new_potion._intencities:
 73                new_potion._intencities[name] = self.__calculate_intencity(
 74                    new_potion._intencities[name] * other)
 75            return new_potion
 76        pass
 77
 78    @invalidating
 79    def __sub__(self, other):
 80        if type(other) is Potion:
 81            new_potion = Potion(self.get_effects, self._duration)
 82            for name, _ in other._effects.items():
 83                if name not in new_potion._effects.keys:
 84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
 85                new_intencity = new_potion._intencities[name] - \
 86                    other._intencities[name]
 87                if new_intencity <= 0:
 88                    new_potion._effects.pop(name)
 89                    new_potion._intencities.pop(name)
 90                    continue
 91                new_potion._intencities[name] = new_intencity
 92            return new_potion
 93        pass
 94
 95    @invalidating
 96    def __truediv__(self, other):
 97        if type(other) is int:
 98            new_potion = Potion(self.get_effects, self._duration)
 99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)
102            return new_potion
103        pass
104
105    def __eq__(self, other):
106        if type(other) is not Potion:
107            return False
108        if len(self._intencities) != len(other._intencities):
109            return False
110        for name in self._effects.keys():
111            if name not in other._effects.keys:
112                return False
113            if self._intencities[name] != other._intencities[name]:
114                return False
115        return True
116
117    def __lt__(self, other):
118        if type(other) is not Potion:
119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)
121
122    def __mt__(self, other):
123        if type(other) is not Potion:
124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)
126
127    def get_effects(self) -> dict:
128        return dict(self._effects)
129
130    def get_intencities(self) -> dict:
131        return dict(self._intencities)
132
133    def deplete(self):
134        self.__is_depleted = True
135
136    def get_depletion(self):
137        return self.__is_depleted
138
139    def get_effect_mass(self, name):
140        return sum(name.split(""))
141
142
143class ГоспожатаПоХимия:
144
145    def apply(target, potion: Potion):
146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects.items()])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for effect in ordered_effects.values():
152            for _ in range(potion.get_intencities()):
153                effect(target)
154            potion.deplete()
155
156    def tick():
157        pass

EE.EEEEEEEEEEEEEEEEE
======================================================================
ERROR: test_applying (test.TestBasicPotion)
Test applying a potion to a target.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 63, in test_applying
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 979 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 76, in test_depletion
potion.int_attr_fun(self._target)
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 979 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: 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)
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_superbness (test.TestPotionComparison)
Test superbness of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 316, in test_superbness
potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_combination_no_overlap (test.TestPotionOperations)
Test combining potions with no overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 93, in test_combination_no_overlap
potion = potion1 + potion2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_combination_with_overlap (test.TestPotionOperations)
Test combining potions with overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 103, in test_combination_with_overlap
potion = potion1 + potion2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 256, in test_deprecation
potion = potion1 + potion2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 118, in test_dilution
half_potion = base_potion * 0.5
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 110, in test_potentiation
potion = potion * 3
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
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 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 212, in test_separation
potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 9
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: 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 379, in test_applying_depleted_potion
self._dimitrichka.apply(self._target, potion)
TypeError: ГоспожатаПоХимия.apply() takes 2 positional arguments but 3 were given

======================================================================
ERROR: test_applying_normal_case (test.TestГоспожатаПоХимия)
Test applying a normal potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 350, in test_applying_normal_case
self._dimitrichka.apply(self._target, potion)
TypeError: ГоспожатаПоХимия.apply() takes 2 positional arguments but 3 were given

======================================================================
ERROR: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 404, in test_applying_order
self._dimitrichka.apply(self._target, potion)
TypeError: ГоспожатаПоХимия.apply() takes 2 positional arguments but 3 were given

======================================================================
ERROR: 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 364, in test_applying_part_of_potion
potion.int_attr_fun(temp_target)
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 979 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
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 423, in test_ticking_immutable
potion = potion1 + potion2 # Excepted duration is 2 with intensity of 2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
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 454, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion1)
TypeError: ГоспожатаПоХимия.apply() takes 2 positional arguments but 3 were given

======================================================================
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 479, in test_ticking_multiple_targets
potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
File "/tmp/solution.py", line 13, in with_invalidation
if self.__is_used or self.__is_depleted:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
File "/tmp/solution.py", line 39, in __getattr__
if name in self._applied_effect:
[Previous line repeated 978 more times]
RecursionError: maximum recursion depth exceeded

======================================================================
ERROR: test_ticking_mutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 438, in test_ticking_mutable
self._dimitrichka.apply(self._target, potion)
TypeError: ГоспожатаПоХимия.apply() takes 2 positional arguments but 3 were given

----------------------------------------------------------------------
Ran 20 tests in 0.032s

FAILED (errors=19)

Дискусия
История

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name in effects.keys():33        for name in effects.keys():
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
n51                if name in self._effects.keys:n51                if name in self._effects.keys():
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
n82            for name, _ in other._effects.items:n82            for name, _ in other._effects.items():
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
n110        for name in self._effects.keys:n110        for name in self._effects.keys():
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
n149                               for name, effect in potion.get_effects.items])n149                               for name, effect in potion.get_effects.items()])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
t151        for _, effect in ordered_effects.items:t151        for effect in ordered_effects.values():
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
t33        for name, _ in effects.items:t33        for name in effects.keys():
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
82            for name, _ in other._effects.items:82            for name, _ in other._effects.items:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects.items])149                               for name, effect in potion.get_effects.items])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects.items:151        for _, effect in ordered_effects.items:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
n33        for name, _ in effects:n33        for name, _ in effects.items:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
n82            for name, _ in other._effects:n82            for name, _ in other._effects.items:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
n149                               for name, effect in potion.get_effects])n149                               for name, effect in potion.get_effects.items])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
t151        for _, effect in ordered_effects:t151        for _, effect in ordered_effects.items:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
t33        for name, _ in self._effects:t33        for name, _ in effects:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
82            for name, _ in other._effects:82            for name, _ in other._effects:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

t1import matht1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name, _ in self._effects:33        for name, _ in self._effects:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
82            for name, _ in other._effects:82            for name, _ in other._effects:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
t33        for name in self._effects.keys:t33        for name, _ in self._effects:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name, _ in new_potion._intencities:72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
82            for name, _ in other._effects:82            for name, _ in other._effects:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name in self._effects.keys:33        for name in self._effects.keys:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattr__(self, name: str):36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
n72            for name in new_potion._intencities.keys:n72            for name, _ in new_potion._intencities:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
t82            for name in other._effects.keys:t82            for name, _ in other._effects:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name in self._effects.keys:33        for name in self._effects.keys:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
t36    def __getattribute__(self, name: str):t36    def __getattr__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
41        self._applied_effects.add(name)41        self._applied_effects.add(name)
42        return self._effects[name]42        return self._effects[name]
4343
44    @invalidating44    @invalidating
45    def __add__(self, other):45    def __add__(self, other):
46        if type(other) is Potion:46        if type(other) is Potion:
47            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
48            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
49            new_intencities = self._intencities49            new_intencities = self._intencities
50            for name, effect in other._effects:50            for name, effect in other._effects:
51                if name in self._effects.keys:51                if name in self._effects.keys:
52                    new_intencities[name] += 152                    new_intencities[name] += 1
53                    continue53                    continue
54                new_effects[name] = effect54                new_effects[name] = effect
55                new_intencities[name] = 155                new_intencities[name] = 1
56            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
57            pot._intencities = new_intencities57            pot._intencities = new_intencities
58            return pot58            return pot
59        pass59        pass
6060
61    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
62        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
63        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
64        if whole_part <= 0.5:64        if whole_part <= 0.5:
65            return math.floor(new_intencity)65            return math.floor(new_intencity)
66        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6767
68    @invalidating68    @invalidating
69    def __mul__(self, other):69    def __mul__(self, other):
70        if type(other) in (int, float):70        if type(other) in (int, float):
71            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
72            for name in new_potion._intencities.keys:72            for name in new_potion._intencities.keys:
73                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
74                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
75            return new_potion75            return new_potion
76        pass76        pass
7777
78    @invalidating78    @invalidating
79    def __sub__(self, other):79    def __sub__(self, other):
80        if type(other) is Potion:80        if type(other) is Potion:
81            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
82            for name in other._effects.keys:82            for name in other._effects.keys:
83                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
85                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
86                    other._intencities[name]86                    other._intencities[name]
87                if new_intencity <= 0:87                if new_intencity <= 0:
88                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
89                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
90                    continue90                    continue
91                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
92            return new_potion92            return new_potion
93        pass93        pass
9494
95    @invalidating95    @invalidating
96    def __truediv__(self, other):96    def __truediv__(self, other):
97        if type(other) is int:97        if type(other) is int:
98            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
99            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
100                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
101                    intencity, other)101                    intencity, other)
102            return new_potion102            return new_potion
103        pass103        pass
104104
105    def __eq__(self, other):105    def __eq__(self, other):
106        if type(other) is not Potion:106        if type(other) is not Potion:
107            return False107            return False
108        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
109            return False109            return False
110        for name in self._effects.keys:110        for name in self._effects.keys:
111            if name not in other._effects.keys:111            if name not in other._effects.keys:
112                return False112                return False
113            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
114                return False114                return False
115        return True115        return True
116116
117    def __lt__(self, other):117    def __lt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
121121
122    def __mt__(self, other):122    def __mt__(self, other):
123        if type(other) is not Potion:123        if type(other) is not Potion:
124            return False124            return False
125        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
126126
127    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
128        return dict(self._effects)128        return dict(self._effects)
129129
130    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
131        return dict(self._intencities)131        return dict(self._intencities)
132132
133    def deplete(self):133    def deplete(self):
134        self.__is_depleted = True134        self.__is_depleted = True
135135
136    def get_depletion(self):136    def get_depletion(self):
137        return self.__is_depleted137        return self.__is_depleted
138138
139    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
140        return sum(name.split(""))140        return sum(name.split(""))
141141
142142
143class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
144144
145    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
146        if potion.get_depletion:146        if potion.get_depletion:
147            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
148        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
149                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
151        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
152            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
153                effect(target)153                effect(target)
154            potion.deplete()154            potion.deplete()
155155
156    def tick():156    def tick():
157        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name in self._effects.keys:33        for name in self._effects.keys:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
36    def __getattribute__(self, name: str):36    def __getattribute__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
39        if name in self._applied_effect:39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
tt41        self._applied_effects.add(name)
41        return self._effects[name]42        return self._effects[name]
4243
43    @invalidating44    @invalidating
44    def __add__(self, other):45    def __add__(self, other):
45        if type(other) is Potion:46        if type(other) is Potion:
46            new_effects = dict(self._effects)47            new_effects = dict(self._effects)
47            new_duration = max(self._duration, other._duration)48            new_duration = max(self._duration, other._duration)
48            new_intencities = self._intencities49            new_intencities = self._intencities
49            for name, effect in other._effects:50            for name, effect in other._effects:
50                if name in self._effects.keys:51                if name in self._effects.keys:
51                    new_intencities[name] += 152                    new_intencities[name] += 1
52                    continue53                    continue
53                new_effects[name] = effect54                new_effects[name] = effect
54                new_intencities[name] = 155                new_intencities[name] = 1
55            pot = Potion(new_effects, new_duration)56            pot = Potion(new_effects, new_duration)
56            pot._intencities = new_intencities57            pot._intencities = new_intencities
57            return pot58            return pot
58        pass59        pass
5960
60    def __calculate_intencity(intencity, multiplier):61    def __calculate_intencity(intencity, multiplier):
61        new_intencity = intencity * multiplier62        new_intencity = intencity * multiplier
62        whole_part = new_intencity - int(new_intencity)63        whole_part = new_intencity - int(new_intencity)
63        if whole_part <= 0.5:64        if whole_part <= 0.5:
64            return math.floor(new_intencity)65            return math.floor(new_intencity)
65        return math.ceil(new_intencity)66        return math.ceil(new_intencity)
6667
67    @invalidating68    @invalidating
68    def __mul__(self, other):69    def __mul__(self, other):
69        if type(other) in (int, float):70        if type(other) in (int, float):
70            new_potion = Potion(self.get_effects, self._duration)71            new_potion = Potion(self.get_effects, self._duration)
71            for name in new_potion._intencities.keys:72            for name in new_potion._intencities.keys:
72                new_potion._intencities[name] = self.__calculate_intencity(73                new_potion._intencities[name] = self.__calculate_intencity(
73                    new_potion._intencities[name] * other)74                    new_potion._intencities[name] * other)
74            return new_potion75            return new_potion
75        pass76        pass
7677
77    @invalidating78    @invalidating
78    def __sub__(self, other):79    def __sub__(self, other):
79        if type(other) is Potion:80        if type(other) is Potion:
80            new_potion = Potion(self.get_effects, self._duration)81            new_potion = Potion(self.get_effects, self._duration)
81            for name in other._effects.keys:82            for name in other._effects.keys:
82                if name not in new_potion._effects.keys:83                if name not in new_potion._effects.keys:
83                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)84                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
84                new_intencity = new_potion._intencities[name] - \85                new_intencity = new_potion._intencities[name] - \
85                    other._intencities[name]86                    other._intencities[name]
86                if new_intencity <= 0:87                if new_intencity <= 0:
87                    new_potion._effects.pop(name)88                    new_potion._effects.pop(name)
88                    new_potion._intencities.pop(name)89                    new_potion._intencities.pop(name)
89                    continue90                    continue
90                new_potion._intencities[name] = new_intencity91                new_potion._intencities[name] = new_intencity
91            return new_potion92            return new_potion
92        pass93        pass
9394
94    @invalidating95    @invalidating
95    def __truediv__(self, other):96    def __truediv__(self, other):
96        if type(other) is int:97        if type(other) is int:
97            new_potion = Potion(self.get_effects, self._duration)98            new_potion = Potion(self.get_effects, self._duration)
98            for name, intencity in self._intencities:99            for name, intencity in self._intencities:
99                new_potion._intencities[name] = self.__calculate_intencity(100                new_potion._intencities[name] = self.__calculate_intencity(
100                    intencity, other)101                    intencity, other)
101            return new_potion102            return new_potion
102        pass103        pass
103104
104    def __eq__(self, other):105    def __eq__(self, other):
105        if type(other) is not Potion:106        if type(other) is not Potion:
106            return False107            return False
107        if len(self._intencities) != len(other._intencities):108        if len(self._intencities) != len(other._intencities):
108            return False109            return False
109        for name in self._effects.keys:110        for name in self._effects.keys:
110            if name not in other._effects.keys:111            if name not in other._effects.keys:
111                return False112                return False
112            if self._intencities[name] != other._intencities[name]:113            if self._intencities[name] != other._intencities[name]:
113                return False114                return False
114        return True115        return True
115116
116    def __lt__(self, other):117    def __lt__(self, other):
117        if type(other) is not Potion:118        if type(other) is not Potion:
118            return False119            return False
119        return sum(self._intencities.values) < sum(other._intencities.values)120        return sum(self._intencities.values) < sum(other._intencities.values)
120121
121    def __mt__(self, other):122    def __mt__(self, other):
122        if type(other) is not Potion:123        if type(other) is not Potion:
123            return False124            return False
124        return sum(self._intencities.values) > sum(other._intencities.values)125        return sum(self._intencities.values) > sum(other._intencities.values)
125126
126    def get_effects(self) -> dict:127    def get_effects(self) -> dict:
127        return dict(self._effects)128        return dict(self._effects)
128129
129    def get_intencities(self) -> dict:130    def get_intencities(self) -> dict:
130        return dict(self._intencities)131        return dict(self._intencities)
131132
132    def deplete(self):133    def deplete(self):
133        self.__is_depleted = True134        self.__is_depleted = True
134135
135    def get_depletion(self):136    def get_depletion(self):
136        return self.__is_depleted137        return self.__is_depleted
137138
138    def get_effect_mass(self, name):139    def get_effect_mass(self, name):
139        return sum(name.split(""))140        return sum(name.split(""))
140141
141142
142class ГоспожатаПоХимия:143class ГоспожатаПоХимия:
143144
144    def apply(target, potion: Potion):145    def apply(target, potion: Potion):
145        if potion.get_depletion:146        if potion.get_depletion:
146            raise TypeError(POTION_DEPLETED_MESSAGE)147            raise TypeError(POTION_DEPLETED_MESSAGE)
147        ordered_effects = list([(name, effect)148        ordered_effects = list([(name, effect)
148                               for name, effect in potion.get_effects])149                               for name, effect in potion.get_effects])
149        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))150        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
150        for _, effect in ordered_effects:151        for _, effect in ordered_effects:
151            for _ in range(potion.get_intencities()):152            for _ in range(potion.get_intencities()):
152                effect(target)153                effect(target)
153            potion.deplete()154            potion.deplete()
154155
155    def tick():156    def tick():
156        pass157        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
32        self._intencities = {}32        self._intencities = {}
33        for name in self._effects.keys:33        for name in self._effects.keys:
34            self._intencities[name] = 134            self._intencities[name] = 1
3535
n36    def __getattribute__(self, __name: str) -> Any:n36    def __getattribute__(self, name: str):
37        if self.__is_depleted:37        if self.__is_depleted:
38            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
n39        if __name in self._applied_effect:n39        if name in self._applied_effect:
40            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
t41        return self._effects[__name]t41        return self._effects[name]
4242
43    @invalidating43    @invalidating
44    def __add__(self, other):44    def __add__(self, other):
45        if type(other) is Potion:45        if type(other) is Potion:
46            new_effects = dict(self._effects)46            new_effects = dict(self._effects)
47            new_duration = max(self._duration, other._duration)47            new_duration = max(self._duration, other._duration)
48            new_intencities = self._intencities48            new_intencities = self._intencities
49            for name, effect in other._effects:49            for name, effect in other._effects:
50                if name in self._effects.keys:50                if name in self._effects.keys:
51                    new_intencities[name] += 151                    new_intencities[name] += 1
52                    continue52                    continue
53                new_effects[name] = effect53                new_effects[name] = effect
54                new_intencities[name] = 154                new_intencities[name] = 1
55            pot = Potion(new_effects, new_duration)55            pot = Potion(new_effects, new_duration)
56            pot._intencities = new_intencities56            pot._intencities = new_intencities
57            return pot57            return pot
58        pass58        pass
5959
60    def __calculate_intencity(intencity, multiplier):60    def __calculate_intencity(intencity, multiplier):
61        new_intencity = intencity * multiplier61        new_intencity = intencity * multiplier
62        whole_part = new_intencity - int(new_intencity)62        whole_part = new_intencity - int(new_intencity)
63        if whole_part <= 0.5:63        if whole_part <= 0.5:
64            return math.floor(new_intencity)64            return math.floor(new_intencity)
65        return math.ceil(new_intencity)65        return math.ceil(new_intencity)
6666
67    @invalidating67    @invalidating
68    def __mul__(self, other):68    def __mul__(self, other):
69        if type(other) in (int, float):69        if type(other) in (int, float):
70            new_potion = Potion(self.get_effects, self._duration)70            new_potion = Potion(self.get_effects, self._duration)
71            for name in new_potion._intencities.keys:71            for name in new_potion._intencities.keys:
72                new_potion._intencities[name] = self.__calculate_intencity(72                new_potion._intencities[name] = self.__calculate_intencity(
73                    new_potion._intencities[name] * other)73                    new_potion._intencities[name] * other)
74            return new_potion74            return new_potion
75        pass75        pass
7676
77    @invalidating77    @invalidating
78    def __sub__(self, other):78    def __sub__(self, other):
79        if type(other) is Potion:79        if type(other) is Potion:
80            new_potion = Potion(self.get_effects, self._duration)80            new_potion = Potion(self.get_effects, self._duration)
81            for name in other._effects.keys:81            for name in other._effects.keys:
82                if name not in new_potion._effects.keys:82                if name not in new_potion._effects.keys:
83                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)83                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
84                new_intencity = new_potion._intencities[name] - \84                new_intencity = new_potion._intencities[name] - \
85                    other._intencities[name]85                    other._intencities[name]
86                if new_intencity <= 0:86                if new_intencity <= 0:
87                    new_potion._effects.pop(name)87                    new_potion._effects.pop(name)
88                    new_potion._intencities.pop(name)88                    new_potion._intencities.pop(name)
89                    continue89                    continue
90                new_potion._intencities[name] = new_intencity90                new_potion._intencities[name] = new_intencity
91            return new_potion91            return new_potion
92        pass92        pass
9393
94    @invalidating94    @invalidating
95    def __truediv__(self, other):95    def __truediv__(self, other):
96        if type(other) is int:96        if type(other) is int:
97            new_potion = Potion(self.get_effects, self._duration)97            new_potion = Potion(self.get_effects, self._duration)
98            for name, intencity in self._intencities:98            for name, intencity in self._intencities:
99                new_potion._intencities[name] = self.__calculate_intencity(99                new_potion._intencities[name] = self.__calculate_intencity(
100                    intencity, other)100                    intencity, other)
101            return new_potion101            return new_potion
102        pass102        pass
103103
104    def __eq__(self, other):104    def __eq__(self, other):
105        if type(other) is not Potion:105        if type(other) is not Potion:
106            return False106            return False
107        if len(self._intencities) != len(other._intencities):107        if len(self._intencities) != len(other._intencities):
108            return False108            return False
109        for name in self._effects.keys:109        for name in self._effects.keys:
110            if name not in other._effects.keys:110            if name not in other._effects.keys:
111                return False111                return False
112            if self._intencities[name] != other._intencities[name]:112            if self._intencities[name] != other._intencities[name]:
113                return False113                return False
114        return True114        return True
115115
116    def __lt__(self, other):116    def __lt__(self, other):
117        if type(other) is not Potion:117        if type(other) is not Potion:
118            return False118            return False
119        return sum(self._intencities.values) < sum(other._intencities.values)119        return sum(self._intencities.values) < sum(other._intencities.values)
120120
121    def __mt__(self, other):121    def __mt__(self, other):
122        if type(other) is not Potion:122        if type(other) is not Potion:
123            return False123            return False
124        return sum(self._intencities.values) > sum(other._intencities.values)124        return sum(self._intencities.values) > sum(other._intencities.values)
125125
126    def get_effects(self) -> dict:126    def get_effects(self) -> dict:
127        return dict(self._effects)127        return dict(self._effects)
128128
129    def get_intencities(self) -> dict:129    def get_intencities(self) -> dict:
130        return dict(self._intencities)130        return dict(self._intencities)
131131
132    def deplete(self):132    def deplete(self):
133        self.__is_depleted = True133        self.__is_depleted = True
134134
135    def get_depletion(self):135    def get_depletion(self):
136        return self.__is_depleted136        return self.__is_depleted
137137
138    def get_effect_mass(self, name):138    def get_effect_mass(self, name):
139        return sum(name.split(""))139        return sum(name.split(""))
140140
141141
142class ГоспожатаПоХимия:142class ГоспожатаПоХимия:
143143
144    def apply(target, potion: Potion):144    def apply(target, potion: Potion):
145        if potion.get_depletion:145        if potion.get_depletion:
146            raise TypeError(POTION_DEPLETED_MESSAGE)146            raise TypeError(POTION_DEPLETED_MESSAGE)
147        ordered_effects = list([(name, effect)147        ordered_effects = list([(name, effect)
148                               for name, effect in potion.get_effects])148                               for name, effect in potion.get_effects])
149        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))149        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
150        for _, effect in ordered_effects:150        for _, effect in ordered_effects:
151            for _ in range(potion.get_intencities()):151            for _ in range(potion.get_intencities()):
152                effect(target)152                effect(target)
153            potion.deplete()153            potion.deplete()
154154
155    def tick():155    def tick():
156        pass156        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10def invalidating(f):10def invalidating(f):
11    def with_invalidation(self, other):11    def with_invalidation(self, other):
12        assert type(self) is Potion12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True18            other.__is_used = True
19        self.__is_used = True19        self.__is_used = True
20        return f(self, other)20        return f(self, other)
21    return with_invalidation21    return with_invalidation
2222
2323
24class Potion:24class Potion:
25    _applied_effects = set()25    _applied_effects = set()
26    __is_used = False26    __is_used = False
27    __is_depleted = False27    __is_depleted = False
2828
29    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
30        self._effects = effects30        self._effects = effects
31        self._duration = duration31        self._duration = duration
t32        self._intencities = {name: 1 for name in effects.keys}t32        self._intencities = {}
33        for name in self._effects.keys:
34            self._intencities[name] = 1
3335
34    def __getattribute__(self, __name: str) -> Any:36    def __getattribute__(self, __name: str) -> Any:
35        if self.__is_depleted:37        if self.__is_depleted:
36            raise TypeError(POTION_DEPLETED_MESSAGE)38            raise TypeError(POTION_DEPLETED_MESSAGE)
37        if __name in self._applied_effect:39        if __name in self._applied_effect:
38            raise TypeError(EFFECT_DEPLETED_MESSAGE)40            raise TypeError(EFFECT_DEPLETED_MESSAGE)
39        return self._effects[__name]41        return self._effects[__name]
4042
41    @invalidating43    @invalidating
42    def __add__(self, other):44    def __add__(self, other):
43        if type(other) is Potion:45        if type(other) is Potion:
44            new_effects = dict(self._effects)46            new_effects = dict(self._effects)
45            new_duration = max(self._duration, other._duration)47            new_duration = max(self._duration, other._duration)
46            new_intencities = self._intencities48            new_intencities = self._intencities
47            for name, effect in other._effects:49            for name, effect in other._effects:
48                if name in self._effects.keys:50                if name in self._effects.keys:
49                    new_intencities[name] += 151                    new_intencities[name] += 1
50                    continue52                    continue
51                new_effects[name] = effect53                new_effects[name] = effect
52                new_intencities[name] = 154                new_intencities[name] = 1
53            pot = Potion(new_effects, new_duration)55            pot = Potion(new_effects, new_duration)
54            pot._intencities = new_intencities56            pot._intencities = new_intencities
55            return pot57            return pot
56        pass58        pass
5759
58    def __calculate_intencity(intencity, multiplier):60    def __calculate_intencity(intencity, multiplier):
59        new_intencity = intencity * multiplier61        new_intencity = intencity * multiplier
60        whole_part = new_intencity - int(new_intencity)62        whole_part = new_intencity - int(new_intencity)
61        if whole_part <= 0.5:63        if whole_part <= 0.5:
62            return math.floor(new_intencity)64            return math.floor(new_intencity)
63        return math.ceil(new_intencity)65        return math.ceil(new_intencity)
6466
65    @invalidating67    @invalidating
66    def __mul__(self, other):68    def __mul__(self, other):
67        if type(other) in (int, float):69        if type(other) in (int, float):
68            new_potion = Potion(self.get_effects, self._duration)70            new_potion = Potion(self.get_effects, self._duration)
69            for name in new_potion._intencities.keys:71            for name in new_potion._intencities.keys:
70                new_potion._intencities[name] = self.__calculate_intencity(72                new_potion._intencities[name] = self.__calculate_intencity(
71                    new_potion._intencities[name] * other)73                    new_potion._intencities[name] * other)
72            return new_potion74            return new_potion
73        pass75        pass
7476
75    @invalidating77    @invalidating
76    def __sub__(self, other):78    def __sub__(self, other):
77        if type(other) is Potion:79        if type(other) is Potion:
78            new_potion = Potion(self.get_effects, self._duration)80            new_potion = Potion(self.get_effects, self._duration)
79            for name in other._effects.keys:81            for name in other._effects.keys:
80                if name not in new_potion._effects.keys:82                if name not in new_potion._effects.keys:
81                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)83                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
82                new_intencity = new_potion._intencities[name] - \84                new_intencity = new_potion._intencities[name] - \
83                    other._intencities[name]85                    other._intencities[name]
84                if new_intencity <= 0:86                if new_intencity <= 0:
85                    new_potion._effects.pop(name)87                    new_potion._effects.pop(name)
86                    new_potion._intencities.pop(name)88                    new_potion._intencities.pop(name)
87                    continue89                    continue
88                new_potion._intencities[name] = new_intencity90                new_potion._intencities[name] = new_intencity
89            return new_potion91            return new_potion
90        pass92        pass
9193
92    @invalidating94    @invalidating
93    def __truediv__(self, other):95    def __truediv__(self, other):
94        if type(other) is int:96        if type(other) is int:
95            new_potion = Potion(self.get_effects, self._duration)97            new_potion = Potion(self.get_effects, self._duration)
96            for name, intencity in self._intencities:98            for name, intencity in self._intencities:
97                new_potion._intencities[name] = self.__calculate_intencity(99                new_potion._intencities[name] = self.__calculate_intencity(
98                    intencity, other)100                    intencity, other)
99            return new_potion101            return new_potion
100        pass102        pass
101103
102    def __eq__(self, other):104    def __eq__(self, other):
103        if type(other) is not Potion:105        if type(other) is not Potion:
104            return False106            return False
105        if len(self._intencities) != len(other._intencities):107        if len(self._intencities) != len(other._intencities):
106            return False108            return False
107        for name in self._effects.keys:109        for name in self._effects.keys:
108            if name not in other._effects.keys:110            if name not in other._effects.keys:
109                return False111                return False
110            if self._intencities[name] != other._intencities[name]:112            if self._intencities[name] != other._intencities[name]:
111                return False113                return False
112        return True114        return True
113115
114    def __lt__(self, other):116    def __lt__(self, other):
115        if type(other) is not Potion:117        if type(other) is not Potion:
116            return False118            return False
117        return sum(self._intencities.values) < sum(other._intencities.values)119        return sum(self._intencities.values) < sum(other._intencities.values)
118120
119    def __mt__(self, other):121    def __mt__(self, other):
120        if type(other) is not Potion:122        if type(other) is not Potion:
121            return False123            return False
122        return sum(self._intencities.values) > sum(other._intencities.values)124        return sum(self._intencities.values) > sum(other._intencities.values)
123125
124    def get_effects(self) -> dict:126    def get_effects(self) -> dict:
125        return dict(self._effects)127        return dict(self._effects)
126128
127    def get_intencities(self) -> dict:129    def get_intencities(self) -> dict:
128        return dict(self._intencities)130        return dict(self._intencities)
129131
130    def deplete(self):132    def deplete(self):
131        self.__is_depleted = True133        self.__is_depleted = True
132134
133    def get_depletion(self):135    def get_depletion(self):
134        return self.__is_depleted136        return self.__is_depleted
135137
136    def get_effect_mass(self, name):138    def get_effect_mass(self, name):
137        return sum(name.split(""))139        return sum(name.split(""))
138140
139141
140class ГоспожатаПоХимия:142class ГоспожатаПоХимия:
141143
142    def apply(target, potion: Potion):144    def apply(target, potion: Potion):
143        if potion.get_depletion:145        if potion.get_depletion:
144            raise TypeError(POTION_DEPLETED_MESSAGE)146            raise TypeError(POTION_DEPLETED_MESSAGE)
145        ordered_effects = list([(name, effect)147        ordered_effects = list([(name, effect)
146                               for name, effect in potion.get_effects])148                               for name, effect in potion.get_effects])
147        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))149        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
148        for _, effect in ordered_effects:150        for _, effect in ordered_effects:
149            for _ in range(potion.get_intencities()):151            for _ in range(potion.get_intencities()):
150                effect(target)152                effect(target)
151            potion.deplete()153            potion.deplete()
152154
153    def tick():155    def tick():
154        pass156        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import mathf1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
nn8 
9 
10def invalidating(f):
11    def with_invalidation(self, other):
12        assert type(self) is Potion
13        if self.__is_used or self.__is_depleted:
14            raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
15        if type(other) is Potion:
16            if other.__is_used or other.__is_depleted:
17                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
18            other.__is_used = True
19        self.__is_used = True
20        return f(self, other)
21    return with_invalidation
822
923
10class Potion:24class Potion:
11    _applied_effects = set()25    _applied_effects = set()
12    __is_used = False26    __is_used = False
13    __is_depleted = False27    __is_depleted = False
1428
15    def __init__(self, effects: dict, duration: int) -> None:29    def __init__(self, effects: dict, duration: int) -> None:
16        self._effects = effects30        self._effects = effects
17        self._duration = duration31        self._duration = duration
18        self._intencities = {name: 1 for name in effects.keys}32        self._intencities = {name: 1 for name in effects.keys}
t19 t
20    def invalidating(f):
21        def with_invalidation(self: Potion, other):
22            if self.__is_used or self.__is_depleted:
23                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
24            if type(other) is Potion:
25                if other.__is_used or other.__is_depleted:
26                    raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
27                other.__is_used = True
28            self.__is_used = True
29            return f(self, other)
30        return with_invalidation
3133
32    def __getattribute__(self, __name: str) -> Any:34    def __getattribute__(self, __name: str) -> Any:
33        if self.__is_depleted:35        if self.__is_depleted:
34            raise TypeError(POTION_DEPLETED_MESSAGE)36            raise TypeError(POTION_DEPLETED_MESSAGE)
35        if __name in self._applied_effect:37        if __name in self._applied_effect:
36            raise TypeError(EFFECT_DEPLETED_MESSAGE)38            raise TypeError(EFFECT_DEPLETED_MESSAGE)
37        return self._effects[__name]39        return self._effects[__name]
3840
39    @invalidating41    @invalidating
40    def __add__(self, other):42    def __add__(self, other):
41        if type(other) is Potion:43        if type(other) is Potion:
42            new_effects = dict(self._effects)44            new_effects = dict(self._effects)
43            new_duration = max(self._duration, other._duration)45            new_duration = max(self._duration, other._duration)
44            new_intencities = self._intencities46            new_intencities = self._intencities
45            for name, effect in other._effects:47            for name, effect in other._effects:
46                if name in self._effects.keys:48                if name in self._effects.keys:
47                    new_intencities[name] += 149                    new_intencities[name] += 1
48                    continue50                    continue
49                new_effects[name] = effect51                new_effects[name] = effect
50                new_intencities[name] = 152                new_intencities[name] = 1
51            pot = Potion(new_effects, new_duration)53            pot = Potion(new_effects, new_duration)
52            pot._intencities = new_intencities54            pot._intencities = new_intencities
53            return pot55            return pot
54        pass56        pass
5557
56    def __calculate_intencity(intencity, multiplier):58    def __calculate_intencity(intencity, multiplier):
57        new_intencity = intencity * multiplier59        new_intencity = intencity * multiplier
58        whole_part = new_intencity - int(new_intencity)60        whole_part = new_intencity - int(new_intencity)
59        if whole_part <= 0.5:61        if whole_part <= 0.5:
60            return math.floor(new_intencity)62            return math.floor(new_intencity)
61        return math.ceil(new_intencity)63        return math.ceil(new_intencity)
6264
63    @invalidating65    @invalidating
64    def __mul__(self, other):66    def __mul__(self, other):
65        if type(other) in (int, float):67        if type(other) in (int, float):
66            new_potion = Potion(self.get_effects, self._duration)68            new_potion = Potion(self.get_effects, self._duration)
67            for name in new_potion._intencities.keys:69            for name in new_potion._intencities.keys:
68                new_potion._intencities[name] = self.__calculate_intencity(70                new_potion._intencities[name] = self.__calculate_intencity(
69                    new_potion._intencities[name] * other)71                    new_potion._intencities[name] * other)
70            return new_potion72            return new_potion
71        pass73        pass
7274
73    @invalidating75    @invalidating
74    def __sub__(self, other):76    def __sub__(self, other):
75        if type(other) is Potion:77        if type(other) is Potion:
76            new_potion = Potion(self.get_effects, self._duration)78            new_potion = Potion(self.get_effects, self._duration)
77            for name in other._effects.keys:79            for name in other._effects.keys:
78                if name not in new_potion._effects.keys:80                if name not in new_potion._effects.keys:
79                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)81                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
80                new_intencity = new_potion._intencities[name] - \82                new_intencity = new_potion._intencities[name] - \
81                    other._intencities[name]83                    other._intencities[name]
82                if new_intencity <= 0:84                if new_intencity <= 0:
83                    new_potion._effects.pop(name)85                    new_potion._effects.pop(name)
84                    new_potion._intencities.pop(name)86                    new_potion._intencities.pop(name)
85                    continue87                    continue
86                new_potion._intencities[name] = new_intencity88                new_potion._intencities[name] = new_intencity
87            return new_potion89            return new_potion
88        pass90        pass
8991
90    @invalidating92    @invalidating
91    def __truediv__(self, other):93    def __truediv__(self, other):
92        if type(other) is int:94        if type(other) is int:
93            new_potion = Potion(self.get_effects, self._duration)95            new_potion = Potion(self.get_effects, self._duration)
94            for name, intencity in self._intencities:96            for name, intencity in self._intencities:
95                new_potion._intencities[name] = self.__calculate_intencity(97                new_potion._intencities[name] = self.__calculate_intencity(
96                    intencity, other)98                    intencity, other)
97            return new_potion99            return new_potion
98        pass100        pass
99101
100    def __eq__(self, other):102    def __eq__(self, other):
101        if type(other) is not Potion:103        if type(other) is not Potion:
102            return False104            return False
103        if len(self._intencities) != len(other._intencities):105        if len(self._intencities) != len(other._intencities):
104            return False106            return False
105        for name in self._effects.keys:107        for name in self._effects.keys:
106            if name not in other._effects.keys:108            if name not in other._effects.keys:
107                return False109                return False
108            if self._intencities[name] != other._intencities[name]:110            if self._intencities[name] != other._intencities[name]:
109                return False111                return False
110        return True112        return True
111113
112    def __lt__(self, other):114    def __lt__(self, other):
113        if type(other) is not Potion:115        if type(other) is not Potion:
114            return False116            return False
115        return sum(self._intencities.values) < sum(other._intencities.values)117        return sum(self._intencities.values) < sum(other._intencities.values)
116118
117    def __mt__(self, other):119    def __mt__(self, other):
118        if type(other) is not Potion:120        if type(other) is not Potion:
119            return False121            return False
120        return sum(self._intencities.values) > sum(other._intencities.values)122        return sum(self._intencities.values) > sum(other._intencities.values)
121123
122    def get_effects(self) -> dict:124    def get_effects(self) -> dict:
123        return dict(self._effects)125        return dict(self._effects)
124126
125    def get_intencities(self) -> dict:127    def get_intencities(self) -> dict:
126        return dict(self._intencities)128        return dict(self._intencities)
127129
128    def deplete(self):130    def deplete(self):
129        self.__is_depleted = True131        self.__is_depleted = True
130132
131    def get_depletion(self):133    def get_depletion(self):
132        return self.__is_depleted134        return self.__is_depleted
133135
134    def get_effect_mass(self, name):136    def get_effect_mass(self, name):
135        return sum(name.split(""))137        return sum(name.split(""))
136138
137139
138class ГоспожатаПоХимия:140class ГоспожатаПоХимия:
139141
140    def apply(target, potion: Potion):142    def apply(target, potion: Potion):
141        if potion.get_depletion:143        if potion.get_depletion:
142            raise TypeError(POTION_DEPLETED_MESSAGE)144            raise TypeError(POTION_DEPLETED_MESSAGE)
143        ordered_effects = list([(name, effect)145        ordered_effects = list([(name, effect)
144                               for name, effect in potion.get_effects])146                               for name, effect in potion.get_effects])
145        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))147        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
146        for _, effect in ordered_effects:148        for _, effect in ordered_effects:
147            for _ in range(potion.get_intencities()):149            for _ in range(potion.get_intencities()):
148                effect(target)150                effect(target)
149            potion.deplete()151            potion.deplete()
150152
151    def tick():153    def tick():
152        pass154        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

t1import matht1import math
2from typing import Any2from typing import Any
33
4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."4EFFECT_DEPLETED_MESSAGE = "Effect is depleted."
5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"5EFFECT_CANT_REMOVE_MESSAGE = "Effect can't be removed"
6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."6BIGGER_THAN_ITSELF_MESSAGE = "Potion is now part of something bigger than itself."
7POTION_DEPLETED_MESSAGE = "Potion is depleted."7POTION_DEPLETED_MESSAGE = "Potion is depleted."
88
99
10class Potion:10class Potion:
11    _applied_effects = set()11    _applied_effects = set()
12    __is_used = False12    __is_used = False
13    __is_depleted = False13    __is_depleted = False
1414
15    def __init__(self, effects: dict, duration: int) -> None:15    def __init__(self, effects: dict, duration: int) -> None:
16        self._effects = effects16        self._effects = effects
17        self._duration = duration17        self._duration = duration
18        self._intencities = {name: 1 for name in effects.keys}18        self._intencities = {name: 1 for name in effects.keys}
1919
20    def invalidating(f):20    def invalidating(f):
21        def with_invalidation(self: Potion, other):21        def with_invalidation(self: Potion, other):
22            if self.__is_used or self.__is_depleted:22            if self.__is_used or self.__is_depleted:
23                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)23                raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
24            if type(other) is Potion:24            if type(other) is Potion:
25                if other.__is_used or other.__is_depleted:25                if other.__is_used or other.__is_depleted:
26                    raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)26                    raise TypeError(BIGGER_THAN_ITSELF_MESSAGE)
27                other.__is_used = True27                other.__is_used = True
28            self.__is_used = True28            self.__is_used = True
29            return f(self, other)29            return f(self, other)
30        return with_invalidation30        return with_invalidation
3131
32    def __getattribute__(self, __name: str) -> Any:32    def __getattribute__(self, __name: str) -> Any:
33        if self.__is_depleted:33        if self.__is_depleted:
34            raise TypeError(POTION_DEPLETED_MESSAGE)34            raise TypeError(POTION_DEPLETED_MESSAGE)
35        if __name in self._applied_effect:35        if __name in self._applied_effect:
36            raise TypeError(EFFECT_DEPLETED_MESSAGE)36            raise TypeError(EFFECT_DEPLETED_MESSAGE)
37        return self._effects[__name]37        return self._effects[__name]
3838
39    @invalidating39    @invalidating
40    def __add__(self, other):40    def __add__(self, other):
41        if type(other) is Potion:41        if type(other) is Potion:
42            new_effects = dict(self._effects)42            new_effects = dict(self._effects)
43            new_duration = max(self._duration, other._duration)43            new_duration = max(self._duration, other._duration)
44            new_intencities = self._intencities44            new_intencities = self._intencities
45            for name, effect in other._effects:45            for name, effect in other._effects:
46                if name in self._effects.keys:46                if name in self._effects.keys:
47                    new_intencities[name] += 147                    new_intencities[name] += 1
48                    continue48                    continue
49                new_effects[name] = effect49                new_effects[name] = effect
50                new_intencities[name] = 150                new_intencities[name] = 1
51            pot = Potion(new_effects, new_duration)51            pot = Potion(new_effects, new_duration)
52            pot._intencities = new_intencities52            pot._intencities = new_intencities
53            return pot53            return pot
54        pass54        pass
5555
56    def __calculate_intencity(intencity, multiplier):56    def __calculate_intencity(intencity, multiplier):
57        new_intencity = intencity * multiplier57        new_intencity = intencity * multiplier
58        whole_part = new_intencity - int(new_intencity)58        whole_part = new_intencity - int(new_intencity)
59        if whole_part <= 0.5:59        if whole_part <= 0.5:
60            return math.floor(new_intencity)60            return math.floor(new_intencity)
61        return math.ceil(new_intencity)61        return math.ceil(new_intencity)
6262
63    @invalidating63    @invalidating
64    def __mul__(self, other):64    def __mul__(self, other):
65        if type(other) in (int, float):65        if type(other) in (int, float):
66            new_potion = Potion(self.get_effects, self._duration)66            new_potion = Potion(self.get_effects, self._duration)
67            for name in new_potion._intencities.keys:67            for name in new_potion._intencities.keys:
68                new_potion._intencities[name] = self.__calculate_intencity(68                new_potion._intencities[name] = self.__calculate_intencity(
69                    new_potion._intencities[name] * other)69                    new_potion._intencities[name] * other)
70            return new_potion70            return new_potion
71        pass71        pass
7272
73    @invalidating73    @invalidating
74    def __sub__(self, other):74    def __sub__(self, other):
75        if type(other) is Potion:75        if type(other) is Potion:
76            new_potion = Potion(self.get_effects, self._duration)76            new_potion = Potion(self.get_effects, self._duration)
77            for name in other._effects.keys:77            for name in other._effects.keys:
78                if name not in new_potion._effects.keys:78                if name not in new_potion._effects.keys:
79                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)79                    raise TypeError(EFFECT_CANT_REMOVE_MESSAGE)
80                new_intencity = new_potion._intencities[name] - \80                new_intencity = new_potion._intencities[name] - \
81                    other._intencities[name]81                    other._intencities[name]
82                if new_intencity <= 0:82                if new_intencity <= 0:
83                    new_potion._effects.pop(name)83                    new_potion._effects.pop(name)
84                    new_potion._intencities.pop(name)84                    new_potion._intencities.pop(name)
85                    continue85                    continue
86                new_potion._intencities[name] = new_intencity86                new_potion._intencities[name] = new_intencity
87            return new_potion87            return new_potion
88        pass88        pass
8989
90    @invalidating90    @invalidating
91    def __truediv__(self, other):91    def __truediv__(self, other):
92        if type(other) is int:92        if type(other) is int:
93            new_potion = Potion(self.get_effects, self._duration)93            new_potion = Potion(self.get_effects, self._duration)
94            for name, intencity in self._intencities:94            for name, intencity in self._intencities:
95                new_potion._intencities[name] = self.__calculate_intencity(95                new_potion._intencities[name] = self.__calculate_intencity(
96                    intencity, other)96                    intencity, other)
97            return new_potion97            return new_potion
98        pass98        pass
9999
100    def __eq__(self, other):100    def __eq__(self, other):
101        if type(other) is not Potion:101        if type(other) is not Potion:
102            return False102            return False
103        if len(self._intencities) != len(other._intencities):103        if len(self._intencities) != len(other._intencities):
104            return False104            return False
105        for name in self._effects.keys:105        for name in self._effects.keys:
106            if name not in other._effects.keys:106            if name not in other._effects.keys:
107                return False107                return False
108            if self._intencities[name] != other._intencities[name]:108            if self._intencities[name] != other._intencities[name]:
109                return False109                return False
110        return True110        return True
111111
112    def __lt__(self, other):112    def __lt__(self, other):
113        if type(other) is not Potion:113        if type(other) is not Potion:
114            return False114            return False
115        return sum(self._intencities.values) < sum(other._intencities.values)115        return sum(self._intencities.values) < sum(other._intencities.values)
116116
117    def __mt__(self, other):117    def __mt__(self, other):
118        if type(other) is not Potion:118        if type(other) is not Potion:
119            return False119            return False
120        return sum(self._intencities.values) > sum(other._intencities.values)120        return sum(self._intencities.values) > sum(other._intencities.values)
121121
122    def get_effects(self) -> dict:122    def get_effects(self) -> dict:
123        return dict(self._effects)123        return dict(self._effects)
124124
125    def get_intencities(self) -> dict:125    def get_intencities(self) -> dict:
126        return dict(self._intencities)126        return dict(self._intencities)
127127
128    def deplete(self):128    def deplete(self):
129        self.__is_depleted = True129        self.__is_depleted = True
130130
131    def get_depletion(self):131    def get_depletion(self):
132        return self.__is_depleted132        return self.__is_depleted
133133
134    def get_effect_mass(self, name):134    def get_effect_mass(self, name):
135        return sum(name.split(""))135        return sum(name.split(""))
136136
137137
138class ГоспожатаПоХимия:138class ГоспожатаПоХимия:
139139
140    def apply(target, potion: Potion):140    def apply(target, potion: Potion):
141        if potion.get_depletion:141        if potion.get_depletion:
142            raise TypeError(POTION_DEPLETED_MESSAGE)142            raise TypeError(POTION_DEPLETED_MESSAGE)
143        ordered_effects = list([(name, effect)143        ordered_effects = list([(name, effect)
144                               for name, effect in potion.get_effects])144                               for name, effect in potion.get_effects])
145        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))145        ordered_effects.sort(key=lambda n, _: potion.get_effect_mass(n))
146        for _, effect in ordered_effects:146        for _, effect in ordered_effects:
147            for _ in range(potion.get_intencities()):147            for _ in range(potion.get_intencities()):
148                effect(target)148                effect(target)
149            potion.deplete()149            potion.deplete()
150150
151    def tick():151    def tick():
152        pass152        pass
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op