1import unittest
2
3from solution import *
4
5
6class SanityTest(unittest.TestCase):
7 """Sanity tests for Alchemy Workshop."""
8
9 def test_potion(self):
10 """Test Potion class."""
11 self.assertIsInstance(Potion({'do_nothing': lambda target: None}, duration=2), Potion)
12
13 def test_госпожата_по_химия(self):
14 """Test ГоспожатаПоХимия class."""
15 self.assertIsInstance(ГоспожатаПоХимия(), ГоспожатаПоХимия)
16
17
18if __name__ == '__main__':
19 unittest.main()
1import copy
2import unittest
3
4from solution import *
5
6
7class Target:
8 """Test target."""
9
10 def __init__(self, **kwargs):
11 """Initializator."""
12 self._cache = kwargs
13 for key, val in kwargs.items():
14 setattr(self, key, val)
15
16 def _refresh(self):
17 """Refresh all values to their initial state."""
18 for key, val in self._cache.items():
19 setattr(self, key, val)
20
21
22def int_attr_fun(target):
23 """Test function for altering int attribute."""
24 target.int_attr *= 10
25
26
27def float_attr_fun(target):
28 """Test function for altering float attribute."""
29 target.float_attr += 1
30
31
32def list_attr_fun(target):
33 """Test function for altering list attribute."""
34 target.list_attr.append(4)
35
36
37def dict_attr_fun(target):
38 """Test function for altering dict attribute."""
39 target.dict_attr = {val:key for key, val in target.dict_attr.items()}
40
41
42class TestBasicPotion(unittest.TestCase):
43 """Test Potion class for basic functionality."""
44
45 def setUp(self):
46 """Set up a test target."""
47 self._target = Target(int_attr=5, float_attr=3.14,
48 list_attr=[1, 2, 3],
49 dict_attr={'name': 'Борис', 'професия': 'жалбар'})
50
51 def test_empty(self):
52 """Test initialization with empty effects."""
53 potion = Potion({}, duration=0)
54 self.assertIsInstance(potion, Potion)
55
56 def test_applying(self):
57 """Test applying a potion to a target."""
58 potion = Potion({'int_attr_fun': int_attr_fun,
59 'float_attr_fun': float_attr_fun,
60 'list_attr_fun': list_attr_fun,
61 'dict_attr_fun': dict_attr_fun},
62 duration=1)
63 potion.int_attr_fun(self._target)
64 self.assertEqual(self._target.int_attr, 50)
65 potion.float_attr_fun(self._target)
66 self.assertAlmostEqual(self._target.float_attr, 4.14)
67 potion.list_attr_fun(self._target)
68 self.assertEqual(self._target.list_attr, [1, 2, 3, 4])
69 potion.dict_attr_fun(self._target)
70 self.assertEqual(self._target.dict_attr, {'Борис': 'name', 'жалбар': 'професия'})
71
72 def test_depletion(self):
73 """Test depletion of a potion effect."""
74 potion = Potion({'int_attr_fun': int_attr_fun},
75 duration=2)
76 potion.int_attr_fun(self._target)
77 self.assertEqual(self._target.int_attr, 50)
78 with self.assertRaisesRegex(TypeError, 'Effect is depleted\.'):
79 potion.int_attr_fun(self._target)
80
81
82class TestPotionOperations(unittest.TestCase):
83 """Test operations for Potion class."""
84
85 def setUp(self):
86 """Set up a test target."""
87 self._target = Target(int_attr=5, float_attr=3.14)
88
89 def test_combination_no_overlap(self):
90 """Test combining potions with no overlap."""
91 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
92 potion2 = Potion({'float_attr_fun': float_attr_fun}, duration=2)
93 potion = potion1 + potion2
94 potion.int_attr_fun(self._target)
95 potion.float_attr_fun(self._target)
96 self.assertEqual(self._target.int_attr, 50)
97 self.assertAlmostEqual(self._target.float_attr, 4.14)
98
99 def test_combination_with_overlap(self):
100 """Test combining potions with overlap."""
101 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
102 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=2)
103 potion = potion1 + potion2
104 potion.int_attr_fun(self._target)
105 self.assertEqual(self._target.int_attr, 500)
106
107 def test_potentiation(self):
108 """Test potentiation of a potion."""
109 potion = Potion({'int_attr_fun': int_attr_fun}, duration=1)
110 potion = potion * 3
111 potion.int_attr_fun(self._target)
112 self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
113
114 def test_dilution(self):
115 """Test dilution of a potion."""
116 # Test at half
117 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1)
118 half_potion = base_potion * 0.5
119 half_potion.int_attr_fun(self._target)
120 self.assertEqual(self._target.int_attr, 5)
121 # Test above half
122 self._target = copy.deepcopy(self._target)
123 self._target._refresh()
124 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1)
125 half_potion = base_potion * 0.51
126 half_potion.int_attr_fun(self._target)
127 self.assertEqual(self._target.int_attr, 50)
128 # Test below half
129 self._target = copy.deepcopy(self._target)
130 self._target._refresh()
131 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1)
132 half_potion = base_potion * 0.49
133 half_potion.int_attr_fun(self._target)
134 self.assertEqual(self._target.int_attr, 5)
135 # Test around zero
136 self._target = copy.deepcopy(self._target)
137 self._target._refresh()
138 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1)
139 half_potion = base_potion * 0.0001
140 half_potion.int_attr_fun(self._target)
141 self.assertEqual(self._target.int_attr, 5)
142 # Test actual division
143 self._target = copy.deepcopy(self._target)
144 self._target._refresh()
145 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
146 half_potion = base_potion * 0.5
147 half_potion.int_attr_fun(self._target)
148 self.assertEqual(self._target.int_attr, 50)
149 # Test rounding to odd number (built-in round() always goes to an even number)
150 self._target = copy.deepcopy(self._target)
151 self._target._refresh()
152 base_potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
153 half_potion = base_potion * 0.5
154 half_potion.int_attr_fun(self._target)
155 self.assertEqual(self._target.int_attr, 50)
156
157 def test_purification(self):
158 """Test purification of a potion."""
159 # Test normal behaviour
160 potion1 = Potion({'int_attr_fun': int_attr_fun,
161 'float_attr_fun': float_attr_fun},
162 duration=1)
163 potion2 = Potion({'int_attr_fun': int_attr_fun},
164 duration=1)
165 potion = potion1 - potion2
166 potion.float_attr_fun(self._target)
167 self.assertAlmostEqual(self._target.float_attr, 4.14)
168 with self.assertRaises(AttributeError):
169 potion.int_attr_fun(self._target)
170 # Test mismatching effects
171 self._target = copy.deepcopy(self._target)
172 self._target._refresh()
173 potion1 = Potion({'int_attr_fun': int_attr_fun,
174 'float_attr_fun': float_attr_fun},
175 duration=1)
176 potion2 = Potion({'int_attr_fun': int_attr_fun},
177 duration=1)
178 with self.assertRaises(TypeError):
179 potion2 - potion1
180 # Test with intensity
181 self._target = copy.deepcopy(self._target)
182 self._target._refresh()
183 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
184 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
185 potion_decorator = Potion({'float_attr_fun': float_attr_fun}, duration=1)
186 potion1 = potion1 + potion_decorator
187 potion = potion1 - potion2
188 potion.float_attr_fun(self._target)
189 self.assertAlmostEqual(self._target.float_attr, 4.14)
190 potion.int_attr_fun(self._target)
191 self.assertEqual(self._target.int_attr, 50)
192 # Test with intensity resulting in zero
193 self._target = copy.deepcopy(self._target)
194 self._target._refresh()
195 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
196 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
197 potion = potion1 - potion2
198 with self.assertRaises(AttributeError):
199 potion.int_attr_fun(self._target)
200 # Test with higher intensity on the right
201 self._target = copy.deepcopy(self._target)
202 self._target._refresh()
203 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
204 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
205 potion = potion1 - potion2
206 with self.assertRaises(AttributeError):
207 potion.int_attr_fun(self._target)
208
209 def test_separation(self):
210 """Test separation of a potion."""
211 # Test normal case
212 potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 9
213 potion1, potion2, potion3 = potion / 3
214 potion1.int_attr_fun(self._target)
215 self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
216 self._target = copy.deepcopy(self._target)
217 self._target._refresh()
218 potion2.int_attr_fun(self._target)
219 self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
220 self._target = copy.deepcopy(self._target)
221 self._target._refresh()
222 potion3.int_attr_fun(self._target)
223 self.assertEqual(self._target.int_attr, 5 * (10 ** 3))
224 # Test resulting in one
225 self._target = copy.deepcopy(self._target)
226 self._target._refresh()
227 potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
228 potion1, potion2, potion3 = potion / 3
229 potion1.int_attr_fun(self._target)
230 self.assertEqual(self._target.int_attr, 50)
231 self._target = copy.deepcopy(self._target)
232 self._target._refresh()
233 potion2.int_attr_fun(self._target)
234 self.assertEqual(self._target.int_attr, 50)
235 self._target = copy.deepcopy(self._target)
236 self._target._refresh()
237 potion3.int_attr_fun(self._target)
238 self.assertEqual(self._target.int_attr, 50)
239 # Test rounding to odd
240 self._target = copy.deepcopy(self._target)
241 self._target._refresh()
242 potion = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
243 potion1, potion2 = potion / 2
244 potion1.int_attr_fun(self._target)
245 self.assertEqual(self._target.int_attr, 50)
246 self._target = copy.deepcopy(self._target)
247 self._target._refresh()
248 potion2.int_attr_fun(self._target)
249 self.assertEqual(self._target.int_attr, 50)
250
251 def test_deprecation(self):
252 """Test deprecation of a potion."""
253 # Addition
254 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
255 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
256 potion = potion1 + potion2
257 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
258 potion1.int_attr_fun(self._target)
259 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
260 potion2.int_attr_fun(self._target)
261 # Multiplication
262 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
263 potion = potion1 * 2
264 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
265 potion1.int_attr_fun(self._target)
266 # Subtraction
267 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
268 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
269 potion = potion1 - potion2
270 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
271 potion1.int_attr_fun(self._target)
272 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
273 potion2.int_attr_fun(self._target)
274 # Division
275 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
276 potion = potion1 / 1
277 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
278 potion1.int_attr_fun(self._target)
279
280
281class TestPotionComparison(unittest.TestCase):
282 """Test comparisons for Potion class."""
283
284 def test_equal(self):
285 """Test equality of potions."""
286 # Normal case
287 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
288 potion2 = Potion({'float_attr_fun': float_attr_fun}, duration=1)
289 potion3 = Potion({'int_attr_fun': int_attr_fun,
290 'float_attr_fun': float_attr_fun},
291 duration=1)
292 self.assertEqual(potion1 + potion2, potion3)
293 # With intensity
294 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
295 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
296 potion3 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
297 potion4 = potion1 + potion2
298 self.assertEqual(potion4, potion3)
299 # Not equal due to different methods
300 potion1 = Potion({'float_attr_fun': float_attr_fun}, duration=1)
301 potion2 = Potion({'int_attr_fun': int_attr_fun,
302 'float_attr_fun': float_attr_fun},
303 duration=1)
304 self.assertNotEqual(potion1, potion2)
305 # Not equal due to different intensity
306 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
307 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
308 potion3 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 3
309 potion4 = potion1 + potion2
310 self.assertNotEqual(potion4, potion3)
311
312 def test_superbness(self):
313 """Test superbness of potions."""
314 # Normal case
315 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
316 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
317 self.assertLess(potion1, potion2)
318 self.assertGreater(potion2, potion1)
319 self.assertNotEqual(potion1, potion2)
320 # Diffetent intensity for different methods
321 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
322 potion2 = Potion({'float_attr_fun': float_attr_fun}, duration=1) * 3
323 self.assertLess(potion1, potion2)
324 self.assertGreater(potion2, potion1)
325 self.assertNotEqual(potion1, potion2)
326 # Equal intensity for different methods
327 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
328 potion2 = Potion({'float_attr_fun': float_attr_fun}, duration=1) * 2
329 self.assertFalse(potion1 > potion2)
330 self.assertFalse(potion1 < potion2)
331
332
333class TestГоспожатаПоХимия(unittest.TestCase):
334 """Test ГоспожатаПоХимия."""
335
336 def setUp(self):
337 """Set up a test target."""
338 self._target = Target(int_attr=5, float_attr=3.14,
339 list_attr=[1, 2, 3],
340 dict_attr={'name': 'Борис', 'професия': 'жалбар'})
341 self._dimitrichka = ГоспожатаПоХимия()
342
343 def test_applying_normal_case(self):
344 """Test applying a normal potion."""
345 potion = Potion({'int_attr_fun': int_attr_fun,
346 'float_attr_fun': float_attr_fun,
347 'list_attr_fun': list_attr_fun,
348 'dict_attr_fun': dict_attr_fun},
349 duration=1)
350 self._dimitrichka.apply(self._target, potion)
351 self.assertEqual(self._target.int_attr, 50)
352 self.assertAlmostEqual(self._target.float_attr, 4.14)
353 self.assertEqual(self._target.list_attr, [1, 2, 3, 4])
354 self.assertEqual(self._target.dict_attr, {'Борис': 'name', 'жалбар': 'професия'})
355
356 def test_applying_part_of_potion(self):
357 """Test applying only a part of a potion."""
358 potion = Potion({'int_attr_fun': int_attr_fun,
359 'float_attr_fun': float_attr_fun,
360 'list_attr_fun': list_attr_fun,
361 'dict_attr_fun': dict_attr_fun},
362 duration=1)
363 temp_target = Target(int_attr=5)
364 potion.int_attr_fun(temp_target)
365 self._dimitrichka.apply(self._target, potion)
366 self.assertEqual(self._target.int_attr, 5) # This should be the original value
367 self.assertAlmostEqual(self._target.float_attr, 4.14)
368 self.assertEqual(self._target.list_attr, [1, 2, 3, 4])
369 self.assertEqual(self._target.dict_attr, {'Борис': 'name', 'жалбар': 'професия'})
370
371 def test_applying_depleted_potion(self):
372 """Test applying a depleted potion or a potion that was used in a reaction."""
373 # Apply a depleted potion
374 potion = Potion({'int_attr_fun': int_attr_fun,
375 'float_attr_fun': float_attr_fun,
376 'list_attr_fun': list_attr_fun,
377 'dict_attr_fun': dict_attr_fun},
378 duration=1)
379 self._dimitrichka.apply(self._target, potion)
380 with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
381 self._dimitrichka.apply(self._target, potion)
382 with self.assertRaisesRegex(TypeError, 'Potion is depleted\.'):
383 potion = potion * 2
384 # Apply a potion that was used in a reaction
385 potion = Potion({'int_attr_fun': int_attr_fun,
386 'float_attr_fun': float_attr_fun,
387 'list_attr_fun': list_attr_fun,
388 'dict_attr_fun': dict_attr_fun},
389 duration=1)
390 _ = potion * 2
391 with self.assertRaisesRegex(TypeError, 'Potion is now part of something bigger than itself\.'):
392 self._dimitrichka.apply(self._target, potion)
393
394 def test_applying_order(self):
395 """Test applying order of a potion."""
396 # aa_name should have precedence
397 def z_name(target):
398 target.int_attr += 2
399 def aa_name(target):
400 target.int_attr *= 2
401 potion = Potion({'z_name': z_name,
402 'aa_name': aa_name},
403 duration=1)
404 self._dimitrichka.apply(self._target, potion)
405 self.assertEqual(self._target.int_attr, 12)
406 # z_name should have precedence
407 self._target = copy.deepcopy(self._target)
408 self._target._refresh()
409 def z_name(target):
410 target.int_attr += 2
411 def a_name(target):
412 target.int_attr *= 2
413 potion = Potion({'z_name': z_name,
414 'a_name': a_name},
415 duration=1)
416 self._dimitrichka.apply(self._target, potion)
417 self.assertEqual(self._target.int_attr, 14)
418
419 def test_ticking_immutable(self):
420 """Test ticking after applying a potion with immutable attributes."""
421 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
422 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=2)
423 potion = potion1 + potion2 # Excepted duration is 2 with intensity of 2
424 self._dimitrichka.apply(self._target, potion)
425 self.assertEqual(self._target.int_attr, 500)
426 self._dimitrichka.tick()
427 self.assertEqual(self._target.int_attr, 500)
428 self._dimitrichka.tick()
429 self.assertEqual(self._target.int_attr, 5)
430
431 def test_ticking_mutable(self):
432 """Test ticking after applying a potion with mutable attributes."""
433 potion = Potion({'int_attr_fun': int_attr_fun,
434 'float_attr_fun': float_attr_fun,
435 'list_attr_fun': list_attr_fun,
436 'dict_attr_fun': dict_attr_fun},
437 duration=1)
438 self._dimitrichka.apply(self._target, potion)
439 self.assertEqual(self._target.int_attr, 50)
440 self.assertAlmostEqual(self._target.float_attr, 4.14)
441 self.assertEqual(self._target.list_attr, [1, 2, 3, 4])
442 self.assertEqual(self._target.dict_attr, {'Борис': 'name', 'жалбар': 'професия'})
443 self._dimitrichka.tick()
444 self.assertEqual(self._target.int_attr, 5)
445 self.assertAlmostEqual(self._target.float_attr, 3.14)
446 self.assertEqual(self._target.list_attr, [1, 2, 3])
447 self.assertEqual(self._target.dict_attr, {'name': 'Борис', 'професия': 'жалбар'})
448
449 def test_ticking_multiple_potions(self):
450 """Test ticking after applying multiple potions which affect the same attribute."""
451 # Same attribute
452 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
453 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=2)
454 self._dimitrichka.apply(self._target, potion1)
455 self._dimitrichka.apply(self._target, potion2)
456 self.assertEqual(self._target.int_attr, 500)
457 self._dimitrichka.tick()
458 self.assertEqual(self._target.int_attr, 50)
459 self._dimitrichka.tick()
460 self.assertEqual(self._target.int_attr, 5)
461 # Different attributes
462 self._target = copy.deepcopy(self._target)
463 self._target._refresh()
464 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1)
465 potion2 = Potion({'float_attr_fun': float_attr_fun}, duration=2)
466 self._dimitrichka.apply(self._target, potion1)
467 self._dimitrichka.apply(self._target, potion2)
468 self.assertEqual(self._target.int_attr, 50)
469 self.assertAlmostEqual(self._target.float_attr, 4.14)
470 self._dimitrichka.tick()
471 self.assertEqual(self._target.int_attr, 5)
472 self.assertAlmostEqual(self._target.float_attr, 4.14)
473 self._dimitrichka.tick()
474 self.assertEqual(self._target.int_attr, 5)
475 self.assertAlmostEqual(self._target.float_attr, 3.14)
476
477 def test_ticking_multiple_targets(self):
478 """Test ticking after applying a potion with mutable attributes."""
479 potion1 = Potion({'int_attr_fun': int_attr_fun}, duration=1) * 2
480 potion2 = Potion({'int_attr_fun': int_attr_fun}, duration=2)
481 target1 = self._target
482 target2 = Target(int_attr=5, float_attr=3.14,
483 list_attr=[1, 2, 3],
484 dict_attr={'name': 'Борис', 'професия': 'жалбар'})
485 self._dimitrichka.apply(target1, potion1)
486 self._dimitrichka.apply(target2, potion2)
487 self.assertEqual(target1.int_attr, 500)
488 self.assertEqual(target2.int_attr, 50)
489 self._dimitrichka.tick()
490 self.assertEqual(target1.int_attr, 5)
491 self.assertEqual(target2.int_attr, 50)
492 self._dimitrichka.tick()
493 self.assertEqual(target1.int_attr, 5)
494 self.assertEqual(target2.int_attr, 5)
495
496
497if __name__ == '__main__':
498 unittest.main()
Мартин Кузманов
01.12.2023 14:03Ако имаме обект "target" с "target.size"= 5 първоначално, и приложим отвара с ефект "grow"- "target.size" * 3 с "duration"=2 , след което отвара с "grow" - "target.size"* 5 с "duration"=3, след второто "tick()-ване" се очаква "target.size" вече да е 25 и след третото съответно 5 отново, нали?
|
Георги Кунчев
01.12.2023 08:51Първото описание е просто интродукция. Не приемай думата "списък" за дефинираща `list`. Винаги се очаква ефектите да са в речник.
Не се очаква да тестваме с ефект, който не е колабъл. Всичко, с което ще тестваме, ще са валидни ефекти спрямо дефиницията, подадени в речник.
|
Мартин Кузманов
30.11.2023 23:21Каква поведение се очаква при несъответсвие с изискванията (в условие "Ефекти")
Всеки ефект е callable.
....
?
|
Мартин Кузманов
30.11.2023 22:53Каква е разликата в условие "Potion" effects - списък от ефекти
и в условие "Ефекти"" effects -речник от ефекти?
|
Георги Кунчев
29.11.2023 14:26Прав си. Примерът беше некоректен. Преправих го с отделни инициализации.
|
Михаил Цанков
29.11.2023 13:31Имам два въпроса по следния код:
```
# target_1.size = 5
grow_potion = Potion({'grow': lambda target: setattr(target, 'size', target.size*2)}, duration=2)
grow_potion.grow(target_1)
# target_1.size = 10
# target_2.size = 5
triple_grow_potion = grow_potion + grow_potion + grow_potion
triple_grow_potion.grow(target_2)
# target_2.size = 40
```
1. На ред 3 използваме ефекта ```grow``` и той изчезва от potion-a но след това го комбинираме и се връща обратно?
2. Възможно ли е ```grow_potion + grow_potion + grow_potion``` според условието това е същото поведение като ```grow_potion * 3```, но по условията по долу имам чувството че трябва да се хвърля "Potion is now part of something bigger than itself.", защото ```grow_potion``` бива използван след първия +. Разбира се, може и да е твърде deep, за да го разбера.
|