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

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

10 точки общо

20 успешни теста
0 неуспешни теста
Код (edge cases work)

  1import copy
  2
  3class Potion:
  4
  5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):
  6        self.depleted_effects = set()
  7        self.effects = effects
  8        self.duration = duration
  9        self.sacrificed = sacrificed
 10        self.depleted = depleted
 11        self.intensities = {}
 12        # make the effects methods and add intensity 1 for each name
 13        for name, func in self.effects.items():
 14            setattr(self, name, func)
 15
 16        if not intensities:
 17            for name, func in self.effects.items():
 18                self.intensities.update({name : 1})
 19        else:
 20            self.intensities = intensities
 21
 22    def __add__(self, other):
 23        if self.depleted or other.depleted:
 24            raise TypeError("Potion is depleted.")
 25        if self.sacrificed or other.sacrificed:
 26            raise TypeError("Potion is now part of something bigger than itself.")
 27        self_active_effects = set(self.effects.keys()) - self.depleted_effects
 28        other_active_effects = set(other.effects.keys()) - other.depleted_effects
 29        #union the effects of both
 30        updated_effects_keys = self_active_effects | other_active_effects
 31        updated_effects = {}
 32        updated_intensities = {}
 33        # traverse both intensities dict-s and add to the updated one
 34        for name, intensity in self.intensities.items():
 35            if name in updated_effects_keys and name not in self.depleted_effects:
 36                if updated_intensities.get(name):
 37                    updated_intensities[name] += intensity
 38                else:
 39                    updated_intensities[name] = intensity
 40
 41        for name, intensity in other.intensities.items():
 42            if name in updated_effects_keys and name not in other.depleted_effects:
 43                if updated_intensities.get(name):
 44                    updated_intensities[name] += intensity
 45                else:
 46                    updated_intensities[name] = intensity
 47
 48        for effect, func in self.effects.items():
 49            if effect in updated_effects_keys:
 50                updated_effects.update({effect : func})
 51
 52        for effect, func in other.effects.items():
 53            if effect in updated_effects_keys:
 54                updated_effects.update({effect : func})
 55
 56        self.sacrificed = True
 57        other.sacrificed = True
 58        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)
 59
 60    def __mul__(self,number):
 61        if self.depleted:
 62            raise TypeError("Potion is depleted.")
 63        if self.sacrificed:
 64            raise TypeError("Potion is now part of something bigger than itself.")
 65        active_effects_keys= set(self.effects.keys()) - self.depleted_effects
 66        updated_effects = {}
 67        updated_intensities = {}
 68        for effect in active_effects_keys:
 69            updated_effects.update({effect : self.effects[effect]})
 70        for name, intensity in self.intensities.items():
 71            if name not in active_effects_keys:
 72                continue
 73            if intensity * number % 1 == 0.5:
 74                updated_intensities.update({name : int(intensity * number)})
 75            else:
 76                updated_intensities.update({name : round(intensity * number)})
 77
 78        self.sacrificed=True
 79        return Potion(updated_effects, self.duration, updated_intensities)
 80
 81    def __sub__(self, other):
 82        if self.depleted or other.depleted:
 83            raise TypeError("Potion is depleted.")
 84        if self.sacrificed or other.sacrificed:
 85            raise TypeError("Potion is now part of something bigger than itself.")
 86        updated_effects = copy.deepcopy(self.effects)
 87        updated_intensities = copy.deepcopy(self.intensities)
 88        if not set(self.effects.keys()) >= set(other.effects.keys()):
 89            raise TypeError("The effects differ in the potions.")
 90        # traverse the effects_intensity pairs and if effect not present in the right remove it 
 91        for name, intensity in self.intensities.items():
 92            if not name in set(other.effects.keys()) or name in other.depleted_effects:
 93                continue
 94            else:
 95                diff = intensity - other.intensities[name]
 96                if diff <= 0:
 97                    del updated_intensities[name]
 98                    del updated_effects[name]
 99                    continue
100                updated_intensities[name] = diff
101        # remove the effects and coresponding intensities of depleted effects in left potion
102        for effect in self.depleted_effects:
103            del updated_effects[effect]
104            del updated_intensities[effect]
105
106        self.sacrificed = True
107        other.sacrificed = True
108        return Potion(updated_effects, self.duration, updated_intensities)
109
110    def __truediv__(self, number):
111        if self.depleted:
112            raise TypeError("Potion is depleted.")
113        if self.sacrificed:
114            raise TypeError("Potion is now part of something bigger than itself.")
115        active_effects_keys= set(self.effects.keys()) - self.depleted_effects
116        updated_effects = {}
117        for effect in active_effects_keys:
118            updated_effects.update({effect : self.effects[effect]})
119        updated_intensities = {}
120        result = []
121        for name, intensity in self.intensities.items():
122            if name not in active_effects_keys:
123                continue
124            if intensity / number % 1 == 0.5:
125                updated_intensities.update({name : int(intensity / number)})
126            else:
127                updated_intensities.update({name : round(intensity / number)})
128
129        for times in range(number):
130            final_effects = copy.deepcopy(updated_effects)
131            final_intensities = copy.deepcopy(updated_intensities)
132            result.append(Potion(final_effects, self.duration, final_intensities))
133
134        self.sacrificed = True
135        return tuple(result)
136
137    def __eq__(self, other):
138        if self.depleted or other.depleted:
139            raise TypeError("Potion is depleted.")
140        if self.sacrificed or other.sacrificed:
141            raise TypeError("Potion is now part of something bigger than itself.")
142        if set(self.intensities.keys()) != set(other.intensities.keys()):
143            return False
144
145        for name, intensity in self.intensities.items():
146            if self.intensities[name] != other.intensities[name]:
147                return False
148        return True
149
150    def __gt__(self, other):
151        if self.depleted or other.depleted:
152            raise TypeError("Potion is depleted.")
153        if self.sacrificed or other.sacrificed:
154            raise TypeError("Potion is now part of something bigger than itself.")
155
156        sum_first = 0
157        sum_second = 0
158        for name, intensity in self.intensities.items():
159            sum_first += intensity
160        for name, intensity in other.intensities.items():
161            sum_second += intensity
162
163        return sum_first > sum_second
164
165    def __lt__(self, other):
166        if self.depleted or other.depleted:
167            raise TypeError("Potion is depleted.")
168        if self.sacrificed or other.sacrificed:
169            raise TypeError("Potion is now part of something bigger than itself.")
170
171        sum_first = 0
172        sum_second = 0
173        for name, intensity in self.intensities.items():
174            sum_first += intensity
175        for name, intensity in other.intensities.items():
176            sum_second += intensity
177
178        return sum_first < sum_second
179
180    @staticmethod
181    def effect_fortifier(func, times):
182        def effect_fortified(target):
183            for _ in range(times):
184                func(target)
185            return target
186        return effect_fortified
187
188    def __getattribute__(self, name):
189        # if it is not a method or not an effect no problem
190        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):
191            return object.__getattribute__(self, name)
192        # if potion has been used in something bigger raise the error
193        if object.__getattribute__(self, "sacrificed"):
194            raise TypeError("Potion is now part of something bigger than itself.")
195        # if potion has been applied already raise the error
196        if object.__getattribute__(self, "depleted"):
197            raise TypeError("Potion is depleted.")
198        # if it hasn't been used before add it to the list of depleted then allow it 
199        if name not in object.__getattribute__(self, "depleted_effects"):
200            object.__getattribute__(self, "depleted_effects").add(name)
201            # fortified based on the current intensity
202            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])
203        # otherwise throw the error
204        raise TypeError("Effect is depleted.")
205
206
207class ГоспожатаПоХимия:
208
209    def __init__(self):
210        self.active_potions = []
211        self.affected_targets = []
212
213    @staticmethod
214    def molecular_mass(name):
215        mass = 0
216        for pos in range(0, len(name)):
217            mass += ord(name[pos])
218        return mass
219
220    def apply(self, target, potion):
221        # check if the potion is depleted first or has been sac-ed
222        if set(potion.effects.keys()) == potion.depleted_effects:
223            raise TypeError("Potion is depleted.")
224        if potion.sacrificed:
225            raise TypeError("Potion is now part of something bigger than itself.")
226        
227        if potion.duration==0:
228            return None
229
230        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)
231        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)
232        #check if target has been affected already
233        seen = False
234        for target_id, original_data in self.affected_targets:
235            if id(target) == target_id:
236                seen = True
237        # save the original data otherwise
238        if not seen:
239            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))
240
241        self.active_potions.append((copy.deepcopy(potion), target))
242
243        for effect in remaining_effects:
244            #apply the effect to the target
245            method=getattr(potion,effect)
246            method(target)
247        # deem the potion depleted after the process
248        potion.depleted = True
249
250    def tick(self):
251        for potion, target in self.active_potions:
252            potion.duration -= 1
253            if potion.duration == 0:
254                # Find the original information and normalize the target
255                for target_id, original_data in self.affected_targets:
256                    if id(target) == target_id:
257                        target.__dict__ = copy.deepcopy(original_data)
258                # Reapply effects for remaining active potions
259                for potion_2,target_2 in self.active_potions:
260                    if potion_2.duration != 0 and target == target_2:
261                        for effect in potion_2.effects:
262                            method = getattr(potion_2, effect)
263                            method(target)
264        # Remove the timed-out potion-target pairs from the list of active ones
265        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]

....................
----------------------------------------------------------------------
Ran 20 tests in 0.003s

OK

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

f1import copyf1import copy
22
3class Potion:3class Potion:
44
5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):
6        self.depleted_effects = set()6        self.depleted_effects = set()
7        self.effects = effects7        self.effects = effects
8        self.duration = duration8        self.duration = duration
9        self.sacrificed = sacrificed9        self.sacrificed = sacrificed
10        self.depleted = depleted10        self.depleted = depleted
11        self.intensities = {}11        self.intensities = {}
12        # make the effects methods and add intensity 1 for each name12        # make the effects methods and add intensity 1 for each name
13        for name, func in self.effects.items():13        for name, func in self.effects.items():
14            setattr(self, name, func)14            setattr(self, name, func)
1515
16        if not intensities:16        if not intensities:
17            for name, func in self.effects.items():17            for name, func in self.effects.items():
18                self.intensities.update({name : 1})18                self.intensities.update({name : 1})
19        else:19        else:
20            self.intensities = intensities20            self.intensities = intensities
2121
22    def __add__(self, other):22    def __add__(self, other):
23        if self.depleted or other.depleted:23        if self.depleted or other.depleted:
24            raise TypeError("Potion is depleted.")24            raise TypeError("Potion is depleted.")
25        if self.sacrificed or other.sacrificed:25        if self.sacrificed or other.sacrificed:
26            raise TypeError("Potion is now part of something bigger than itself.")26            raise TypeError("Potion is now part of something bigger than itself.")
27        self_active_effects = set(self.effects.keys()) - self.depleted_effects27        self_active_effects = set(self.effects.keys()) - self.depleted_effects
28        other_active_effects = set(other.effects.keys()) - other.depleted_effects28        other_active_effects = set(other.effects.keys()) - other.depleted_effects
29        #union the effects of both29        #union the effects of both
30        updated_effects_keys = self_active_effects | other_active_effects30        updated_effects_keys = self_active_effects | other_active_effects
31        updated_effects = {}31        updated_effects = {}
32        updated_intensities = {}32        updated_intensities = {}
33        # traverse both intensities dict-s and add to the updated one33        # traverse both intensities dict-s and add to the updated one
34        for name, intensity in self.intensities.items():34        for name, intensity in self.intensities.items():
35            if name in updated_effects_keys and name not in self.depleted_effects:35            if name in updated_effects_keys and name not in self.depleted_effects:
36                if updated_intensities.get(name):36                if updated_intensities.get(name):
37                    updated_intensities[name] += intensity37                    updated_intensities[name] += intensity
38                else:38                else:
39                    updated_intensities[name] = intensity39                    updated_intensities[name] = intensity
4040
41        for name, intensity in other.intensities.items():41        for name, intensity in other.intensities.items():
42            if name in updated_effects_keys and name not in other.depleted_effects:42            if name in updated_effects_keys and name not in other.depleted_effects:
43                if updated_intensities.get(name):43                if updated_intensities.get(name):
44                    updated_intensities[name] += intensity44                    updated_intensities[name] += intensity
45                else:45                else:
46                    updated_intensities[name] = intensity46                    updated_intensities[name] = intensity
4747
48        for effect, func in self.effects.items():48        for effect, func in self.effects.items():
49            if effect in updated_effects_keys:49            if effect in updated_effects_keys:
50                updated_effects.update({effect : func})50                updated_effects.update({effect : func})
5151
52        for effect, func in other.effects.items():52        for effect, func in other.effects.items():
53            if effect in updated_effects_keys:53            if effect in updated_effects_keys:
54                updated_effects.update({effect : func})54                updated_effects.update({effect : func})
5555
56        self.sacrificed = True56        self.sacrificed = True
57        other.sacrificed = True57        other.sacrificed = True
58        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)58        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)
5959
60    def __mul__(self,number):60    def __mul__(self,number):
61        if self.depleted:61        if self.depleted:
62            raise TypeError("Potion is depleted.")62            raise TypeError("Potion is depleted.")
63        if self.sacrificed:63        if self.sacrificed:
64            raise TypeError("Potion is now part of something bigger than itself.")64            raise TypeError("Potion is now part of something bigger than itself.")
n65        updated_intensities = copy.deepcopy(self.intensities)n65        active_effects_keys= set(self.effects.keys()) - self.depleted_effects
66        updated_effects = {}
67        updated_intensities = {}
68        for effect in active_effects_keys:
69            updated_effects.update({effect : self.effects[effect]})
66        for name, intensity in updated_intensities.items():70        for name, intensity in self.intensities.items():
71            if name not in active_effects_keys:
72                continue
67            if intensity * number % 1 == 0.5:73            if intensity * number % 1 == 0.5:
n68                updated_intensities[name] = int(intensity * number)n74                updated_intensities.update({name : int(intensity * number)})
69            else:75            else:
n70                updated_intensities[name] = round(intensity * number)n76                updated_intensities.update({name : round(intensity * number)})
7177
72        self.sacrificed=True78        self.sacrificed=True
n73        return Potion(self.effects, self.duration, updated_intensities)n79        return Potion(updated_effects, self.duration, updated_intensities)
7480
75    def __sub__(self, other):81    def __sub__(self, other):
76        if self.depleted or other.depleted:82        if self.depleted or other.depleted:
77            raise TypeError("Potion is depleted.")83            raise TypeError("Potion is depleted.")
78        if self.sacrificed or other.sacrificed:84        if self.sacrificed or other.sacrificed:
79            raise TypeError("Potion is now part of something bigger than itself.")85            raise TypeError("Potion is now part of something bigger than itself.")
80        updated_effects = copy.deepcopy(self.effects)86        updated_effects = copy.deepcopy(self.effects)
81        updated_intensities = copy.deepcopy(self.intensities)87        updated_intensities = copy.deepcopy(self.intensities)
82        if not set(self.effects.keys()) >= set(other.effects.keys()):88        if not set(self.effects.keys()) >= set(other.effects.keys()):
83            raise TypeError("The effects differ in the potions.")89            raise TypeError("The effects differ in the potions.")
84        # traverse the effects_intensity pairs and if effect not present in the right remove it 90        # traverse the effects_intensity pairs and if effect not present in the right remove it 
85        for name, intensity in self.intensities.items():91        for name, intensity in self.intensities.items():
n86            if not name in set(other.effects.keys()):n92            if not name in set(other.effects.keys()) or name in other.depleted_effects:
87                continue93                continue
88            else:94            else:
89                diff = intensity - other.intensities[name]95                diff = intensity - other.intensities[name]
n90                if diff < 0:n96                if diff <= 0:
91                    del updated_intensities[name]97                    del updated_intensities[name]
92                    del updated_effects[name]98                    del updated_effects[name]
93                    continue99                    continue
94                updated_intensities[name] = diff100                updated_intensities[name] = diff
95        # remove the effects and coresponding intensities of depleted effects in left potion101        # remove the effects and coresponding intensities of depleted effects in left potion
96        for effect in self.depleted_effects:102        for effect in self.depleted_effects:
97            del updated_effects[effect]103            del updated_effects[effect]
98            del updated_intensities[effect]104            del updated_intensities[effect]
99105
100        self.sacrificed = True106        self.sacrificed = True
101        other.sacrificed = True107        other.sacrificed = True
102        return Potion(updated_effects, self.duration, updated_intensities)108        return Potion(updated_effects, self.duration, updated_intensities)
103109
104    def __truediv__(self, number):110    def __truediv__(self, number):
105        if self.depleted:111        if self.depleted:
106            raise TypeError("Potion is depleted.")112            raise TypeError("Potion is depleted.")
107        if self.sacrificed:113        if self.sacrificed:
108            raise TypeError("Potion is now part of something bigger than itself.")114            raise TypeError("Potion is now part of something bigger than itself.")
n109 n115        active_effects_keys= set(self.effects.keys()) - self.depleted_effects
110        updated_intensities = copy.deepcopy(self.intensities)116        updated_effects = {}
117        for effect in active_effects_keys:
118            updated_effects.update({effect : self.effects[effect]})
119        updated_intensities = {}
111        result = []120        result = []
n112 n
113        for name, intensity in self.intensities.items():121        for name, intensity in self.intensities.items():
nn122            if name not in active_effects_keys:
123                continue
114            if intensity / number % 1 == 0.5:124            if intensity / number % 1 == 0.5:
n115                updated_intensities[name] = int(intensity / number)n125                updated_intensities.update({name : int(intensity / number)})
116            else:126            else:
n117                updated_intensities[name] = round(intensity / number)n127                updated_intensities.update({name : round(intensity / number)})
118128
119        for times in range(number):129        for times in range(number):
n120            final_effects = copy.deepcopy(self.effects)n130            final_effects = copy.deepcopy(updated_effects)
121            final_intensities = copy.deepcopy(updated_intensities)131            final_intensities = copy.deepcopy(updated_intensities)
122            result.append(Potion(final_effects, self.duration, final_intensities))132            result.append(Potion(final_effects, self.duration, final_intensities))
123133
124        self.sacrificed = True134        self.sacrificed = True
125        return tuple(result)135        return tuple(result)
126136
127    def __eq__(self, other):137    def __eq__(self, other):
128        if self.depleted or other.depleted:138        if self.depleted or other.depleted:
129            raise TypeError("Potion is depleted.")139            raise TypeError("Potion is depleted.")
130        if self.sacrificed or other.sacrificed:140        if self.sacrificed or other.sacrificed:
131            raise TypeError("Potion is now part of something bigger than itself.")141            raise TypeError("Potion is now part of something bigger than itself.")
132        if set(self.intensities.keys()) != set(other.intensities.keys()):142        if set(self.intensities.keys()) != set(other.intensities.keys()):
133            return False143            return False
134144
135        for name, intensity in self.intensities.items():145        for name, intensity in self.intensities.items():
136            if self.intensities[name] != other.intensities[name]:146            if self.intensities[name] != other.intensities[name]:
137                return False147                return False
138        return True148        return True
139149
140    def __gt__(self, other):150    def __gt__(self, other):
141        if self.depleted or other.depleted:151        if self.depleted or other.depleted:
142            raise TypeError("Potion is depleted.")152            raise TypeError("Potion is depleted.")
143        if self.sacrificed or other.sacrificed:153        if self.sacrificed or other.sacrificed:
144            raise TypeError("Potion is now part of something bigger than itself.")154            raise TypeError("Potion is now part of something bigger than itself.")
145155
146        sum_first = 0156        sum_first = 0
147        sum_second = 0157        sum_second = 0
148        for name, intensity in self.intensities.items():158        for name, intensity in self.intensities.items():
149            sum_first += intensity159            sum_first += intensity
150        for name, intensity in other.intensities.items():160        for name, intensity in other.intensities.items():
151            sum_second += intensity161            sum_second += intensity
152162
153        return sum_first > sum_second163        return sum_first > sum_second
154164
155    def __lt__(self, other):165    def __lt__(self, other):
156        if self.depleted or other.depleted:166        if self.depleted or other.depleted:
157            raise TypeError("Potion is depleted.")167            raise TypeError("Potion is depleted.")
158        if self.sacrificed or other.sacrificed:168        if self.sacrificed or other.sacrificed:
159            raise TypeError("Potion is now part of something bigger than itself.")169            raise TypeError("Potion is now part of something bigger than itself.")
160170
161        sum_first = 0171        sum_first = 0
162        sum_second = 0172        sum_second = 0
163        for name, intensity in self.intensities.items():173        for name, intensity in self.intensities.items():
164            sum_first += intensity174            sum_first += intensity
165        for name, intensity in other.intensities.items():175        for name, intensity in other.intensities.items():
166            sum_second += intensity176            sum_second += intensity
167177
168        return sum_first < sum_second178        return sum_first < sum_second
169179
170    @staticmethod180    @staticmethod
171    def effect_fortifier(func, times):181    def effect_fortifier(func, times):
172        def effect_fortified(target):182        def effect_fortified(target):
173            for _ in range(times):183            for _ in range(times):
174                func(target)184                func(target)
175            return target185            return target
176        return effect_fortified186        return effect_fortified
177187
178    def __getattribute__(self, name):188    def __getattribute__(self, name):
179        # if it is not a method or not an effect no problem189        # if it is not a method or not an effect no problem
180        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):190        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):
181            return object.__getattribute__(self, name)191            return object.__getattribute__(self, name)
182        # if potion has been used in something bigger raise the error192        # if potion has been used in something bigger raise the error
183        if object.__getattribute__(self, "sacrificed"):193        if object.__getattribute__(self, "sacrificed"):
184            raise TypeError("Potion is now part of something bigger than itself.")194            raise TypeError("Potion is now part of something bigger than itself.")
185        # if potion has been applied already raise the error195        # if potion has been applied already raise the error
186        if object.__getattribute__(self, "depleted"):196        if object.__getattribute__(self, "depleted"):
187            raise TypeError("Potion is depleted.")197            raise TypeError("Potion is depleted.")
188        # if it hasn't been used before add it to the list of depleted then allow it 198        # if it hasn't been used before add it to the list of depleted then allow it 
189        if name not in object.__getattribute__(self, "depleted_effects"):199        if name not in object.__getattribute__(self, "depleted_effects"):
190            object.__getattribute__(self, "depleted_effects").add(name)200            object.__getattribute__(self, "depleted_effects").add(name)
191            # fortified based on the current intensity201            # fortified based on the current intensity
192            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])202            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])
193        # otherwise throw the error203        # otherwise throw the error
194        raise TypeError("Effect is depleted.")204        raise TypeError("Effect is depleted.")
195205
196206
197class ГоспожатаПоХимия:207class ГоспожатаПоХимия:
198208
199    def __init__(self):209    def __init__(self):
200        self.active_potions = []210        self.active_potions = []
201        self.affected_targets = []211        self.affected_targets = []
202212
203    @staticmethod213    @staticmethod
204    def molecular_mass(name):214    def molecular_mass(name):
205        mass = 0215        mass = 0
206        for pos in range(0, len(name)):216        for pos in range(0, len(name)):
207            mass += ord(name[pos])217            mass += ord(name[pos])
208        return mass218        return mass
209219
210    def apply(self, target, potion):220    def apply(self, target, potion):
211        # check if the potion is depleted first or has been sac-ed221        # check if the potion is depleted first or has been sac-ed
212        if set(potion.effects.keys()) == potion.depleted_effects:222        if set(potion.effects.keys()) == potion.depleted_effects:
213            raise TypeError("Potion is depleted.")223            raise TypeError("Potion is depleted.")
214        if potion.sacrificed:224        if potion.sacrificed:
215            raise TypeError("Potion is now part of something bigger than itself.")225            raise TypeError("Potion is now part of something bigger than itself.")
nn226        
227        if potion.duration==0:
228            return None
216229
217        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)230        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)
218        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)231        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)
219        #check if target has been affected already232        #check if target has been affected already
220        seen = False233        seen = False
221        for target_id, original_data in self.affected_targets:234        for target_id, original_data in self.affected_targets:
222            if id(target) == target_id:235            if id(target) == target_id:
223                seen = True236                seen = True
224        # save the original data otherwise237        # save the original data otherwise
225        if not seen:238        if not seen:
226            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))239            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))
227240
228        self.active_potions.append((copy.deepcopy(potion), target))241        self.active_potions.append((copy.deepcopy(potion), target))
229242
230        for effect in remaining_effects:243        for effect in remaining_effects:
231            #apply the effect to the target244            #apply the effect to the target
t232            potion.effects[effect](target)t245            method=getattr(potion,effect)
246            method(target)
233        # deem the potion depleted after the process247        # deem the potion depleted after the process
234        potion.depleted = True248        potion.depleted = True
235249
236    def tick(self):250    def tick(self):
237        for potion, target in self.active_potions:251        for potion, target in self.active_potions:
238            potion.duration -= 1252            potion.duration -= 1
239            if potion.duration == 0:253            if potion.duration == 0:
240                # Find the original information and normalize the target254                # Find the original information and normalize the target
241                for target_id, original_data in self.affected_targets:255                for target_id, original_data in self.affected_targets:
242                    if id(target) == target_id:256                    if id(target) == target_id:
243                        target.__dict__ = copy.deepcopy(original_data)257                        target.__dict__ = copy.deepcopy(original_data)
244                # Reapply effects for remaining active potions258                # Reapply effects for remaining active potions
245                for potion_2,target_2 in self.active_potions:259                for potion_2,target_2 in self.active_potions:
246                    if potion_2.duration != 0 and target == target_2:260                    if potion_2.duration != 0 and target == target_2:
247                        for effect in potion_2.effects:261                        for effect in potion_2.effects:
248                            method = getattr(potion_2, effect)262                            method = getattr(potion_2, effect)
249                            method(target)263                            method(target)
250        # Remove the timed-out potion-target pairs from the list of active ones264        # Remove the timed-out potion-target pairs from the list of active ones
251        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]265        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
22
3class Potion:3class Potion:
44
5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):
n6        setattr(self, "depleted_effects", set())n6        self.depleted_effects = set()
7        self.effects = effects7        self.effects = effects
8        self.duration = duration8        self.duration = duration
9        self.sacrificed = sacrificed9        self.sacrificed = sacrificed
10        self.depleted = depleted10        self.depleted = depleted
11        self.intensities = {}11        self.intensities = {}
12        # make the effects methods and add intensity 1 for each name12        # make the effects methods and add intensity 1 for each name
13        for name, func in self.effects.items():13        for name, func in self.effects.items():
14            setattr(self, name, func)14            setattr(self, name, func)
1515
16        if not intensities:16        if not intensities:
17            for name, func in self.effects.items():17            for name, func in self.effects.items():
18                self.intensities.update({name : 1})18                self.intensities.update({name : 1})
19        else:19        else:
n20            self.intensities=intensitiesn20            self.intensities = intensities
2121
22    def __add__(self, other):22    def __add__(self, other):
n23 n
24        if self.depleted or other.depleted:23        if self.depleted or other.depleted:
25            raise TypeError("Potion is depleted.")24            raise TypeError("Potion is depleted.")
n26        n
27        if self.sacrificed or other.sacrificed:25        if self.sacrificed or other.sacrificed:
28            raise TypeError("Potion is now part of something bigger than itself.")26            raise TypeError("Potion is now part of something bigger than itself.")
n29 n
30        self_active_effects = set(self.effects.keys())-self.depleted_effects27        self_active_effects = set(self.effects.keys()) - self.depleted_effects
31        other_active_effects = set(other.effects.keys())-other.depleted_effects28        other_active_effects = set(other.effects.keys()) - other.depleted_effects
32        #union the effects of both29        #union the effects of both
33        updated_effects_keys = self_active_effects | other_active_effects30        updated_effects_keys = self_active_effects | other_active_effects
34        updated_effects = {}31        updated_effects = {}
35        updated_intensities = {}32        updated_intensities = {}
36        # traverse both intensities dict-s and add to the updated one33        # traverse both intensities dict-s and add to the updated one
n37        for name,intensity in self.intensities.items():n34        for name, intensity in self.intensities.items():
38            if name in updated_effects_keys and name not in self.depleted_effects:35            if name in updated_effects_keys and name not in self.depleted_effects:
39                if updated_intensities.get(name):36                if updated_intensities.get(name):
40                    updated_intensities[name] += intensity37                    updated_intensities[name] += intensity
41                else:38                else:
42                    updated_intensities[name] = intensity39                    updated_intensities[name] = intensity
4340
44        for name, intensity in other.intensities.items():41        for name, intensity in other.intensities.items():
45            if name in updated_effects_keys and name not in other.depleted_effects:42            if name in updated_effects_keys and name not in other.depleted_effects:
46                if updated_intensities.get(name):43                if updated_intensities.get(name):
47                    updated_intensities[name] += intensity44                    updated_intensities[name] += intensity
48                else:45                else:
49                    updated_intensities[name] = intensity46                    updated_intensities[name] = intensity
5047
51        for effect, func in self.effects.items():48        for effect, func in self.effects.items():
52            if effect in updated_effects_keys:49            if effect in updated_effects_keys:
53                updated_effects.update({effect : func})50                updated_effects.update({effect : func})
n54        n51 
55        for effect, func in other.effects.items():52        for effect, func in other.effects.items():
56            if effect in updated_effects_keys:53            if effect in updated_effects_keys:
57                updated_effects.update({effect : func})54                updated_effects.update({effect : func})
n58                n55 
59        self.sacrificed = True56        self.sacrificed = True
60        other.sacrificed = True57        other.sacrificed = True
61        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)58        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)
n62    n59 
63    def __mul__(self,number):60    def __mul__(self,number):
n64 n
65        if self.depleted:61        if self.depleted:
66            raise TypeError("Potion is depleted.")62            raise TypeError("Potion is depleted.")
n67        n
68        if self.sacrificed:63        if self.sacrificed:
69            raise TypeError("Potion is now part of something bigger than itself.")64            raise TypeError("Potion is now part of something bigger than itself.")
n70 n
71        updated_intensities = copy.deepcopy(self.intensities)65        updated_intensities = copy.deepcopy(self.intensities)
72        for name, intensity in updated_intensities.items():66        for name, intensity in updated_intensities.items():
73            if intensity * number % 1 == 0.5:67            if intensity * number % 1 == 0.5:
74                updated_intensities[name] = int(intensity * number)68                updated_intensities[name] = int(intensity * number)
75            else:69            else:
76                updated_intensities[name] = round(intensity * number)70                updated_intensities[name] = round(intensity * number)
nn71 
77        self.sacrificed=True72        self.sacrificed=True
78        return Potion(self.effects, self.duration, updated_intensities)73        return Potion(self.effects, self.duration, updated_intensities)
n79        n74 
80    def __sub__(self, other):75    def __sub__(self, other):
81        if self.depleted or other.depleted:76        if self.depleted or other.depleted:
82            raise TypeError("Potion is depleted.")77            raise TypeError("Potion is depleted.")
n83        n
84        if self.sacrificed or other.sacrificed:78        if self.sacrificed or other.sacrificed:
85            raise TypeError("Potion is now part of something bigger than itself.")79            raise TypeError("Potion is now part of something bigger than itself.")
n86 n
87        updated_effects = copy.deepcopy(self.effects)80        updated_effects = copy.deepcopy(self.effects)
88        updated_intensities = copy.deepcopy(self.intensities)81        updated_intensities = copy.deepcopy(self.intensities)
89        if not set(self.effects.keys()) >= set(other.effects.keys()):82        if not set(self.effects.keys()) >= set(other.effects.keys()):
n90            raise TypeError("The effects differ in the poitions.")n83            raise TypeError("The effects differ in the potions.")
91        84        # traverse the effects_intensity pairs and if effect not present in the right remove it 
92        for name, intensity in self.intensities.items():85        for name, intensity in self.intensities.items():
n93            diff = intensity - other.intensities[name]n86            if not name in set(other.effects.keys()):
94            if diff < 0:
95                del updated_intensities[name]
96                del updated_effects[name]
97                continue87                continue
nn88            else:
89                diff = intensity - other.intensities[name]
90                if diff < 0:
91                    del updated_intensities[name]
92                    del updated_effects[name]
93                    continue
98            updated_intensities[name] = diff94                updated_intensities[name] = diff
99 
100        # remove the effects and coresponding intensities of depleted effects in left potion95        # remove the effects and coresponding intensities of depleted effects in left potion
101        for effect in self.depleted_effects:96        for effect in self.depleted_effects:
102            del updated_effects[effect]97            del updated_effects[effect]
103            del updated_intensities[effect]98            del updated_intensities[effect]
10499
105        self.sacrificed = True100        self.sacrificed = True
106        other.sacrificed = True101        other.sacrificed = True
107        return Potion(updated_effects, self.duration, updated_intensities)102        return Potion(updated_effects, self.duration, updated_intensities)
n108    n103 
109    def __truediv__(self, number):104    def __truediv__(self, number):
110        if self.depleted:105        if self.depleted:
111            raise TypeError("Potion is depleted.")106            raise TypeError("Potion is depleted.")
n112        n
113        if self.sacrificed:107        if self.sacrificed:
114            raise TypeError("Potion is now part of something bigger than itself.")108            raise TypeError("Potion is now part of something bigger than itself.")
n115        n109 
116        updated_intensities = copy.deepcopy(self.intensities)110        updated_intensities = copy.deepcopy(self.intensities)
117        result = []111        result = []
118112
119        for name, intensity in self.intensities.items():113        for name, intensity in self.intensities.items():
n120            if (intensity / number) % 1 == 0.5:n114            if intensity / number % 1 == 0.5:
121                updated_intensities[name] = int(intensity / number)115                updated_intensities[name] = int(intensity / number)
122            else:116            else:
123                updated_intensities[name] = round(intensity / number)117                updated_intensities[name] = round(intensity / number)
124118
n125        for times in range(0, number):n119        for times in range(number):
126            final_effects = copy.deepcopy(self.effects)120            final_effects = copy.deepcopy(self.effects)
127            final_intensities = copy.deepcopy(updated_intensities)121            final_intensities = copy.deepcopy(updated_intensities)
128            result.append(Potion(final_effects, self.duration, final_intensities))122            result.append(Potion(final_effects, self.duration, final_intensities))
n129        n123 
130        self.sacrificed = True124        self.sacrificed = True
n131 n
132        return tuple(result)125        return tuple(result)
n133    n126 
134    def __eq__(self, other):127    def __eq__(self, other):
135        if self.depleted or other.depleted:128        if self.depleted or other.depleted:
136            raise TypeError("Potion is depleted.")129            raise TypeError("Potion is depleted.")
n137        n
138        if self.sacrificed or other.sacrificed:130        if self.sacrificed or other.sacrificed:
139            raise TypeError("Potion is now part of something bigger than itself.")131            raise TypeError("Potion is now part of something bigger than itself.")
n140        n
141        if set(self.intensities.keys()) != set(other.intensities.keys()):132        if set(self.intensities.keys()) != set(other.intensities.keys()):
142            return False133            return False
n143        n134 
144        for name, intensity in self.intensities.items():135        for name, intensity in self.intensities.items():
145            if self.intensities[name] != other.intensities[name]:136            if self.intensities[name] != other.intensities[name]:
146                return False137                return False
n147        n
148        return True138        return True
n149    n139 
150    def __gt__(self, other):140    def __gt__(self, other):
151        if self.depleted or other.depleted:141        if self.depleted or other.depleted:
152            raise TypeError("Potion is depleted.")142            raise TypeError("Potion is depleted.")
n153        n
154        if self.sacrificed or other.sacrificed:143        if self.sacrificed or other.sacrificed:
155            raise TypeError("Potion is now part of something bigger than itself.")144            raise TypeError("Potion is now part of something bigger than itself.")
n156        n145 
157        sum_first = 0146        sum_first = 0
158        sum_second = 0147        sum_second = 0
159        for name, intensity in self.intensities.items():148        for name, intensity in self.intensities.items():
160            sum_first += intensity149            sum_first += intensity
n161 n
162        for name, intensity in other.intensities.items():150        for name, intensity in other.intensities.items():
163            sum_second += intensity151            sum_second += intensity
n164        n152 
165        return sum_first > sum_second153        return sum_first > sum_second
n166    n154 
167    # strictly less == not strictly greater
168    def __lt__(self, other):155    def __lt__(self, other):
n169        return not self.__gt__(other)n156        if self.depleted or other.depleted:
157            raise TypeError("Potion is depleted.")
158        if self.sacrificed or other.sacrificed:
159            raise TypeError("Potion is now part of something bigger than itself.")
160 
161        sum_first = 0
162        sum_second = 0
163        for name, intensity in self.intensities.items():
164            sum_first += intensity
165        for name, intensity in other.intensities.items():
166            sum_second += intensity
167 
168        return sum_first < sum_second
170169
171    @staticmethod170    @staticmethod
172    def effect_fortifier(func, times):171    def effect_fortifier(func, times):
173        def effect_fortified(target):172        def effect_fortified(target):
n174            for _ in range(0, times):n173            for _ in range(times):
175                func(target)174                func(target)
176            return target175            return target
177        return effect_fortified176        return effect_fortified
n178 n
179177
180    def __getattribute__(self, name):178    def __getattribute__(self, name):
181        # if it is not a method or not an effect no problem179        # if it is not a method or not an effect no problem
182        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):180        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):
183            return object.__getattribute__(self, name)181            return object.__getattribute__(self, name)
184        # if potion has been used in something bigger raise the error182        # if potion has been used in something bigger raise the error
185        if object.__getattribute__(self, "sacrificed"):183        if object.__getattribute__(self, "sacrificed"):
186            raise TypeError("Potion is now part of something bigger than itself.")184            raise TypeError("Potion is now part of something bigger than itself.")
187        # if potion has been applied already raise the error185        # if potion has been applied already raise the error
188        if object.__getattribute__(self, "depleted"):186        if object.__getattribute__(self, "depleted"):
189            raise TypeError("Potion is depleted.")187            raise TypeError("Potion is depleted.")
190        # if it hasn't been used before add it to the list of depleted then allow it 188        # if it hasn't been used before add it to the list of depleted then allow it 
191        if name not in object.__getattribute__(self, "depleted_effects"):189        if name not in object.__getattribute__(self, "depleted_effects"):
192            object.__getattribute__(self, "depleted_effects").add(name)190            object.__getattribute__(self, "depleted_effects").add(name)
193            # fortified based on the current intensity191            # fortified based on the current intensity
194            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])192            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])
195        # otherwise throw the error193        # otherwise throw the error
196        raise TypeError("Effect is depleted.")194        raise TypeError("Effect is depleted.")
197195
198196
199class ГоспожатаПоХимия:197class ГоспожатаПоХимия:
200198
201    def __init__(self):199    def __init__(self):
202        self.active_potions = []200        self.active_potions = []
203        self.affected_targets = []201        self.affected_targets = []
204202
205    @staticmethod203    @staticmethod
206    def molecular_mass(name):204    def molecular_mass(name):
207        mass = 0205        mass = 0
208        for pos in range(0, len(name)):206        for pos in range(0, len(name)):
209            mass += ord(name[pos])207            mass += ord(name[pos])
210        return mass208        return mass
211209
212    def apply(self, target, potion):210    def apply(self, target, potion):
213        # check if the potion is depleted first or has been sac-ed211        # check if the potion is depleted first or has been sac-ed
214        if set(potion.effects.keys()) == potion.depleted_effects:212        if set(potion.effects.keys()) == potion.depleted_effects:
215            raise TypeError("Potion is depleted.")213            raise TypeError("Potion is depleted.")
n216        n
217        if potion.sacrificed:214        if potion.sacrificed:
218            raise TypeError("Potion is now part of something bigger than itself.")215            raise TypeError("Potion is now part of something bigger than itself.")
n219        n216 
220        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)217        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)
n221 n
222        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)218        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)
n223 n
224        #check if target has been affected already219        #check if target has been affected already
n225 n
226        seen = False220        seen = False
n227 n
228        for target_id, original_data in self.affected_targets:221        for target_id, original_data in self.affected_targets:
n229            if id(target) ==  target_id:n222            if id(target) == target_id:
230                seen = True223                seen = True
231        # save the original data otherwise224        # save the original data otherwise
232        if not seen:225        if not seen:
233            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))226            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))
234227
235        self.active_potions.append((copy.deepcopy(potion), target))228        self.active_potions.append((copy.deepcopy(potion), target))
236229
237        for effect in remaining_effects:230        for effect in remaining_effects:
238            #apply the effect to the target231            #apply the effect to the target
239            potion.effects[effect](target)232            potion.effects[effect](target)
n240 n
241        # deem the potion depleted after the process233        # deem the potion depleted after the process
242        potion.depleted = True234        potion.depleted = True
243235
244    def tick(self):236    def tick(self):
245        for potion, target in self.active_potions:237        for potion, target in self.active_potions:
246            potion.duration -= 1238            potion.duration -= 1
247            if potion.duration == 0:239            if potion.duration == 0:
248                # Find the original information and normalize the target240                # Find the original information and normalize the target
249                for target_id, original_data in self.affected_targets:241                for target_id, original_data in self.affected_targets:
250                    if id(target) == target_id:242                    if id(target) == target_id:
251                        target.__dict__ = copy.deepcopy(original_data)243                        target.__dict__ = copy.deepcopy(original_data)
n252 n
253                # Reapply effects for remaining active potions244                # Reapply effects for remaining active potions
254                for potion_2,target_2 in self.active_potions:245                for potion_2,target_2 in self.active_potions:
255                    if potion_2.duration != 0 and target == target_2:246                    if potion_2.duration != 0 and target == target_2:
256                        for effect in potion_2.effects:247                        for effect in potion_2.effects:
n257                            method=getattr(potion_2,effect)n248                            method = getattr(potion_2, effect)
258                            method(target)249                            method(target)
t259 t
260        # Remove the timed-out potion-target pairs from the list of active ones250        # Remove the timed-out potion-target pairs from the list of active ones
261        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]251        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1import copyf1import copy
22
3class Potion:3class Potion:
44
5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):5    def __init__(self, effects, duration, intensities=False, sacrificed=False, depleted=False):
6        setattr(self, "depleted_effects", set())6        setattr(self, "depleted_effects", set())
7        self.effects = effects7        self.effects = effects
8        self.duration = duration8        self.duration = duration
9        self.sacrificed = sacrificed9        self.sacrificed = sacrificed
10        self.depleted = depleted10        self.depleted = depleted
11        self.intensities = {}11        self.intensities = {}
12        # make the effects methods and add intensity 1 for each name12        # make the effects methods and add intensity 1 for each name
13        for name, func in self.effects.items():13        for name, func in self.effects.items():
14            setattr(self, name, func)14            setattr(self, name, func)
1515
16        if not intensities:16        if not intensities:
17            for name, func in self.effects.items():17            for name, func in self.effects.items():
18                self.intensities.update({name : 1})18                self.intensities.update({name : 1})
19        else:19        else:
20            self.intensities=intensities20            self.intensities=intensities
2121
22    def __add__(self, other):22    def __add__(self, other):
2323
24        if self.depleted or other.depleted:24        if self.depleted or other.depleted:
25            raise TypeError("Potion is depleted.")25            raise TypeError("Potion is depleted.")
nn26        
27        if self.sacrificed or other.sacrificed:
28            raise TypeError("Potion is now part of something bigger than itself.")
2629
27        self_active_effects = set(self.effects.keys())-self.depleted_effects30        self_active_effects = set(self.effects.keys())-self.depleted_effects
28        other_active_effects = set(other.effects.keys())-other.depleted_effects31        other_active_effects = set(other.effects.keys())-other.depleted_effects
29        #union the effects of both32        #union the effects of both
30        updated_effects_keys = self_active_effects | other_active_effects33        updated_effects_keys = self_active_effects | other_active_effects
31        updated_effects = {}34        updated_effects = {}
32        updated_intensities = {}35        updated_intensities = {}
33        # traverse both intensities dict-s and add to the updated one36        # traverse both intensities dict-s and add to the updated one
34        for name,intensity in self.intensities.items():37        for name,intensity in self.intensities.items():
35            if name in updated_effects_keys and name not in self.depleted_effects:38            if name in updated_effects_keys and name not in self.depleted_effects:
36                if updated_intensities.get(name):39                if updated_intensities.get(name):
37                    updated_intensities[name] += intensity40                    updated_intensities[name] += intensity
38                else:41                else:
39                    updated_intensities[name] = intensity42                    updated_intensities[name] = intensity
4043
41        for name, intensity in other.intensities.items():44        for name, intensity in other.intensities.items():
42            if name in updated_effects_keys and name not in other.depleted_effects:45            if name in updated_effects_keys and name not in other.depleted_effects:
43                if updated_intensities.get(name):46                if updated_intensities.get(name):
44                    updated_intensities[name] += intensity47                    updated_intensities[name] += intensity
45                else:48                else:
46                    updated_intensities[name] = intensity49                    updated_intensities[name] = intensity
4750
48        for effect, func in self.effects.items():51        for effect, func in self.effects.items():
49            if effect in updated_effects_keys:52            if effect in updated_effects_keys:
50                updated_effects.update({effect : func})53                updated_effects.update({effect : func})
51        54        
52        for effect, func in other.effects.items():55        for effect, func in other.effects.items():
53            if effect in updated_effects_keys:56            if effect in updated_effects_keys:
54                updated_effects.update({effect : func})57                updated_effects.update({effect : func})
55                58                
56        self.sacrificed = True59        self.sacrificed = True
57        other.sacrificed = True60        other.sacrificed = True
58        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)61        return Potion(updated_effects, max(self.duration,other.duration), updated_intensities)
59    62    
60    def __mul__(self,number):63    def __mul__(self,number):
6164
62        if self.depleted:65        if self.depleted:
63            raise TypeError("Potion is depleted.")66            raise TypeError("Potion is depleted.")
nn67        
68        if self.sacrificed:
69            raise TypeError("Potion is now part of something bigger than itself.")
6470
65        updated_intensities = copy.deepcopy(self.intensities)71        updated_intensities = copy.deepcopy(self.intensities)
66        for name, intensity in updated_intensities.items():72        for name, intensity in updated_intensities.items():
67            if intensity * number % 1 == 0.5:73            if intensity * number % 1 == 0.5:
68                updated_intensities[name] = int(intensity * number)74                updated_intensities[name] = int(intensity * number)
69            else:75            else:
70                updated_intensities[name] = round(intensity * number)76                updated_intensities[name] = round(intensity * number)
71        self.sacrificed=True77        self.sacrificed=True
72        return Potion(self.effects, self.duration, updated_intensities)78        return Potion(self.effects, self.duration, updated_intensities)
73        79        
74    def __sub__(self, other):80    def __sub__(self, other):
75        if self.depleted or other.depleted:81        if self.depleted or other.depleted:
76            raise TypeError("Potion is depleted.")82            raise TypeError("Potion is depleted.")
nn83        
84        if self.sacrificed or other.sacrificed:
85            raise TypeError("Potion is now part of something bigger than itself.")
7786
78        updated_effects = copy.deepcopy(self.effects)87        updated_effects = copy.deepcopy(self.effects)
79        updated_intensities = copy.deepcopy(self.intensities)88        updated_intensities = copy.deepcopy(self.intensities)
80        if not set(self.effects.keys()) >= set(other.effects.keys()):89        if not set(self.effects.keys()) >= set(other.effects.keys()):
81            raise TypeError("The effects differ in the poitions.")90            raise TypeError("The effects differ in the poitions.")
82        91        
83        for name, intensity in self.intensities.items():92        for name, intensity in self.intensities.items():
84            diff = intensity - other.intensities[name]93            diff = intensity - other.intensities[name]
85            if diff < 0:94            if diff < 0:
86                del updated_intensities[name]95                del updated_intensities[name]
87                del updated_effects[name]96                del updated_effects[name]
88                continue97                continue
89            updated_intensities[name] = diff98            updated_intensities[name] = diff
9099
91        # remove the effects and coresponding intensities of depleted effects in left potion100        # remove the effects and coresponding intensities of depleted effects in left potion
92        for effect in self.depleted_effects:101        for effect in self.depleted_effects:
93            del updated_effects[effect]102            del updated_effects[effect]
94            del updated_intensities[effect]103            del updated_intensities[effect]
95104
96        self.sacrificed = True105        self.sacrificed = True
97        other.sacrificed = True106        other.sacrificed = True
98        return Potion(updated_effects, self.duration, updated_intensities)107        return Potion(updated_effects, self.duration, updated_intensities)
99    108    
100    def __truediv__(self, number):109    def __truediv__(self, number):
101        if self.depleted:110        if self.depleted:
102            raise TypeError("Potion is depleted.")111            raise TypeError("Potion is depleted.")
103        112        
nn113        if self.sacrificed:
114            raise TypeError("Potion is now part of something bigger than itself.")
115        
104        updated_intensities = copy.deepcopy(self.intensities)116        updated_intensities = copy.deepcopy(self.intensities)
105        result = []117        result = []
106118
107        for name, intensity in self.intensities.items():119        for name, intensity in self.intensities.items():
108            if (intensity / number) % 1 == 0.5:120            if (intensity / number) % 1 == 0.5:
109                updated_intensities[name] = int(intensity / number)121                updated_intensities[name] = int(intensity / number)
110            else:122            else:
111                updated_intensities[name] = round(intensity / number)123                updated_intensities[name] = round(intensity / number)
112124
113        for times in range(0, number):125        for times in range(0, number):
114            final_effects = copy.deepcopy(self.effects)126            final_effects = copy.deepcopy(self.effects)
115            final_intensities = copy.deepcopy(updated_intensities)127            final_intensities = copy.deepcopy(updated_intensities)
116            result.append(Potion(final_effects, self.duration, final_intensities))128            result.append(Potion(final_effects, self.duration, final_intensities))
117        129        
118        self.sacrificed = True130        self.sacrificed = True
119131
120        return tuple(result)132        return tuple(result)
121    133    
122    def __eq__(self, other):134    def __eq__(self, other):
123        if self.depleted or other.depleted:135        if self.depleted or other.depleted:
124            raise TypeError("Potion is depleted.")136            raise TypeError("Potion is depleted.")
125        137        
nn138        if self.sacrificed or other.sacrificed:
139            raise TypeError("Potion is now part of something bigger than itself.")
140        
126        if set(self.intensities.keys()) != set(other.intensities.keys()):141        if set(self.intensities.keys()) != set(other.intensities.keys()):
127            return False142            return False
128        143        
129        for name, intensity in self.intensities.items():144        for name, intensity in self.intensities.items():
130            if self.intensities[name] != other.intensities[name]:145            if self.intensities[name] != other.intensities[name]:
131                return False146                return False
132        147        
133        return True148        return True
134    149    
135    def __gt__(self, other):150    def __gt__(self, other):
136        if self.depleted or other.depleted:151        if self.depleted or other.depleted:
137            raise TypeError("Potion is depleted.")152            raise TypeError("Potion is depleted.")
tt153        
154        if self.sacrificed or other.sacrificed:
155            raise TypeError("Potion is now part of something bigger than itself.")
138        156        
139        sum_first = 0157        sum_first = 0
140        sum_second = 0158        sum_second = 0
141        for name, intensity in self.intensities.items():159        for name, intensity in self.intensities.items():
142            sum_first += intensity160            sum_first += intensity
143161
144        for name, intensity in other.intensities.items():162        for name, intensity in other.intensities.items():
145            sum_second += intensity163            sum_second += intensity
146        164        
147        return sum_first > sum_second165        return sum_first > sum_second
148    166    
149    # strictly less == not strictly greater167    # strictly less == not strictly greater
150    def __lt__(self, other):168    def __lt__(self, other):
151        return not self.__gt__(other)169        return not self.__gt__(other)
152170
153    @staticmethod171    @staticmethod
154    def effect_fortifier(func, times):172    def effect_fortifier(func, times):
155        def effect_fortified(target):173        def effect_fortified(target):
156            for _ in range(0, times):174            for _ in range(0, times):
157                func(target)175                func(target)
158            return target176            return target
159        return effect_fortified177        return effect_fortified
160178
161179
162    def __getattribute__(self, name):180    def __getattribute__(self, name):
163        # if it is not a method or not an effect no problem181        # if it is not a method or not an effect no problem
164        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):182        if not callable(object.__getattribute__(self, name)) or not object.__getattribute__(self, "effects").get(name):
165            return object.__getattribute__(self, name)183            return object.__getattribute__(self, name)
166        # if potion has been used in something bigger raise the error184        # if potion has been used in something bigger raise the error
167        if object.__getattribute__(self, "sacrificed"):185        if object.__getattribute__(self, "sacrificed"):
168            raise TypeError("Potion is now part of something bigger than itself.")186            raise TypeError("Potion is now part of something bigger than itself.")
169        # if potion has been applied already raise the error187        # if potion has been applied already raise the error
170        if object.__getattribute__(self, "depleted"):188        if object.__getattribute__(self, "depleted"):
171            raise TypeError("Potion is depleted.")189            raise TypeError("Potion is depleted.")
172        # if it hasn't been used before add it to the list of depleted then allow it 190        # if it hasn't been used before add it to the list of depleted then allow it 
173        if name not in object.__getattribute__(self, "depleted_effects"):191        if name not in object.__getattribute__(self, "depleted_effects"):
174            object.__getattribute__(self, "depleted_effects").add(name)192            object.__getattribute__(self, "depleted_effects").add(name)
175            # fortified based on the current intensity193            # fortified based on the current intensity
176            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])194            return Potion.effect_fortifier(object.__getattribute__(self, name), object.__getattribute__(self, "intensities")[name])
177        # otherwise throw the error195        # otherwise throw the error
178        raise TypeError("Effect is depleted.")196        raise TypeError("Effect is depleted.")
179197
180198
181class ГоспожатаПоХимия:199class ГоспожатаПоХимия:
182200
183    def __init__(self):201    def __init__(self):
184        self.active_potions = []202        self.active_potions = []
185        self.affected_targets = []203        self.affected_targets = []
186204
187    @staticmethod205    @staticmethod
188    def molecular_mass(name):206    def molecular_mass(name):
189        mass = 0207        mass = 0
190        for pos in range(0, len(name)):208        for pos in range(0, len(name)):
191            mass += ord(name[pos])209            mass += ord(name[pos])
192        return mass210        return mass
193211
194    def apply(self, target, potion):212    def apply(self, target, potion):
195        # check if the potion is depleted first or has been sac-ed213        # check if the potion is depleted first or has been sac-ed
196        if set(potion.effects.keys()) == potion.depleted_effects:214        if set(potion.effects.keys()) == potion.depleted_effects:
197            raise TypeError("Potion is depleted.")215            raise TypeError("Potion is depleted.")
198        216        
199        if potion.sacrificed:217        if potion.sacrificed:
200            raise TypeError("Potion is now part of something bigger than itself.")218            raise TypeError("Potion is now part of something bigger than itself.")
201        219        
202        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)220        remaining_effects = list(set(potion.effects.keys()) - potion.depleted_effects)
203221
204        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)222        remaining_effects.sort(key=ГоспожатаПоХимия.molecular_mass, reverse=True)
205223
206        #check if target has been affected already224        #check if target has been affected already
207225
208        seen = False226        seen = False
209227
210        for target_id, original_data in self.affected_targets:228        for target_id, original_data in self.affected_targets:
211            if id(target) ==  target_id:229            if id(target) ==  target_id:
212                seen = True230                seen = True
213        # save the original data otherwise231        # save the original data otherwise
214        if not seen:232        if not seen:
215            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))233            self.affected_targets.append((id(target), copy.deepcopy(target.__dict__)))
216234
217        self.active_potions.append((copy.deepcopy(potion), target))235        self.active_potions.append((copy.deepcopy(potion), target))
218236
219        for effect in remaining_effects:237        for effect in remaining_effects:
220            #apply the effect to the target238            #apply the effect to the target
221            potion.effects[effect](target)239            potion.effects[effect](target)
222240
223        # deem the potion depleted after the process241        # deem the potion depleted after the process
224        potion.depleted = True242        potion.depleted = True
225243
226    def tick(self):244    def tick(self):
227        for potion, target in self.active_potions:245        for potion, target in self.active_potions:
228            potion.duration -= 1246            potion.duration -= 1
229            if potion.duration == 0:247            if potion.duration == 0:
230                # Find the original information and normalize the target248                # Find the original information and normalize the target
231                for target_id, original_data in self.affected_targets:249                for target_id, original_data in self.affected_targets:
232                    if id(target) == target_id:250                    if id(target) == target_id:
233                        target.__dict__ = copy.deepcopy(original_data)251                        target.__dict__ = copy.deepcopy(original_data)
234252
235                # Reapply effects for remaining active potions253                # Reapply effects for remaining active potions
236                for potion_2,target_2 in self.active_potions:254                for potion_2,target_2 in self.active_potions:
237                    if potion_2.duration != 0 and target == target_2:255                    if potion_2.duration != 0 and target == target_2:
238                        for effect in potion_2.effects:256                        for effect in potion_2.effects:
239                            method=getattr(potion_2,effect)257                            method=getattr(potion_2,effect)
240                            method(target)258                            method(target)
241259
242        # Remove the timed-out potion-target pairs from the list of active ones260        # Remove the timed-out potion-target pairs from the list of active ones
243        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]261        self.active_potions = [(potion, target) for potion, target in self.active_potions if potion.duration != 0]
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op