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

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

6 точки общо

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

  1import copy
  2import math
  3import ctypes
  4from typing import Any
  5
  6class Effect:
  7
  8     def __init__(self,name,func):
  9        self.func=func
 10        self.name=name
 11
 12        self.intensity=1
 13        self.has_been_used= False
 14        self.is_part_of_bigger= False
 15        self.has_teacher_used= False
 16        self.molecular_mass=0
 17
 18
 19        for ch in self.name:
 20            self.molecular_mass+=ord(ch)
 21
 22     def __copy__(self):
 23         new_effect=Effect(self.name,self.func)
 24         new_effect.intensity=self.intensity
 25         new_effect.has_been_used=self.has_been_used
 26         return new_effect
 27
 28     def __call__(self,target):
 29        if self.has_been_used:
 30            raise TypeError("Effect is depleted.")
 31        if self.has_teacher_used:
 32            raise TypeError("Potion is depleted.")
 33        if self.is_part_of_bigger:
 34            raise TypeError("Potion is now part of something bigger than itself.")
 35        
 36        for i in range(self.intensity):
 37            self.func(target)
 38        
 39        self.has_been_used= True
 40
 41
 42class Potion:
 43
 44    def __init__(self, effects, duration):
 45        
 46        self.is_part= False
 47        self.has_teacher_used= False
 48        self.effects={}
 49        self.duration= duration
 50        for effect,func in effects.items():
 51            new_effect=Effect(effect,func)
 52            setattr(self,effect,new_effect)
 53            self.effects[effect]=new_effect
 54
 55
 56    def add_effect(self, name, new_effect):
 57        setattr(self,name,new_effect)
 58        self.effects[name]=new_effect
 59
 60    def __add__(self,other):
 61        if self.is_part or other.is_part:
 62            raise TypeError("Potion is now part of something bigger than itself.")
 63        if self.has_teacher_used or other.has_teacher_used:
 64            raise TypeError("Potion is depleted.")
 65        
 66        new_duration= max(self.duration, other.duration)
 67        new_potion=Potion({}, new_duration)
 68
 69        for name,effect in self.effects.items():
 70            new_potion.add_effect(name,copy.copy(effect))
 71            effect.is_part_of_bigger=True
 72
 73        for name,effect in other.effects.items():
 74            if name in new_potion.effects:
 75                new_potion.effects[name].intensity+=effect.intensity
 76            else:
 77                new_potion.add_effect(name,copy.copy(effect))
 78            effect.is_part_of_bigger=True
 79
 80        self.is_part= True
 81        other.is_part= True
 82        return new_potion
 83    
 84
 85    def __mul__(self,number):
 86        if self.is_part:
 87            raise TypeError("Potion is now part of something bigger than itself.")
 88        if self.has_teacher_used:
 89            raise TypeError("Potion is depleted.")
 90
 91        new_potion= self+Potion({},0)
 92        for name,effect in new_potion.effects.items():
 93            effect.intensity*=number
 94            if effect.intensity-math.floor(effect.intensity)<=0.5:
 95                effect.intensity=math.floor(effect.intensity)
 96            else:
 97                effect.intensity=math.ceil(effect.intensity)
 98
 99        self.is_part= True
100        return new_potion
101    
102
103    def __sub__(self,other):
104        if self.is_part or other.is_part:
105            raise TypeError("Potion is now part of something bigger than itself.")
106        if self.has_teacher_used or other.has_teacher_used:
107            raise TypeError("Potion is depleted.")
108
109        for name,effect in other.effects.items():
110            if  effect.has_been_used:
111                continue
112            if (name not in self.effects)or(self.effects[name].has_been_used):
113                raise TypeError(f"Invalid effect: {name}")
114            effect.is_part_of_bigger=True
115  
116        new_potion=Potion({},self.duration)
117
118        for name, effect in self.effects.items():
119            current_effect= copy.copy(effect)
120            if name in other.effects:
121                if effect.intensity-other.effects[name].intensity<=0:
122                    continue
123                if not other.effects[name].has_been_used:
124                    current_effect.intensity-=other.effects[name].intensity
125            new_potion.add_effect(name,current_effect) 
126            effect.is_part_of_bigger=True
127        
128        self.is_part= True
129        other.is_part= True
130        return new_potion
131    
132
133    def __truediv__(self,number):
134        if self.is_part:
135            raise TypeError("Potion is now part of something bigger than itself.")
136        if self.has_teacher_used:
137            raise TypeError("Potion is depleted.")
138        
139        result= []
140        for i in range(number):
141            result.append(self*(1/number))
142            self.is_part=False
143        self.is_part=True
144        return tuple(result)
145    
146
147    def __eq__(self,other):
148        if self.is_part or other.is_part:
149            raise TypeError("Potion is now part of something bigger than itself.")
150        if self.has_teacher_used or other.has_teacher_used:
151            raise TypeError("Potion is depleted.")
152
153        if set(self.effects.keys()) != set(other.effects.keys()):
154            return False
155        
156        for name,effect in self.effects.items():
157            if effect.has_been_used != other.effects[name].has_been_used:
158                return False
159            if effect.intensity != other.effects[name].intensity:
160                return False
161        return True
162    
163    
164    def get_effects_sum(self):
165        result=0
166
167        for name, effect in self.effects.items():
168            if not effect.has_been_used:
169                result += effect.intensity
170        return result
171    
172
173    def __lt__(self,other):
174        if self.is_part or other.is_part:
175            raise TypeError("Potion is now part of something bigger than itself.")
176        if self.has_teacher_used or other.has_teacher_used:
177            raise TypeError("Potion is depleted.")
178        
179        return self.get_effects_sum()< other.get_effects_sum()
180    
181
182    def __gt__(self,other):
183        return other < self
184
185
186class ГоспожатаПоХимия:
187
188    def __init__(self):
189        #self.values_container= {}
190        self.ticks_counter=0
191    
192    def apply(self,target, potion):
193        if potion.is_part:
194            raise TypeError("Potion is now part of something bigger than itself.")
195        if potion.has_teacher_used:
196            raise TypeError("Potion is depleted.")
197        if potion.duration == 0:
198            return 
199        
200        potion.has_teacher_used= True
201
202        result= list(potion.effects.values())
203        sorted_result= sorted_effects = sorted(result, key=lambda effect: effect.molecular_mass, reverse=True)
204
205        target_id= id(target)
206
207        # if target_id not in self.values_container:
208        #     self.values_container[target_id] = [copy.deepcopy(target),[copy.deepcopy(potion)], target]
209        # else:
210        #     self.values_container[target_id][1].append(copy.deepcopy(potion))
211
212        for effect in sorted_result:
213            if not effect.has_been_used:
214                effect.func(target)
215                effect.has_been_used= True
216                effect.has_teacher_used= True
217        self.values_container[target_id].pop()
218        self.values_container[target_id].append(target)
219
220    
221    def tick(self):
222        pass
223        # self.ticks_counter+=1
224
225        # for current_id,values in self.values_container.items():
226        #     values[2]=values[0]
227        #     for potion in values[1]:
228        #         if potion.duration<=self.ticks_counter:
229        #             values[1].remove(potion)
230        #     for potion in values[1]:
231        #         result= list(potion.effects.values())
232        #         sorted_result= sorted_effects = sorted(result, key=lambda effect: effect.molecular_mass, reverse=True)
233        #         for effect in sorted_result:
234        #             if not effect.has_been_used:
235        #                 effect.func(values[2])
236
237 

.......F....EEEEEEEE
======================================================================
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)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
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)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
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)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
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 365, in test_applying_part_of_potion
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
ERROR: test_ticking_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 424, in test_ticking_immutable
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
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)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
ERROR: test_ticking_multiple_targets (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with mutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 485, in test_ticking_multiple_targets
self._dimitrichka.apply(target1, potion1)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
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)
File "/tmp/solution.py", line 217, in apply
self.values_container[target_id].pop()
AttributeError: 'ГоспожатаПоХимия' object has no attribute 'values_container'

======================================================================
FAIL: test_deprecation (test.TestPotionOperations)
Test deprecation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 270, in test_deprecation
with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
AssertionError: TypeError not raised

----------------------------------------------------------------------
Ran 20 tests in 0.002s

FAILED (failures=1, errors=8)

Дискусия
История
Това решение има само една версия.