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

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

2 точки общо

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

  1class Potion:
  2
  3    def __init__(self, effects, duration):
  4        self.effects = effects
  5        self.duration = duration
  6        self.is_part_of_something_bigger = False
  7        self.effects_intensity = {}
  8
  9        self.set_effects_as_attr()
 10        self.set_effects_intensities()
 11
 12    def set_effects_as_attr(self):
 13        for effect_key in self.effects:
 14            setattr(self, effect_key, self.effects[effect_key])
 15
 16    def set_effects_intensities(self):
 17        for effect_key in self.effects:
 18            self.effects_intensity[effect_key] = 1
 19
 20    def disable_effect(self, effect_key):
 21        self.effects_intensity[effect_key] = -2
 22
 23    def lower_intensity(self, effect_key):
 24        if self.effects_intensity[effect_key] == 0 or self.effects_intensity[effect_key] == 1:
 25            self.disable_effect(effect_key)
 26        else:
 27            self.effects_intensity[effect_key] -= 1
 28
 29    def filter_repeating_effects(self, other_potion):
 30        effects_left = {}
 31        for effect_name in self.effects:
 32            if effect_name not in other_potion.effects:
 33                effects_left[effect_name] = self.effects[effect_name]
 34        return effects_left
 35
 36    def call_methods(self, effect_func, effect):
 37        def wrapper(target):
 38            for n in range(self.effects_intensity[effect]):
 39                effect_func(target)
 40        return wrapper
 41
 42    def __getattr__(self, item):
 43        if item in self.effects:
 44            if self.effects_intensity[item] < -1:
 45                raise TypeError("Effect is depleted.")
 46            return self.call_methods(self.effects[item], item)
 47        raise AttributeError("Attribute not found")
 48
 49    def __getattribute__(self, item):
 50        if item in object.__getattribute__(self, "effects") and object.__getattribute__(self, "is_part_of_something_bigger"):
 51            raise TypeError("Potion is now part of something bigger than itself.")
 52        else:
 53            return object.__getattribute__(self, item)
 54
 55    def __add__(self, other):
 56        self.is_part_of_something_bigger = True
 57        combined_effects = self.effects | other.effects
 58        new_duration = self.duration if self.duration > other.duration else other.duration
 59        combined_potion = Potion(combined_effects, new_duration)
 60        for effect_key in self.effects:
 61            if effect_key in other.effects:
 62                if self.effects_intensity[effect_key] > 0 and other.effects_intensity[effect_key] > 0:
 63                    combined_potion.effects_intensity[effect_key] = self.effects_intensity[effect_key] + other.effects_intensity[effect_key]
 64                elif not self.effects_intensity[effect_key] and not other.effects_intensity[effect_key]:
 65                    combined_potion.disable_effect(effect_key)
 66        return combined_potion
 67
 68    def __sub__(self, other):
 69        self.is_part_of_something_bigger = True
 70        filtered_effects = self.filter_repeating_effects(other)
 71        for effect in self.other.effects:
 72            if effect not in self.effects:
 73                raise TypeError("Removing potion effects which you do not have is illegal !!!")
 74            elif self.effects_intensity[effect] > other.effects_intensity[effect]:
 75                filtered_effects[effect] = self.effects[effect]
 76
 77        purified_potion = Potion(filtered_effects, self.duration)
 78        for effect in purified_potion.effects:
 79            if self.effects_intensity[effect] > other.effects_intensity[effect]:
 80                left_intensity = self.effects_intensity[effect] - other.effects_intensity[effect]
 81                purified_potion.effects_intensity[effect] = left_intensity
 82            else:
 83                purified_potion.effects_intensity[effect] = self.effects_intensity[effect]
 84        return purified_potion
 85
 86    def __mul__(self, multi):
 87        self.is_part_of_something_bigger = True
 88        new_effects_intensity = [round(self.effects_intensity[effect_key] * multi) for effect_key in self.effects]
 89        new_potion = Potion(self.effects, self.duration)
 90        new_potion.effects_intensity = new_effects_intensity
 91        return new_potion
 92
 93    def __truediv__(self, div):
 94        self.is_part_of_something_bigger = True
 95        new_potions = ()
 96        for n in range(div):
 97            diluted_potion = Potion(self.effects, self.duration)
 98            diluted_potion.effects_intensity = [round(self.effects_intensity[effect_key] / div) for effect_key in self.effects]
 99            new_potions.append(diluted_potion)
100        return new_potions
101
102    def __eq__(self, other):
103        return self.effects == other.effects and self.effects_intensity == other.effects_intensity
104
105    def __gt__(self, other):
106        return sum(self.effects_intensity.values()) > sum(other.effects_intensity.values())
107
108    def __lt__(self, other):
109        return sum(self.effects_intensity.values()) < sum(other.effects_intensity.values())
110
111
112class ГоспожатаПоХимия:
113
114    used_potions = []
115    attacked_targets = []
116
117    def __init__(self):
118        self.magic_pairs = []
119        self.target = None
120        self.unpoisoned_target_data = None
121        self.current_poison_duration = None
122
123    def apply(self, target, potion):
124        self.target = target
125        if self.is_usable(potion):
126            if not self.unpoisoned_target_data and target not in self.attacked_targets:
127                self.unpoisoned_target_data = vars(target)
128                self.attacked_targets.append(target)
129
130            self.current_poison_duration = potion.duration
131            self.sort_potion_effects(potion)
132            for effect, _ in self.magic_pairs:
133                if potion.effects_intensity[effect] >= 0:
134                    potion.__getattr__(effect)(target)
135            self.used_potions.append(potion)
136
137    def is_usable(self, potion):
138        if potion not in self.used_potions and not potion.is_part_of_something_bigger:
139            return True
140        raise TypeError("Potion is depleted.")
141
142    def sort_potion_effects(self, potion):
143        for effect in potion.effects:
144            self.magic_pairs.append((effect, self.calculate_molecular_mass(effect)))
145        return self.magic_pairs.sort()
146
147    @staticmethod
148    def calculate_molecular_mass(effect):
149        return sum(ord(c) for c in effect)
150
151    def purify_target(self):
152        possibly_poisoned_target_data = vars(self.target)
153        for attr in self.unpoisoned_target_data:
154            if possibly_poisoned_target_data[attr] != self.unpoisoned_target_data[attr]:
155                possibly_poisoned_target_data[attr] = self.unpoisoned_target_data[attr]
156
157    def tick(self):
158        pass
159
160    def __getattribute__(self, item):
161        if item == "tick":
162            self.current_poison_duration -= 1
163            if self.current_poison_duration <= 0:
164                return object.__getattribute__(self, 'purify_target')
165        return object.__getattribute__(self, item)

.F.FE.FFFFEEFEEEFEEE
======================================================================
ERROR: test_superbness (test.TestPotionComparison)
Test superbness of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 317, in test_superbness
self.assertLess(potion1, potion2)
File "/usr/lib/python3.10/unittest/case.py", line 1230, in assertLess
if not a < b:
File "/tmp/solution.py", line 110, in __lt__
return sum(self.effects_intensity.values()) < sum(other.effects_intensity.values())
AttributeError: 'list' object has no attribute 'values'

======================================================================
ERROR: test_purification (test.TestPotionOperations)
Test purification of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 165, in test_purification
potion = potion1 - potion2
File "/tmp/solution.py", line 72, in __sub__
for effect in self.other.effects:
File "/tmp/solution.py", line 48, in __getattr__
raise AttributeError("Attribute not found")
AttributeError: Attribute not found

======================================================================
ERROR: test_separation (test.TestPotionOperations)
Test separation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 213, in test_separation
potion1, potion2, potion3 = potion / 3
File "/tmp/solution.py", line 99, in __truediv__
diluted_potion.effects_intensity = [round(self.effects_intensity[effect_key] / div) for effect_key in self.effects]
File "/tmp/solution.py", line 99, in <listcomp>
diluted_potion.effects_intensity = [round(self.effects_intensity[effect_key] / div) for effect_key in self.effects]
TypeError: list indices must be integers or slices, not str

======================================================================
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 126, in apply
if self.is_usable(potion):
File "/tmp/solution.py", line 141, in is_usable
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.

======================================================================
ERROR: test_applying_order (test.TestГоспожатаПоХимия)
Test applying order of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 416, in test_applying_order
self._dimitrichka.apply(self._target, potion)
File "/tmp/solution.py", line 134, in apply
if potion.effects_intensity[effect] >= 0:
KeyError: 'aa_name'

======================================================================
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 126, in apply
if self.is_usable(potion):
File "/tmp/solution.py", line 141, in is_usable
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.

======================================================================
ERROR: test_ticking_multiple_potions (test.TestГоспожатаПоХимия)
Test ticking after applying multiple potions which affect the same attribute.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 455, in test_ticking_multiple_potions
self._dimitrichka.apply(self._target, potion2)
File "/tmp/solution.py", line 126, in apply
if self.is_usable(potion):
File "/tmp/solution.py", line 141, in is_usable
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.

======================================================================
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 134, in apply
if potion.effects_intensity[effect] >= 0:
TypeError: list indices must be integers or slices, not str

======================================================================
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 126, in apply
if self.is_usable(potion):
File "/tmp/solution.py", line 141, in is_usable
raise TypeError("Potion is depleted.")
TypeError: Potion is depleted.

======================================================================
FAIL: test_depletion (test.TestBasicPotion)
Test depletion of a potion effect.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 78, in test_depletion
with self.assertRaisesRegex(TypeError, 'Effect is depleted\.'):
AssertionError: TypeError not raised

======================================================================
FAIL: test_equal (test.TestPotionComparison)
Test equality of potions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 298, in test_equal
self.assertEqual(potion4, potion3)
AssertionError: <solution.Potion object at 0x7fa7545cb7f0> != <solution.Potion object at 0x7fa7545ca920>

======================================================================
FAIL: test_combination_with_overlap (test.TestPotionOperations)
Test combining potions with overlap.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 105, in test_combination_with_overlap
self.assertEqual(self._target.int_attr, 500)
AssertionError: 50 != 500

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

======================================================================
FAIL: test_dilution (test.TestPotionOperations)
Test dilution of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 120, in test_dilution
self.assertEqual(self._target.int_attr, 5)
AssertionError: 50 != 5

======================================================================
FAIL: test_potentiation (test.TestPotionOperations)
Test potentiation of a potion.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 112, in test_potentiation
self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
AssertionError: 50 != 5000

======================================================================
FAIL: test_applying_depleted_potion (test.TestГоспожатаПоХимия)
Test applying a depleted potion or a potion that was used in a reaction.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 382, in test_applying_depleted_potion
with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
AssertionError: TypeError not raised

======================================================================
FAIL: test_ticking_immutable (test.TestГоспожатаПоХимия)
Test ticking after applying a potion with immutable attributes.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 429, in test_ticking_immutable
self.assertEqual(self._target.int_attr, 5)
AssertionError: 500 != 5

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

FAILED (failures=8, errors=9)

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